/**
 * Components CSS - Arcade Creative Suite Pro
 * Buttons, inputs, cards, modals, toasts, etc.
 */

/* ==================== BUTTONS ==================== */

/* Primary Button */
.btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-6);
    background: linear-gradient(135deg, var(--color-accent) 0%, #ff6b35 100%);
    color: white;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: none;
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    box-shadow: var(--shadow-accent);
}

.btn-primary:hover {
    background: linear-gradient(135deg, #ff6b35 0%, var(--color-accent) 100%);
    transform: translateY(-2px);
    box-shadow: var(--shadow-accent-lg);
}

.btn-primary:active {
    transform: scale(0.98);
}

.btn-primary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
}

/* Secondary Button */
.btn-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-6);
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: 1px solid rgba(255, 140, 0, 0.3);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.btn-secondary:hover {
    background: rgba(255, 140, 0, 0.2);
    border-color: rgba(255, 140, 0, 0.5);
}

.btn-secondary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
    background: rgba(255, 140, 0, 0.05);
    border-color: rgba(255, 140, 0, 0.15);
}

/* Mandate C — toolbar clip-workflow tiering. .btn-secondary is already accent-bordered
   (0.3), so a plain --color-border-accent hairline would be a no-op; instead lift
   "Author clips" to a warm mid-tier (active 0.6 border + a hotter fill) so it reads as
   the lead-in to the primary "Render clips", a step above the plan-maintenance
   secondaries beside it. Same orange family — no new color. */
.btn-secondary.frames-toolbar-cta-2 {
    background: rgba(255, 140, 0, 0.16);
    border-color: var(--color-border-active);
}
.btn-secondary.frames-toolbar-cta-2:hover {
    background: rgba(255, 140, 0, 0.24);
    border-color: rgba(255, 140, 0, 0.75);
}

/* ======================= FRAMES — zoned grid toolbar (design §5/§7) =======================
   ONE control scale — 36px primary / 32px ghost / 36px overflow rows — replacing the 46px
   slabs. Scoped to .frames-* only; the global .btn classes are never touched. */
.frames-plan-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    flex: 1 1 auto;
    min-width: 0;
}
.frames-toolbar-zone {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}
.frames-toolbar-zone--direct { margin-right: auto; }   /* directing ghosts sit left */
.frames-toolbar-overflow { position: relative; flex-shrink: 0; }

.frames-toolbar-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    font-size: 13px;
    font-weight: var(--font-weight-medium, 500);
    line-height: 1;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-default);
    background: transparent;
    color: var(--color-text-secondary, #cbd5e1);
    cursor: pointer;
    white-space: nowrap;
    transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.frames-toolbar-btn i, .frames-toolbar-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.frames-toolbar-btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.05);
    border-color: var(--color-border-strong);
    color: var(--color-text-primary);
}
.frames-toolbar-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.frames-toolbar-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Primary terminal action (Render clips): 36px filled accent. */
.frames-toolbar-btn--primary {
    height: 36px;
    background: var(--color-accent, #ff8c00);
    border-color: var(--color-accent, #ff8c00);
    color: #fff;
    font-weight: var(--font-weight-semibold, 600);
}
.frames-toolbar-btn--primary:hover:not(:disabled) {
    background: var(--color-accent-hover, #ff9e2c);
    border-color: var(--color-accent-hover, #ff9e2c);
    color: #fff;
}
/* Quiet labeled Download-all (Zone 1 when clips unavailable): muted, no border weight. */
.frames-toolbar-btn--quiet { color: var(--color-text-muted, #94a3b8); border-color: transparent; }
.frames-toolbar-btn--quiet:hover:not(:disabled) { border-color: var(--color-border-default); }
/* Icon-only ghost (overflow ⋯ + Zone-2 Download-all): square 32px. */
.frames-toolbar-btn--icon-ghost { width: 32px; padding: 0; justify-content: center; }

/* Author motion prompts — the warm mid-tier lead-in to Render clips (same orange family). */
.frames-toolbar-btn.frames-toolbar-cta-2 {
    background: rgba(255, 140, 0, 0.16);
    border-color: var(--color-border-active);
    color: var(--color-text-primary);
}
.frames-toolbar-btn.frames-toolbar-cta-2:hover:not(:disabled) {
    background: rgba(255, 140, 0, 0.24);
    border-color: rgba(255, 140, 0, 0.75);
}

/* Overflow popover positioning — anchored to the ⋯ button (overrides the grouped
   .frames-node-popover `position: fixed`, which is JS-placed). Scoped to the
   `.frames-toolbar-overflow` parent so its (0,2,0) specificity beats the grouped
   `.frames-node-popover, .frames-toolbar-popover` rule (0,1,0) that follows later in
   the file — otherwise the whole block (position/top/right/width) loses the cascade
   and the popover renders fixed at the wrong anchor / unreachable. */
.frames-toolbar-overflow .frames-toolbar-popover {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    width: auto;
    min-width: 200px;
}
.frames-toolbar-popover.hidden { display: none; }
.frames-toolbar-popover-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    height: 36px;
    padding: 0 10px;
    font-size: 13px;
    color: var(--color-text-secondary, #cbd5e1);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    text-align: left;
    white-space: nowrap;
}
.frames-toolbar-popover-item i, .frames-toolbar-popover-item svg { width: 16px; height: 16px; flex-shrink: 0; }
.frames-toolbar-popover-item:hover { background: rgba(255, 255, 255, 0.06); color: var(--color-text-primary); }
.frames-toolbar-popover-item.hidden { display: none; }

/* Modal footers join the one control scale (design §7): the plan-review + bible-editor
   footer buttons drop from 46px slabs to 36px. Scoped via the .frames-plan-footer-actions
   ancestor — the global .btn classes are untouched. */
.frames-plan-footer-actions .btn-primary,
.frames-plan-footer-actions .btn-secondary {
    height: 36px;
    min-height: 36px;
    padding-top: 0;
    padding-bottom: 0;
    font-size: 13px;
    border-radius: var(--radius-md);
}

/* design §6 — the disabled Generate Frames calms to a non-primary look when it is NOT the
   filled primary (empty shot list), so a disabled control is never the only filled primary.
   id+class beats .btn-primary (0,1,0) without touching the global class. */
#generate-frames-btn.is-demoted {
    background: transparent;
    border: 1px solid var(--color-border-default);
    color: var(--color-text-secondary, #94a3b8);
    box-shadow: none;
}

/* §2.2 one-filled-primary (Slate & Call Sheet): the Author CTA's base class is .btn-primary,
   but side-by-side with Generate shot list in the Slate footer only the PROMOTED state may
   read filled — un-promoted it calms to the secondary look. Same id-beats-.btn-primary
   pattern as #generate-frames-btn.is-demoted above. */
#frames-bible-author-btn:not(.is-promoted) {
    background: transparent;
    border: 1px solid var(--color-border-default);
    color: var(--color-text-secondary, #94a3b8);
    box-shadow: none;
}

/* design §A2 — the gate's zero-named-character empty-state line. */
.frames-cast-empty-note {
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    line-height: 1.5;
}

/* Danger Button */
.btn-danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-6);
    background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
    color: white;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: none;
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);
}

.btn-danger:hover {
    background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
    transform: translateY(-2px);
    box-shadow: 0 6px 24px rgba(239, 68, 68, 0.4);
}

.btn-danger:active {
    transform: scale(0.98);
}

/* Ghost Button */
.btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.btn-ghost:hover {
    color: var(--color-text-primary);
    background: var(--color-bg-secondary);
}

/* Icon Button */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: transparent;
    color: var(--color-text-muted);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.btn-icon:hover {
    color: var(--color-text-primary);
    background: var(--color-bg-secondary);
    border-color: var(--color-border-strong);
}

.btn-icon.active {
    color: var(--color-accent);
    background: var(--color-accent-subtle);
    border-color: var(--color-border-accent);
}

/* Small Button */
.btn-sm {
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-xs);
}

/* Large Button */
.btn-lg {
    padding: var(--space-4) var(--space-8);
    font-size: var(--font-size-base);
}

/* Full Width Button */
.btn-full {
    width: 100%;
}

/* ==================== BATCH ACTION BUTTONS ==================== */

/* Batch actions container (used in results panels) */
.batch-actions {
    display: flex;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-secondary);
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-4);
}

.batch-actions.hidden {
    display: none;
}

.batch-actions .btn-secondary {
    display: inline-flex;
    align-items: center;
}

/* Results header with batch actions */
.results-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border-default);
}

.results-header-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
}

.results-header-actions {
    display: flex;
    gap: var(--space-2);
}

/* Storyboard action button - consistent with btn-secondary */
.btn-storyboard {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-6);
    background: rgba(139, 92, 246, 0.1);
    color: #a78bfa;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: 1px solid rgba(139, 92, 246, 0.3);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.btn-storyboard:hover {
    background: rgba(139, 92, 246, 0.2);
    border-color: rgba(139, 92, 246, 0.5);
}

.btn-storyboard:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background: rgba(139, 92, 246, 0.05);
    border-color: rgba(139, 92, 246, 0.15);
}

/* Batch count badge */
.batch-count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 var(--space-2);
    background: var(--color-accent);
    color: white;
    font-size: 11px;
    font-weight: var(--font-weight-semibold);
    border-radius: var(--radius-full);
    margin-left: var(--space-2);
}

/* Transfer in progress state */
.btn-transferring {
    position: relative;
    pointer-events: none;
}

.btn-transferring::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
    animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

/* Batch actions header (for results panels) */
.batch-actions-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-4);
    background: rgba(0, 0, 0, 0.3);
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-4);
}

.batch-actions-header .batch-info {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.batch-actions-header .batch-info strong {
    color: var(--color-text-primary);
}

/* ==================== FORM INPUTS ==================== */

/* Label */
.form-label {
    display: block;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-2);
}

/* Text Input */
.form-input {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-primary);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    outline: none;
    transition: all var(--transition-fast);
}

.form-input:focus {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.1);
}

.form-input::placeholder {
    color: var(--color-text-disabled);
}

/* Textarea */
.form-textarea {
    width: 100%;
    min-height: 100px;
    padding: var(--space-3) var(--space-4);
    background: var(--color-bg-primary);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    font-family: inherit;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    outline: none;
    resize: vertical;
    transition: all var(--transition-fast);
}

.form-textarea:focus {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.1);
}

/* Select */
.form-select {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-primary);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    outline: none;
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 36px;
}

.form-select:focus {
    border-color: var(--color-accent);
}

/* Range Slider */
.form-range {
    width: 100%;
    height: 4px;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    appearance: none;
    cursor: pointer;
}

.form-range::-webkit-slider-thumb {
    appearance: none;
    width: 16px;
    height: 16px;
    background: var(--color-accent);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: transform var(--transition-fast);
}

.form-range::-webkit-slider-thumb:hover {
    transform: scale(1.2);
}

/* Form Group */
.form-group {
    margin-bottom: var(--space-5);
}

.form-group:last-child {
    margin-bottom: 0;
}

/* ==================== UPLOAD SLOT ==================== */

.upload-slot {
    position: relative;
    border: 2px dashed var(--color-border-default);
    border-radius: var(--radius-xl);
    background: rgba(30, 41, 59, 0.5);
    cursor: pointer;
    transition: all var(--transition-fast);
    overflow: hidden;
}

.upload-slot:hover {
    border-color: var(--color-text-disabled);
    background: rgba(30, 41, 59, 0.7);
}

.upload-slot.drag-over {
    border-color: var(--color-accent);
    background: var(--color-accent-subtle);
    transform: scale(1.02);
}

.upload-slot.filled {
    border-style: solid;
    border-color: var(--color-border-strong);
}

.upload-slot-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    text-align: center;
}

.upload-slot-icon {
    width: 48px;
    height: 48px;
    margin-bottom: var(--space-3);
    color: var(--color-text-disabled);
}

.upload-slot-text {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.upload-slot-preview {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.upload-slot-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.upload-slot-clear {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    width: 28px;
    height: 28px;
    background: rgba(0, 0, 0, 0.6);
    border: none;
    border-radius: var(--radius-full);
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.upload-slot:hover .upload-slot-clear {
    opacity: 1;
}

/* Add More button for single image upload */
.upload-slot-add-more {
    position: absolute;
    bottom: var(--space-2);
    left: var(--space-2);
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    background: rgba(0, 0, 0, 0.7);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: var(--radius-md);
    color: white;
    font-size: var(--text-xs);
    cursor: pointer;
    opacity: 0;
    transition: all var(--transition-fast);
    z-index: 5;
}

.upload-slot:hover .upload-slot-add-more {
    opacity: 1;
}

.upload-slot-add-more:hover {
    background: rgba(255, 140, 0, 0.8);
    border-color: rgba(255, 140, 0, 0.5);
}

/* ==================== GLASS PANEL ==================== */

.glass-panel {
    background: rgba(30, 41, 59, 0.6);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(71, 85, 105, 0.3);
}

/* ==================== CARDS ==================== */

.card {
    background: var(--color-bg-surface);
    backdrop-filter: blur(10px);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    overflow: hidden;
}

.card-header {
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-border-subtle);
}

.card-body {
    padding: var(--space-5);
}

.card-footer {
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--color-border-subtle);
    background: rgba(0, 0, 0, 0.2);
}

/* ==================== MODE SELECTOR (Tabs) ==================== */

.mode-selector {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
    gap: var(--space-1);
    padding: var(--space-4);
    border-bottom: 1px solid var(--color-border-default);
}

.mode-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-2);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--color-text-disabled);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.mode-btn:hover {
    color: var(--color-text-muted);
    background: var(--color-bg-secondary);
}

.mode-btn.active {
    color: var(--color-accent);
    background: var(--color-bg-secondary);
    box-shadow: inset 0 0 0 1px var(--color-border-default);
}

.mode-btn-icon {
    width: 20px;
    height: 20px;
    margin-bottom: var(--space-1);
}

.mode-btn-label {
    font-size: 10px;
    font-weight: var(--font-weight-medium);
}

/* ==================== TOAST NOTIFICATIONS ==================== */

.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    min-width: 300px;
    max-width: 400px;
    animation: slideIn 0.3s ease;
}

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateX(100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

.toast-success {
    border-color: var(--color-success-border);
}

.toast-error {
    border-color: var(--color-error-border);
}

.toast-warning {
    border-color: var(--color-warning-border);
}

.toast-info {
    border-color: var(--color-info-border);
}

.toast-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.toast-success .toast-icon { color: var(--color-success); }
.toast-error .toast-icon { color: var(--color-error); }
.toast-warning .toast-icon { color: var(--color-warning); }
.toast-info .toast-icon { color: var(--color-info); }

.toast-content {
    flex: 1;
    min-width: 0;
}

.toast-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: var(--space-1);
}

.toast-message {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* An optional inline action button appended to a toast (deep-link recovery, e.g. the
   Frames verify "no mapping" → matcher hand-off). Reuses the toast token palette. */
.toast-action-btn {
    margin-top: var(--space-2);
    padding: 3px 10px;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.toast-action-btn:hover {
    background: var(--color-bg-secondary);
    border-color: var(--color-text-muted);
}

.toast-close {
    width: 20px;
    height: 20px;
    background: none;
    border: none;
    color: var(--color-text-disabled);
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
}

.toast-close:hover {
    color: var(--color-text-muted);
}

/* ==================== PROGRESS INDICATORS ==================== */

.spinner {
    width: 20px;
    height: 20px;
    border: 2px solid var(--color-bg-tertiary);
    border-top-color: var(--color-accent);
    border-radius: var(--radius-full);
    animation: spin 1s linear infinite;
}

.spinner-lg {
    width: 48px;
    height: 48px;
    border-width: 4px;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* Shared upload-busy overlay (utils/upload-feedback.js) */
.upload-busy-host { position: relative; }

.upload-busy-overlay {
    position: absolute;
    inset: 0;
    z-index: 30; /* above slot previews and AI-assist z-10 overlays */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    background: rgba(15, 23, 42, 0.85);
    border-radius: inherit;
    text-align: center;
}

.upload-busy-label {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    max-width: 90%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* .spinner sets width/height but spans are inline by default */
span.spinner { display: inline-block; }

/* Toasts must sit above modals (--z-modal: 400). The container ships with
   Tailwind z-50, which the build emits as !important — so this must be too. */
#toast-container { z-index: var(--z-toast) !important; }

/* Progress Bar */
.progress-bar {
    width: 100%;
    height: 6px;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--color-accent), #ff6b35);
    border-radius: var(--radius-full);
    transition: width var(--transition-base);
}

/* ==================== BADGES ==================== */

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    border-radius: var(--radius-full);
}

.badge-success {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.badge-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.badge-error {
    background: var(--color-error-bg);
    color: var(--color-error);
}

.badge-info {
    background: var(--color-info-bg);
    color: var(--color-info);
}

/* ==================== DIVIDER ==================== */

.divider {
    width: 100%;
    height: 1px;
    background: var(--color-border-default);
    margin: var(--space-4) 0;
}

/* ==================== LINE CLAMP UTILITIES ==================== */

.line-clamp-1 {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.line-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.line-clamp-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ==================== SECTION TITLE ==================== */

.section-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-3);
}

.section-title-text {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.section-title-action {
    font-size: var(--font-size-xs);
    color: var(--color-accent);
    background: none;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

.section-title-action:hover {
    color: var(--color-accent-light);
}

/* ==================== EMPTY STATE ==================== */

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: var(--space-10);
}

/* Override to ensure hidden class works on empty-state */
.empty-state.hidden {
    display: none;
}

.empty-state-icon {
    width: 64px;
    height: 64px;
    margin-bottom: var(--space-4);
    color: var(--color-text-disabled);
}

.empty-state-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: var(--space-2);
}

.empty-state-description {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    max-width: 300px;
}

/* ==================== LAZY LOADING ==================== */

/* Lazy image states */
.lazy-image {
    opacity: 0.7;
    filter: blur(5px);
    transition: opacity 0.3s ease, filter 0.3s ease;
}

.lazy-image.loading {
    animation: lazy-pulse 1.5s ease-in-out infinite;
}

.lazy-image.loaded {
    opacity: 1;
    filter: none;
}

.lazy-image.load-error {
    opacity: 0.5;
    cursor: pointer;
}

@keyframes lazy-pulse {
    0%, 100% { opacity: 0.7; }
    50% { opacity: 0.4; }
}

/* ==================== SCROLL TO TOP ==================== */

.scroll-to-top-btn {
    position: fixed;
    bottom: 2rem;
    right: 2rem;
    width: 48px;
    height: 48px;
    border-radius: var(--radius-full);
    background: linear-gradient(135deg, var(--color-accent) 0%, #ff6b35 100%);
    color: white;
    border: none;
    cursor: pointer;
    box-shadow: 0 4px 12px rgba(255, 140, 0, 0.3);
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
    animation: fadeInUp 0.3s ease;
}

.scroll-to-top-btn:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 20px rgba(255, 140, 0, 0.4);
}

@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ==================== BULK PROGRESS OVERLAY ==================== */

.bulk-progress-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

.bulk-progress-card {
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    padding: var(--space-8);
    min-width: 300px;
    max-width: 400px;
    text-align: center;
}

.bulk-progress-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    margin-bottom: var(--space-4);
}

.bulk-progress-message {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    margin-bottom: var(--space-4);
}

.bulk-progress-bar {
    height: 8px;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    overflow: hidden;
    margin-bottom: var(--space-2);
}

.bulk-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--color-accent), #ff6b35);
    border-radius: var(--radius-full);
    transition: width 0.3s ease;
}

.bulk-progress-count {
    font-size: var(--font-size-xs);
    color: var(--color-text-disabled);
}

/* ==================== UPLOAD PROGRESS OVERLAY (Image Edit) ==================== */

.upload-progress-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(6px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 30;
    transition: opacity 0.3s ease;
}

.upload-progress-overlay.fade-out {
    opacity: 0;
}

.upload-progress-card {
    text-align: center;
    max-width: 280px;
}

.upload-progress-icon {
    color: var(--color-accent);
    margin-bottom: var(--space-3);
    animation: uploadPulse 1.5s ease-in-out infinite;
}

@keyframes uploadPulse {
    0%, 100% { opacity: 0.7; transform: scale(1); }
    50% { opacity: 1; transform: scale(1.05); }
}

.upload-progress-text {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: var(--space-3);
}

.upload-progress-bar {
    height: 6px;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    overflow: hidden;
    margin-bottom: var(--space-2);
}

.upload-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--color-accent), #ff6b35);
    border-radius: var(--radius-full);
    transition: width 0.3s ease;
    width: 0%;
}

/* Indeterminate state for single-file uploads */
.upload-progress-fill.indeterminate {
    width: 100% !important;
    animation: indeterminateProgress 1.5s ease-in-out infinite;
}

@keyframes indeterminateProgress {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

.upload-progress-count {
    font-size: var(--font-size-xs);
    color: var(--color-text-disabled);
}

/* ==================== LOADING SKELETON ==================== */

@keyframes skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ==================== GENERATION CARDS ==================== */

/* Base generation card */
.gen-card {
    position: relative;
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--color-bg-secondary);
    transition: all 0.3s ease;
}

/* Skeleton shimmer state */
.gen-card--skeleton {
    aspect-ratio: 1;
    background: linear-gradient(90deg,
        var(--color-bg-secondary) 0%,
        var(--color-bg-tertiary) 50%,
        var(--color-bg-secondary) 100%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s infinite;
}

/* Generating state - dimmed shimmer + progress overlay */
.gen-card--generating {
    aspect-ratio: 1;
}

.gen-card--generating .gen-card-shimmer {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        var(--color-bg-secondary) 0%,
        var(--color-bg-tertiary) 50%,
        var(--color-bg-secondary) 100%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 2s infinite;
    opacity: 0.5;
}

.gen-card-progress {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 1;
}

.gen-card-progress svg {
    width: 48px;
    height: 48px;
}

.gen-card-progress .progress-ring-bg {
    stroke: var(--color-bg-tertiary);
    fill: none;
    stroke-width: 3;
}

.gen-card-progress .progress-ring-fill {
    stroke: var(--color-accent);
    fill: none;
    stroke-width: 3;
    stroke-linecap: round;
    transition: stroke-dashoffset 0.3s ease;
    transform: rotate(-90deg);
    transform-origin: center;
}

.gen-card-progress .progress-text {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
    margin-top: 0.5rem;
}

/* Complete state - fade in media */
.gen-card--complete {
    aspect-ratio: auto;
}

.gen-card--complete img,
.gen-card--complete video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    animation: genCardReveal 0.4s ease;
}

@keyframes genCardReveal {
    from { opacity: 0; transform: scale(0.97); }
    to { opacity: 1; transform: scale(1); }
}

/* Error state */
.gen-card--error {
    aspect-ratio: 1;
    border: 2px solid var(--color-error, #ef4444);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1rem;
}

/* Card label overlay (for angles, locations, variations) */
.gen-card-label {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.5rem;
    background: linear-gradient(transparent, rgba(0,0,0,0.7));
    z-index: 2;
}

.gen-card-label span {
    font-size: 0.75rem;
    color: white;
    font-weight: 500;
}

/* Live stage line on the video skeleton card (Seedance 2.0): backend stage
   label on the left, client-side elapsed mm:ss on the right. Sits above the
   shimmer, below nothing — dropped when the card rebuilds on complete/error. */
.gen-card-stage {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.65));
    z-index: 2;
}

.gen-card-stage-label {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gen-card-stage-elapsed {
    font-size: 0.75rem;
    color: var(--color-text-tertiary, #94a3b8);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

/* Storyboard card progress overlay (batch style/enhance) */
.storyboard-card-progress {
    position: absolute;
    inset: 0;
    z-index: 5;
    pointer-events: none;
}

/* Queue panel badge pulse */
.queue-badge-pulse {
    animation: queuePulse 2s infinite;
}

@keyframes queuePulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

/* Remote job indicator - subtle opacity to distinguish from local jobs */
.queue-job--remote {
    opacity: 0.75;
}

/* ==================== DASHBOARD GRID ==================== */

#dashboard-content {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-4);
    padding: var(--space-4);
}

/* ==================== LIST VIEW ==================== */

#dashboard-content.list-view {
    display: flex !important;
    flex-direction: column;
    gap: 0;
    padding: 0 !important;
}

/* Hide grid cards in list view (list uses .list-row instead) */
#dashboard-content.list-view .generation-card {
    display: none !important;
}

/* Day group headers */
.list-day-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    position: sticky;
    top: 0;
    z-index: 10;
    background: rgba(24, 24, 27, 0.95);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.list-day-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-muted, #94a3b8);
}

.list-day-count {
    font-size: 11px;
    font-weight: 500;
    color: var(--color-text-muted, #64748b);
    background: rgba(255, 255, 255, 0.05);
    padding: 2px 8px;
    border-radius: 10px;
}

/* List rows */
.list-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.list-row:hover {
    background: rgba(255, 255, 255, 0.03);
}

/* Checkbox column (multi-select) */
.list-col-checkbox {
    flex-shrink: 0;
    width: 20px;
    display: flex;
    align-items: center;
}

/* Thumbnail column */
.list-col-thumb {
    flex-shrink: 0;
}

.list-thumb {
    width: 48px;
    height: 48px;
    border-radius: 8px;
    overflow: hidden;
    background: #1e1e2e;
    position: relative;
}

.list-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.list-thumb--text {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 153, 0, 0.08);
}

.list-thumb--video::after {
    content: '';
}

.list-thumb-play {
    position: absolute;
    bottom: 2px;
    right: 2px;
    width: 16px;
    height: 16px;
    color: white;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}

/* Type column */
.list-col-type {
    flex-shrink: 0;
    width: 80px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.list-type-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.list-type-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--color-text-secondary, #cbd5e1);
}

/* Prompt column */
.list-col-prompt {
    flex: 1;
    min-width: 0;
    overflow: hidden;
}

.list-prompt-text {
    font-size: 13px;
    color: var(--color-text-primary, #f1f5f9);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block;
}

/* Date column */
.list-col-date {
    flex-shrink: 0;
    width: 72px;
    font-size: 12px;
    font-family: var(--font-mono, 'JetBrains Mono', 'Fira Code', monospace);
    color: var(--color-text-muted, #64748b);
    text-align: right;
}

/* Credits column */
.list-col-credits {
    flex-shrink: 0;
    width: 48px;
    font-size: 12px;
    font-family: var(--font-mono, 'JetBrains Mono', 'Fira Code', monospace);
    color: var(--color-text-muted, #64748b);
    text-align: right;
}

.list-credits-suffix {
    font-size: 10px;
    margin-left: 1px;
    opacity: 0.6;
}

/* Actions column */
.list-col-actions {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 2px;
}

.list-action-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 6px;
    border: none;
    background: transparent;
    color: var(--color-text-muted, #64748b);
    cursor: pointer;
    opacity: 0;
    transition: all 0.12s ease;
}

.list-row:hover .list-action-btn {
    opacity: 1;
}

/* ---- Lasso (rubber-band) selection ---- */
/* !important is required because Tailwind config sets important: true —
   utility classes on the scroller / cards would otherwise win. */

.dashboard-lasso {
    position: absolute !important;
    pointer-events: none !important;
    border: 2px dashed #ff8c00 !important;
    background: rgba(255, 140, 0, 0.22) !important;
    box-shadow: 0 0 0 1px rgba(255, 140, 0, 0.4), 0 4px 16px rgba(255, 140, 0, 0.25) !important;
    border-radius: 2px !important;
    z-index: 50 !important;
    display: none;
}

.dashboard-lasso.dashboard-lasso--visible {
    display: block !important;
}

/* Applied on pointerdown — establishes positioning context for the
   absolutely-positioned rect and kills native text selection while the
   user is drag-selecting over the cards. */
.dashboard-lasso--active {
    position: relative !important;
}
.dashboard-lasso--active,
.dashboard-lasso--active * {
    user-select: none !important;
    -webkit-user-select: none !important;
}

/* Live highlight on cards/rows intersected by the current lasso rect. */
.generation-card.lasso-hover,
.list-row.lasso-hover {
    outline: 3px solid #ff8c00 !important;
    outline-offset: -3px !important;
    box-shadow: 0 0 16px rgba(255, 140, 0, 0.45) !important;
}

/* "Will be deselected" visual during a lasso-remove drag (items that are
   currently selected and hovered by the lasso rect). */
.generation-card.lasso-remove,
.list-row.lasso-remove {
    outline: 3px dashed #ff6b6b !important;
    outline-offset: -3px !important;
    opacity: 0.6 !important;
}

.list-action-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--color-text-primary, #f1f5f9);
}

/* Always show favorited star, even without hover */
.list-action-btn--active {
    color: #facc15;
    opacity: 1;
}

.list-action-btn--active:hover {
    color: #fbbf24;
}

/* Kebab dropdown menu */
.list-kebab-menu {
    z-index: 50;
    min-width: 180px;
    padding: 4px;
    border-radius: 10px;
    background: #1e1e2e;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

.list-kebab-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 12px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--color-text-secondary, #cbd5e1);
    font-size: 13px;
    cursor: pointer;
    text-align: left;
    transition: background 0.1s;
}

.list-kebab-item:hover {
    background: rgba(255, 255, 255, 0.06);
    color: var(--color-text-primary, #f1f5f9);
}

.list-kebab-item--danger {
    color: #f87171;
}

.list-kebab-item--danger:hover {
    background: rgba(239, 68, 68, 0.1);
    color: #fca5a5;
}

.list-kebab-divider {
    height: 1px;
    background: rgba(255, 255, 255, 0.06);
    margin: 4px 0;
}

/* Kebab submenu (hover flyout) */
.list-kebab-item--submenu {
    position: relative;
}

.list-kebab-item--submenu .list-kebab-chevron {
    margin-left: auto;
    opacity: 0.5;
}

/*
 * HOVER SUBMENU BRIDGE PATTERN:
 * The submenu uses a ::before pseudo-element as an invisible hover bridge
 * between the parent menu item and the submenu. This transparent bridge
 * keeps the :hover chain intact while the cursor travels across the visual
 * gap. Without it, the submenu closes as soon as the mouse leaves the
 * parent item. Always use this pattern for CSS-only hover submenus.
 */
.list-kebab-submenu {
    position: absolute;
    top: -4px;
    right: calc(100% + 4px);
    min-width: 160px;
    padding: 4px;
    border-radius: 10px;
    background: #1e1e2e;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.12s ease;
    z-index: 51;
}

/* Invisible hover bridge from submenu back to parent item */
.list-kebab-submenu::before {
    content: '';
    position: absolute;
    top: 0;
    right: -8px; /* extends rightward toward parent menu */
    width: 8px;
    height: 100%;
}

/* Flip submenu to the right when not enough space on left */
.list-kebab-submenu--flip {
    right: auto;
    left: calc(100% + 4px);
}

.list-kebab-submenu--flip::before {
    right: auto;
    left: -8px; /* bridge extends leftward toward parent menu */
}

.list-kebab-item--submenu:hover .list-kebab-submenu {
    opacity: 1;
    pointer-events: auto;
}

/* Expanded view Prompt AI dropdown */
.prompt-ai-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    min-width: 160px;
    padding: 4px;
    border-radius: 10px;
    background: #1e1e2e;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    z-index: 50;
}

/* ==================== FILTER BAR ==================== */

.filter-btn {
    padding: var(--space-2) var(--space-4);
    background: var(--color-bg-tertiary);
    color: var(--color-text-muted);
    border: none;
    border-radius: var(--radius-lg);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.filter-btn:hover {
    background: var(--color-bg-secondary);
    color: var(--color-text-primary);
}

.filter-btn.active,
.filter-btn[class*="bg-arcade-orange"] {
    background: var(--color-accent);
    color: white;
}

/* ==================== HISTORY STRIP ==================== */

.history-item {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: var(--radius-md);
    overflow: hidden;
    border: 2px solid transparent;
    cursor: pointer;
    transition: all var(--transition-fast);
    background: var(--color-bg-secondary);
}

.history-item:hover {
    border-color: var(--color-accent);
    transform: scale(1.05);
}

.history-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

#image-history-strip,
#video-history-strip {
    padding: var(--space-4);
    background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, transparent 100%);
    border-radius: var(--radius-lg);
}

#image-history-items,
#video-history-items,
#video-image-history-items,
#angles-history-items,
#journey-history-items {
    display: flex;
    gap: var(--space-3);
    overflow-x: auto;
    padding-bottom: var(--space-2);
    scrollbar-width: thin;
    scrollbar-color: var(--color-text-disabled) transparent;
}

#image-history-items::-webkit-scrollbar,
#video-history-items::-webkit-scrollbar,
#video-image-history-items::-webkit-scrollbar,
#angles-history-items::-webkit-scrollbar,
#journey-history-items::-webkit-scrollbar {
    height: 4px;
}

#image-history-items::-webkit-scrollbar-thumb,
#video-history-items::-webkit-scrollbar-thumb,
#video-image-history-items::-webkit-scrollbar-thumb,
#angles-history-items::-webkit-scrollbar-thumb,
#journey-history-items::-webkit-scrollbar-thumb {
    background: var(--color-text-disabled);
    border-radius: var(--radius-full);
}

/* History item position context for badges */
.history-item {
    position: relative;
}

/* Duration badge for video history items */
.history-item .duration {
    position: absolute;
    bottom: 2px;
    right: 2px;
    padding: 1px 4px;
    background: rgba(0, 0, 0, 0.75);
    color: white;
    font-size: 9px;
    border-radius: var(--radius-sm);
    font-weight: 500;
}

/* VEO badge for extendable videos */
.history-item .veo-badge {
    position: absolute;
    top: 2px;
    left: 2px;
    padding: 1px 3px;
    background: var(--color-accent);
    color: white;
    font-size: 7px;
    font-weight: 700;
    border-radius: var(--radius-sm);
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

/* Image error placeholder for failed thumbnails */
.history-item img.img-error {
    background: var(--color-bg-tertiary) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='2' ry='2'/%3E%3Ccircle cx='8.5' cy='8.5' r='1.5'/%3E%3Cpolyline points='21 15 16 10 5 21'/%3E%3C/svg%3E") no-repeat center;
    min-width: 48px;
    min-height: 48px;
    opacity: 0.5;
}

/* ==================== FRAME SELECTOR ==================== */

#frame-selector-modal .glass-panel {
    max-height: 90vh;
    overflow-y: auto;
}

#frameSelectorVideo {
    background: var(--color-bg-secondary);
}

#frameSeeker {
    height: 8px;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    background: var(--color-bg-secondary);
    border-radius: var(--radius-full);
}

#frameSeeker::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--color-accent);
    cursor: pointer;
    transition: transform var(--transition-fast);
}

#frameSeeker::-webkit-slider-thumb:hover {
    transform: scale(1.2);
}

#frameSeeker::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--color-accent);
    cursor: pointer;
    border: none;
}

#framePreviewCanvas {
    min-width: 320px;
    min-height: 180px;
}

/* Keyboard hints styling */
#frame-selector-modal kbd {
    font-family: var(--font-mono);
    font-size: 10px;
}

/* ==================== FRAME SELECTOR STATE OVERLAYS ==================== */

.frame-selector-overlay {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.95);
    backdrop-filter: blur(4px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 20;
    border-radius: var(--radius-lg);
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* Capture flash animation */
.capture-flash {
    position: absolute;
    inset: 0;
    background: white;
    opacity: 0;
    animation: flash 0.3s ease;
    pointer-events: none;
    border-radius: var(--radius-lg);
}

@keyframes flash {
    0% { opacity: 0; }
    10% { opacity: 0.8; }
    100% { opacity: 0; }
}

/* Success checkmark animation */
.success-checkmark {
    width: 4rem;
    height: 4rem;
    background: rgba(16, 185, 129, 0.2);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    animation: pop 0.5s ease;
}

@keyframes pop {
    0% { transform: scale(0); opacity: 0; }
    50% { transform: scale(1.2); }
    100% { transform: scale(1); opacity: 1; }
}

/* Canvas capture pulse effect */
#framePreviewCanvas.capture-pulse {
    animation: capturePulse 0.3s ease;
}

@keyframes capturePulse {
    0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
    70% { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
    100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
}

/* Canvas error state */
#framePreviewCanvas.canvas-error {
    border-color: var(--color-error-border);
    opacity: 0.6;
}

/* Disabled button states during processing */
#frame-selector-modal .btn-primary:disabled,
#frame-selector-modal .btn-secondary:disabled {
    pointer-events: none;
    opacity: 0.5;
    cursor: not-allowed;
}

/* Seeker disabled state */
#frameSeeker:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

/* CORS warning badge pulse */
#cors-warning {
    animation: pulseBadge 2s ease-in-out infinite;
}

@keyframes pulseBadge {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

/* ==================== DRAWING FEATURE ==================== */

/* Drawing option card (horizontal bar layout) */
.drawing-option-card {
    padding: var(--space-4);
    border-radius: var(--radius-xl);
    background: linear-gradient(135deg, var(--color-accent-subtle) 0%, rgba(255, 107, 53, 0.08) 100%);
    border: 1px solid var(--color-border-accent);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.drawing-option-card:hover {
    border-color: var(--color-border-active);
    background: linear-gradient(135deg, var(--color-accent-muted) 0%, rgba(255, 107, 53, 0.12) 100%);
    box-shadow: var(--shadow-accent);
}

.drawing-option-icon {
    width: 48px;
    height: 48px;
    background: var(--color-accent-muted);
    border-radius: var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* Fix for Lucide icon color - explicit stroke */
.drawing-option-icon i,
.drawing-option-icon svg {
    width: 24px;
    height: 24px;
    color: var(--color-accent) !important;
    stroke: var(--color-accent) !important;
}

.drawing-option-content {
    flex: 1;
    text-align: left;
}

.drawing-option-content h4 {
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    margin-bottom: 2px;
}

.drawing-option-content p {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin: 0;
}

.drawing-option-card .btn-secondary {
    flex-shrink: 0;
}

/* Visibility management classes */
.drawing-hidden {
    display: none !important;
}

/* Drawing button in edit section */
.drawing-button-hint {
    margin-top: var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
}

.drawing-button-hint i,
.drawing-button-hint svg {
    width: 12px;
    height: 12px;
}

/* Drawing Toolbar */
#drawing-toolbar {
    flex-shrink: 0;
}

/* Drawing Color Swatches */
.drawing-color-swatch {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    transition: all var(--transition-fast);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
}

.drawing-color-swatch:hover {
    transform: scale(1.15);
    box-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
}

.drawing-color-swatch.active {
    border-color: var(--color-accent);
    transform: scale(1.1);
    box-shadow: 0 0 0 2px var(--color-accent), 0 0 12px var(--color-accent);
}

/* Special styling for white swatch visibility */
.drawing-color-swatch[data-color="#ffffff"] {
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.3);
}

/* Drawing Tool Buttons */
.drawing-tool-btn {
    padding: var(--space-2);
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text-muted);
    border: none;
    cursor: pointer;
    transition: all var(--transition-fast);
    display: flex;
    align-items: center;
    justify-content: center;
}

.drawing-tool-btn:hover {
    color: var(--color-text-primary);
    background: var(--color-bg-tertiary);
}

.drawing-tool-btn.active {
    color: var(--color-accent);
    background: var(--color-accent-subtle);
}

/* Drawing canvas responsive sizing */
#drawingCanvas {
    cursor: crosshair;
    touch-action: none;
}

/* Eraser cursor */
#drawingCanvas.eraser-mode {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2'%3E%3Crect x='4' y='4' width='16' height='16' rx='2'/%3E%3C/svg%3E") 12 12, crosshair;
}

/* ==================== LOGO STYLES ==================== */

/* Sidebar logo container */
.sidebar-logo {
    display: block;
    transition: all var(--transition-fast);
}

/* Orange gradient effect for logo images */
.logo-gradient {
    /* Transform black to orange using CSS filters */
    filter:
        brightness(0)           /* Make fully black */
        invert(1)               /* Invert to white */
        sepia(1)                /* Add sepia tone base */
        saturate(10)            /* Boost saturation */
        hue-rotate(-15deg)      /* Fine-tune to orange */
        drop-shadow(0 0 8px rgba(255, 140, 0, 0.4));
    transition: filter var(--transition-fast), transform var(--transition-fast);
}

/* Hover effect - enhanced glow */
.logo-gradient:hover {
    filter:
        brightness(0)
        invert(1)
        sepia(1)
        saturate(10)
        hue-rotate(-15deg)
        drop-shadow(0 0 12px rgba(255, 140, 0, 0.6))
        drop-shadow(0 0 20px rgba(255, 140, 0, 0.3));
    transform: scale(1.02);
}

/* Login page logo - larger with more prominent glow */
.logo-login {
    filter:
        brightness(0)
        invert(1)
        sepia(1)
        saturate(10)
        hue-rotate(-15deg)
        drop-shadow(0 0 15px rgba(255, 140, 0, 0.5))
        drop-shadow(0 0 30px rgba(255, 140, 0, 0.25));
}

/* Mobile sidebar logo - compact size */
.logo-mobile {
    object-fit: contain;
    max-width: 40px;
    max-height: 40px;
}

/* Desktop sidebar logo - full width */
.logo-desktop {
    max-height: 40px;
    width: auto;
    object-fit: contain;
}

/* Animated gradient shift on hover (optional premium effect) */
@keyframes logo-glow-pulse {
    0%, 100% {
        filter:
            brightness(0)
            invert(1)
            sepia(1)
            saturate(10)
            hue-rotate(-15deg)
            drop-shadow(0 0 8px rgba(255, 140, 0, 0.4));
    }
    50% {
        filter:
            brightness(0)
            invert(1)
            sepia(1)
            saturate(10)
            hue-rotate(-15deg)
            drop-shadow(0 0 15px rgba(255, 140, 0, 0.6))
            drop-shadow(0 0 25px rgba(255, 140, 0, 0.3));
    }
}

/* Apply pulse animation on focus/active state */
.logo-gradient:focus,
.logo-gradient.pulse {
    animation: logo-glow-pulse 2s ease-in-out infinite;
}

/* ==================== MULTI-IMAGE UPLOAD GRID ==================== */

#uploadedImagesGrid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-2);
}

#uploadedImagesGrid .image-thumb {
    position: relative;
    aspect-ratio: 1;
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 2px solid var(--color-border-default);
    background: var(--color-bg-secondary);
    transition: all var(--transition-fast);
}

#uploadedImagesGrid .image-thumb:hover {
    border-color: var(--color-border-strong);
}

#uploadedImagesGrid .image-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

#uploadedImagesGrid .image-thumb-remove {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    background: rgba(239, 68, 68, 0.9);
    border: none;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--transition-fast);
    color: white;
}

#uploadedImagesGrid .image-thumb:hover .image-thumb-remove {
    opacity: 1;
}

#uploadedImagesGrid .image-thumb-remove:hover {
    background: rgba(220, 38, 38, 1);
}

#uploadedImagesGrid .image-thumb-remove svg,
#uploadedImagesGrid .image-thumb-remove i {
    width: 12px;
    height: 12px;
}

/* Add more button in grid */
#uploadedImagesGrid .add-more-btn {
    aspect-ratio: 1;
    border: 2px dashed var(--color-border-default);
    border-radius: var(--radius-lg);
    background: transparent;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition-fast);
    color: var(--color-text-disabled);
}

#uploadedImagesGrid .add-more-btn:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: var(--color-accent-subtle);
}

#uploadedImagesGrid .add-more-btn svg,
#uploadedImagesGrid .add-more-btn i {
    width: 24px;
    height: 24px;
    margin-bottom: var(--space-1);
}

#uploadedImagesGrid .add-more-btn span {
    font-size: 10px;
    font-weight: var(--font-weight-medium);
}

/* Image count badge */
.image-count-badge {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-top: var(--space-2);
    text-align: center;
}

/* ==================== MULTI-IMAGE GALLERY (Main Canvas) ==================== */

#edit-gallery-state {
    background: var(--color-bg-primary);
}

#gallery-grid {
    max-height: calc(100% - 60px);
    align-content: start;
}

.gallery-thumb {
    position: relative;
    aspect-ratio: 1;
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 2px solid var(--color-border-default);
    cursor: pointer;
    transition: all var(--transition-fast);
    background: var(--color-bg-secondary);
}

.gallery-thumb:hover {
    border-color: var(--color-border-strong);
    transform: scale(1.02);
}

.gallery-thumb.selected {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px var(--color-accent-subtle);
}

.gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.gallery-thumb-remove {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.7);
    border: none;
    color: white;
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--transition-fast);
    display: flex;
    align-items: center;
    justify-content: center;
}

.gallery-thumb:hover .gallery-thumb-remove {
    opacity: 1;
}

.gallery-thumb-remove:hover {
    background: var(--color-danger);
}

.gallery-thumb-remove svg,
.gallery-thumb-remove i {
    width: 14px;
    height: 14px;
}

/* Selected indicator badge */
.gallery-thumb-selected-badge {
    position: absolute;
    bottom: 6px;
    left: 6px;
    background: var(--color-accent);
    color: white;
    font-size: 9px;
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Add more button in gallery grid */
#gallery-grid .gallery-add-btn {
    aspect-ratio: 1;
    border: 2px dashed var(--color-border-default);
    border-radius: var(--radius-lg);
    background: transparent;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition-fast);
    color: var(--color-text-disabled);
}

#gallery-grid .gallery-add-btn:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: var(--color-accent-subtle);
}

#gallery-grid .gallery-add-btn svg,
#gallery-grid .gallery-add-btn i {
    width: 28px;
    height: 28px;
    margin-bottom: var(--space-2);
}

#gallery-grid .gallery-add-btn span {
    font-size: 11px;
    font-weight: var(--font-weight-medium);
}

/* ==========================================
   Video Drop Overlay
   ========================================== */

#video-drop-overlay {
    transition: opacity 0.2s ease, visibility 0.2s ease;
    opacity: 0;
    visibility: hidden;
}

#video-drop-overlay.active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

#video-drop-overlay .drop-zone-card {
    transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    transform: scale(0.95);
    opacity: 0;
}

#video-drop-overlay.active .drop-zone-card {
    transform: scale(1);
    opacity: 1;
}

#video-drop-overlay.drag-active .drop-zone-card {
    transform: scale(1.02);
    border-color: #ffb347;
    box-shadow: 0 0 40px rgba(255, 140, 0, 0.3),
                inset 0 0 60px rgba(255, 140, 0, 0.05);
}

#video-drop-overlay.drag-active .drop-zone-icon {
    background: linear-gradient(135deg, rgba(255, 140, 0, 0.3) 0%, rgba(255, 107, 53, 0.2) 100%);
    animation: videoDropPulse 1.5s ease-in-out infinite;
}

#video-drop-overlay.drag-active .drop-zone-icon i,
#video-drop-overlay.drag-active .drop-zone-icon svg {
    transform: translateY(-4px);
    transition: transform 0.3s ease;
}

@keyframes videoDropPulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(255, 140, 0, 0.4);
    }
    50% {
        box-shadow: 0 0 0 20px rgba(255, 140, 0, 0);
    }
}

/* ==========================================
   Storyboard Upload Drop Overlay
   ========================================== */

#storyboard-upload-overlay {
    transition: opacity 0.2s ease, visibility 0.2s ease;
    opacity: 0;
    visibility: hidden;
}

#storyboard-upload-overlay.active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

#storyboard-upload-overlay .drop-zone-card {
    transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    transform: scale(0.95);
    opacity: 0;
}

#storyboard-upload-overlay.active .drop-zone-card {
    transform: scale(1);
    opacity: 1;
}

#storyboard-upload-overlay.drag-active .drop-zone-card {
    transform: scale(1.02);
    border-color: #ffb347;
    box-shadow: 0 0 40px rgba(255, 140, 0, 0.3);
}

#storyboard-upload-overlay.drag-active .drop-zone-icon {
    animation: storyboardDropPulse 1.5s ease-in-out infinite;
}

@keyframes storyboardDropPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 140, 0, 0.4); }
    50% { box-shadow: 0 0 0 20px rgba(255, 140, 0, 0); }
}

/* ==========================================
   Creative Director Components
   ========================================== */

/* Variation Type Cards */
.variation-type-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background: var(--color-bg-tertiary);
    border: 2px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: center;
}

.variation-type-card:hover {
    border-color: rgba(255, 140, 0, 0.5);
    background: rgba(255, 140, 0, 0.05);
}

.variation-type-card.selected {
    border-color: var(--color-accent);
    background: rgba(255, 140, 0, 0.1);
}

.variation-type-card.selected i,
.variation-type-card.selected svg {
    color: var(--color-accent) !important;
}

.variation-type-card .variation-name {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: 2px;
}

.variation-type-card .variation-desc {
    font-size: var(--font-size-xs);
    color: var(--color-text-disabled);
}

/* DP Checkbox Cards (Cinematographer selection) */
.dp-checkbox {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--color-bg-tertiary);
    border: 2px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: left;
}

.dp-checkbox:hover {
    border-color: rgba(255, 140, 0, 0.5);
    background: rgba(255, 140, 0, 0.05);
}

.dp-checkbox.selected {
    border-color: var(--color-accent);
    background: rgba(255, 140, 0, 0.1);
}

.dp-checkbox .dp-check {
    width: 20px;
    height: 20px;
    border-radius: var(--radius-sm);
    border: 2px solid var(--color-border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all var(--transition-fast);
}

.dp-checkbox.selected .dp-check {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: white;
}

.dp-checkbox:not(.selected) .dp-check i,
.dp-checkbox:not(.selected) .dp-check svg {
    display: none;
}

.dp-checkbox .dp-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.dp-checkbox .dp-name {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dp-checkbox .dp-style {
    font-size: 10px;
    color: var(--color-text-disabled);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Image Count Buttons */
.image-count-btn {
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-bg-tertiary);
    border: 2px solid var(--color-border-default);
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.image-count-btn:hover {
    border-color: rgba(255, 140, 0, 0.5);
    color: var(--color-text-primary);
}

.image-count-btn.selected {
    border-color: var(--color-accent);
    background: var(--color-accent);
    color: white;
}

/* Resolution Buttons */
.resolution-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-3);
    background: var(--color-bg-tertiary);
    border: 2px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.resolution-btn:hover {
    border-color: rgba(255, 140, 0, 0.5);
}

.resolution-btn.selected {
    border-color: var(--color-accent);
    background: rgba(255, 140, 0, 0.1);
}

.resolution-btn .resolution-label {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
}

.resolution-btn .resolution-mult {
    font-size: var(--font-size-xs);
    color: var(--color-text-disabled);
}

.resolution-btn.selected .resolution-label,
.resolution-btn.selected .resolution-mult {
    color: var(--color-accent);
}

/* Time Direction Buttons (Creative Director - Temporal Shift) */
.time-direction-btn.selected {
    border-color: var(--color-accent) !important;
    background: rgba(255, 140, 0, 0.2) !important;
    color: var(--color-accent) !important;
}

/* Aspect Ratio Buttons */
.aspect-ratio-btn {
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-tertiary);
    border: 2px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    transition: all var(--transition-fast);
}

.aspect-ratio-btn:hover {
    border-color: rgba(255, 140, 0, 0.5);
    color: var(--color-text-primary);
}

.aspect-ratio-btn.selected {
    border-color: var(--color-accent);
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
}

/* Type Options Panels */
.type-options {
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ==================== PROJECT SELECTOR ==================== */

/* Project dropdown animation */
#project-dropdown {
    transform-origin: top left;
    animation: dropdownIn 150ms ease;
}

@keyframes dropdownIn {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Project item hover states */
.project-item {
    transition: background-color 150ms ease;
    position: relative;
}

.project-item.active::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background-color: var(--color-accent);
    border-radius: 0 2px 2px 0;
}

/* Project modal styling */
#project-modal .modal-content {
    animation: modalIn 200ms ease;
}

@keyframes modalIn {
    from {
        opacity: 0;
        transform: scale(0.95) translateY(-10px);
    }
    to {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
}

/* ==================== CHARACTER GRID ==================== */

/* Session bundling (2026-08-11): the outer element is no longer the CSS grid — it is a
   flex COLUMN of session sections + one loose-cards block, each carrying its own
   `grid grid-cols-*` utilities. `grid-auto-rows` would be inert here, so it's gone;
   `min-height: 0` still matters (flex-1 child must shrink for overflow scroll). */
#characters-grid {
    min-height: 0;
}

.character-group-grid {
    grid-auto-rows: min-content; /* Prevent row collapse in a height-constrained parent */
}

/* ==================== CHARACTER CARDS ==================== */

.character-card {
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.character-card:hover {
    border-color: var(--color-accent);
    transform: translateY(-2px);
}

.character-card-thumbnail {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1; /* Square for headshots */
    background: var(--color-bg-tertiary);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.character-card-thumbnail img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center; /* Center for square headshots */
}

.character-card-thumbnail i,
.character-card-thumbnail svg {
    color: var(--color-text-disabled);
}

.character-card-info {
    padding: var(--space-3);
}

.character-card-name {
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.character-card-meta {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-1);
}

/* ==================== CHARACTER PORTRAIT LIGHTBOX ==================== */

.character-lightbox-overlay {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.character-lightbox-overlay.character-lightbox-visible {
    opacity: 1;
}

.character-lightbox-overlay.character-lightbox-closing {
    opacity: 0;
}

.character-lightbox-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
}

.character-lightbox-content {
    position: relative;
    max-width: 90vw;
    max-height: 90vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.character-lightbox-image {
    max-width: 90vw;
    max-height: 90vh;
    object-fit: contain;
    border-radius: var(--radius-lg);
}

.character-lightbox-close {
    position: absolute;
    top: -2.5rem;
    right: -0.5rem;
    color: white;
    background: rgba(0, 0, 0, 0.5);
    border: none;
    border-radius: 50%;
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.2s ease;
}

.character-lightbox-close:hover {
    background: rgba(0, 0, 0, 0.8);
}

/* ==================== REFERENCE IMAGE CARDS ==================== */

.reference-image-card {
    position: relative;
    aspect-ratio: 1;
    cursor: pointer;
}

.reference-image-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.reference-image-card .absolute {
    position: absolute;
}

.reference-image-card button {
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.reference-image-card:hover button {
    opacity: 1;
}

/* ==================== CHARACTER THUMBNAIL PLACEHOLDER ==================== */

/* Shimmer placeholder for pending thumbnails */
.character-thumbnail-pending {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        var(--color-bg-secondary) 0%,
        var(--color-bg-tertiary) 50%,
        var(--color-bg-secondary) 100%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s infinite;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Orange spinner overlay for pending thumbnails */
.character-thumbnail-spinner {
    width: 24px;
    height: 24px;
    border: 2px solid var(--color-bg-tertiary);
    border-top-color: var(--color-accent);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

/* Fade-in for loaded thumbnails */
.character-thumbnail-loaded {
    opacity: 0;
    transition: opacity 0.3s ease;
}

.character-thumbnail-loaded.visible {
    opacity: 1;
}

/* ==================== CHARACTER TYPE BADGES ==================== */

.character-type-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.375rem;
    border-radius: 9999px;
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    line-height: 1.4;
    white-space: nowrap;
    position: absolute;
    top: 0.375rem;
    left: 0.375rem;
    z-index: 2;
    backdrop-filter: blur(4px);
}

.character-type-person {
    background: rgba(148, 163, 184, 0.15);
    color: #94a3b8;
}

.character-type-animated_character {
    background: rgba(96, 165, 250, 0.15);
    color: #60a5fa;
}

.character-type-subject {
    background: rgba(74, 222, 128, 0.15);
    color: #4ade80;
}

/* Likeness clearance badges — Characters gallery (2026-07-11) */
.character-likeness-badge {
    display: inline-block; padding: 1px 6px; border-radius: 3px;
    font-size: 9px; font-weight: 700; letter-spacing: 0.03em;
}
.character-likeness-unreviewed { background: rgba(245, 158, 11, 0.15); color: #fbbf24; border: 1px solid rgba(245, 158, 11, 0.4); }
.character-likeness-cleared { background: rgba(34, 197, 94, 0.12); color: #4ade80; border: 1px solid rgba(34, 197, 94, 0.35); }
.character-likeness-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }

/* Card context: pin the likeness badge to the thumbnail's bottom-left so it
   never collides with the absolutely-positioned type badge (top-left) or the
   centered flex content. Detail-view usage stays inline in its flex row. */
.character-card-thumbnail .character-likeness-badge {
    position: absolute;
    bottom: 0.375rem;
    left: 0.375rem;
    z-index: 2;
    backdrop-filter: blur(4px);
}

/* ==================== SESSION GROUPS (characters + scenes) ====================
   Spec 2026-08-11 "characters-scenes-session-bundling". Engine-born assets (Cinematic
   Frames auto-create, casting-deck intake) are bundled per spot instead of flooding the
   flat library. Same accordion language as the Frames bins (:9784+), scoped to the two
   galleries. `important: true` in tailwind.config.js means anything that has to beat a
   utility needs !important — the collapse rule does, the rest are on bare classes. */

.character-group {
    display: flex;
    flex-direction: column;
    width: 100%;
}
.character-group-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}
.character-group-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex: 1;
    min-width: 0;
    background: none;
    border: none;
    padding: 0;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-primary);
    cursor: pointer;
    text-align: left;
}
.character-group-toggle i { color: var(--color-accent); flex-shrink: 0; }
.character-group-toggle:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.character-group-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.character-group-count {
    flex-shrink: 0;
    padding: 1px 7px;
    border-radius: 9999px;
    background: var(--color-bg-tertiary);
    font-size: var(--font-size-xs);
    font-weight: 500;
    color: var(--color-text-muted);
}
.character-group-toggle .character-group-chevron {
    margin-left: auto;
    flex-shrink: 0;
    color: var(--color-text-muted);
    transition: transform 150ms ease-out;
}
.character-group.is-collapsed .character-group-chevron { transform: rotate(-90deg); }
.character-group.is-collapsed > *:not(.character-group-head) { display: none !important; }
.character-group.is-collapsed .character-group-head { margin-bottom: 0; }
.character-group-select {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 2px 8px;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: transparent;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: all var(--transition-fast);
}
.character-group-select:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
}

/* Multi-select (T3b): the check mounts on the card ROOT — the WS thumbnail patch
   rewrites .character-card-thumbnail and would wipe an overlay parked inside it. */
.character-card.is-selectable {
    position: relative;
}
.character-card-check {
    position: absolute;
    top: 0.375rem;
    right: 0.375rem;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 9999px;
    border: 1.5px solid rgba(255, 255, 255, 0.65);
    background: rgba(15, 23, 42, 0.7);
    color: transparent;
    backdrop-filter: blur(4px);
    pointer-events: none;
}
.character-card.is-selected .character-card-check {
    border-color: var(--color-accent);
    background: var(--color-accent);
    color: #fff;
}
.character-card.is-selected {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px var(--color-accent) inset;
}

/* Scene gallery mirror — same behaviour, tighter type for the narrow controls rail. */
.scene-group {
    display: flex;
    flex-direction: column;
    width: 100%;
}
.scene-group-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}
.scene-group-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
    background: none;
    border: none;
    padding: 0;
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-text-primary);
    cursor: pointer;
    text-align: left;
}
.scene-group-toggle i { color: var(--color-accent); flex-shrink: 0; }
.scene-group-toggle:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.scene-group-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.scene-group-count {
    flex-shrink: 0;
    padding: 0 6px;
    border-radius: 9999px;
    background: var(--color-bg-tertiary);
    font-size: 10px;
    font-weight: 500;
    color: var(--color-text-muted);
}
.scene-group-toggle .scene-group-chevron {
    margin-left: auto;
    flex-shrink: 0;
    color: var(--color-text-muted);
    transition: transform 150ms ease-out;
}
.scene-group.is-collapsed .scene-group-chevron { transform: rotate(-90deg); }
.scene-group.is-collapsed > *:not(.scene-group-head) { display: none !important; }
.scene-group.is-collapsed .scene-group-head { margin-bottom: 0; }

/* Type filter tabs */
.type-filter-tab {
    color: var(--color-text-muted);
    background: transparent;
    border: 1px solid transparent;
    transition: all 0.15s ease;
}

.type-filter-tab:hover {
    color: var(--color-text-primary);
    background: rgba(255, 255, 255, 0.05);
}

.type-filter-tab.active {
    color: var(--color-text-primary);
    background: rgba(255, 140, 0, 0.15);
    border-color: rgba(255, 140, 0, 0.3);
}

/* ==================== STORYBOARD STUDIO ==================== */

/* Storyboard Grid */
.storyboard-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-4);
    padding: var(--space-6);
    align-content: start;
}

/* Responsive: 3 columns on smaller screens */
@media (max-width: 1200px) {
    .storyboard-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (max-width: 900px) {
    .storyboard-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Storyboard pagination controls */
.storyboard-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--color-border-default);
    background: var(--color-bg-secondary);
}

.storyboard-pagination-info {
    color: var(--color-text-secondary);
    font-size: 0.875rem;
}

.storyboard-pagination-buttons {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Storyboard Item Card */
.storyboard-card {
    position: relative;
    aspect-ratio: 16/9;
    background: var(--color-bg-secondary);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: grab;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
    border: 2px solid var(--color-border-default);
}

.storyboard-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
    border-color: var(--color-border-strong);
}

.storyboard-card.dragging {
    opacity: 0.5;
    cursor: grabbing;
    transform: scale(0.95);
}

.storyboard-card.drag-over {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px var(--color-accent-subtle);
}

.storyboard-card-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.storyboard-card-position {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    width: 24px;
    height: 24px;
    background: rgba(0, 0, 0, 0.7);
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: var(--font-weight-semibold);
    color: white;
    z-index: 2;
}

.storyboard-card-remove {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    width: 24px;
    height: 24px;
    background: rgba(239, 68, 68, 0.9);
    border: none;
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity var(--transition-fast);
    cursor: pointer;
    z-index: 2;
}

.storyboard-card:hover .storyboard-card-remove {
    opacity: 1;
}

.storyboard-card-remove:hover {
    background: rgba(220, 38, 38, 1);
}

.storyboard-card-label {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: var(--space-2);
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
    font-size: 11px;
    color: var(--color-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Add card (empty slot) */
.storyboard-card.storyboard-card-add {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--color-border-default);
    background: transparent;
    cursor: pointer;
}

.storyboard-card.storyboard-card-add:hover {
    border-color: var(--color-accent);
    background: rgba(255, 107, 53, 0.1);
    transform: none;
    box-shadow: none;
}

/* Keyboard focus indicator */
.storyboard-card.focused {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.storyboard-card.selected {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px var(--color-accent-subtle);
}

.storyboard-card.selected .storyboard-card-select {
    opacity: 1;
    background: var(--color-accent);
}

/* Selection checkbox */
.storyboard-card-select {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    background: rgba(0, 0, 0, 0.6);
    border-radius: var(--radius-md);
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--transition-fast), background var(--transition-fast);
}

.storyboard-card:hover .storyboard-card-select,
.storyboard-card.selected .storyboard-card-select {
    opacity: 1;
}

.storyboard-card-select input {
    width: 14px;
    height: 14px;
    cursor: pointer;
}

/* ==================== THUMBNAIL STRIP ==================== */

.storyboard-card-add-wrapper {
    position: relative;
}

.thumbnail-strip {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%) translateY(10px);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out, transform 200ms ease-out;
    z-index: 50;
}

.thumbnail-strip.visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
}

.thumbnail-strip-item {
    width: 48px;
    height: 27px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    cursor: pointer;
    border: 2px solid transparent;
    transition: transform 100ms ease-out, border-color 100ms ease-out;
    flex-shrink: 0;
}

.thumbnail-strip-item:hover {
    transform: scale(1.05);
    border-color: var(--color-accent);
}

.thumbnail-strip-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.thumbnail-strip-see-all {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-accent);
    background: transparent;
    border: none;
    cursor: pointer;
    white-space: nowrap;
    transition: color 100ms ease-out;
}

.thumbnail-strip-see-all:hover {
    color: var(--color-accent-hover);
}

.thumbnail-strip-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 200px;
    height: 27px;
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
}

/* ==================== FRAME INSERTION DIVIDERS ==================== */

.storyboard-card-wrapper {
    position: relative;
}

/* Invisible hover capture zone - large clickable area */
.frame-insert-zone {
    position: absolute;
    top: 0;
    width: 28px;
    height: 100%;
    cursor: pointer;
    z-index: 15;
    display: flex;
    align-items: center;
    justify-content: center;
}

.frame-insert-zone.left {
    left: -14px;
}

.frame-insert-zone.right {
    right: -14px;
}

/* Visible bar inside the zone */
.frame-insert-divider {
    width: 4px;
    height: 0;
    background: var(--color-accent);
    border-radius: 4px;
    transition: all 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

/* On zone hover - bar expands with glow */
.frame-insert-zone:hover .frame-insert-divider,
.frame-insert-zone.active .frame-insert-divider {
    width: 8px;
    height: 70%;
    box-shadow: 0 0 16px var(--color-accent-glow);
}

/* Plus icon inside the bar */
.frame-insert-divider-icon {
    opacity: 0;
    transform: scale(0.5);
    transition: all 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
    color: white;
    font-size: 14px;
    font-weight: 600;
    pointer-events: none;
}

.frame-insert-zone:hover .frame-insert-divider-icon,
.frame-insert-zone.active .frame-insert-divider-icon {
    opacity: 1;
    transform: scale(1);
}

/* Lit zone paints above its sibling zones while its menu is open, so the
   orange "+" bar of the active divider never sits under an adjacent zone. */
.frame-insert-zone.active {
    z-index: 60;
}

/* Insert Menu Dropdown — body-portaled, position:fixed (JS sets top/left). */
.frame-insert-menu {
    position: fixed;
    min-width: 160px;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    z-index: var(--z-popover);
    opacity: 0;
    pointer-events: none;
    transition: opacity 150ms ease-out;
}

.frame-insert-menu.open {
    opacity: 1;
    pointer-events: auto;
}

.frame-insert-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3) var(--space-4);
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    background: transparent;
    border: none;
    cursor: pointer;
    text-align: left;
    transition: background 100ms ease-out;
}

.frame-insert-menu-item:hover {
    background: var(--color-bg-hover);
}

.frame-insert-menu-item i {
    width: 16px;
    height: 16px;
    color: var(--color-text-muted);
}

.frame-insert-menu-divider {
    height: 1px;
    background: var(--color-border-default);
    margin: var(--space-1) 0;
}

/* ==================== BLANK FRAME PLACEHOLDER ==================== */

.storyboard-card.storyboard-card-blank {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    border: 2px dashed rgba(255, 140, 0, 0.4);
    background: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 10px,
        rgba(255, 140, 0, 0.02) 10px,
        rgba(255, 140, 0, 0.02) 20px
    );
    overflow: visible !important;  /* Allow generate popover to overflow */
}

.storyboard-card-blank:hover {
    border-color: rgba(255, 140, 0, 0.6);
    transform: none;
}

.blank-frame-actions {
    display: flex;
    gap: var(--space-2);
}

.blank-frame-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2);
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    cursor: pointer;
    transition: all 100ms ease-out;
}

.blank-frame-btn:hover {
    background: rgba(255, 140, 0, 0.1);
    border-color: var(--color-accent);
    color: var(--color-accent);
}

.blank-frame-btn i {
    width: 20px;
    height: 20px;
}

/* Blank frame generate popover */
.blank-frame-generate-popover {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: var(--space-2);
    width: 280px;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--space-4);
    z-index: 100;
    opacity: 0;
    pointer-events: none;
    transition: opacity 150ms ease-out;
}

.blank-frame-generate-popover.open {
    opacity: 1;
    pointer-events: auto;
}

.blank-frame-generate-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: var(--space-3);
}

.blank-frame-smart-btn {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3);
    background: linear-gradient(135deg, var(--color-accent) 0%, #ff6b35 100%);
    border: none;
    border-radius: var(--radius-md);
    color: white;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: all 100ms ease-out;
}

.blank-frame-smart-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-accent);
}

.blank-frame-smart-btn i {
    width: 16px;
    height: 16px;
}

.blank-frame-smart-hint {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-top: var(--space-1);
    margin-bottom: var(--space-3);
}

.blank-frame-divider {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-3) 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.blank-frame-divider::before,
.blank-frame-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--color-border-default);
}

.blank-frame-prompt-input {
    width: 100%;
    padding: var(--space-2);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    resize: none;
}

.blank-frame-prompt-input:focus {
    outline: none;
    border-color: var(--color-accent);
}

.blank-frame-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-3);
}

/* ==================== ANGLE PICKER POPOVER ==================== */

.angle-picker-popover {
    position: fixed;
    width: 360px;
    /* Flex column with a shrinkable body: header + footer are ALWAYS fully
       visible and hit-testable. A fixed max-height with overflow:hidden used
       to CLIP the footer once the custom textarea expanded — the Generate
       button still reported a rect but presses in the clipped region fell
       through to the page underneath and closed the picker. */
    display: flex;
    flex-direction: column;
    max-height: min(560px, calc(100vh - 16px));
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    z-index: var(--z-popover);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out;
}

.angle-picker-popover.open {
    opacity: 1;
    pointer-events: auto;
}

.angle-picker-header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    border-bottom: 1px solid var(--color-border-default);
    flex-shrink: 0;
}

.angle-picker-source-thumb {
    width: 64px;
    height: 36px;
    border-radius: var(--radius-sm);
    object-fit: cover;
    border: 1px solid var(--color-border-default);
}

.angle-picker-source-info {
    flex: 1;
    min-width: 0;
}

.angle-picker-source-label {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.angle-picker-resolution {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    margin-top: var(--space-1);
}

.angle-picker-resolution label {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.angle-picker-resolution select {
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    color: var(--color-text-primary);
}

.angle-picker-body {
    /* The shrink region: scrolls internally so the footer never clips. */
    flex: 1 1 auto;
    min-height: 0;
    max-height: 260px;
    overflow-y: auto;
    padding: var(--space-2);
}

.angle-picker-category {
    margin-bottom: var(--space-2);
}

.angle-picker-category-header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    background: transparent;
    border: none;
    width: 100%;
    cursor: pointer;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    transition: background 100ms ease-out;
    border-radius: var(--radius-sm);
}

.angle-picker-category-header:hover {
    background: var(--color-bg-hover);
}

.angle-picker-category-header i {
    width: 14px;
    height: 14px;
    color: var(--color-text-muted);
    transition: transform 150ms ease-out;
}

.angle-picker-category-header.expanded i {
    transform: rotate(90deg);
}

.angle-picker-category-count {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-left: auto;
}

.angle-picker-angles {
    display: none;
    padding-left: var(--space-4);
}

.angle-picker-category.expanded .angle-picker-angles {
    display: block;
}

.angle-picker-angle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    background: transparent;
    border: none;
    width: 100%;
    cursor: pointer;
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    transition: all 100ms ease-out;
    border-radius: var(--radius-sm);
}

.angle-picker-angle:hover {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}

.angle-picker-angle.selected {
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
}

.angle-picker-angle-checkbox {
    width: 16px;
    height: 16px;
    border: 2px solid var(--color-border-strong);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 150ms ease;
}

.angle-picker-angle.selected .angle-picker-angle-checkbox {
    background: var(--color-accent);
    border-color: var(--color-accent);
}

.angle-picker-angle.selected .angle-picker-angle-checkbox::after {
    content: '';
    width: 10px;
    height: 10px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
    background-size: contain;
    background-repeat: no-repeat;
}

.angle-picker-angle-name {
    flex: 1;
    text-align: left;
}

.angle-picker-footer {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3);
    border-top: 1px solid var(--color-border-default);
    flex-shrink: 0;
}

.angle-picker-footer-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-2);
}

.angle-picker-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.angle-picker-selection-count {
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
}

.angle-picker-cost {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    white-space: nowrap;
}

.angle-picker-actions {
    display: flex;
    gap: var(--space-2);
}

/* Pinned custom-angle section: a leading checkbox row plus a reveal-on-select
   description textarea. Lives ABOVE the categories inside .angle-picker-body. */
.angle-picker-custom {
    margin-bottom: var(--space-2);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--color-border-default);
}

.angle-picker-custom-input {
    padding: var(--space-2) var(--space-2) 0 var(--space-4);
}

.angle-picker-custom-input.hidden {
    display: none;
}

.angle-picker-custom-input textarea {
    width: 100%;
    resize: vertical;
    min-height: 56px;
    padding: var(--space-2);
    font-size: var(--font-size-xs);
    line-height: 1.4;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    color: var(--color-text-primary);
}

.angle-picker-custom-input textarea:focus {
    outline: none;
    border-color: var(--color-accent);
}

.angle-picker-custom-count {
    margin-top: 2px;
    text-align: right;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* Shared segmented radiogroup — used by the angle picker footer AND the Style
   DNA popover (versions 1–8, aspect ratio). A select was too small to read at
   a glance — every option must be visible and one tap away. */
.sb-segment-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.sb-segment-field > label,
.sb-segment-field > span {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

.sb-segments {
    display: flex;
    width: 100%;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--color-bg-secondary);
}

.sb-segment {
    flex: 1;
    padding: var(--space-1) 0;
    background: transparent;
    border: none;
    border-right: 1px solid var(--color-border-default);
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    cursor: pointer;
    white-space: nowrap;
    transition: background 100ms ease-out, color 100ms ease-out;
}

.sb-segment:last-child {
    border-right: none;
}

.sb-segment:hover {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}

.sb-segment.selected {
    background: var(--color-accent);
    color: #fff;
    font-weight: var(--font-weight-medium);
}

/* Compact variant for text labels (aspect ratios: 'Original', '16:9', …). */
.sb-segments--compact .sb-segment {
    font-size: var(--font-size-xs);
    padding: var(--space-1) 2px;
}

/* ==================== GALLERY MODAL ==================== */

.gallery-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out;
}

.gallery-modal.open {
    opacity: 1;
    pointer-events: auto;
}

.gallery-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.8);
}

.gallery-modal-content {
    position: relative;
    width: 90%;
    max-width: 900px;
    max-height: 85vh;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    display: flex;
    flex-direction: column;
    transform: scale(0.95);
    transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.gallery-modal.open .gallery-modal-content {
    transform: scale(1);
}

.gallery-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) var(--space-6);
    border-bottom: 1px solid var(--color-border-default);
}

.gallery-modal-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
}

.gallery-modal-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: all 100ms ease-out;
}

.gallery-modal-close:hover {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}

.gallery-modal-filters {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-6);
    border-bottom: 1px solid var(--color-border-default);
}

.gallery-modal-tabs {
    display: flex;
    gap: var(--space-1);
}

.gallery-modal-tab {
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 100ms ease-out;
}

.gallery-modal-tab:hover {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}

.gallery-modal-tab.active {
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
}

.gallery-modal-search {
    flex: 1;
    max-width: 250px;
    margin-left: auto;
}

.gallery-modal-search input {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    padding-left: var(--space-8);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
}

.gallery-modal-search input:focus {
    outline: none;
    border-color: var(--color-accent);
}

.gallery-modal-search-icon {
    position: absolute;
    left: var(--space-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-text-muted);
}

.gallery-modal-body {
    flex: 1;
    overflow-y: auto;
    padding: var(--space-4) var(--space-6);
}

.gallery-modal-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: var(--space-3);
}

.gallery-modal-item {
    position: relative;
    aspect-ratio: 16/9;
    border-radius: var(--radius-md);
    overflow: hidden;
    cursor: pointer;
    border: 2px solid transparent;
    transition: all 100ms ease-out;
}

.gallery-modal-item:hover {
    transform: scale(1.02);
    border-color: var(--color-border-strong);
}

.gallery-modal-item.selected {
    border-color: var(--color-accent);
}

.gallery-modal-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.gallery-modal-item-check {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    width: 20px;
    height: 20px;
    background: var(--color-accent);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    opacity: 0;
    transform: scale(0.8);
    transition: all 100ms ease-out;
}

.gallery-modal-item.selected .gallery-modal-item-check {
    opacity: 1;
    transform: scale(1);
}

.gallery-modal-skeleton {
    aspect-ratio: 16/9;
    border-radius: var(--radius-md);
    background: linear-gradient(
        90deg,
        var(--color-bg-secondary) 25%,
        var(--color-bg-tertiary) 50%,
        var(--color-bg-secondary) 75%
    );
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s infinite;
}

.gallery-modal-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: var(--space-8);
    color: var(--color-text-muted);
}

.gallery-modal-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--color-border-default);
}

.gallery-modal-selection-count {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.gallery-modal-actions {
    display: flex;
    gap: var(--space-2);
}

/* Completed section */
.storyboard-completed {
    border-top: 1px solid var(--color-border-default);
    background: rgba(0, 0, 0, 0.2);
}

.completed-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-4);
}

/* Drop zone styling */
.drop-zone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    border: 2px dashed var(--color-border-default);
    border-radius: var(--radius-xl);
    background: rgba(30, 41, 59, 0.3);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: center;
}

.drop-zone:hover {
    border-color: var(--color-text-disabled);
    background: rgba(30, 41, 59, 0.5);
}

.drop-zone.drag-over {
    border-color: var(--color-accent);
    background: rgba(255, 107, 53, 0.1);
    transform: scale(1.02);
}

/* Control section styling */
.control-section {
    margin-bottom: var(--space-4);
}

.control-label {
    display: block;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-2);
}

.control-divider {
    border: none;
    border-top: 1px solid var(--color-border-default);
    margin: var(--space-4) 0;
}

/* Storyboard preview container */
.storyboard-preview {
    background: radial-gradient(ellipse at top right, var(--color-bg-secondary), var(--color-bg-primary), #000);
}

/* Modal styles */
.modal {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal.hidden {
    display: none;
}

.modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
}

.modal-content {
    position: relative;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    max-width: 480px;
    width: 90%;
    animation: modalIn 200ms ease;
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-5);
    border-bottom: 1px solid var(--color-border-default);
}

.modal-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
}

.modal-close {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--color-text-muted);
    cursor: pointer;
    border-radius: var(--radius-md);
    transition: all var(--transition-fast);
}

.modal-close:hover {
    background: var(--color-bg-tertiary);
    color: var(--color-text-primary);
}

.modal-body {
    padding: var(--space-5);
}

.modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--color-border-default);
    background: rgba(0, 0, 0, 0.2);
    border-radius: 0 0 var(--radius-xl) var(--radius-xl);
}

.modal-lg {
    max-width: 640px;
}

/* ================================================================
   Storyboard Stack Badge (Phase 3)
   ================================================================ */

.storyboard-card-stack-badge {
    position: absolute;
    bottom: 0.5rem;
    left: 0.5rem;
    background: rgba(59, 130, 246, 0.9);
    color: white;
    font-size: 0.65rem;
    font-weight: 600;
    padding: 0.15rem 0.4rem;
    border-radius: 0.25rem;
    cursor: pointer;
    transition: all 0.15s ease;
    z-index: 5;
}

.storyboard-card-stack-badge:hover {
    background: rgba(59, 130, 246, 1);
    transform: scale(1.05);
}

/* Prompt indicator */
.storyboard-card-prompt-badge {
    position: absolute;
    bottom: 0.5rem;
    right: 0.5rem;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    font-size: 0.6rem;
    padding: 0.15rem 0.35rem;
    border-radius: 0.25rem;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.15s ease;
}

.storyboard-card-prompt-badge:hover {
    opacity: 1;
}

.storyboard-card-prompt-badge.has-prompt {
    background: rgba(34, 197, 94, 0.8);
}

.storyboard-card-prompt-badge.has-prompt:hover {
    background: rgba(34, 197, 94, 1);
}

/* ================================================================
   Stack Modal Frame Grid
   ================================================================ */

.stack-frame-card {
    position: relative;
    border-radius: 0.5rem;
    overflow: hidden;
    background: var(--color-bg-secondary);
    cursor: pointer;
    transition: all 0.15s ease;
    border: 2px solid transparent;
}

.stack-frame-card:hover {
    transform: translateY(-2px);
}

.stack-frame-card.is-primary {
    border-color: var(--color-accent);
}

.stack-frame-card img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

.stack-frame-card-actions {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(transparent, rgba(0,0,0,0.8));
    padding: 1rem 0.5rem 0.5rem;
    display: flex;
    gap: 0.5rem;
    justify-content: center;
}

.stack-frame-primary-badge {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    background: var(--color-accent);
    color: white;
    font-size: 0.65rem;
    font-weight: 600;
    padding: 0.15rem 0.4rem;
    border-radius: 0.25rem;
}

/* Extra small icon button */
.btn-xs {
    width: 24px;
    height: 24px;
    padding: 0;
    font-size: 0.75rem;
}

/* ================================================================
   Storyboard Prompt Editor (Phase 3)
   ================================================================ */

.prompt-editor-overlay {
    position: fixed;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    width: 90%;
    max-width: 600px;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.75rem;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
    z-index: 1100;  /* Higher than modal overlays */
    animation: slideUp 0.2s ease;
}

@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

.prompt-editor-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--color-border-default);
}

.prompt-editor-title {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-primary);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.prompt-editor-source {
    font-size: 0.65rem;
    padding: 0.15rem 0.4rem;
    border-radius: 0.25rem;
    background: rgba(255, 255, 255, 0.1);
    color: var(--color-text-secondary);
}

.prompt-editor-source.ai {
    background: rgba(147, 51, 234, 0.2);
    color: rgb(167, 139, 250);
}

.prompt-editor-source.context {
    background: rgba(34, 197, 94, 0.2);
    color: rgb(134, 239, 172);
}

.prompt-editor-body {
    padding: 1rem;
}

.prompt-editor-textarea {
    width: 100%;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.5rem;
    padding: 0.75rem;
    font-size: 0.875rem;
    color: var(--color-text-primary);
    resize: vertical;
    min-height: 80px;
}

.prompt-editor-textarea:focus {
    outline: none;
    border-color: var(--color-accent);
}

.prompt-editor-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--color-border-default);
}

/* Regenerate Confirmation Toast */
.regenerate-confirm-toast {
    position: fixed;
    bottom: 5rem;
    left: 50%;
    transform: translateX(-50%);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.75rem;
    padding: 0.75rem 1rem;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
    z-index: 1200;
    animation: slideUp 0.2s ease;
}

.regenerate-confirm-content {
    display: flex;
    align-items: center;
    gap: 1rem;
    color: var(--color-text-primary);
    font-size: 0.875rem;
}

.regenerate-confirm-actions {
    display: flex;
    gap: 0.5rem;
}

/* Expanded View Prompt Section */
.expanded-prompt-section {
    padding: 0 1rem;
}

.expanded-prompt-display {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

.expanded-prompt-display p {
    flex: 1;
    margin: 0;
}

.truncate-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.expanded-prompt-editor {
    margin-top: 0.5rem;
}

.expanded-prompt-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

/* Prompt Review List */
.prompt-review-list {
    max-height: 400px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.prompt-review-item {
    display: flex;
    gap: 1rem;
    padding: 1rem;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.5rem;
}

.prompt-review-item.unchecked {
    opacity: 0.5;
}

.prompt-review-thumb {
    width: 60px;
    height: 60px;
    border-radius: 0.375rem;
    object-fit: cover;
    flex-shrink: 0;
}

.prompt-review-content {
    flex: 1;
    min-width: 0;
}

.prompt-review-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.prompt-review-label {
    font-weight: 500;
    color: var(--color-text-primary);
}

.prompt-review-old {
    font-size: 0.75rem;
    color: var(--color-text-tertiary);
    margin-bottom: 0.25rem;
}

.prompt-review-new textarea {
    width: 100%;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.375rem;
    padding: 0.5rem;
    font-size: 0.875rem;
    color: var(--color-text-primary);
    resize: vertical;
    min-height: 60px;
}

/* ================================================================
   Storyboard Provider Tabs (Phase 4)
   ================================================================ */

.provider-tabs {
    display: flex;
    gap: 8px;
}

.provider-tab {
    flex: 1;
    padding: 8px 16px;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: 6px;
    color: var(--color-text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s ease;
}

.provider-tab:hover {
    background: var(--color-bg-tertiary);
    color: var(--color-text-primary);
}

.provider-tab.active {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: white;
}

/* ================================================================
   Storyboard Card Status (Phase 4)
   ================================================================ */

.storyboard-card-status {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 6;
}

.storyboard-card-status.status-generating {
    background: rgba(59, 130, 246, 0.9);
    color: white;
    animation: pulse-glow-blue 1.5s ease-in-out infinite;
    overflow: visible;
}

.storyboard-card-status.status-generating::after {
    content: '';
    position: absolute;
    inset: -2px;
    border: 2px solid transparent;
    border-top-color: rgba(59, 130, 246, 0.8);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.storyboard-card-status.status-complete {
    background: rgba(34, 197, 94, 0.9);
    color: white;
}

.storyboard-card-status.status-failed {
    background: rgba(239, 68, 68, 0.9);
    color: white;
}

.storyboard-card-status.status-swapping {
    background: rgba(168, 85, 247, 0.9);
    color: white;
    animation: pulse-glow-purple 1.5s ease-in-out infinite;
    overflow: visible;
}

.storyboard-card-status.status-swapping::after {
    content: '';
    position: absolute;
    inset: -2px;
    border: 2px solid transparent;
    border-top-color: rgba(168, 85, 247, 0.8);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.status-uploading {
    background: rgba(59, 130, 246, 0.3);
    border: 1px solid rgba(59, 130, 246, 0.5);
    animation: pulse-glow-blue 2s ease-in-out infinite;
}

/* Full-card generating overlay */
.storyboard-card-generating-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.45);
    z-index: 5;
    color: white;
    pointer-events: none;
}

.storyboard-card-generating-overlay svg {
    filter: drop-shadow(0 0 6px rgba(59, 130, 246, 0.6));
}

@keyframes pulse-glow-blue {
    0%, 100% {
        box-shadow: 0 0 4px rgba(59, 130, 246, 0.4);
    }
    50% {
        box-shadow: 0 0 12px rgba(59, 130, 246, 0.8);
    }
}

@keyframes pulse-glow-purple {
    0%, 100% {
        box-shadow: 0 0 4px rgba(168, 85, 247, 0.4);
    }
    50% {
        box-shadow: 0 0 12px rgba(168, 85, 247, 0.8);
    }
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ================================================================
   Video Play Overlay
   ================================================================ */

.video-play-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.15s ease;
    cursor: pointer;
    z-index: 4;
}

.storyboard-card:hover .video-play-overlay {
    opacity: 1;
}

.video-play-overlay i {
    color: white;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}

/* ================================================================
   Video Playback Modal (Phase 4)
   ================================================================ */

.video-playback-modal {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    animation: fadeIn 0.2s ease;
}

.video-playback-content {
    position: relative;
    max-width: 90vw;
    max-height: 90vh;
    background: var(--color-bg-secondary);
    border-radius: 0.75rem;
    overflow: hidden;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.video-playback-close {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    width: 32px;
    height: 32px;
    background: rgba(0, 0, 0, 0.6);
    border: none;
    border-radius: 50%;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
    transition: background 0.15s ease;
}

.video-playback-close:hover {
    background: rgba(0, 0, 0, 0.8);
}

.video-playback-player {
    display: block;
    max-width: 100%;
    max-height: 80vh;
}

.video-playback-actions {
    display: flex;
    justify-content: center;
    gap: 0.75rem;
}

/* Video modal navigation */
.video-nav-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 48px;
    height: 48px;
    background: rgba(0, 0, 0, 0.6);
    border: none;
    border-radius: 50%;
    color: white;
    cursor: pointer;
    z-index: 10;
    transition: background 0.15s ease, transform 0.15s ease;
    display: flex;
    align-items: center;
    justify-content: center;
}

.video-nav-btn:hover {
    background: rgba(0, 0, 0, 0.8);
    transform: translateY(-50%) scale(1.1);
}

.video-nav-prev {
    left: 1rem;
}

.video-nav-next {
    right: 1rem;
}

.video-playback-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    background: var(--color-bg-tertiary);
    border-top: 1px solid var(--color-border-default);
}

.video-playback-counter {
    font-size: 0.875rem;
    color: var(--color-text-secondary);
    min-width: 60px;
}

.video-playback-shortcuts {
    flex: 1;
    text-align: center;
}

/* ================================================================
   Control Slider Styling
   ================================================================ */

.control-slider {
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    background: var(--color-border-default);
    border-radius: 2px;
    outline: none;
}

.control-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    background: var(--color-accent);
    border-radius: 50%;
    cursor: pointer;
    transition: transform 0.1s ease;
}

.control-slider::-webkit-slider-thumb:hover {
    transform: scale(1.2);
}

.control-slider::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background: var(--color-accent);
    border: none;
    border-radius: 50%;
    cursor: pointer;
}

/* ================================================================
   Control Select Styling
   ================================================================ */

.control-select {
    width: 100%;
    padding: 0.5rem 0.75rem;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.375rem;
    color: var(--color-text-primary);
    font-size: 0.875rem;
    cursor: pointer;
    transition: border-color 0.15s ease;
}

.control-select:hover {
    border-color: var(--color-border-hover);
}

.control-select:focus {
    outline: none;
    border-color: var(--color-accent);
}

.control-select option {
    background: var(--color-bg-secondary);
    color: var(--color-text-primary);
}

.control-select option:disabled {
    color: var(--color-text-muted);
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ==============================================================================
   Storyboard Version Styles
   ============================================================================== */

.version-list-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    background: var(--color-bg-tertiary);
    border-radius: 0.5rem;
    cursor: pointer;
    transition: background-color 0.15s;
}

.version-list-item:hover {
    background: var(--color-bg-secondary);
}

.version-list-item.is-current {
    border-left: 3px solid var(--color-accent);
}

.version-list-item .version-indicator {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--color-text-muted);
}

.version-list-item.is-current .version-indicator {
    background: var(--color-accent);
}

.version-list-item .version-info {
    flex: 1;
    min-width: 0;
}

.version-list-item .version-label {
    font-weight: 500;
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.version-list-item .version-meta {
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.version-list-item .version-actions {
    display: flex;
    gap: 0.25rem;
    opacity: 0;
    transition: opacity 0.15s;
}

.version-list-item:hover .version-actions {
    opacity: 1;
}

.version-badge {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    padding: 0.125rem 0.375rem;
    border-radius: 0.25rem;
    background: var(--color-accent);
    color: white;
}

/* Auto-save indicator */
.autosave-indicator {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.autosave-indicator.saving {
    color: var(--color-accent);
}

.autosave-indicator.saved {
    color: var(--color-success);
}

.autosave-indicator.error {
    color: var(--color-error);
}

/* ================================================================
   Storyboard Export Preview (Phase 6)
   ================================================================ */

.storyboard-export-container {
    position: fixed;
    left: -9999px;
    top: 0;
    background: white;
    padding: 40px;
    width: 1200px;
}

.storyboard-export-header {
    text-align: center;
    margin-bottom: 30px;
    padding-bottom: 20px;
    border-bottom: 2px solid #e5e7eb;
}

.storyboard-export-title {
    font-size: 28px;
    font-weight: 700;
    color: #1f2937;
    margin: 0 0 8px 0;
}

.storyboard-export-meta {
    font-size: 14px;
    color: #6b7280;
}

.storyboard-export-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
}

.storyboard-export-item {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    overflow: hidden;
}

.storyboard-export-item-image {
    width: 100%;
    aspect-ratio: 16/9;
    object-fit: cover;
    display: block;
}

.storyboard-export-item-info {
    padding: 12px;
}

.storyboard-export-item-number {
    display: inline-block;
    background: #3b82f6;
    color: white;
    font-size: 12px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 4px;
    margin-bottom: 6px;
}

.storyboard-export-item-prompt {
    font-size: 11px;
    color: #4b5563;
    line-height: 1.4;
    max-height: 44px;
    overflow: hidden;
}

.storyboard-export-footer {
    margin-top: 30px;
    padding-top: 20px;
    border-top: 1px solid #e5e7eb;
    text-align: center;
    font-size: 12px;
    color: #9ca3af;
}

/* ================================================================
   STORYBOARD FRAME DETAILS MODAL (Phase A)
   ================================================================ */

.frame-details-layout {
    display: grid;
    grid-template-columns: 1fr 200px;
    gap: var(--space-6);
}

@media (max-width: 768px) {
    .frame-details-layout {
        grid-template-columns: 1fr;
    }
}

.frame-details-preview {
    aspect-ratio: 16/9;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.frame-details-preview img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.frame-details-actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.frame-details-prompt {
    border-top: 1px solid var(--color-border-default);
    padding-top: var(--space-4);
}

.frame-details-alternatives {
    border-top: 1px solid var(--color-border-default);
    padding-top: var(--space-4);
}

.frame-details-alternatives .alternative-thumb {
    aspect-ratio: 16/9;
    cursor: pointer;
    border: 2px solid transparent;
    border-radius: var(--radius-md);
    overflow: hidden;
    position: relative;
    transition: border-color 0.15s, transform 0.15s;
}

.frame-details-alternatives .alternative-thumb:hover {
    transform: scale(1.02);
}

.frame-details-alternatives .alternative-thumb.is-primary {
    border-color: var(--color-accent);
}

.frame-details-alternatives .alternative-thumb.is-selected {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px var(--color-accent-subtle);
}

.frame-details-alternatives .alternative-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.alternative-primary-badge {
    position: absolute;
    top: 4px;
    left: 4px;
    background: var(--color-accent);
    color: white;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ================================================================
   STORYBOARD GALLERY PICKER (Phase A)
   ================================================================ */

.gallery-picker {
    position: absolute;
    inset: 0;
    background: var(--color-bg-secondary);
    padding: var(--space-6);
    overflow-y: auto;
    z-index: 10;
    border-radius: var(--radius-lg);
}

.gallery-picker-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-4);
}

.gallery-picker-filters {
    display: flex;
    gap: var(--space-3);
}

.gallery-picker-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-3);
}

@media (max-width: 768px) {
    .gallery-picker-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

.gallery-picker-item {
    aspect-ratio: 1;
    cursor: pointer;
    border-radius: var(--radius-md);
    overflow: hidden;
    border: 2px solid transparent;
    transition: border-color 0.15s, transform 0.15s;
    background: var(--color-bg-tertiary);
}

.gallery-picker-item:hover {
    border-color: var(--color-accent);
    transform: scale(1.02);
}

.gallery-picker-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.gallery-picker-divider {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin: var(--space-6) 0;
    color: var(--color-text-tertiary);
    font-size: 0.875rem;
}

.gallery-picker-divider::before,
.gallery-picker-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--color-border-default);
}

.gallery-picker-upload {
    border: 2px dashed var(--color-border-default);
    border-radius: var(--radius-lg);
    padding: var(--space-8);
    text-align: center;
    transition: border-color 0.15s, background 0.15s;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.gallery-picker-upload:hover {
    border-color: var(--color-border-hover);
}

.gallery-picker-upload.drag-over {
    border-color: var(--color-accent);
    background: rgba(255, 107, 53, 0.1);
}

.gallery-picker-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--space-8);
    color: var(--color-text-secondary);
}

.gallery-picker-empty {
    text-align: center;
    padding: var(--space-8);
    color: var(--color-text-tertiary);
}

/* ==================== STORYBOARD EXPANDED VIEW ==================== */

.storyboard-expanded-view {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: var(--space-4);
    opacity: 0;
    transform: scale(0.95);
    transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1),
                transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.storyboard-expanded-view.visible {
    opacity: 1;
    transform: scale(1);
}

.storyboard-expanded-view.hidden {
    display: none;
}

.expanded-content {
    display: flex;
    gap: var(--space-6);
    flex: 1;
    min-height: 0;
}

/* Left: Frame Preview Area */
.expanded-frame-area {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.expanded-image-container {
    position: relative;
    flex: 1;
    background: var(--color-bg-secondary);
    border-radius: var(--radius-xl);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.expanded-image-container img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    transition: opacity 0.3s ease;
}

.expanded-image-container img.crossfade {
    opacity: 0;
}

/* Region Edit Toggle Button */
.region-edit-toggle {
    position: absolute;
    top: var(--space-3);
    left: var(--space-3);
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: var(--radius-lg);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: all 0.2s ease;
    opacity: 0;
}

.expanded-image-container:hover .region-edit-toggle,
.region-edit-toggle.active {
    opacity: 1;
}

.region-edit-toggle:hover {
    background: rgba(0, 0, 0, 0.8);
    color: var(--color-text-primary);
    border-color: rgba(255, 255, 255, 0.2);
}

.region-edit-toggle.active {
    background: var(--color-accent);
    color: white;
    border-color: var(--color-accent);
}

/* Region Edit SVG Overlay - crosshair when active */
#storyboard-annotation-overlay.drawing-active {
    cursor: crosshair;
}

/* Region Edit Modal - slide up animation */
.region-edit-panel {
    transform: translateY(100%);
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.region-edit-panel.visible {
    transform: translateY(0);
}

/* Mode Toggle Overlay (Video/Image pill) */
.mode-toggle-overlay {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    display: flex;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(8px);
    border-radius: var(--radius-full);
    padding: 2px;
    z-index: 20;
}

.mode-toggle-overlay.hidden {
    display: none;
}

.mode-toggle-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.mode-toggle-btn:hover {
    color: var(--color-text-primary);
}

.mode-toggle-btn.active {
    background: rgba(255, 255, 255, 0.2);
    color: var(--color-text-primary);
}

.expanded-frame-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: var(--space-4);
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
}

.expanded-position-badge {
    width: 40px;
    height: 40px;
    background: rgba(0, 0, 0, 0.7);
    border-radius: var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    font-weight: var(--font-weight-bold);
    color: white;
}

.expanded-label {
    font-size: 1.125rem;
    color: white;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}

.expanded-loading {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    color: white;
    font-size: 0.875rem;
}

.expanded-loading .loading-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid rgba(255, 255, 255, 0.2);
    border-top-color: var(--color-accent);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

/* Edit Options under image */
.expanded-edit-options {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) 0;
}

.edit-option {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: 0.875rem;
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: color var(--transition-fast);
}

.edit-option:hover {
    color: var(--color-text-primary);
}

.edit-option input[type="radio"] {
    accent-color: var(--color-accent);
}

/* Video element in expanded view */
#expanded-frame-video {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: var(--radius-lg);
}

/* Video Actions */
.expanded-video-actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) 0;
}

/* Right: Quick Edit Panel */
.expanded-quick-edit {
    width: 320px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: rgba(30, 41, 59, 0.5);
    border-radius: var(--radius-xl);
    padding: var(--space-4);
    border: 1px solid var(--color-border-default);
}

.quick-edit-title {
    font-size: 1rem;
    font-weight: var(--font-weight-semibold);
    color: white;
    margin-bottom: var(--space-3);
}

.quick-edit-textarea {
    width: 100%;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    padding: var(--space-3);
    color: var(--color-text-primary);
    font-size: 0.875rem;
    resize: none;
    transition: border-color var(--transition-fast);
}

.quick-edit-textarea:focus {
    outline: none;
    border-color: var(--color-accent);
}

.quick-edit-textarea::placeholder {
    color: var(--color-text-tertiary);
}

/* Chat-Style Quick Edit Input */
.chat-input-container {
    position: relative;
    display: flex;
    align-items: flex-end;
    background: rgba(30, 41, 59, 0.5);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    padding: var(--space-2);
    padding-right: var(--space-1);
    transition: all var(--transition-fast);
}

.chat-input-container:focus-within {
    border-color: rgba(255, 140, 0, 0.5);
    box-shadow: 0 0 0 2px rgba(255, 140, 0, 0.1);
}

.chat-input {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    line-height: 1.5;
    padding: var(--space-1) var(--space-2);
    resize: none;
    min-height: 24px;
    max-height: 120px;
    overflow-y: auto;
}

.chat-input::placeholder {
    color: var(--color-text-muted);
}

.chat-send-btn {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-lg);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.chat-send-btn:hover:not(:disabled) {
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
}

.chat-send-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.chat-send-btn.has-content {
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
}

/* Icon Action Bar */
.icon-action-bar {
    display: flex;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) 0;
    margin-bottom: var(--space-3);
    border-top: 1px solid var(--color-border-subtle);
    border-bottom: 1px solid var(--color-border-subtle);
}

.icon-action-btn {
    position: relative;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-lg);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.icon-action-btn:hover {
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-primary);
}

.icon-action-btn.hidden {
    display: none;
}

/* Swap Character Badge */
.swap-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    width: 16px;
    height: 16px;
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-subtle);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.swap-badge svg {
    width: 10px;
    height: 10px;
    color: var(--color-text-secondary);
}

.icon-action-btn:hover .swap-badge {
    background: var(--color-bg-secondary);
}

.icon-action-btn:hover .swap-badge svg {
    color: var(--color-text-primary);
}

/* Action Popovers */
.action-popover {
    position: absolute;
    bottom: calc(100% + var(--space-2));
    left: 50%;
    transform: translateX(-50%);
    min-width: 180px;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    padding: var(--space-2);
    z-index: 100;
}

.action-popover.hidden {
    display: none;
}

.action-popover .popover-title {
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.popover-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    text-align: left;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.popover-item:hover {
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-primary);
}

.popover-item-danger {
    color: #ef4444;
}

.popover-item-danger:hover {
    background: rgba(239, 68, 68, 0.1);
    color: #ef4444;
}

.quick-edit-actions {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* Video Versions Section */
.video-versions-section {
    margin-bottom: var(--space-2);
}

.video-versions-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
}

.video-version-thumb {
    position: relative;
    aspect-ratio: 16/9;
    border-radius: var(--radius-md);
    overflow: hidden;
    cursor: pointer;
    border: 2px solid transparent;
    transition: all var(--transition-fast);
}

.video-version-thumb:hover {
    border-color: var(--color-border-default);
    transform: scale(1.05);
}

.video-version-thumb.is-selected {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px rgba(249, 115, 22, 0.3);
}

.video-version-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.video-version-thumb .version-number {
    position: absolute;
    top: 2px;
    left: 2px;
    background: rgba(0, 0, 0, 0.7);
    color: white;
    font-size: 0.625rem;
    padding: 1px 4px;
    border-radius: var(--radius-sm);
}

.video-version-thumb .version-provider {
    position: absolute;
    bottom: 2px;
    right: 2px;
    background: rgba(0, 0, 0, 0.7);
    color: var(--color-text-secondary);
    font-size: 0.5rem;
    padding: 1px 3px;
    border-radius: var(--radius-sm);
    text-transform: uppercase;
}

.video-version-thumb .version-play-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 20px;
    height: 20px;
    background: rgba(0, 0, 0, 0.6);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.video-version-thumb:hover .version-play-icon {
    opacity: 1;
}

/* Image Versions Section */
.image-versions-section {
    margin-bottom: var(--space-2);
}

.image-versions-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-2);
}

.image-version-thumb {
    position: relative;
    aspect-ratio: 16/9;
    border-radius: var(--radius-md);
    overflow: hidden;
    cursor: pointer;
    border: 2px solid transparent;
    transition: all var(--transition-fast);
}

.image-version-thumb:hover {
    border-color: var(--color-border-default);
    transform: scale(1.05);
}

.image-version-thumb.is-selected {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px rgba(249, 115, 22, 0.3);
}

.image-version-thumb.is-primary {
    border-color: var(--color-success);
}

.image-version-thumb.is-primary.is-selected {
    border-color: var(--color-accent);
}

.image-version-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.image-version-thumb .version-number {
    position: absolute;
    top: 2px;
    left: 2px;
    background: rgba(0, 0, 0, 0.7);
    color: white;
    font-size: 0.625rem;
    padding: 1px 4px;
    border-radius: var(--radius-sm);
}

.image-version-thumb .version-label {
    position: absolute;
    bottom: 2px;
    left: 2px;
    right: 2px;
    background: rgba(0, 0, 0, 0.7);
    color: var(--color-text-secondary);
    font-size: 0.5rem;
    padding: 1px 3px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.image-version-thumb .primary-badge {
    position: absolute;
    top: 2px;
    left: 2px;
    background: var(--color-accent);
    color: white;
    font-size: 0.5rem;
    padding: 1px 3px;
    border-radius: var(--radius-sm);
}

.image-version-thumb .version-remove-btn {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 16px;
    height: 16px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(239, 68, 68, 0.9);
    color: white;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--transition-fast);
}

.image-version-thumb:hover .version-remove-btn {
    opacity: 1;
}

.image-version-thumb .version-remove-btn:hover {
    background: rgba(220, 38, 38, 1);
}

/* Filmstrip */
.expanded-filmstrip {
    margin-top: var(--space-4);
    padding: var(--space-3);
    background: rgba(30, 41, 59, 0.5);
    border-radius: var(--radius-xl);
    border: 1px solid var(--color-border-default);
}

.filmstrip-scroll {
    display: flex;
    gap: var(--space-3);
    overflow-x: auto;
    padding: var(--space-2);
    scroll-behavior: smooth;
}

.filmstrip-scroll::-webkit-scrollbar {
    height: 6px;
}

.filmstrip-scroll::-webkit-scrollbar-track {
    background: transparent;
}

.filmstrip-scroll::-webkit-scrollbar-thumb {
    background: var(--color-border-strong);
    border-radius: 3px;
}

.filmstrip-item {
    flex-shrink: 0;
    width: 120px;
    aspect-ratio: 16/9;
    background: var(--color-bg-secondary);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: pointer;
    border: 2px solid transparent;
    transition: border-color 0.3s ease, transform 0.3s ease;
    position: relative;
}

.filmstrip-item:hover {
    border-color: var(--color-border-strong);
    transform: translateY(-2px);
}

.filmstrip-item.active {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 2px var(--color-accent-subtle);
}

.filmstrip-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.filmstrip-item-position {
    position: absolute;
    top: 4px;
    left: 4px;
    width: 20px;
    height: 20px;
    background: rgba(0, 0, 0, 0.7);
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    color: white;
}

.filmstrip-video-badge {
    position: absolute;
    bottom: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    background: var(--color-accent);
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
}

.filmstrip-editing-badge {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    background: rgba(0, 0, 0, 0.7);
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-accent);
}

.filmstrip-item.editing {
    border-color: var(--color-accent);
    opacity: 0.8;
}

.filmstrip-item.has-video {
    border-color: var(--color-accent-subtle);
}

.filmstrip-item.generating {
    border-color: rgba(59, 130, 246, 0.7);
    animation: pulse-glow-blue 1.5s ease-in-out infinite;
}

.filmstrip-item.generating img {
    opacity: 0.5;
}

.filmstrip-item.swapping {
    border-color: rgba(168, 85, 247, 0.7);
    animation: pulse-glow-purple 1.5s ease-in-out infinite;
}

.filmstrip-item.swapping img {
    opacity: 0.5;
}

.filmstrip-item.failed {
    border-color: rgba(239, 68, 68, 0.5);
}

.filmstrip-generating-badge {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba(59, 130, 246, 0.9);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    z-index: 3;
}

.filmstrip-failed-badge {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba(239, 68, 68, 0.9);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    z-index: 3;
}

/* Animation for frame switching */
@keyframes crossfade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.frame-crossfade-enter {
    animation: crossfade-in 0.3s ease forwards;
}

/* Responsive expanded view */
@media (max-width: 1024px) {
    .expanded-content {
        flex-direction: column;
    }

    .expanded-quick-edit {
        width: 100%;
        order: 2;
    }

    .expanded-frame-area {
        order: 1;
    }
}

@media (max-width: 768px) {
    .expanded-filmstrip {
        display: none;
    }
}

/* ==================== STORYBOARD FLOATING TOOLBAR ==================== */

.storyboard-floating-toolbar {
    position: sticky;
    top: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    margin: var(--space-4);
    margin-bottom: 0;
    /* background: rgba(30, 30, 35, 0.85); */
    backdrop-filter: blur(12px);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
    flex-wrap: wrap;
}

/* Scene detection progress integrated into toolbar */
.toolbar-scene-progress {
    width: 100%;
    overflow: hidden;
    margin-top: var(--space-2);
    transition: max-height 0.3s ease, opacity 0.3s ease, margin 0.3s ease;
    max-height: 40px;
    opacity: 1;
}

.toolbar-scene-progress.hidden {
    max-height: 0;
    opacity: 0;
    margin-top: 0;
}

.toolbar-scene-progress-bar {
    width: 100%;
    height: 3px;
    background: var(--bg-tertiary);
    border-radius: 2px;
    overflow: hidden;
}

.toolbar-scene-progress-fill {
    height: 100%;
    background: var(--accent);
    border-radius: 2px;
    transition: width 0.3s ease;
}

.toolbar-scene-progress-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-top: var(--space-1);
}

.toolbar-section {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.toolbar-center {
    flex: 1;
    justify-content: center;
}

.toolbar-right {
    justify-content: flex-end;
}

/* Toolbar Buttons */
.toolbar-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: transparent;
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: none;
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.toolbar-btn svg,
.toolbar-btn i {
    pointer-events: none;
}

.toolbar-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--color-text-primary);
}

.toolbar-btn.active {
    background: rgba(255, 140, 0, 0.2);
    color: var(--color-accent);
}

.toolbar-btn-label {
    display: none;
}

@media (min-width: 768px) {
    .toolbar-btn-label {
        display: inline;
    }
}

.toolbar-btn-primary {
    background: linear-gradient(135deg, var(--color-accent) 0%, #ff6b35 100%);
    color: white;
}

.toolbar-btn-primary:hover {
    background: linear-gradient(135deg, #ff6b35 0%, var(--color-accent) 100%);
    transform: translateY(-1px);
}

.toolbar-btn-primary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
}

.toolbar-btn-secondary {
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
    border: 1px solid rgba(255, 140, 0, 0.3);
}

.toolbar-btn-secondary:hover {
    background: rgba(255, 140, 0, 0.2);
}

/* Credit Badge */
.toolbar-credit-badge {
    padding: 0 var(--space-2);
    background: rgba(0, 0, 0, 0.3);
    font-size: var(--font-size-xs);
    border-radius: var(--radius-full);
}

/* Save Indicator */
.toolbar-save-indicator {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    color: #22c55e;
    font-size: var(--font-size-xs);
}

/* Back Arrow in Toolbar (shown in expanded view) */
.toolbar-back-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-right: var(--space-2);
    margin-right: var(--space-2);
    color: var(--color-text-muted);
    border-right: 1px solid var(--color-border-subtle);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.toolbar-back-arrow:hover {
    color: var(--color-text-primary);
    transform: translateX(-2px);
}

.toolbar-back-arrow.hidden {
    display: none;
}

/* Toolbar Dropdowns */
.toolbar-dropdown {
    position: relative;
}

.toolbar-dropdown-trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    max-width: 200px;
}

.toolbar-dropdown-trigger:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--color-border-default);
}

.toolbar-dropdown-trigger span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Storyboard Name Inline Edit */
.storyboard-name-pencil {
    opacity: 0;
    transition: opacity 0.15s ease;
}

.toolbar-dropdown-trigger:hover .storyboard-name-pencil {
    opacity: 1;
}

.storyboard-name-input {
    background: transparent;
    border: 1px solid var(--color-accent);
    border-radius: 4px;
    color: white;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    padding: 2px 6px;
    outline: none;
    width: 160px;
    max-width: 240px;
}

.toolbar-dropdown-menu {
    position: absolute;
    top: calc(100% + var(--space-2));
    left: 0;
    min-width: 220px;
    padding: var(--space-2);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    z-index: 100;
}

.toolbar-dropdown-right {
    left: auto;
    right: 0;
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    background: transparent;
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    text-align: left;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.dropdown-item:hover {
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-primary);
}

.dropdown-item-danger {
    color: #ef4444;
}

.dropdown-item-danger:hover {
    background: rgba(239, 68, 68, 0.1);
    color: #ef4444;
}

.dropdown-divider {
    height: 1px;
    margin: var(--space-2) 0;
    background: var(--color-border-subtle);
}

.dropdown-label {
    display: block;
    padding: var(--space-1) var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.dropdown-section {
    max-height: 200px;
    overflow-y: auto;
}

/* Version Chip */
.toolbar-version-chip {
    position: relative;
}

.version-chip-trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    border: 1px solid rgba(255, 140, 0, 0.3);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.version-chip-trigger:hover {
    background: rgba(255, 140, 0, 0.2);
}

/* Settings Popover */
.toolbar-popover {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    width: 280px;
    padding: var(--space-4);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    z-index: 100;
}

.popover-title {
    margin-bottom: var(--space-4);
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
}

.popover-section {
    margin-bottom: var(--space-4);
}

.popover-section:last-child {
    margin-bottom: 0;
}

.popover-label {
    display: block;
    margin-bottom: var(--space-2);
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
}

/* Provider Toggle in Popover */
.popover-provider-toggle {
    display: flex;
    gap: var(--space-1);
    padding: var(--space-1);
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-lg);
}

.popover-provider-btn {
    flex: 1;
    padding: var(--space-2);
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.popover-provider-btn.active {
    background: var(--color-accent);
    color: white;
}

/* Empty State Welcome Card */
.empty-welcome-card {
    max-width: 400px;
    padding: var(--space-8);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-xl);
    text-align: center;
}

.empty-welcome-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 80px;
    height: 80px;
    margin-bottom: var(--space-4);
    background: rgba(255, 140, 0, 0.1);
    color: var(--color-accent);
    border-radius: var(--radius-full);
}

.empty-welcome-title {
    margin-bottom: var(--space-2);
    color: var(--color-text-primary);
    font-size: var(--font-size-xl);
    font-weight: var(--font-weight-semibold);
}

.empty-welcome-text {
    margin-bottom: var(--space-6);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    line-height: 1.6;
}

.empty-welcome-actions {
    display: flex;
    gap: var(--space-3);
    justify-content: center;
    margin-bottom: var(--space-4);
}

.empty-welcome-hint {
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
}

/* Multi-Select Action Bar */
.storyboard-action-bar {
    position: fixed;
    bottom: var(--space-6);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-6);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: 40;
}

.action-bar-count {
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
}

.action-bar-divider {
    width: 1px;
    height: 24px;
    background: var(--color-border-subtle);
}

/* Cinematic Style Popover */
.style-popover {
    position: absolute;
    bottom: calc(100% + var(--space-2));
    left: 50%;
    transform: translateX(-50%);
    width: 320px;
    padding: var(--space-4);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
}

.style-popover-title {
    margin-bottom: var(--space-2);
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
}

.style-popover-subtitle {
    margin-bottom: var(--space-4);
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
}

.style-option {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: left;
    width: 100%;
}

.style-option:hover {
    background: rgba(255, 255, 255, 0.03);
}

.style-option.selected {
    background: rgba(255, 140, 0, 0.1);
    border-color: rgba(255, 140, 0, 0.3);
}

.style-option-radio {
    width: 16px;
    height: 16px;
    margin-top: 2px;
    border: 2px solid var(--color-border-default);
    border-radius: var(--radius-full);
    flex-shrink: 0;
    transition: all var(--transition-fast);
}

.style-option.selected .style-option-radio {
    border-color: var(--color-accent);
    background: var(--color-accent);
    box-shadow: inset 0 0 0 3px var(--color-bg-secondary);
}

.style-option-info {
    flex: 1;
}

.style-option-name {
    display: block;
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
}

.style-option-desc {
    display: block;
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
}

.style-popover-footer {
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-border-subtle);
}

.style-popover-estimate {
    margin-bottom: var(--space-3);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
}

.style-popover-estimate strong {
    color: var(--color-accent);
}

/* ============================================
   Download Option Buttons
   ============================================ */

.download-option-btn {
    display: block;
    padding: var(--space-4);
    background: var(--color-slate-800);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: left;
}

.download-option-btn:hover {
    background: var(--color-slate-700);
    border-color: var(--color-arcade-orange);
}

.download-option-btn:active {
    transform: scale(0.99);
}

.download-option-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: rgba(255, 140, 0, 0.1);
    border-radius: var(--radius-md);
    color: var(--color-arcade-orange);
    flex-shrink: 0;
}

/* ============================================
   Character Swap Gallery
   ============================================ */

.character-swap-gallery {
    display: flex;
    gap: 0.75rem;
    overflow-x: auto;
    padding: 0.5rem 0;
    scrollbar-width: thin;
    scrollbar-color: var(--color-slate-600) transparent;
}

.character-swap-gallery::-webkit-scrollbar {
    height: 6px;
}

.character-swap-gallery::-webkit-scrollbar-track {
    background: transparent;
}

.character-swap-gallery::-webkit-scrollbar-thumb {
    background: var(--color-slate-600);
    border-radius: 3px;
}

.character-swap-card {
    position: relative;
    flex-shrink: 0;
    width: 100px;
    cursor: pointer;
    background: var(--color-slate-800);
    border: 2px solid transparent;
    border-radius: 0.5rem;
    padding: 0.5rem;
    transition: all 0.15s ease;
    text-align: center;
}

.character-swap-card:hover {
    border-color: var(--color-slate-600);
    background: var(--color-slate-700);
}

.character-swap-card.selected {
    border-color: var(--color-arcade-orange);
    background: rgba(255, 107, 0, 0.1);
}

.character-swap-card.disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

.character-swap-card-image {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    object-fit: cover;
    margin: 0 auto 0.5rem;
    background: var(--color-slate-700);
}

.character-swap-card-name {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-slate-200);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.character-swap-card-refs {
    font-size: 0.625rem;
    color: var(--color-slate-500);
    margin-top: 0.25rem;
}

.character-swap-card .check-overlay {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    width: 20px;
    height: 20px;
    background: var(--color-arcade-orange);
    border-radius: 50%;
    display: none;
    align-items: center;
    justify-content: center;
}

.character-swap-card.selected .check-overlay {
    display: flex;
}

.char-swap-estimate {
    border: 1px solid var(--color-slate-700);
}

/* =============================================================================
   Batch Video Grid
   ============================================================================= */

#video-result-batch {
    align-items: center;
    justify-content: center;
    padding: 0.75rem;
    box-sizing: border-box;
}

.video-batch-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: 1fr 1fr;
    gap: 0.75rem;
    width: 100%;
    height: 100%;
    padding: 0.75rem;
    box-sizing: border-box;
}

.video-batch-card {
    min-height: 0;
    border-radius: 8px;
    background: var(--color-bg-secondary);
    overflow: hidden;
    position: relative;
    border: 2px solid var(--color-border);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
    cursor: pointer;
}

.video-batch-card.complete:hover {
    border-color: var(--color-arcade-orange);
    box-shadow: 0 0 0 2px rgba(255, 140, 0, 0.3);
}

.video-batch-card.generating,
.video-batch-card.error {
    cursor: default;
}

.video-batch-card video {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Generating state */
.video-batch-card.generating {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.video-batch-card.generating .spinner {
    width: 32px;
    height: 32px;
    border: 3px solid var(--color-arcade-orange);
    border-top-color: transparent;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.video-batch-card.generating .status-text {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: var(--color-text-secondary);
}

.video-batch-card.generating .elapsed-time {
    font-size: 0.625rem;
    color: var(--color-text-tertiary);
    margin-top: 0.25rem;
}

/* Error state */
.video-batch-card.error {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(239, 68, 68, 0.1);
    border-color: rgba(239, 68, 68, 0.3);
}

.video-batch-card.error .error-icon {
    width: 32px;
    height: 32px;
    color: #ef4444;
}

.video-batch-card.error .error-text {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: #ef4444;
    text-align: center;
    padding: 0 0.5rem;
}

/* Complete state - action overlay */
.video-batch-card .video-card-actions {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.5rem;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.video-batch-card:hover .video-card-actions {
    opacity: 1;
}

.video-batch-card .video-card-actions button {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    border: none;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease;
}

.video-batch-card .video-card-actions button:hover {
    background: var(--color-arcade-orange);
}

.video-batch-card .video-card-actions button svg {
    width: 16px;
    height: 16px;
}

/* Play overlay for completed cards */
.video-batch-card .video-card-play-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: opacity 0.2s ease;
    pointer-events: none;
}

.video-batch-card.complete:hover .video-card-play-overlay {
    opacity: 1;
}

.video-batch-card .video-card-play-overlay .play-icon {
    width: 48px;
    height: 48px;
    color: white;
    filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5));
}

/* Index badge */
/* Canvas expansion when video batch mode is active */
.video-batch-canvas-expanded {
    max-width: 100% !important;
    aspect-ratio: unset !important;
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
}

#batch-expanded-view .batch-expanded-main {
    padding: 2rem;
}

.video-batch-card .index-badge {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    font-size: 0.75rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
}

/* ==========================================
   Batch Expanded View
   ========================================== */

.batch-expanded-main {
    flex: 1;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    padding: 1rem;
}

.batch-expanded-video {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
    background: #000;
}

/* Navigation Arrows */
.batch-nav-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.5);
    border: none;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease, opacity 0.2s ease;
    z-index: 10;
}

.batch-nav-arrow:hover {
    background: var(--color-arcade-orange);
}

.batch-nav-arrow:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.batch-nav-arrow:disabled:hover {
    background: rgba(0, 0, 0, 0.5);
}

.batch-nav-left {
    left: 1rem;
}

.batch-nav-right {
    right: 1rem;
}

.batch-nav-arrow svg {
    width: 24px;
    height: 24px;
}

/* Counter Badge */
.batch-counter {
    position: absolute;
    top: 1rem;
    left: 1rem;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    padding: 0.25rem 0.75rem;
    border-radius: 9999px;
    font-size: 0.875rem;
    font-weight: 500;
    z-index: 10;
}

/* Filmstrip */
.batch-filmstrip {
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 0.75rem;
    background: rgba(0, 0, 0, 0.3);
    border-top: 1px solid var(--color-border);
    flex-shrink: 0;
}

.batch-filmstrip-item {
    position: relative;
    width: 100px;
    height: 56px;
    border-radius: 6px;
    overflow: hidden;
    border: 2px solid var(--color-border);
    cursor: pointer;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
    flex-shrink: 0;
}

.batch-filmstrip-item:hover {
    border-color: var(--color-text-secondary);
}

.batch-filmstrip-item.active {
    border-color: var(--color-arcade-orange);
    box-shadow: 0 0 0 2px rgba(255, 140, 0, 0.3);
}

.batch-filmstrip-item img,
.batch-filmstrip-item video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.batch-filmstrip-item .filmstrip-badge {
    position: absolute;
    top: 4px;
    left: 4px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    font-size: 0.625rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ==========================================
   Edit Batch Grid (Image Editing Variations)
   ========================================== */

.edit-batch-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: 1fr 1fr;
    gap: 0.75rem;
    width: 100%;
    height: 100%;
    padding: 0.75rem;
    box-sizing: border-box;
}

.edit-batch-card {
    min-height: 0;
    border-radius: 8px;
    background: var(--color-bg-secondary);
    overflow: hidden;
    position: relative;
    border: 2px solid var(--color-border);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
    cursor: pointer;
}

.edit-batch-card.complete:hover {
    border-color: var(--color-arcade-orange);
    box-shadow: 0 0 0 2px rgba(255, 140, 0, 0.3);
}

.edit-batch-card.generating,
.edit-batch-card.error {
    cursor: default;
}

.edit-batch-card img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Generating state */
.edit-batch-card.generating {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.edit-batch-card.generating .spinner {
    width: 32px;
    height: 32px;
    border: 3px solid var(--color-arcade-orange);
    border-top-color: transparent;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.edit-batch-card.generating .status-text {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: var(--color-text-secondary);
}

/* Error state */
.edit-batch-card.error {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(239, 68, 68, 0.1);
    border-color: rgba(239, 68, 68, 0.3);
}

.edit-batch-card.error .error-icon {
    width: 32px;
    height: 32px;
    color: #ef4444;
}

.edit-batch-card.error .error-text {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: #ef4444;
    text-align: center;
    padding: 0 0.5rem;
}

/* Complete state - action overlay */
.edit-batch-card .edit-card-actions {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.5rem;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.edit-batch-card:hover .edit-card-actions {
    opacity: 1;
}

.edit-batch-card .edit-card-actions button {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    border: none;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease;
}

.edit-batch-card .edit-card-actions button:hover {
    background: var(--color-arcade-orange);
}

.edit-batch-card .edit-card-actions button svg {
    width: 16px;
    height: 16px;
}

/* Index badge */
.edit-batch-card .index-badge {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    font-size: 0.75rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
}

/* Expand overlay for completed cards */
.edit-batch-card .edit-card-expand-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: opacity 0.2s ease;
    pointer-events: none;
}

.edit-batch-card.complete:hover .edit-card-expand-overlay {
    opacity: 1;
}

.edit-batch-card .edit-card-expand-overlay .expand-icon {
    width: 48px;
    height: 48px;
    color: white;
    filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5));
}

/* Canvas expansion when batch mode is active */
.edit-batch-canvas-expanded {
    max-width: 100% !important;
    aspect-ratio: unset !important;
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border: none !important;
}

#edit-batch-expanded-view .batch-expanded-main {
    padding: 2rem;
}

/* ============================================
   Send-to Flyout Menu (reusable component)
   ============================================ */
.send-to-flyout-wrap {
    position: relative;
}

.send-to-flyout {
    position: absolute;
    bottom: calc(100% + 0.5rem);
    right: 0;
    min-width: 180px;
    background: rgba(15, 23, 42, 0.95);
    backdrop-filter: blur(12px);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    padding: 0.375rem 0;
    z-index: 50;
    opacity: 0;
    pointer-events: none;
    transform: translateY(4px);
    transition: opacity 150ms ease-out, transform 150ms ease-out;
}

.send-to-flyout.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

.send-to-flyout button {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.5rem 0.75rem;
    background: none;
    border: none;
    color: var(--color-text-secondary);
    font-size: 0.8125rem;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
    white-space: nowrap;
}

.send-to-flyout button:hover {
    background: rgba(255, 140, 0, 0.15);
    color: white;
}

.send-to-flyout button svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* ============================================
   Card Hover Actions (standalone / reusable)
   Works inside any position:relative parent.
   ============================================ */
.edit-card-actions {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.5rem;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    opacity: 0;
    transition: opacity 0.2s ease;
    z-index: 5;
}

/* Show on parent hover (works with any parent) */
:hover > .edit-card-actions {
    opacity: 1;
}

.edit-card-actions button {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    border: none;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease;
}

.edit-card-actions button:hover {
    background: var(--color-arcade-orange);
}

.edit-card-actions button svg {
    width: 16px;
    height: 16px;
}

/* ============================================
   Drag-to-Storyboard Drop Target
   ============================================ */

/* When any image drag is active on the page */
.storyboard-drop-ready {
    filter: brightness(1.3);
    transition: filter 200ms ease, transform 200ms ease;
}

.storyboard-drop-ready .storyboard-badge {
    animation: badgePulse 1.5s ease-in-out infinite;
}

/* When cursor hovers over the storyboard icon */
.storyboard-drop-hover {
    transform: scale(1.2) !important;
    filter: brightness(1.5) !important;
    transition: transform 150ms cubic-bezier(0.34, 1.56, 0.64, 1),
                filter 150ms ease !important;
}

.storyboard-drop-hover::after {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: 12px;
    border: 2px solid rgba(251, 146, 60, 0.8);
    box-shadow: 0 0 12px rgba(251, 146, 60, 0.4);
    animation: glowRing 1s ease-in-out infinite alternate;
    pointer-events: none;
}

/* Expanded hit area during drag */
.storyboard-drop-active {
    position: relative;
}

.storyboard-drop-active::before {
    content: '';
    position: absolute;
    inset: -20px;
    pointer-events: auto;
}

/* Success flash */
.storyboard-drop-success {
    animation: dropSuccess 400ms ease-out;
}

/* Error shake */
.storyboard-drop-error {
    animation: dropShake 300ms ease-out;
}

@keyframes glowRing {
    from { box-shadow: 0 0 8px rgba(251, 146, 60, 0.3); }
    to   { box-shadow: 0 0 16px rgba(251, 146, 60, 0.6); }
}

@keyframes badgePulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.15); }
}

@keyframes dropSuccess {
    0%   { background-color: transparent; }
    30%  { background-color: rgba(34, 197, 94, 0.3); transform: scale(1.1); }
    100% { background-color: transparent; transform: scale(1); }
}

@keyframes dropShake {
    0%, 100% { transform: translateX(0); }
    20%      { transform: translateX(-4px); }
    40%      { transform: translateX(4px); }
    60%      { transform: translateX(-3px); }
    80%      { transform: translateX(2px); }
}

/* ==================== GENERATION BAR ==================== */

.generation-bar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1rem;
    min-height: 48px;
    background: rgba(30, 41, 59, 0.92);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-bottom: 1px solid rgba(255, 140, 0, 0.15);
    border-radius: 0.75rem 0.75rem 0 0;
    transform: translateY(0);
    opacity: 1;
    transition: transform 200ms ease-out, opacity 200ms ease-out;
    width: 100%;
    box-sizing: border-box;
}

.generation-bar .generation-bar-content {
    display: flex;
    align-items: center;
    width: 100%;
    gap: 0.5rem;
}

.generation-bar-enter {
    transform: translateY(-100%);
    opacity: 0;
}

.generation-bar-exit {
    transform: translateY(-100%);
    opacity: 0;
}

.generation-bar-progress {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 2px;
    background: linear-gradient(90deg, var(--color-accent, #ff8c00), #ff6b35);
    border-radius: 0 1px 0 0;
    transition: width 300ms ease-out;
}

/* ============================================================================
   Frame Version Strip (share page)
   ============================================================================ */

.frame-version-thumb {
    transition: all 0.15s ease;
}

.frame-version-thumb:hover {
    opacity: 0.85;
    transform: scale(1.08);
}

/* ==================== ADMIN MODULE ==================== */

/* User table scroll */
.admin-users-scroll {
    max-height: calc(100vh - 200px);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 140, 0, 0.3) transparent;
}
.admin-users-scroll::-webkit-scrollbar { width: 8px; height: 8px; }
.admin-users-scroll::-webkit-scrollbar-track { background: rgba(15, 23, 42, 0.5); border-radius: 4px; }
.admin-users-scroll::-webkit-scrollbar-thumb { background: rgba(255, 140, 0, 0.3); border-radius: 4px; }
.admin-users-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255, 140, 0, 0.5); }
#admin-users-table-wrapper thead { backdrop-filter: blur(8px); }

/* Table rows */
#admin-users-tbody tr { transition: background-color 0.15s ease; }
#admin-users-tbody tr:nth-child(even) { background-color: rgba(30, 41, 59, 0.3); }
#admin-users-tbody tr:hover { background-color: rgba(255, 140, 0, 0.08); }

/* Action buttons */
.admin-action-btn { padding: 0.375rem; border-radius: 0.375rem; transition: all 0.15s ease; }
.admin-action-btn:hover { background-color: rgba(255, 255, 255, 0.1); }
.admin-action-btn.danger:hover { background-color: rgba(239, 68, 68, 0.2); color: #ef4444; }
.admin-action-btn.success:hover { background-color: rgba(34, 197, 94, 0.2); color: #22c55e; }
.admin-action-btn.warning:hover { background-color: rgba(245, 158, 11, 0.2); color: #f59e0b; }

/* Generation type badges */
.admin-type-badge {
    display: inline-flex; align-items: center; gap: 0.25rem;
    padding: 0.25rem 0.5rem; border-radius: 9999px;
    font-size: 0.625rem; font-weight: 500; text-transform: uppercase;
}
.admin-type-badge.type-image_edit { background: rgba(59, 130, 246, 0.2); color: #60a5fa; }
.admin-type-badge.type-image_generate { background: rgba(34, 197, 94, 0.2); color: #4ade80; }
.admin-type-badge.type-style_transfer { background: rgba(168, 85, 247, 0.2); color: #c084fc; }
.admin-type-badge.type-video_generate { background: rgba(245, 158, 11, 0.2); color: #fbbf24; }
.admin-type-badge.type-speech_generate { background: rgba(236, 72, 153, 0.2); color: #f472b6; }

/* Batch type badges */
.admin-batch-badge {
    display: inline-flex; align-items: center;
    padding: 0.125rem 0.375rem; border-radius: 9999px;
    font-size: 0.5rem; font-weight: 500; text-transform: uppercase;
}
.admin-batch-badge.batch-angle { background: rgba(56, 189, 248, 0.2); color: #38bdf8; }
.admin-batch-badge.batch-journey { background: rgba(167, 139, 250, 0.2); color: #a78bfa; }
.admin-batch-badge.batch-director { background: rgba(251, 146, 60, 0.2); color: #fb923c; }
.admin-batch-badge.batch-variation { background: rgba(52, 211, 153, 0.2); color: #34d399; }

/* Prompt details modal */
#prompt-detail-preview img, #prompt-detail-preview video { width: 100%; height: 100%; object-fit: contain; }
#prompt-detail-metadata .metadata-key { color: #94a3b8; font-weight: 500; }
#prompt-detail-metadata .metadata-value { color: #fff; }

/* Credit cost categories */
.cost-category {
    padding: 0.75rem;
    background: rgba(30, 41, 59, 0.3);
    border-radius: 0.5rem;
    border: 1px solid rgba(71, 85, 105, 0.3);
}
.cost-item { display: flex; flex-direction: column; gap: 0.25rem; }
.form-input-sm { padding: 0.375rem 0.5rem !important; font-size: 0.75rem !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   Adjustment Panel — Lightroom-style image adjustments + film grain
   ═══════════════════════════════════════════════════════════════════════════ */

.adjustment-panel {
    display: flex;
    flex-direction: column;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.5rem;
    overflow: hidden;
    font-size: var(--font-size-sm);
}

/* Header */
.adjustment-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border-subtle);
    background: var(--color-bg-primary);
    flex-wrap: wrap;
}

/* Active LUT indicator */
.adj-lut-indicator {
    width: 100%;
    padding: 2px var(--space-4);
    background: var(--color-accent-subtle);
    color: var(--color-accent);
    font-size: 0.65rem;
    font-weight: 600;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.adjustment-header-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-primary);
    font-weight: 600;
    font-size: var(--font-size-sm);
}

.adjustment-header-actions {
    display: flex;
    gap: var(--space-1);
}

.adjustment-header-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: none;
    border-radius: 0.375rem;
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.adjustment-header-btn:hover {
    background: var(--color-accent-subtle);
    color: var(--color-accent);
}

/* Section */
.adjustment-section {
    border-bottom: 1px solid var(--color-border-subtle);
}

.adjustment-section:last-of-type {
    border-bottom: none;
}

.adjustment-section-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: none;
    background: transparent;
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    cursor: pointer;
    transition: color var(--transition-fast);
}

.adjustment-section-title:hover {
    color: var(--color-text-primary);
}

.adjustment-section-title .section-chevron {
    margin-left: auto;
    transition: transform var(--transition-fast);
}

.adjustment-section-title.collapsed .section-chevron {
    transform: rotate(-90deg);
}

.adjustment-section-body {
    padding: 0 8px 6px;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.adjustment-section-body.collapsed {
    display: none;
}

/* Slider Row */
.adjustment-slider {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.adjustment-slider-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.adjustment-slider-header label {
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    font-weight: 500;
}

.adjustment-value {
    font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    min-width: 2rem;
    text-align: right;
    transition: color var(--transition-fast);
}

.adjustment-value.modified {
    color: var(--color-accent);
}

/* Range Slider Styling */
.adjustment-slider input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    outline: none;
    cursor: pointer;
}

.adjustment-slider input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--color-accent);
    border: 2px solid var(--color-bg-primary);
    cursor: pointer;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.adjustment-slider input[type="range"]::-webkit-slider-thumb:hover {
    transform: scale(1.2);
}

.adjustment-slider input[type="range"]::-webkit-slider-thumb:active {
    transform: scale(1.3);
    box-shadow: 0 0 0 4px rgba(255, 140, 0, 0.2);
}

.adjustment-slider input[type="range"]::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--color-accent);
    border: 2px solid var(--color-bg-primary);
    cursor: pointer;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.adjustment-slider input[type="range"]::-moz-range-thumb:hover {
    transform: scale(1.2);
}

.adjustment-slider input[type="range"]::-moz-range-thumb:active {
    transform: scale(1.3);
    box-shadow: 0 0 0 4px rgba(255, 140, 0, 0.2);
}

.adjustment-slider input[type="range"]::-moz-range-track {
    height: 4px;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    border: none;
}

/* Select Dropdown */
.adjustment-select {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: 0.375rem;
    color: var(--color-text-primary);
    font-size: var(--font-size-xs);
    cursor: pointer;
    outline: none;
    transition: border-color var(--transition-fast);
}

.adjustment-select:hover,
.adjustment-select:focus {
    border-color: var(--color-accent);
}

/* Toggle Switch */
.adjustment-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-1) 0;
}

.adjustment-toggle > label:first-child {
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    font-weight: 500;
}

.adjustment-switch {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    cursor: pointer;
}

.adjustment-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.adjustment-switch-slider {
    position: absolute;
    inset: 0;
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    transition: background var(--transition-fast);
}

.adjustment-switch-slider::before {
    content: '';
    position: absolute;
    height: 16px;
    width: 16px;
    left: 2px;
    bottom: 2px;
    background: var(--color-text-muted);
    border-radius: 50%;
    transition: transform var(--transition-fast), background var(--transition-fast);
}

.adjustment-switch input:checked + .adjustment-switch-slider {
    background: var(--color-accent);
}

.adjustment-switch input:checked + .adjustment-switch-slider::before {
    transform: translateX(16px);
    background: white;
}

/* Grain Preset Chips */
.adjustment-preset-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding-top: var(--space-2);
}

.grain-preset-chip {
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    cursor: pointer;
    transition: all var(--transition-fast);
    white-space: nowrap;
}

.grain-preset-chip:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: var(--color-accent-subtle);
}

.grain-preset-chip.active {
    border-color: var(--color-accent);
    background: var(--color-accent);
    color: white;
}

/* Footer */
.adjustment-footer {
    display: flex;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--color-border-subtle);
    background: var(--color-bg-primary);
}

.adjustment-footer-btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: none;
    border-radius: 0.375rem;
    font-size: var(--font-size-xs);
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.adjustment-footer-btn-secondary {
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
}

.adjustment-footer-btn-secondary:hover {
    background: rgba(255, 255, 255, 0.15);
    color: var(--color-text-primary);
}

.adjustment-footer-btn-primary {
    background: var(--color-accent);
    color: white;
}

.adjustment-footer-btn-primary:hover {
    filter: brightness(1.1);
}

/* Undo/Redo button disabled state */
.adjustment-header-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.adjustment-header-btn:disabled:hover {
    color: var(--color-text-muted);
    background: transparent;
}

/* Before/After label overlay */
.adj-before-after-label {
    position: absolute;
    top: var(--space-2);
    left: 50%;
    transform: translateX(-50%);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-full);
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    color: var(--color-text-primary);
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease;
    z-index: 10;
}

.adj-before-after-label.visible {
    opacity: 1;
}

/* ─── Tone Curve Editor ─── */

.tone-curve-channels {
    display: flex;
    gap: 2px;
    padding: var(--space-1) 0;
}

.tone-curve-channel-btn {
    flex: 1;
    padding: var(--space-1) 0;
    border: 1px solid var(--color-border-default);
    border-radius: 0.25rem;
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: center;
}

.tone-curve-channel-btn:hover {
    border-color: var(--color-text-muted);
    color: var(--color-text-secondary);
}

.tone-curve-channel-btn.active {
    border-color: var(--color-text-primary);
    background: rgba(255, 255, 255, 0.08);
    color: var(--color-text-primary);
}

.tone-curve-ch-red.active {
    border-color: #ff5555;
    background: rgba(255, 85, 85, 0.12);
    color: #ff5555;
}

.tone-curve-ch-green.active {
    border-color: #55cc55;
    background: rgba(85, 204, 85, 0.12);
    color: #55cc55;
}

.tone-curve-ch-blue.active {
    border-color: #5588ff;
    background: rgba(85, 136, 255, 0.12);
    color: #5588ff;
}

.tone-curve-container {
    width: 100%;
    aspect-ratio: 4/3;
    border-radius: 0.375rem;
    overflow: hidden;
    border: 1px solid var(--color-border-subtle);
}

.tone-curve-canvas {
    display: block;
    width: 100%;
    height: 100%;
    cursor: crosshair;
}

.tone-curve-presets {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding-top: var(--space-1);
}

.tone-curve-preset-btn {
    padding: 2px var(--space-2);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--color-text-muted);
    font-size: 0.65rem;
    cursor: pointer;
    transition: all var(--transition-fast);
    white-space: nowrap;
}

.tone-curve-preset-btn:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: var(--color-accent-subtle);
}

.tone-curve-preset-btn.active {
    border-color: var(--color-accent);
    background: var(--color-accent);
    color: white;
}

/* ─── HSL Panel ─── */

.hsl-subtabs {
    display: flex;
    gap: 2px;
    padding: var(--space-1) 0;
    border-bottom: 1px solid var(--color-border-subtle);
    margin-bottom: var(--space-2);
}

.hsl-subtab {
    flex: 1;
    padding: var(--space-1) 0;
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: center;
}

.hsl-subtab:hover {
    color: var(--color-text-secondary);
}

.hsl-subtab.active {
    color: var(--color-accent);
    border-bottom-color: var(--color-accent);
}

.hsl-color-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: 6px;
    vertical-align: middle;
}

.hsl-slider {
    margin-bottom: 2px;
}

/* ─── Split Toning ─── */

.split-tone-group {
    margin-bottom: var(--space-2);
}

.split-tone-label {
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: var(--space-1);
}

.split-tone-hue-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
}

.split-tone-swatch {
    width: 24px;
    height: 24px;
    min-width: 24px;
    border-radius: 50%;
    border: 2px solid var(--color-border-default);
    background: var(--color-bg-tertiary);
    opacity: 0.2;
    margin-top: 18px;
    transition: all var(--transition-fast);
}

.split-tone-slider {
    flex: 1;
}

.split-tone-hue-input {
    background: linear-gradient(
        to right,
        hsl(0,100%,50%),
        hsl(60,100%,50%),
        hsl(120,100%,50%),
        hsl(180,100%,50%),
        hsl(240,100%,50%),
        hsl(300,100%,50%),
        hsl(360,100%,50%)
    ) !important;
    height: 6px !important;
    border-radius: var(--radius-full) !important;
}

.split-tone-presets {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border-subtle);
    margin-top: var(--space-2);
}

/* ─── Scopes ─── */

.scope-mode-tabs {
    display: flex;
    gap: 2px;
    margin-bottom: var(--space-2);
}

.scope-mode-btn {
    flex: 1;
    padding: var(--space-1) 0;
    border: 1px solid var(--color-border-default);
    border-radius: 0.25rem;
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition-fast);
    text-align: center;
}

.scope-mode-btn:hover {
    color: var(--color-text-secondary);
    border-color: var(--color-text-muted);
}

.scope-mode-btn.active {
    color: var(--color-accent);
    border-color: var(--color-accent);
    background: var(--color-accent-subtle);
}

.scope-mount {
    width: 100%;
    aspect-ratio: 16/9;
    border-radius: 0.375rem;
    overflow: hidden;
    border: 1px solid var(--color-border-subtle);
}

.scope-mount[data-scope-mode="vectorscope"] {
    max-width: 200px;
    aspect-ratio: 1;
}

.scope-canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* ─── Floating Adjustment Panel ─────────────────────────────────── */

.floating-adjustment-panel {
    position: absolute;
    left: 0;
    top: 0;
    width: 300px;
    max-height: calc(100vh - 120px);
    background: rgba(15, 15, 28, 0.95);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
    /* SCS P0c: onto the z token scale (was a bare 1000). The old value put the adjustment panel
       above EVERY modal in the app — a blocking dialog could be painted over by a floating tool.
       `--z-modal` keeps it above the deck (--z-sticky) and the rack (--z-overlay) and level with
       the modal band, where a later-mounted modal wins on DOM order, which is the correct
       outcome. `!important` per the `important: true` Tailwind interplay (worked example:
       #toast-container, :918). */
    z-index: var(--z-modal) !important;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.floating-adjustment-panel-header {
    padding: 8px 12px;
    background: rgba(255, 255, 255, 0.03);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: grab;
    user-select: none;
    flex-shrink: 0;
}

.floating-adjustment-panel-header:active {
    cursor: grabbing;
}

.fp-header-left {
    display: flex;
    align-items: center;
    gap: 6px;
}

.fp-header-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-primary);
}

.fp-header-actions {
    display: flex;
    align-items: center;
    gap: 2px;
}

.fp-header-btn {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: 4px;
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.fp-header-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--color-text-primary);
}

.fp-header-btn:disabled {
    opacity: 0.3;
    cursor: default;
}

.fp-header-btn:disabled:hover {
    background: transparent;
    color: var(--color-text-secondary);
}

.floating-adjustment-panel-body {
    flex: 1;
    overflow-y: auto;
    padding: 6px;
}

.floating-adjustment-panel-body::-webkit-scrollbar {
    width: 4px;
}

.floating-adjustment-panel-body::-webkit-scrollbar-track {
    background: transparent;
}

.floating-adjustment-panel-body::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 2px;
}

.floating-adjustment-panel-footer {
    padding: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

.fp-footer-btn {
    flex: 1;
    padding: 6px;
    border-radius: 6px;
    border: 1px solid transparent;
    text-align: center;
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}

.fp-footer-btn-secondary {
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-secondary);
    border-color: rgba(255, 255, 255, 0.06);
}

.fp-footer-btn-secondary:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--color-text-primary);
}

.fp-footer-btn-primary {
    background: rgba(249, 115, 22, 0.2);
    border: 1px solid rgba(249, 115, 22, 0.4);
    color: var(--color-accent);
    font-weight: 600;
}

.fp-footer-btn-primary:hover {
    background: rgba(249, 115, 22, 0.3);
    border-color: rgba(249, 115, 22, 0.6);
}

/* Floating panel pill (minimized state) */
.floating-adjustment-pill {
    position: absolute;
    bottom: 16px;
    right: 16px;
    background: rgba(15, 15, 28, 0.92);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(249, 115, 22, 0.35);
    border-radius: 24px;
    padding: 8px 16px;
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    /* SCS P0c: one step below its own panel, on the scale (was a bare 999 under a bare 1000).
       The pair's RELATIVE order is the part that matters — the pill must never cover the panel
       it restores. */
    z-index: calc(var(--z-modal) - 1) !important;
    transition: transform 0.2s ease, border-color 0.2s ease;
    color: var(--color-text-secondary);
    font-size: 12px;
    font-weight: 500;
}

.floating-adjustment-pill:hover {
    transform: scale(1.02);
    border-color: rgba(249, 115, 22, 0.6);
    color: var(--color-text-primary);
}

.fp-pill-hint {
    font-size: 10px;
    opacity: 0.5;
}

/* Toolbar button active state (when floating panel is open) */
.fp-toolbar-active {
    background: rgba(249, 115, 22, 0.25) !important;
    border: 1px solid rgba(249, 115, 22, 0.5) !important;
    color: var(--color-accent) !important;
}

/* Responsive floating panel */
@media (max-width: 1439px) {
    .floating-adjustment-panel {
        width: 280px;
        max-height: calc(100vh - 100px);
    }
}

@media (max-width: 1279px) {
    .floating-adjustment-panel {
        width: 260px;
        max-height: calc(100vh - 80px);
    }
}

/* ============================================================
   Seedance 2.0 Multimodal Panel — refined Apple-inspired aesthetic
   Tight rhythm, soft depth, small caps labels, solid add-tiles.
   ============================================================ */

#videoMultimodalPanel {
    display: none;
    padding: 18px 18px 14px;
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.02),
        rgba(255, 255, 255, 0.005));
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 14px;
    margin-top: 12px;
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.03) inset,
        0 10px 30px -18px rgba(0, 0, 0, 0.5);
}
#videoMultimodalPanel.active { display: block; }

.seedance2-ref-row { margin-bottom: 14px; }
.seedance2-ref-row:last-child { margin-bottom: 0; }
.seedance2-ref-row + .seedance2-ref-row {
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
}

/* Base header (non-collapsible rows like Images) */
.seedance2-ref-row-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-secondary, #94a3b8);
}
.seedance2-ref-row-header > span:first-child,
.seedance2-ref-row-title {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--color-text-primary, #e2e8f0);
}
.seedance2-ref-row-header [data-field],
.seedance2-ref-count {
    font-variant-numeric: tabular-nums;
    color: var(--color-text-secondary);
    font-weight: 500;
}
.seedance2-ref-count {
    margin-left: 2px;
    text-transform: none;
    letter-spacing: 0.02em;
}
.seedance2-ref-row-meta {
    font-size: 10.5px;
    letter-spacing: 0.05em;
    text-transform: none;
    color: var(--color-text-secondary);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.seedance2-ref-row-warning { color: #f59e0b !important; }
.seedance2-ref-row-error { color: #ef4444 !important; }

/* Collapsible row — the header is a <button> but must match the Images row
   visually: same font-size / weight / uppercase tracking. Do NOT use `font: inherit`
   (that resets font-size to the button default). */
.seedance2-ref-row-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    background: none;
    border: 0;
    padding: 6px 8px;
    margin: -6px -8px 4px;
    border-radius: 8px;
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-secondary, #94a3b8);
    transition: background 150ms ease;
}
.seedance2-ref-row-toggle:hover {
    background: rgba(255, 255, 255, 0.03);
}
.seedance2-ref-row-toggle:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.seedance2-ref-row-chevron {
    display: inline-grid;
    place-items: center;
    width: 14px;
    height: 14px;
    margin-right: 4px;
    color: var(--color-text-tertiary, #64748b);
    transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1);
}
.seedance2-ref-row-chevron svg { width: 100%; height: 100%; }
.seedance2-ref-row--collapsible:not(.collapsed) .seedance2-ref-row-chevron {
    transform: rotate(90deg);
}

.seedance2-ref-body {
    overflow: hidden;
    transition:
        max-height 220ms cubic-bezier(0.4, 0, 0.2, 1),
        opacity 180ms ease,
        margin-top 180ms ease;
    max-height: 600px;
    opacity: 1;
    margin-top: 6px;
}
.seedance2-ref-row--collapsible.collapsed .seedance2-ref-body {
    max-height: 0;
    opacity: 0;
    margin-top: 0;
    pointer-events: none;
}

/* Grid uses a fixed cell size so slots across rows are visually consistent.
   Images render square (72×72); videos are wider (115×72) but share the same
   height — this keeps the "Add" tile aligned on the Y-axis across all three rows. */
.seedance2-ref-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 72px);
    gap: 8px;
}
[data-row-type="video"] {
    grid-template-columns: repeat(auto-fill, 115px);
}
[data-row-type="audio"] {
    grid-template-columns: repeat(auto-fill, 160px);
}

/* Populated slot — image/video thumbnail */
.seedance2-ref-slot {
    width: 72px;
    height: 72px;
    border-radius: 10px;
    position: relative;
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.06);
    overflow: hidden;
    cursor: pointer;
    transition:
        border-color 160ms ease,
        transform 160ms ease,
        box-shadow 160ms ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.seedance2-ref-slot:not(.seedance2-ref-slot--empty):not(.seedance2-ref-slot--pending):hover {
    border-color: rgba(255, 255, 255, 0.18);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}
.seedance2-ref-slot--video {
    width: 115px;  /* 16:10 at 72px tall */
    height: 72px;
}
.seedance2-ref-slot[data-type="audio"],
[data-row-type="audio"] .seedance2-ref-slot {
    width: 160px;
    height: 48px;
    border-radius: 8px;
}

/* Uploading slot — shared width/height with neighbours, spinner + label */
.seedance2-ref-slot--pending {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    cursor: progress;
    background:
        linear-gradient(135deg, rgba(255, 122, 24, 0.08), rgba(255, 122, 24, 0.02));
    border: 1px solid rgba(255, 122, 24, 0.3);
    color: var(--color-accent);
    animation: seedance2-pending-pulse 1.8s ease-in-out infinite;
}
.seedance2-ref-slot-pending-label {
    font-size: 10px;
    letter-spacing: 0.04em;
    font-weight: 500;
    opacity: 0.85;
}
.seedance2-spinner {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 2px solid rgba(255, 122, 24, 0.25);
    border-top-color: var(--color-accent);
    animation: seedance2-spin 0.9s linear infinite;
}
@keyframes seedance2-spin {
    to { transform: rotate(360deg); }
}
@keyframes seedance2-pending-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(255, 122, 24, 0.25);
    }
    50% {
        box-shadow: 0 0 0 4px rgba(255, 122, 24, 0.05);
    }
}

/* Empty "add" tile — solid, refined, no dashed border. Size matches the
   populated slots in its row (square for images, 16:10 for video, bar for audio). */
.seedance2-ref-slot--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    color: var(--color-text-tertiary, #64748b);
    background:
        radial-gradient(circle at center,
            rgba(255, 255, 255, 0.04),
            rgba(255, 255, 255, 0.015));
    border: 1px dashed rgba(255, 255, 255, 0.12);
    cursor: pointer;
    appearance: none;
    font-family: inherit;
    transition:
        border-color 160ms ease,
        color 160ms ease,
        background 160ms ease,
        transform 160ms ease;
}
.seedance2-ref-slot--empty.seedance2-ref-slot--video {
    width: 115px;
    height: 72px;
}
[data-row-type="audio"] .seedance2-ref-slot--empty {
    width: 160px;
    height: 48px;
    border-radius: 8px;
}
.seedance2-ref-slot--empty:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    background: rgba(255, 122, 24, 0.06);
    transform: translateY(-1px);
}
.seedance2-ref-slot--empty:active { transform: translateY(0); }
.seedance2-ref-slot--empty:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.seedance2-ref-slot-plus {
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    opacity: 0.85;
    transition: opacity 160ms ease;
}
.seedance2-ref-slot-plus svg { width: 100%; height: 100%; }
.seedance2-ref-slot--empty:hover .seedance2-ref-slot-plus { opacity: 1; }

.seedance2-ref-slot--full {
    cursor: not-allowed;
    opacity: 0.55;
}
.seedance2-ref-slot-full-label {
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
}

.seedance2-ref-slot--drag-over {
    border-color: var(--color-accent) !important;
    border-style: solid !important;
    background: rgba(255, 122, 24, 0.10);
    box-shadow: 0 0 0 3px rgba(255, 122, 24, 0.18);
}
.seedance2-ref-slot--invalid { animation: seedance2-pulse-red 600ms; }
@keyframes seedance2-pulse-red {
    0%, 100% { border-color: rgba(255, 255, 255, 0.06); }
    50% {
        border-color: #ef4444;
        background: rgba(239, 68, 68, 0.15);
        box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.22);
    }
}

.seedance2-ref-slot img,
.seedance2-ref-slot video {
    width: 100%; height: 100%; object-fit: cover;
    display: block;
}

/* Tag badge — small caps pill, subtle */
.seedance2-tag-badge {
    position: absolute;
    top: 5px; left: 5px;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    padding: 2px 6px;
    border-radius: 999px;
    pointer-events: none;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.seedance2-tag-badge--img { background: var(--chip-img-bg-strong); color: var(--chip-img-fg); }
.seedance2-tag-badge--vid { background: var(--chip-vid-bg-strong); color: var(--chip-vid-fg); }
.seedance2-tag-badge--aud { background: var(--chip-aud-bg-strong); color: var(--chip-aud-fg); }

/* Remove button — only visible on slot hover */
.seedance2-ref-slot-remove {
    position: absolute;
    top: 4px; right: 4px;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.65);
    color: rgba(255, 255, 255, 0.9);
    display: flex; align-items: center; justify-content: center;
    border: 0;
    cursor: pointer;
    font-size: 13px;
    line-height: 1;
    font-weight: 400;
    opacity: 0;
    transform: scale(0.85);
    transition: opacity 160ms ease, transform 160ms ease, background 160ms ease;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.seedance2-ref-slot:hover .seedance2-ref-slot-remove,
.seedance2-ref-slot-remove:focus-visible {
    opacity: 1;
    transform: scale(1);
}
.seedance2-ref-slot-remove:hover {
    background: rgba(239, 68, 68, 0.85);
}

/* Codec-failure state on a video tile: shown ONLY when the poster capture's
   decoder demonstrably failed (previewFailure set) — never pre-emptively. */
.seedance2-ref-slot-nopreview {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 4px;
    text-align: center;
    color: var(--color-text-disabled, #64748b);
    background: rgba(148, 163, 184, 0.06);
    cursor: help;
}
.seedance2-ref-slot-nopreview svg {
    width: 16px;
    height: 16px;
    opacity: 0.75;
}
.seedance2-ref-slot-nopreview > span {
    font-size: 9px;
    font-weight: 500;
    letter-spacing: 0.02em;
    line-height: 1.2;
}

.seedance2-duration-badge {
    position: absolute;
    bottom: 4px; right: 4px;
    font-size: 9.5px;
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.6);
    color: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    font-variant-numeric: tabular-nums;
}

.seedance2-duration-smart {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11.5px;
    margin-top: 6px;
    color: var(--color-text-secondary);
}
.seedance2-cost-preview {
    font-size: 11.5px;
    color: var(--color-text-secondary);
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
}
.seedance2-cost-preview strong { color: var(--color-accent); font-weight: 600; }

/* Seedance 2.0 options — pill toggles (Smart Length / Lock Camera). */
.seedance2-options {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 14px;
}
.seedance2-options.hidden { display: none; }
.seedance2-option-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px 6px 10px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.02);
    color: var(--color-text-secondary, #94a3b8);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition:
        background 160ms ease,
        color 160ms ease,
        border-color 160ms ease,
        box-shadow 160ms ease,
        transform 160ms ease;
}
.seedance2-option-pill:hover {
    background: rgba(255, 255, 255, 0.04);
    color: var(--color-text-primary, #e2e8f0);
    border-color: rgba(255, 255, 255, 0.14);
}
.seedance2-option-pill[aria-pressed="true"],
.seedance2-option-pill.active {
    background: rgba(255, 122, 24, 0.18);
    border-color: rgba(255, 122, 24, 0.45);
    color: var(--color-accent);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.04),
        0 0 0 3px rgba(255, 122, 24, 0.08);
}
.seedance2-option-pill[aria-pressed="true"]:hover {
    background: rgba(255, 122, 24, 0.24);
    transform: translateY(-1px);
}
.seedance2-option-pill:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.seedance2-option-pill-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* When Smart Length is active, mute the fixed-duration slider to signal it's
   model-chosen. The duration slider still renders but is visually de-emphasized. */
.seedance2-smart-length-active {
    opacity: 0.4;
    pointer-events: none;
    transition: opacity 180ms ease;
}

@media (prefers-reduced-motion: reduce) {
    .seedance2-ref-slot,
    .seedance2-ref-slot--invalid {
        animation: none !important;
        transition: none !important;
    }
}

/* ----- Seedance 2.0 prompt-chip overlay -----------------------------------
   The overlay mirrors the textarea geometry exactly (same padding, border,
   font, line-height) so chip positions align with the textarea's glyphs.
   Textarea sits on top and is made transparent via .active so only chips show. */
.prompt-chip-wrap {
    position: relative;
    width: 100%;
}
.prompt-chip-overlay {
    position: absolute;
    inset: 0;
    /* Match .form-textarea box model exactly (padding var(--space-3) var(--space-4),
       1px border). Use transparent border so the overlay content box aligns with
       the textarea content box without double-drawing a border. */
    box-sizing: border-box;
    padding: var(--space-3) var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    /* Match .form-textarea font so glyph runs break at identical positions. */
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: 1.5;
    letter-spacing: inherit;
    tab-size: inherit;
    color: var(--color-text-secondary);
    pointer-events: none;
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: normal;
    overflow: hidden;
    z-index: 0;
}
/* The textarea sits on top of the overlay. We keep its text visible by default
   — chips only materialize while the panel is active (see .prompt-chip-wrap.active). */
.prompt-chip-textarea {
    position: relative;
    z-index: 1;
    background-color: transparent !important;
    /* Match overlay line-height explicitly so soft-wrap positions agree. */
    line-height: 1.5;
}
.prompt-chip-wrap.active .prompt-chip-textarea {
    /* Hide native glyphs so only the overlay is visible. Caret stays visible via caret-color. */
    color: transparent !important;
    caret-color: var(--color-text-secondary) !important;
}
.prompt-chip-wrap.active .prompt-chip-textarea::selection {
    background: rgba(255, 122, 24, 0.35);
    color: transparent;
}
/* Chips must be METRICALLY IDENTICAL to the textarea glyphs underneath: any
   advance-width change (padding, border, margin, letter-spacing, or a heavier
   font-weight) shifts every glyph after the chip, and the drift accumulates
   per chip until the textarea's real selection/caret no longer lines up with
   the visible overlay text. Style via background/color/border-radius/box-shadow
   ONLY — the box-shadow spread fakes the pill inset without occupying layout. */
.prompt-chip-overlay > .prompt-chip {
    display: inline;
    padding: 0;
    margin: 0;
    border-radius: 4px;
    font-weight: inherit;
    font-size: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    font-family: inherit;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}
.prompt-chip--img { background: var(--chip-img-bg); color: var(--chip-img-fg); box-shadow: 0 0 0 2px var(--chip-img-bg); }
.prompt-chip--vid { background: var(--chip-vid-bg); color: var(--chip-vid-fg); box-shadow: 0 0 0 2px var(--chip-vid-bg); }
.prompt-chip--aud { background: var(--chip-aud-bg); color: var(--chip-aud-fg); box-shadow: 0 0 0 2px var(--chip-aud-bg); }

/* Autocomplete picker dropdown — Apple-style floating menu with blur + soft shadow. */
.prompt-chip-autocomplete {
    position: absolute;
    z-index: 1000;
    min-width: 200px;
    max-height: 260px;
    overflow-y: auto;
    padding: 4px;
    background: rgba(15, 23, 42, 0.92);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 10px;
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.04) inset,
        0 12px 32px rgba(0, 0, 0, 0.5),
        0 2px 6px rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    animation: seedance2-ac-enter 140ms ease-out;
}
.prompt-chip-autocomplete.hidden { display: none; }
@keyframes seedance2-ac-enter {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}
.prompt-chip-autocomplete-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    color: var(--color-text-primary, #e2e8f0);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: 0.01em;
    transition: background 120ms ease, color 120ms ease;
}
.prompt-chip-autocomplete-item.active,
.prompt-chip-autocomplete-item:hover {
    background: rgba(255, 122, 24, 0.18);
    color: var(--color-accent);
}
.prompt-chip-autocomplete-thumb {
    width: 26px;
    height: 26px;
    object-fit: cover;
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.06);
    flex-shrink: 0;
}

/* ==================== CINEMATIC FRAMES — ENSEMBLE CAST PICKER ====================
   The N-character cast list (replaces the fixed 2-character dropdowns). Rows are
   rendered into #frames-cast-list by cinematic-frames.js from state.cast. Each
   .frames-cast-row carries a library <select>, an optional selected-character
   preview + per-member note input, and a remove button. Styling is intentionally
   light — the rows reuse .form-select / .form-input / .btn-secondary component
   classes; these rules only add structure/affordance polish. */

.frames-cast-row {
    transition: border-color 150ms ease, background-color 150ms ease;
}

/* A row with a selected character reads as "locked in" with a subtle accent. */
.frames-cast-row:has(.frames-cast-preview) {
    border-color: rgb(255 140 0 / 0.35);
}

.frames-cast-row .frames-cast-ordinal {
    line-height: 1.6;
}

.frames-cast-preview img {
    background-color: var(--color-surface-2, #1e293b);
}

/* Keep the add button visually disabled at the 8-row cap. */
#frames-add-cast-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ==================== CINEMATIC FRAMES — COVERAGE PLAN REVIEW ====================
   Director's "review the planned shot-DAG before spending credits" modal.
   Mounted into #frames-plan-review-container (controls.html). Hidden by default
   via the `hidden` Tailwind utility on the root; JS toggles `.open` to animate in.
   Follows the gallery-modal idiom (fixed overlay + backdrop + scale-in panel)
   and uses design tokens throughout. `important: true` is set in tailwind.config,
   so load-bearing display/layout props carry !important to win over utilities. */

/* ============================================================================
   Cinematic Frames — full-width workspace shell (canvas redesign §1.2 / §1.3).
   Standalone rules (lesson #34): NOT appended into any grouped selector. The
   rail slab/lamp/chip/ticker + stage-panel/action-bar families arrive in later
   tasks; the rail here is a STATIC placeholder.
   ============================================================================ */

/* §1.2 — neutralize #preview-panel's padding/centering/scroll so the module-owned
   workspace owns the whole surface. Tailwind important:true ⇒ overrides need !important. */
#preview-panel.frames-fullbleed {
    padding: 0 !important;
    align-items: stretch !important;
    overflow: hidden !important;
}

/* §1.3 — the module-owned grid: 264px rail + flex-1 canvas. */
.frames-workspace {
    display: flex;
    height: 100%;
    min-height: 0;
}

.frames-rail {
    width: 264px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    border-right: 1px solid var(--color-border-default);
    background: var(--color-bg-primary);
}

.frames-canvas {
    flex: 1;
    min-width: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    position: relative;   /* anchors the canvas-level planning overlay in §2.4 (Task 3+) */
}

.frames-stage {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-6);
}

/* Floor (<1280px): the rail may compress to 220px (§1.3, desktop-first). */
@media (max-width: 1280px) {
    .frames-rail { width: 220px; }
}

/* ============================================================================
   Cinematic Frames — stage rail + canvas planning overlay (canvas redesign
   §2.4 / §3). Standalone rules (lesson #34): never appended into a grouped
   selector. Tokens only; no new colors/fonts.
   ============================================================================ */

/* Stage slab — one per rail entry: status lamp + label + one-line statusLine. */
.frames-rail-slab {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    width: 100%;
    text-align: left;
    padding: var(--space-3) var(--space-4);
    background: transparent;
    border: none;
    border-left: 2px solid transparent;
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}
.frames-rail-slab:hover:not(:disabled) { background: var(--color-bg-secondary); }
.frames-rail-slab.is-active {
    background: var(--color-bg-secondary);
    border-left-color: var(--color-accent);
}
.frames-rail-slab.is-locked,
.frames-rail-slab:disabled { cursor: not-allowed; }
.frames-rail-slab:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: -2px;
}

.frames-rail-slab-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.frames-rail-slab-label {
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    color: var(--color-text-muted);
}
.frames-rail-slab-status {
    font-size: var(--font-size-xs);
    line-height: 1.3;
    color: var(--color-text-secondary);
}
.frames-rail-slab--locked .frames-rail-slab-status { color: var(--color-text-disabled); }

/* Status lamp — a small dot; color keyed to status; running pulses. */
.frames-rail-lamp {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    margin-top: 5px;
    border-radius: var(--radius-full);
    background: var(--color-border-strong);
}
.frames-rail-lamp--empty { background: var(--color-border-strong); }
.frames-rail-lamp--locked { background: var(--color-border-default); }
.frames-rail-lamp--ready { background: var(--color-accent); }
.frames-rail-lamp--complete { background: var(--color-success); }
.frames-rail-lamp--attention { background: var(--color-warning); }
.frames-rail-lamp--running {
    background: var(--color-accent);
    animation: frames-rail-lamp-pulse 1.4s ease-in-out infinite;
}
@keyframes frames-rail-lamp-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 var(--color-accent-glow); }
    50% { opacity: 0.55; box-shadow: 0 0 0 4px transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .frames-rail-lamp--running { animation: none; }
}

/* Ensemble summary chips (§3). */
.frames-rail-ensemble-head,
.frames-rail-ticker-eyebrow {
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-muted);
    margin-bottom: var(--space-2);
}
.frames-rail-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    max-width: 100%;
    margin: 0 var(--space-1) var(--space-1) 0;
    padding: 2px var(--space-2);
    border-radius: var(--radius-full);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-subtle);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    cursor: pointer;
}
.frames-rail-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frames-rail-chip img { width: 16px; height: 16px; border-radius: var(--radius-full); object-fit: cover; }
.frames-rail-chip-count {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-top: var(--space-1);
}

/* Now-running ticker (§3). */
.frames-rail-ticker:empty { display: none; }
.frames-rail-ticker-line {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}
.frames-rail-ticker-line i { color: var(--color-accent); }

/* §2.4 — the planning overlay is CANVAS-level: it paints ABOVE whichever stage is active
   (stage sections keep their .hidden state) via position:absolute inside the position:relative
   .frames-canvas — no z-index games beyond a small stacking bump. max-width:none overrides the
   element's flow max-w-2xl so the overlay fills the canvas. */
#frames-planning-state {
    position: absolute;
    inset: 0;
    z-index: 5;
    max-width: none !important;
    background: var(--color-bg-primary);
}

/* ============================================================================
   Cinematic Frames — Sources stage cards + stage action bar (canvas redesign
   §1.3 / §4.1). Standalone rules (lesson #34): never appended into a grouped
   selector. Tokens only; no new colors/fonts, no new utility classes.
   ============================================================================ */

/* A stage content panel — the shared card surface for the Sources cards AND (Tasks 5-7) the
   de-modaled takeover fragments. Base surface only; the takeover panels keep their own more
   specific classes (later in the file) + add their transform/max-width resets on top. */
.frames-stage-panel {
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
}

/* Sources cards sit at canvas width with a comfortable reading measure. */
.frames-sources-card { width: 100%; max-width: 880px; }

.frames-sources-card-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-primary);
}
.frames-sources-card-head i { color: var(--color-accent); }
.frames-sources-card-hint {
    margin-left: auto;
    font-size: var(--font-size-xs);
    font-weight: 400;
    color: var(--color-text-muted);
}

/* The Ensemble card is a programmatic scroll/focus target from the rail chips (§3) — no ring on
   the programmatic focus, but keep a visible ring for real keyboard focus. */
#frames-ensemble-card:focus { outline: none; }
#frames-ensemble-card:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* M10 — resume slot Sources top strip: only occupies space when populated. */
.frames-sources-resume:empty { display: none; }

/* M9 — the Sources stage action bar: cost estimate + run options + the terminal CTA
   (generate-frames-btn, "Build coverage plan"). At canvas width, bottom of the stage flow. */
.frames-stage-actionbar {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4);
    border-radius: var(--radius-lg);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-subtle);
}
.frames-actionbar-estimate {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3);
    border-radius: var(--radius-md);
    background: var(--color-bg-tertiary);
}

/* The 880px reading-measure cap is a SOURCES-stage choice — scoped (id+class beats the
   single-class base regardless of source order) so de-modaled stage footers that opt into
   .frames-stage-actionbar later (Coverage, Task 7) run full canvas width. */
#frames-stage-sources .frames-stage-actionbar { max-width: 880px; }

/* ============================================================================
   Cinematic Frames — Slate & Call Sheet redesign §2.1: two-lane Sources layout.
   Standalone rules (lesson #34): never appended into a grouped selector.
   One DOM node, two layouts: ≥1360px the Call Sheet is a sticky right lane;
   below it docks as a sticky bottom bar. The dock MUST stack below the
   planning overlay (#frames-planning-state, z-index:5) — hence z-index:4.
   ============================================================================ */
.frames-sources-layout {
    display: flex;
    align-items: flex-start;
    gap: var(--space-6);
    width: 100%;
    min-height: 0;
}
.frames-sources-work {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}
.frames-callsheet {
    width: 300px;
    flex-shrink: 0;
    position: sticky;
    top: var(--space-2);
    z-index: 4;
}

@media (max-width: 1359px) {
    .frames-sources-layout { flex-direction: column; }
    .frames-callsheet {
        width: 100%;
        top: auto;
        bottom: 0;
        background: var(--color-bg-primary);
        padding-top: var(--space-2);
    }
    /* Dock mode: the action bar compacts into a row (estimate · options · CTA).
       Review fix: id-scoped so it OUTRANKS the Sources 880px cap
       (#frames-stage-sources .frames-stage-actionbar, 1,1,0) — 1,2,0 wins. */
    #frames-stage-sources .frames-callsheet .frames-stage-actionbar {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        max-width: none;
    }
    .frames-callsheet .frames-actionbar-estimate { flex: 1 1 220px; }
    .frames-callsheet .frames-run-options { flex: 1 1 260px; }
    .frames-callsheet #generate-frames-btn { flex: 1 1 240px; }
    /* Review fix: !important needed — the element carries Tailwind .mt-2 (important build). */
    .frames-callsheet #frames-credit-help { flex: 1 1 100%; margin-top: 0 !important; }
}

/* ============================================================================
   Cinematic Frames — Slate & Call Sheet redesign §2.3: THE BINS (standing set).
   A bin = a Sources card with a clickable prose-summary head. Dim ≠ disabled:
   a dim bin stays fully interactive (never aria-disabled). Collapse hides every
   child except the head — including the JS-injected board panel — via a child
   combinator (no body wrapper, so _renderBoardControl's insertBefore(#frames-shots)
   sibling contract survives untouched). Standalone rules (lesson #34).
   ============================================================================ */
.frames-bin-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    width: 100%;
    max-width: 880px;
}
.frames-bin-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    background: none;
    border: none;
    padding: 0;
    margin-bottom: var(--space-3);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-primary);
    cursor: pointer;
    text-align: left;
}
.frames-bin-head i { color: var(--color-accent); }
.frames-bin-head:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.frames-bin-title { flex-shrink: 0; }
.frames-bin-summary {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 400;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}
.frames-bin-head .frames-sources-card-hint { margin-left: 0; flex-shrink: 0; }
.frames-bin-head .frames-bin-chevron,
.frames-slate-expand .frames-bin-chevron {
    margin-left: 0;
    flex-shrink: 0;
    color: var(--color-text-muted);
    transition: transform 150ms ease-out;
}
.frames-bin.is-collapsed .frames-bin-chevron { transform: rotate(-90deg); }
/* Green "something's in here" check (user request 2026-07-14) + the plain-language
   info glyphs on the run options + the fast-vs-deep caption under the Slate footer. */
.frames-bin-head .frames-bin-check { color: var(--color-success); flex-shrink: 0; }
.frames-hint-icon { color: var(--color-text-muted); flex-shrink: 0; cursor: help; }
.frames-slate-paths {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    line-height: 1.5;
}
.frames-slate-paths strong { color: var(--color-text-secondary); font-weight: 600; }
.frames-slate.is-calm .frames-slate-paths { display: none !important; }
.frames-bin.is-collapsed > *:not(.frames-bin-head) { display: none !important; }
.frames-bin.is-collapsed .frames-bin-head { margin-bottom: 0; }
/* Dim-empty: quieter, still readable, fully interactive; wakes on hover/focus. */
.frames-bin.is-dim { opacity: 0.72; }
.frames-bin.is-dim:hover,
.frames-bin.is-dim:focus-within { opacity: 1; }

/* Deck Style Fidelity D1 (design §2f, C18 honesty surface) — the Look bin's
   "Campaign look" chip. Lives inside .frames-bin-head (preview.html) so it stays
   visible even while the bin is collapsed. Default (count>0): a quiet success pill,
   same family as .frames-deck-gate-chip. `.is-warning` (count 0, routed deck): the
   same amber-advisory language as the gate's own zero-capture/script-conflict banners. */
.frames-deck-style-chip {
    flex-shrink: 0;
    font-size: var(--font-size-xs);
    font-weight: 400;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    background: rgba(34, 197, 94, 0.1);
    border: 1px solid rgba(34, 197, 94, 0.3);
    color: #86efac;
}
.frames-deck-style-chip.is-warning {
    background: rgba(245, 158, 11, 0.1);
    border-color: rgba(245, 158, 11, 0.35);
    color: #fbbf24;
}

/* Deck Style Fidelity D2 (design §2g / C11 gate note 2) — the Campaign look slot's
   promotable rank chips (ALL roles, incl. disqualified dna_only/discard — rationale
   rides the title tooltip) + the director's promote/manual-override picks. `.is-primary`
   mirrors the D1 chip's success family (the resolved primary, whichever precedence set
   it); `.is-discard` quiets a rubric-disqualified chip without hiding it. */
.frames-look-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}
.frames-look-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px 10px;
    border-radius: var(--radius-full);
    border: 1px solid var(--color-border-default);
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
    font-size: var(--font-size-xs);
    cursor: pointer;
}
.frames-look-chip:hover { color: var(--color-text-primary); border-color: var(--color-text-muted); }
.frames-look-chip:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.frames-look-chip-rank { color: var(--color-text-muted); }
.frames-look-chip.is-primary {
    background: rgba(34, 197, 94, 0.12);
    border-color: rgba(34, 197, 94, 0.4);
    color: #86efac;
    font-weight: 600;
}
.frames-look-chip.is-discard { opacity: 0.62; }
.frames-look-chip-star { color: #facc15; flex-shrink: 0; }
.frames-look-chip-thumb {
    width: 16px;
    height: 16px;
    border-radius: 3px;
    object-fit: cover;
    flex-shrink: 0;
}

/* ============================================================================
   Cinematic Frames — Slate & Call Sheet redesign §2.2: THE SLATE.
   One seed surface (type / paste / drop). The hidden duration/pace selects are
   proxied by segmented chips; seeded-calm compresses the Slate to a strip while
   the LIVE #frames-concept textarea stays mounted and editable (§2.12 am. 5/6).
   Standalone rules (lesson #34).
   ============================================================================ */
.frames-slate { display: flex; flex-direction: column; gap: var(--space-3); }
.frames-slate-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-primary);
}
.frames-slate-head i { color: var(--color-accent); }
.frames-slate-head .frames-sources-card-hint { margin-left: auto; }
.frames-slate-expand { background: none; border: none; padding: 0; cursor: pointer; }
.frames-slate-expand:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.frames-slate.is-calm .frames-slate-expand .frames-bin-chevron { transform: rotate(-90deg); }

.frames-slate-format {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    flex-wrap: wrap;
}
.frames-seg-field { display: flex; align-items: center; gap: var(--space-2); }
.frames-seg-label { font-size: var(--font-size-xs); color: var(--color-text-muted); }
.frames-seg {
    display: inline-flex;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.frames-seg-chip {
    background: var(--color-bg-tertiary);
    border: none;
    padding: var(--space-1) var(--space-3);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    cursor: pointer;
}
.frames-seg-chip + .frames-seg-chip { border-left: 1px solid var(--color-border-default); }
.frames-seg-chip:hover { color: var(--color-text-primary); }
.frames-seg-chip.is-on { background: var(--color-accent); color: #fff; font-weight: 600; }
.frames-seg-chip:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

.frames-slate-footer {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}
.frames-slate-price { margin-left: auto; }

/* Seeded-calm: compress the seed input, tuck the intake rows (one chevron click back).
   height needs !important to beat the Tailwind h-24 utility (important:true build). */
.frames-slate.is-calm #frames-concept { height: 3.4em !important; min-height: 0; }
.frames-slate.is-calm .frames-slate-sources,
.frames-slate.is-calm .frames-slate-paste { display: none !important; }

/* Reads-as row (§2.2) — modality status chips + the one-shot paste-correction offer. */
.frames-slate-readsas {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}
.frames-readsas-chip {
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: 999px;
    padding: 2px var(--space-3);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    cursor: pointer;
}
.frames-readsas-chip:hover { color: var(--color-text-primary); }
.frames-readsas-chip.is-on { border-color: var(--color-accent); color: var(--color-accent); }
.frames-readsas-chip:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.frames-readsas-hint { font-size: var(--font-size-xs); color: var(--color-text-disabled); }
.frames-readsas-offer { border-color: var(--color-warning); color: var(--color-warning); }

/* Slate-wide PDF drop target highlight (§2.12 amendment 8). */
.frames-slate.is-dragover { outline: 2px dashed var(--color-accent); outline-offset: -2px; }

/* ============================================================================
   Cinematic Frames — Slate & Call Sheet redesign §2.4: the Call Sheet readout
   ("What we'll build") + the honest free-to-plan line. Standalone (lesson #34).
   ============================================================================ */
.frames-callsheet-readout {
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    margin-bottom: var(--space-3);
}
.frames-callsheet-eyebrow {
    font-size: var(--font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
    margin-bottom: var(--space-2);
}
.frames-callsheet-row {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-1) 0;
    background: none;
    border: none;
    text-align: left;
}
.frames-callsheet-key {
    flex-shrink: 0;
    width: 72px;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}
.frames-callsheet-val {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}
.frames-callsheet-format { cursor: pointer; }
.frames-callsheet-format:hover .frames-callsheet-val { color: var(--color-text-primary); }
.frames-callsheet-format:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.frames-callsheet-freeline {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    text-align: center;
    margin-top: var(--space-2);
}
/* Dock mode: the readout collapses — the bin summaries carry the same facts (§2.1). */
@media (max-width: 1359px) {
    .frames-callsheet-readout { display: none; }
    .frames-callsheet-freeline { flex: 1 1 100%; margin-top: 0; }
}

/* ============================================================================
   Cinematic Frames — Slate & Call Sheet redesign §2.6: MOTION.
   Fast, causal, skippable. Transitions ride STATE FLIPS only (calm/uncalm,
   dim/lit, promote/demote) — never innerHTML re-renders, so nothing flickers
   under per-keystroke repaints and no animation ever sits between the operator
   and their next click. Standalone rules (lesson #34).
   ============================================================================ */
.frames-bin { transition: opacity 200ms ease-out; }                  /* dim ⇄ lit light-up   */
.frames-slate #frames-concept { transition: height 200ms ease-out; } /* seeded-calm compress */
.frames-seg-chip,
.frames-readsas-chip { transition: color 150ms ease-out, border-color 150ms ease-out,
                                   background-color 150ms ease-out; }
#generate-frames-btn,
#generate-shotlist-btn,
#frames-bible-author-btn {          /* the one-filled-primary walk (§2.6 emphasis glow) */
    transition: opacity 200ms ease-out, background-color 200ms ease-out,
                box-shadow 200ms ease-out, color 200ms ease-out;
}
.frames-bin-summary,
.frames-callsheet-val { transition: color 150ms ease-out; }          /* dash→prose settle    */

@media (prefers-reduced-motion: reduce) {
    .frames-bin,
    .frames-slate #frames-concept,
    .frames-bin-head .frames-bin-chevron,
    .frames-slate-expand .frames-bin-chevron,
    .frames-seg-chip,
    .frames-readsas-chip,
    .frames-bin-summary,
    .frames-callsheet-val,
    #generate-frames-btn,
    #generate-shotlist-btn,
    #frames-bible-author-btn { transition: none !important; }
}

/* ============================================================================
   Cinematic Frames — Coverage plan-review STAGE panel (canvas redesign §4.3 M17).
   The de-modaled fragment root carries `.frames-stage-panel js-frames-stage-root
   frames-plan-review-root`; the `.frames-stage-actionbar` base landed in Task 4 (its 880px
   cap is Sources-scoped and does not reach this footer). This standalone rule (lesson #34)
   resets the modal chrome the inner `.frames-plan-panel` still inherits: its base (:9463)
   sets max-width:720px / max-height:85vh / transform:scale(0.96) that ONLY
   `.frames-plan-modal.open …` undid — with `.frames-plan-modal` gone the panel would sit
   shrunk + capped, so we lift the caps and clear the transform here. Two-class specificity
   beats the single-class base, so no !important is needed (Tailwind important:true only
   touches utility classes, never our component rules).
   ============================================================================ */
.frames-plan-review-root .frames-plan-panel {
    max-width: none;
    max-height: none;
    transform: none;
}

/* ============================================================================
   Cinematic Frames — review-bay width lift (canvas redesign §4.2 M14 / §5.6).
   Standalone rules (lesson #34): never appended into a grouped selector. The
   review bay fills the canvas — the max-w-4xl/max-w-2xl caps are lifted on the
   wrappers (they now carry .frames-bay-block instead of the cap utility) and the
   review stage takes the generous space-8 inset in place of the default
   .frames-stage space-6. Task 9's dead-CSS sweep MUST keep these.
   ============================================================================ */

/* §4.2 M14 — the review-bay wrappers span the full canvas width (cap lifted). A
   component class replaces the removed max-w-4xl/max-w-2xl utility, so no Tailwind
   rebuild is needed for the width lift itself. */
.frames-bay-block {
    width: 100%;
    max-width: none;
}

/* The Dailies/Clips review stage takes the §4.2 space-8 inset (one place — the
   wrapper carries the width, the stage carries the padding, no double padding). id
   specificity beats .frames-stage's space-6 regardless of source order. */
#frames-stage-review {
    padding: var(--space-8);
}

/* De-modaled (canvas redesign §4.3, M15–M17): the `.frames-plan-modal` overlay +
   `.frames-plan-modal-backdrop` + the `.open`/`.hidden` overlay toggles are RETIRED — the
   three former takeovers are in-canvas stages now (deck gate → Breakdown, bible editor →
   Bible, plan review → Coverage), each shown by toggling `.hidden` on a `.js-frames-stage-root`.
   `.frames-plan-panel` is KEPT: the deck-gate + plan-review panels still carry it. */
.frames-plan-panel {
    position: relative;
    width: 100%;
    max-width: 720px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    transform: scale(0.96) translateY(8px);
    transition: transform 220ms cubic-bezier(0.34, 1.4, 0.64, 1);
}

/* -------------------- Header -------------------- */
.frames-plan-header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-5) var(--space-6);
    border-bottom: 1px solid var(--color-border-default);
    background:
        radial-gradient(120% 140% at 0% 0%, rgba(255, 140, 0, 0.07) 0%, transparent 55%);
    /* The header is fixed chrome inside a column-flex panel: without these it gets
       CRUSHED and its subtitle visibly overflows onto the section rail below.
       flex-shrink alone is NOT enough — Chrome computes this row-flex container's
       intrinsic height from its basis-0 text block WITHOUT the subtitle line, so
       the auto flex-basis itself under-measures; max-content forces the true one. */
    flex-shrink: 0;
    min-height: max-content;
}

.frames-plan-header-text {
    flex: 1;
    min-width: 0;
}

.frames-plan-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    line-height: var(--line-height-tight);
}

.frames-plan-subtitle {
    margin-top: var(--space-1);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    line-height: var(--line-height-normal);
    max-width: 40ch;
}

/* In-canvas stage surfaces (bible editor + plan review): the header sits beside
   a 264px section rail and a chip strip, so a 40ch two-line subtitle reads as
   text bleeding into the frames around it. One line, ellipsized, full room. */
.frames-bible-editor .frames-plan-subtitle,
.frames-plan-review-root .frames-plan-subtitle {
    max-width: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Task D3 (C18 honesty surface) — the plan-review gate's LOOK badge, painted from the
   server-computed look_mode via the pure framesLookModeBadge() selector. Same success/
   warning token family as .frames-deck-style-chip (D1) so the two honesty surfaces read
   as one system: campaign (tone ok) = quiet success pill; prose/house-with-deck
   (tone warn) = the same amber-advisory language as the gate's other honesty banners.
   Hidden (no markup painted) for house-mode-with-no-routed-deck — nothing to flag. */
.frames-look-mode-badge {
    display: inline-block;
    margin-top: var(--space-1);
    font-size: var(--font-size-xs);
    font-weight: 400;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    white-space: normal;
}
.frames-look-mode-badge--ok {
    background: rgba(34, 197, 94, 0.1);
    border: 1px solid rgba(34, 197, 94, 0.3);
    color: #86efac;
}
.frames-look-mode-badge--warn {
    background: rgba(245, 158, 11, 0.1);
    border: 1px solid rgba(245, 158, 11, 0.35);
    color: #fbbf24;
}

/* Cost summary chip group (top-right) */
.frames-plan-cost-summary {
    display: flex;
    align-items: stretch;
    gap: var(--space-2);
    flex-shrink: 0;
}

.frames-cost-chip {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 58px;
    padding: var(--space-2) var(--space-3);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    text-align: center;
}

.frames-cost-chip-label {
    font-size: 10px;
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
    white-space: nowrap;
}

.frames-cost-chip-value {
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-bold);
    color: var(--color-text-primary);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.frames-cost-chip-unit {
    font-size: 11px;
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-muted);
    margin-left: 1px;
}

/* TOTAL chip — the prominent one (arcade-orange / teal accent) */
.frames-cost-chip--total {
    background: linear-gradient(135deg, rgba(255, 140, 0, 0.16) 0%, rgba(45, 212, 191, 0.14) 100%);
    border-color: var(--color-border-accent);
    box-shadow: inset 0 0 0 1px rgba(255, 140, 0, 0.06);
}

.frames-cost-chip--total .frames-cost-chip-label {
    color: var(--color-accent-light);
}

.frames-cost-chip--total .frames-cost-chip-value {
    color: var(--color-accent);
}

.frames-cost-chip--total .frames-cost-chip-unit {
    color: var(--color-accent-light);
}

.frames-plan-close {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin: -4px -4px 0 0;
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: all 120ms ease-out;
}

.frames-plan-close:hover {
    background: var(--color-bg-hover, var(--color-bg-tertiary));
    color: var(--color-text-primary);
}

/* -------------------- Body / DAG tree -------------------- */
.frames-plan-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--space-5) var(--space-6);
}

.frames-plan-tree {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

/* Scene grouping */
.frames-plan-scene {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.frames-plan-scene-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-bottom: var(--space-1);
}

.frames-plan-scene-head i,
.frames-plan-scene-head svg {
    color: var(--color-accent);
    flex-shrink: 0;
}

.frames-plan-scene-name {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-secondary);
    letter-spacing: 0.01em;
}

.frames-plan-scene-meta {
    margin-left: auto;
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-disabled);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* FINDING 4 — per-location grounding panel (top of the review tree).
   Spec §7 — the per-character Cast panel reuses the EXACT treatment: every `.frames-loc-*` rule below
   is extended with its `.frames-cast-*` sibling so Cast inherits the Apple/Netflix-grade panel with no
   new utilities. Cast sits ABOVE Locations and shares the single "Apply grounding" button. */
.frames-plan-grounding,
.frames-plan-cast {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3);
    margin-bottom: var(--space-3);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    background: var(--color-surface-2, rgba(255, 255, 255, 0.02));
}

.frames-loc-head,
.frames-cast-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-secondary);
}

.frames-loc-head i,
.frames-loc-head svg,
.frames-cast-head i,
.frames-cast-head svg {
    color: var(--color-accent);
    flex-shrink: 0;
}

.frames-loc-head small,
.frames-cast-head small {
    margin-left: auto;
    font-size: 11px;
    font-weight: var(--font-weight-normal);
    color: var(--color-text-disabled);
}

/* Spec 2B — establish-in-gate: the LOUD variant shown when the gate defaults to auto-creating every
   detected location (no Scene selected + a pristine multi-location script). Accent-tinted so the
   director can't miss that N locations will be established; the cost chip shows the price and one
   Apply confirms before any spend. */
.frames-plan-grounding--prominent {
    border-color: var(--color-accent, #ff7a1a);
    background: var(--color-accent-soft, rgba(255, 122, 26, 0.08));
}

.frames-plan-grounding--prominent .frames-loc-head {
    flex-wrap: wrap;
}

.frames-plan-grounding--prominent .frames-loc-head small {
    flex-basis: 100%;
    margin-left: 0;
    margin-top: 2px;
    font-size: 12px;
    color: var(--color-text-secondary);
}

.frames-plan-grounding--prominent .frames-loc-head small strong {
    color: var(--color-text-primary);
    font-weight: var(--font-weight-semibold);
}

/* P1c — self-contained panel: the rows scroll inside their own bounded region so the cost chip +
   Apply (the actions footer) stay reachable even on an 11-location plan (were below the modal fold). */
.frames-grounding-rows,
.frames-cast-rows {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    max-height: 320px;
    overflow-y: auto;
    padding: 2px;            /* breathing room so a focus ring isn't clipped by overflow */
    margin: 0 -2px;
}

.frames-loc-row,
.frames-plan-cast-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-md);
    transition: background 120ms ease;
}
.frames-loc-row:hover,
.frames-plan-cast-row:hover { background: rgba(255, 140, 0, 0.05); }

.frames-loc-name,
.frames-cast-name {
    flex: 1 1 0;
    min-width: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* At-a-glance state pill (✓ Matched / Custom / ✨ Auto-create / Prompt only) — visible without
   opening the dropdown; re-resolved on every select change. The frame-map checkpoint pills
   (`.frames-mapcheck-pill`, C4 T11) share the base treatment via this grouped selector (Lesson
   #20 — a NEW JS hook grouped into the shared family, never double-classed with `frames-loc-*`). */
.frames-loc-pill,
.frames-cast-pill,
.frames-mapcheck-pill {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    padding: 0 8px;
    font-size: 11px;
    font-weight: var(--font-weight-semibold);
    border-radius: var(--radius-full);
    border: 1px solid transparent;
    white-space: nowrap;
}
.frames-loc-pill i, .frames-loc-pill svg,
.frames-cast-pill i, .frames-cast-pill svg,
.frames-mapcheck-pill i, .frames-mapcheck-pill svg { width: 12px; height: 12px; flex-shrink: 0; }
.frames-loc-pill--matched,
.frames-cast-pill--matched {
    color: var(--color-success); background: var(--color-success-bg);
    border-color: var(--color-success-border); cursor: help;
}
.frames-loc-pill--custom,
.frames-cast-pill--custom {
    color: var(--color-info); background: var(--color-info-bg); border-color: var(--color-info-border);
}
/* Auto-create resting state — location "Auto-create" + CAST AUTO-CREATE "Auto-create". */
.frames-loc-pill--auto-create,
.frames-cast-pill--create {
    color: var(--color-accent-light); background: var(--color-accent-subtle);
    border-color: var(--color-border-accent); cursor: help;
}
/* Cast "Skip" mirrors the location "Prompt only" muted treatment (no plate / no identity bound). */
.frames-loc-pill--prompt-only,
.frames-cast-pill--skip {
    color: var(--color-text-muted); background: var(--color-bg-tertiary);
    border-color: var(--color-border-default);
}
/* P1d + CAST AUTO-CREATE — runtime auto-create states (driven by WS during /ground). */
.frames-loc-pill--creating,
.frames-cast-pill--creating {
    color: var(--color-accent-light); background: var(--color-accent-subtle);
    border-color: var(--color-border-accent);
}
.frames-loc-pill--created,
.frames-cast-pill--created {
    color: var(--color-success); background: var(--color-success-bg);
    border-color: var(--color-success-border);
}
.frames-loc-pill--failed,
.frames-cast-pill--failed {
    color: var(--color-error); background: var(--color-error-bg);
    border-color: var(--color-error-border);
}
/* tiny hero thumbnail shown on a created row during the run (loc) / a grounded cast row (cast).
   `.frames-cast-thumb` is grouped here so the Cast thumbnail keeps the treatment with ONLY its own
   class — after de-colliding it no longer co-carries `.frames-loc-thumb`. */
.frames-loc-thumb,
.frames-cast-thumb {
    flex-shrink: 0;
    width: 34px;
    height: 20px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border-default);
}

/* Styled native <select> — keeps native keyboard/mobile a11y; we restyle the trigger (custom chevron,
   token focus ring, full-width). The option list uses native rendering (most accessible). */
/* The frame-map checkpoint <select>s (`.frames-mapcheck-action` / `--target`, C4 T11) share the
   styled-native-select treatment via these grouped selectors (Lesson #20); their compact sizing
   is overridden in the `.frames-mapcheck-*` block below. */
.frames-loc-select,
.frames-cast-select,
.frames-mapcheck-action,
.frames-mapcheck-target {
    flex: 1 1 42%;
    min-width: 150px;
    max-width: 280px;
    appearance: none;
    -webkit-appearance: none;
    padding: 7px 30px 7px 10px;
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    background-color: var(--color-bg-tertiary);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 14px;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 120ms ease;
}
.frames-loc-select:hover,
.frames-cast-select:hover,
.frames-mapcheck-action:hover,
.frames-mapcheck-target:hover { border-color: var(--color-border-strong); }
.frames-loc-select:focus-visible,
.frames-cast-select:focus-visible,
.frames-mapcheck-action:focus-visible,
.frames-mapcheck-target:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-color: var(--color-border-active);
}
/* On the accent-tinted --prominent panel, the default subtle border is invisible — strengthen it. */
.frames-plan-grounding--prominent .frames-loc-select { border-color: var(--color-border-strong); }
/* Cast <optgroup> headers (People / Subjects) — native rendering varies; set what's themeable so the
   dropdown reads cleanly on the dark surface where the platform honors it. */
.frames-cast-select optgroup {
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-secondary);
    background-color: var(--color-bg-tertiary);
}
.frames-cast-select option {
    color: var(--color-text-primary);
    background-color: var(--color-bg-tertiary);
}

/* Pinned actions footer (lives below the scrolling rows, always visible). */
.frames-loc-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    margin-top: var(--space-2);
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border-subtle);
}

/* Prominent cost chip (orange/teal) — money reads as money; replaces the 11px disabled text that
   failed WCAG AA (~2.1:1) on the tinted panel. Hidden until something is being auto-created. */
.frames-loc-cost {
    display: none;
    align-items: center;
    gap: var(--space-1);
    margin-right: auto;
    padding: var(--space-1) var(--space-3);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    font-variant-numeric: tabular-nums;
    color: var(--color-accent);
    background: linear-gradient(135deg, rgba(255, 140, 0, 0.16) 0%, rgba(45, 212, 191, 0.14) 100%);
    border: 1px solid var(--color-border-accent);
    border-radius: var(--radius-lg);
}
.frames-loc-cost--active { display: inline-flex; }
.frames-loc-cost i, .frames-loc-cost svg { color: var(--color-accent-light); }

.frames-loc-ground-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 7px 16px;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: #fff;
    background: var(--color-accent);
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-accent);
    cursor: pointer;
    transition: background 0.15s ease;
}
.frames-loc-ground-btn i, .frames-loc-ground-btn svg { width: 16px; height: 16px; }
.frames-loc-ground-btn:hover:not(:disabled) { background: var(--color-accent-hover); }
.frames-loc-ground-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.frames-loc-ground-btn:disabled { opacity: 0.6; cursor: default; box-shadow: none; }

/* Staggered reveal on open (gated). */
@media (prefers-reduced-motion: no-preference) {
    .frames-loc-row,
    .frames-plan-cast-row { animation: framesLocReveal 0.3s cubic-bezier(0.34, 1.4, 0.64, 1) backwards; }
    .frames-loc-row:nth-child(1),
    .frames-plan-cast-row:nth-child(1) { animation-delay: 0ms; }
    .frames-loc-row:nth-child(2),
    .frames-plan-cast-row:nth-child(2) { animation-delay: 40ms; }
    .frames-loc-row:nth-child(3),
    .frames-plan-cast-row:nth-child(3) { animation-delay: 80ms; }
    .frames-loc-row:nth-child(4),
    .frames-plan-cast-row:nth-child(4) { animation-delay: 120ms; }
    .frames-loc-row:nth-child(5),
    .frames-plan-cast-row:nth-child(5) { animation-delay: 160ms; }
    .frames-loc-row:nth-child(n+6),
    .frames-plan-cast-row:nth-child(n+6) { animation-delay: 200ms; }
}
@keyframes framesLocReveal {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: none; }
}

/* Responsive: on a narrow modal the row wraps — name on its own line, pill + select below. */
@media (max-width: 520px) {
    .frames-loc-row,
    .frames-plan-cast-row { flex-wrap: wrap; }
    .frames-loc-name,
    .frames-cast-name { flex-basis: 100%; }
    .frames-loc-select,
    .frames-cast-select { flex: 1 1 auto; max-width: none; }
}

/* Coverage cluster — visually groups a master + its derived children */
.frames-plan-cluster {
    position: relative;
    padding: var(--space-3);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    background: rgba(15, 23, 42, 0.4);
}

.frames-plan-cluster-label {
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-disabled);
    margin-bottom: var(--space-2);
    padding-left: var(--space-1);
}

/* Node row (master / derived / look-only share this base) */
.frames-plan-node {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    transition: border-color 120ms ease, background 120ms ease;
}

.frames-plan-node:hover {
    border-color: var(--color-border-strong);
}

.frames-plan-node-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.frames-plan-node-text {
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    line-height: var(--line-height-normal);
}

.frames-plan-node-badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.frames-plan-node-aside {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}

/* Master gets a subtle gold edge to read as the anchor of the cluster */
.frames-plan-node--master {
    border-color: rgba(245, 200, 92, 0.4);
    background: linear-gradient(180deg, rgba(245, 200, 92, 0.07) 0%, var(--color-bg-secondary) 60%);
}

.frames-plan-node--master:hover {
    border-color: rgba(245, 200, 92, 0.6);
}

/* Look-only reads muted — it's atmosphere, not coverage */
.frames-plan-node--look {
    border-style: dashed;
    background: rgba(30, 41, 59, 0.45);
}

/* Derived children: nested + connector rail */
.frames-plan-derived-group {
    position: relative;
    margin-top: var(--space-2);
    margin-left: var(--space-4);
    padding-left: var(--space-5);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* Vertical connector rail running down the left of the derived group */
.frames-plan-derived-group::before {
    content: "";
    position: absolute;
    left: 0;
    top: calc(-1 * var(--space-2));
    bottom: calc(var(--space-3) + 11px);
    width: 1.5px;
    background: linear-gradient(180deg, rgba(255, 140, 0, 0.5) 0%, var(--color-border-strong) 100%);
    border-radius: var(--radius-full);
}

/* Each derived row gets an elbow connector tying it to the rail */
.frames-plan-derived-group .frames-plan-node {
    position: relative;
}

.frames-plan-derived-group .frames-plan-node::before {
    content: "";
    position: absolute;
    left: calc(-1 * var(--space-5));
    top: calc(var(--space-3) + 10px);
    width: var(--space-4);
    height: 1.5px;
    background: var(--color-border-strong);
    border-radius: var(--radius-full);
}

/* -------------------- Badges & pills -------------------- */

/* Shot-size badge (WIDE / MEDIUM / MCU / ECU …) — neutral, mono, technical */
.frames-size-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px var(--space-2);
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: var(--font-weight-bold);
    letter-spacing: 0.06em;
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

/* Role badge — base */
.frames-role-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px var(--space-2);
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-radius: var(--radius-full);
    white-space: nowrap;
}

.frames-role-badge i,
.frames-role-badge svg {
    flex-shrink: 0;
}

/* MASTER — gold */
.frames-role-badge--master {
    color: #f5c85c;
    background: rgba(245, 200, 92, 0.14);
    border: 1px solid rgba(245, 200, 92, 0.35);
}

/* DERIVED — accent (arcade-orange) */
.frames-role-badge--derived {
    color: var(--color-accent);
    background: var(--color-accent-subtle);
    border: 1px solid var(--color-border-accent);
}

/* LOOK-ONLY — muted */
.frames-role-badge--look {
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.1);
    border: 1px solid var(--color-border-strong);
}

/* Derivation-method tag (reframe / insert) — quiet, teal-tinted */
.frames-method-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px var(--space-2);
    font-size: 10px;
    font-weight: var(--font-weight-medium);
    letter-spacing: 0.03em;
    color: var(--arcade-teal, #2dd4bf);
    background: rgba(45, 212, 191, 0.1);
    border: 1px solid rgba(45, 212, 191, 0.25);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

.frames-method-badge i,
.frames-method-badge svg {
    flex-shrink: 0;
}

/* Board-binding badge (seams-3) — a node bound to a storyboard panel. Indigo-tinted to read as
   "from the board", distinct from the gold master / teal method badges; surfaces a positional
   misbind at the pre-spend money gate. Dark aesthetic, mirrors the .frames-method-badge shape. */
.frames-board-node-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px var(--space-2);
    font-size: 10px;
    font-weight: var(--font-weight-medium);
    letter-spacing: 0.03em;
    color: #a5b4fc;
    background: rgba(129, 140, 248, 0.12);
    border: 1px solid rgba(129, 140, 248, 0.30);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

.frames-board-node-badge i,
.frames-board-node-badge svg {
    flex-shrink: 0;
}

/* Plan-time empty-start advisory chip (T2.3) — reuses the .frames-board-node-badge shape, re-tinted
   slate/muted so it reads as an advisory next to the indigo board badge. */
.frames-empty-start-badge {
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.12);
    border-color: rgba(148, 163, 184, 0.30);
}

/* Per-node estimated-cost pill */
.frames-cost-pill {
    display: inline-flex;
    align-items: center;
    padding: 2px var(--space-2);
    font-size: 11px;
    font-weight: var(--font-weight-bold);
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Per-node kebab (inert until Task 11) */
.frames-node-menu {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: all 120ms ease-out;
}

.frames-node-menu:hover {
    background: var(--color-bg-tertiary);
    color: var(--color-text-primary);
}

/* Restore affordance on a dropped row (kebab slot becomes a "bring back"). */
.frames-node-restore {
    color: var(--color-accent);
}

.frames-node-restore:hover {
    background: rgba(245, 160, 60, 0.12);
    color: var(--color-accent);
}

/* -------------------- Dropped node row -------------------- */
/* A dropped shot reads as removed-but-recoverable: struck text, dimmed,
   no master/derived emphasis. It sits at the bottom of its scene. */
.frames-plan-node--dropped {
    opacity: 0.55;
    border-style: dashed;
    border-color: var(--color-border-default);
    background: var(--color-bg-tertiary);
}

.frames-plan-node--dropped .frames-plan-node-text {
    text-decoration: line-through;
    color: var(--color-text-muted);
}

.frames-plan-node--dropped:hover {
    opacity: 0.75;
    border-color: var(--color-border-strong);
}

.frames-dropped-tag {
    display: inline-flex;
    align-items: center;
    padding: 2px var(--space-2);
    font-size: 10px;
    font-weight: var(--font-weight-bold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.12);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}

/* -------------------- Per-node edit popover (Task 11) -------------------- */
/* Body-mounted, fixed-positioned in JS so the modal's scroll never clips it.
   Chrome matches the suite's kebab menus (dark surface, soft shadow). */
/* The zoned-toolbar overflow popover (design §7) shares this surface look via a GROUPED
   selector — never by borrowing the .frames-node-popover class (which is a JS query hook;
   Lesson #20). Its positioning (absolute, anchored to the ⋯ button) is overridden below. */
.frames-node-popover,
.frames-toolbar-popover {
    position: fixed;
    z-index: var(--z-popover);  /* 250 — below the overlay/modal band (300/400) and toasts (700) */
    width: 248px;
    max-width: calc(100vw - 16px);
    padding: var(--space-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    animation: framesMenuIn 120ms ease-out;
}

@keyframes framesMenuIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.frames-menu-head {
    padding: var(--space-1) var(--space-2) var(--space-1);
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-text-disabled);
}

/* A labelled control row (shot size / parent / scene selects). */
.frames-menu-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--space-1) var(--space-2);
}

.frames-menu-label {
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
}

/* Reuse .form-select for the field chrome; tighten it for the popover. */
.frames-menu-select.form-select {
    padding: 6px var(--space-3);
    padding-right: 30px;
    font-size: var(--font-size-sm);
    background-color: var(--color-bg-primary);
}

.frames-menu-divider {
    height: 1px;
    margin: var(--space-1) var(--space-2);
    background: var(--color-border-subtle);
}

/* Action items (toggle people-free / drop). */
.frames-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2);
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    text-align: left;
    cursor: pointer;
    transition: background 100ms ease, color 100ms ease;
}

.frames-menu-item i,
.frames-menu-item svg {
    flex-shrink: 0;
    color: var(--color-text-muted);
}

.frames-menu-item:hover {
    background: rgba(255, 255, 255, 0.05);
    color: var(--color-text-primary);
}

.frames-menu-item:hover i,
.frames-menu-item:hover svg {
    color: var(--color-text-primary);
}

.frames-menu-item--danger {
    color: #f87171;
}

.frames-menu-item--danger i,
.frames-menu-item--danger svg {
    color: #f87171;
}

.frames-menu-item--danger:hover {
    background: rgba(239, 68, 68, 0.12);
    color: #fca5a5;
}

.frames-menu-item--danger:hover i,
.frames-menu-item--danger:hover svg {
    color: #fca5a5;
}

/* Stacked action row — a primary label over a muted advisory sub-line (auto empty-start toggle,
   T2.3). The icon sits top-aligned against the two-line text block. */
.frames-menu-item--stacked {
    align-items: flex-start;
}

.frames-menu-item-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.frames-menu-item-sub {
    font-size: 10px;
    font-weight: var(--font-weight-normal);
    color: var(--color-text-muted);
    line-height: 1.3;
    white-space: normal;
}

/* -------------------- In-flight PATCH + error states -------------------- */
/* While an edit PATCH is in flight, dim + lock the panel so a director can't
   stack a second structural edit before the authoritative recompute lands. */
.frames-plan-panel--busy {
    pointer-events: none;
}

.frames-plan-panel--busy::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(8, 12, 22, 0.18);
    border-radius: inherit;
    pointer-events: none;
}

/* Inline error fallback in the footer (used only when no toast host exists). */
.frames-plan-footer-note--error {
    color: #f87171;
}

.frames-plan-footer-note--error i,
.frames-plan-footer-note--error svg {
    color: #f87171;
}

.frames-plan-error-text {
    color: #f87171;
}

/* -------------------- Footer -------------------- */
.frames-plan-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--color-border-default);
    background: rgba(15, 23, 42, 0.5);
    flex-shrink: 0;   /* fixed chrome — same crush-guard as .frames-plan-header */
}

.frames-plan-footer-note {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    min-width: 0;
}

.frames-plan-footer-note i,
.frames-plan-footer-note svg {
    flex-shrink: 0;
    color: var(--color-text-disabled);
}

.frames-plan-footer-actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-shrink: 0;
    /* FW-6: at MAX panel width the action cluster's natural width can exceed the space the
       footer note leaves it — wrap the buttons onto a second row instead of clipping. */
    flex-wrap: wrap;
    row-gap: var(--space-2);
    min-width: 0;
}

/* Mandate C — bible-editor footer grouping. A left lead group holds a de-emphasized
   Close (a dismiss) beside the note; a hairline in the right cluster separates the
   "branch" pair from the "commit" pair. Additive classes only — the shared
   .frames-plan-footer chrome (used by the coverage-plan gate too) is untouched. */
.frames-plan-footer-lead {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}
.frames-plan-footer .is-quiet {
    flex-shrink: 0;
    background: none;
    border: none;
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    cursor: pointer;
    border-radius: var(--radius-md);
    transition: color var(--transition-fast), background var(--transition-fast);
}
.frames-plan-footer .is-quiet:hover {
    color: var(--color-text-primary);
    background: var(--color-bg-tertiary);
}
.frames-plan-footer-sep {
    flex-shrink: 0;
    width: 1px;
    align-self: stretch;
    margin: var(--space-1) var(--space-1);
    background: var(--color-border-default);
}

/* C4 lg7 — bible-editor footer geometry. This footer carries SEVEN actions + a
   two-line hint, far more than the shared coverage-plan footer whose chrome it
   borrows. At the panel's max width (min(1080px, 94vw)) the action cluster's
   natural width (~1300px) overran the panel and, because .frames-plan-footer-actions
   is flex-shrink:0, its own flex-wrap never engaged — the rightmost buttons
   (Finalize / Generate) were clipped by the panel's overflow:hidden and the hint
   was squeezed to one word per line. Scope the fix to the bible variant so the
   shared .frames-plan-footer chrome (the coverage-plan gate) is untouched: let the
   FOOTER wrap, drop the action cluster onto its own full-width row where its
   buttons wrap cleanly, and give the hint the row above at a readable width. */
.frames-bible-editor-footer {
    flex-wrap: wrap;
    row-gap: var(--space-3);
}
.frames-bible-editor-footer .frames-plan-footer-lead {
    flex: 1 1 auto;
    min-width: 0;          /* hint takes the full top row → reads on 1–2 lines, never 1 word/line */
}
.frames-bible-editor-footer .frames-plan-footer-actions {
    flex: 1 1 100%;        /* own the full second row (was flex-shrink:0 → overflowed + clipped) */
    justify-content: flex-end;   /* Generate stays the bottom-right terminal CTA */
    min-width: 0;
}
.frames-bible-editor-footer .frames-plan-footer-actions > button {
    flex: 0 0 auto;        /* never shrink a button into a two-line label */
    white-space: nowrap;
}

/* Responsive: stack the cost summary under the title on narrow viewports */
@media (max-width: 640px) {
    .frames-plan-header {
        flex-wrap: wrap;
    }
    .frames-plan-cost-summary {
        order: 3;
        width: 100%;
        flex-wrap: wrap;
    }
    .frames-cost-chip {
        flex: 1;
        min-width: 0;
    }
}

/* ============================================================================
   Results grid cell (batch + reference-anchored VLM-select)
   The grid is a clean uniform 16:9 gallery — each cell wraps ONLY the
   `.frames-result-card` (multi-candidate cards carry an overlay alternates
   badge). Candidate review lives in the lightbox filmstrip, not the grid.
   ============================================================================ */
.frames-result-cell {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    position: relative;
}

/* Busy state during a re-roll (PAID corrective batch). */
.frames-result-cell--busy {
    pointer-events: none;
}
.frames-result-cell--busy::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(8, 12, 22, 0.45);
    border-radius: var(--radius-lg);
    pointer-events: none;
}

/* Spec 1 — pending skeleton cell for a not-yet-streamed frame. During a live run `state.results` is a
   DENSE array (one entry per node); an entry with no signed_url renders this shimmer so a mid-run
   back-to-grid shows in-flight shots as skeletons next to the finished cards (instead of dropping
   them). Self-sized to the 16:9 grid cell since it has no <img>. */
.frames-result-card--pending {
    position: relative;
    width: 100%;
    aspect-ratio: var(--frames-cell-aspect, 16 / 9);   /* P1a — match the plan AR + the real card */
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: linear-gradient(90deg,
        var(--color-bg-secondary) 0%,
        var(--color-bg-tertiary) 50%,
        var(--color-bg-secondary) 100%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s infinite;
}

/* Higher specificity (.card--pending .overlay--pending = 0,2,0) so this beats the generic
   `.frames-result-overlay` hover layer (0,1,0, defined LATER in this file — the migrated
   result-card block near the end) — which otherwise leaks opacity:0 + inset:0 onto the
   pending overlay, hiding the status/label and filling the card. */
.frames-result-card--pending .frames-result-overlay--pending {
    position: absolute;
    inset: auto 0 0 0;          /* bottom-anchored, NOT full-card */
    opacity: 1;                 /* always shown (the generic overlay is an opacity:0 hover layer) */
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-2);
    background: linear-gradient(to top, rgba(8, 12, 22, 0.55), transparent);
    pointer-events: none;
}

/* P1b — in-flight status on a takeover-rendered pending cell (e.g. "Candidate 2/4…"), so it isn't
   dead shimmer. A tiny pulsing dot signals motion; the candidate text comes from state.cellProgress. */
.frames-result-status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.frames-result-status::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: var(--radius-full);
    background: var(--color-accent);
    animation: framesStatusPulse 1.2s ease-in-out infinite;
}
@keyframes framesStatusPulse {
    0%, 100% { opacity: 0.35; transform: scale(0.8); }
    50% { opacity: 1; transform: scale(1.15); }
}

/* P1b — crossfade a freshly-streamed frame in when the results grid (not the gen-card path) is the
   live surface after a mid-run takeover. Applied to ONLY the just-arrived card (one-shot class). */
.frames-result-card--just-in img {
    animation: genCardReveal 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

@media (prefers-reduced-motion: reduce) {
    .frames-result-card--pending { animation: none; }
    .frames-result-status::before { animation: none; opacity: 1; }
    .frames-result-card--just-in img { animation: none; }
}

/* P1a — the live streaming gen-cards inside the Frames grid share the plan AR too (their GLOBAL
   defaults are square skeleton / auto complete, which would jump on swap). Scoped to the Frames
   grid by id so gen-cards on other tabs (Image Gen, Video, …) keep their own sizing. */
#frames-results-grid .gen-card--skeleton,
#frames-results-grid .gen-card--generating,
#frames-results-grid .gen-card--complete,
#frames-results-grid .gen-card--error {
    aspect-ratio: var(--frames-cell-aspect, 16 / 9);
}

/* ============================================================================
 * Candidate review — clean grid + lightbox filmstrip
 * ----------------------------------------------------------------------------
 * The grid is a uniform 16:9 gallery; multi-candidate cards carry an absolutely-
 * positioned "alternates" badge (never affects cell height). The focused review
 * — status dots, notes, scores-on-hover, override + re-roll — lives in the
 * lightbox as a single non-wrapping horizontal filmstrip.
 * ========================================================================== */

/* --- Grid alternates badge (overlay on .frames-result-card) ----------------- */
.frames-alt-badge {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 22px;
    padding: 0 8px 0 7px;
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
    background: rgba(8, 12, 22, 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--radius-full, 9999px);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    pointer-events: none;
    transition: background 160ms ease-out, border-color 160ms ease-out;
}
.frames-result-card:hover .frames-alt-badge {
    background: rgba(255, 140, 0, 0.92);
    border-color: rgba(255, 255, 255, 0.28);
}
.frames-alt-badge i,
.frames-alt-badge svg {
    width: 12px;
    height: 12px;
    opacity: 0.92;
}

/* --- Lightbox filmstrip wrapper --------------------------------------------- */
.frames-expanded-candidates {
    margin-top: var(--space-5);
}
.frames-result-cell--expanded {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
}

/* Minimal "{N} options" header — no policy jargon, no "X of Y". */
.frames-options-header {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.frames-options-count {
    font-size: 13px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.01em;
    color: var(--color-text-primary, #f1f5f9);
}
.frames-options-hint {
    font-size: 12px;
    color: var(--color-text-muted, #94a3b8);
}

/* The filmstrip: a SINGLE non-wrapping row — overflow-x scroll, centered. This
 * is what keeps candidates from ever affecting layout / cell height. */
.frames-filmstrip {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-1) var(--space-1) var(--space-3);
    overflow-x: auto;
    overflow-y: hidden;
    flex-wrap: nowrap;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}
.frames-filmstrip::-webkit-scrollbar {
    height: 8px;
}
.frames-filmstrip::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
    border-radius: var(--radius-full, 9999px);
}
.frames-filmstrip::-webkit-scrollbar-track {
    background: transparent;
}

/* Individual candidate tile: thumb + caption (status dot + note). */
.frames-filmstrip-tile {
    flex: 0 0 auto;
    width: 128px;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: 0;
    background: transparent;
    border: none;
    cursor: pointer;
    text-align: left;
    border-radius: var(--radius-md, 8px);
    transition: transform 140ms ease-out;
}
.frames-filmstrip-tile:hover {
    transform: translateY(-2px);
}
.frames-filmstrip-tile:focus-visible {
    outline: 2px solid var(--color-arcade-orange, #ff8c00);
    outline-offset: 3px;
}

.frames-filmstrip-thumb {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius-md, 8px);
    background: var(--color-bg-tertiary, #334155);
    border: 2px solid transparent;
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    transition: border-color 140ms ease-out, box-shadow 140ms ease-out;
}
.frames-filmstrip-tile:hover .frames-filmstrip-thumb {
    border-color: var(--color-border-strong, rgba(255, 255, 255, 0.2));
}
.frames-filmstrip-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Selected tile: orange ring + a ✓ corner badge. */
.frames-filmstrip-tile--selected .frames-filmstrip-thumb {
    border-color: var(--color-arcade-orange, #ff8c00);
    box-shadow: 0 0 0 1px var(--color-arcade-orange, #ff8c00),
                var(--shadow-accent, 0 4px 20px rgba(255, 140, 0, 0.25));
}
.frames-filmstrip-tile--selected:hover .frames-filmstrip-thumb {
    border-color: var(--color-arcade-orange, #ff8c00);
}
.frames-filmstrip-check {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    background: var(--color-arcade-orange, #ff8c00);
    border-radius: var(--radius-full, 9999px);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
}
.frames-filmstrip-check i,
.frames-filmstrip-check svg {
    width: 12px;
    height: 12px;
    stroke-width: 3;
}

/* Failed candidate: muted, de-emphasised (still clickable, but visibly weaker). */
.frames-filmstrip-tile--failed {
    opacity: 0.5;
    filter: grayscale(0.35);
}
.frames-filmstrip-tile--failed:hover {
    opacity: 0.7;
    transform: none;
}

/* Caption row: status dot + human note. */
.frames-filmstrip-caption {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 2px;
    min-height: 16px;
}
.frames-status-dot {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full, 9999px);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.04);
}
.frames-status-dot--clean {
    background: var(--color-success, #10b981);
    box-shadow: 0 0 0 3px var(--color-success-bg, rgba(16, 185, 129, 0.1));
}
.frames-status-dot--issue {
    background: var(--color-warning, #f59e0b);
    box-shadow: 0 0 0 3px var(--color-warning-bg, rgba(245, 158, 11, 0.1));
}
.frames-filmstrip-note {
    font-size: 11px;
    line-height: 1.35;
    color: var(--color-text-muted, #94a3b8);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.frames-filmstrip-tile--selected .frames-filmstrip-note {
    color: var(--color-text-secondary, #cbd5e1);
}

/* Re-roll (PAID corrective batch) — prominent at the end of the filmstrip. */
.frames-rebatch-btn {
    flex: 0 0 auto;
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: 36px;
    padding: 0 var(--space-4);
    font-size: 13px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-tertiary, #334155);
    border: 1px solid var(--color-border-default, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    white-space: nowrap;
    transition: background 140ms ease-out, border-color 140ms ease-out, box-shadow 140ms ease-out;
}
.frames-rebatch-btn:hover {
    background: var(--color-bg-secondary, #1e293b);
    border-color: var(--color-arcade-orange, #ff8c00);
    box-shadow: var(--shadow-accent, 0 4px 20px rgba(255, 140, 0, 0.25));
}
.frames-rebatch-btn i,
.frames-rebatch-btn svg {
    flex-shrink: 0;
    color: var(--color-arcade-orange, #ff8c00);
}

/* Spinner while a re-roll is in flight. */
.frames-rebatch-btn--busy {
    pointer-events: none;
    opacity: 0.7;
}
.frames-rebatch-btn--busy i,
.frames-rebatch-btn--busy svg {
    animation: framesRebatchSpin 800ms linear infinite;
}

@keyframes framesRebatchSpin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* --- Director iteration loop (3c.1 B): lock + stale badges, lock + re-derive buttons ------- */
.frames-lock-badge,
.frames-stale-badge {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--radius-full, 9999px);
    border: 1px solid rgba(255, 255, 255, 0.16);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    pointer-events: none;
}
.frames-lock-badge {
    color: #fff;
    background: rgba(255, 140, 0, 0.92);     /* arcade-orange = locked / kept */
}
.frames-stale-badge {
    color: #0b0f1a;
    background: rgba(250, 204, 21, 0.92);    /* amber = needs attention (master changed) */
}
/* When both show, stack the stale badge under the lock badge. */
.frames-lock-badge + .frames-stale-badge {
    top: calc(var(--space-2) + 26px);
}
.frames-lock-badge i, .frames-lock-badge svg,
.frames-stale-badge i, .frames-stale-badge svg { width: 12px; height: 12px; }

/* 3c.2 C: reverse-angle (side B of the 180° line) marker. Top-LEFT so it never collides with the
   lock/stale badges (top-right). A small pill, not an icon, so it reads "REV" at a glance. */
.frames-rev-badge {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 6px;
    height: 18px;
    border-radius: var(--radius-full, 9999px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: #e6f6ff;
    background: rgba(14, 116, 144, 0.92);    /* teal = reverse / opposite side of the line */
    pointer-events: none;
}

/* 3c.2 C thread-3: a reused scene viewpoint (free establishing). Same chrome as the REV badge,
   distinct emerald tint (a REUSE node is people-free look-only and a REV node is a side-B master,
   so they're mutually exclusive in practice — both sit top-left). */
.frames-reuse-badge {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 6px;
    height: 18px;
    border-radius: var(--radius-full, 9999px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: #eafff4;
    background: rgba(5, 150, 105, 0.92);    /* emerald = free / reused asset */
    pointer-events: none;
}

/* A non-A people-free look-only wide CAN be both a reused viewpoint AND tagged a position (POS) — they
   both sit top-left, so stack the REUSE badge below the POS/REV badge instead of overlapping it
   (18px badge height + ~6px gap). _buildLockStaleBadges emits .frames-rev-badge before .frames-reuse-badge. */
.frames-rev-badge + .frames-reuse-badge {
    top: calc(var(--space-2) + 24px);
}

/* Lock + re-derive buttons share the rebatch-btn chrome. */
.frames-lock-btn,
.frames-rederive-btn {
    flex: 0 0 auto;
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: 36px;
    padding: 0 var(--space-4);
    font-size: 13px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-tertiary, #334155);
    border: 1px solid var(--color-border-default, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    white-space: nowrap;
    transition: background 140ms ease-out, border-color 140ms ease-out, box-shadow 140ms ease-out;
}
.frames-lock-btn:hover,
.frames-rederive-btn:hover {
    background: var(--color-bg-secondary, #1e293b);
    border-color: var(--color-arcade-orange, #ff8c00);
    box-shadow: var(--shadow-accent, 0 4px 20px rgba(255, 140, 0, 0.25));
}
.frames-lock-btn i, .frames-lock-btn svg,
.frames-rederive-btn i, .frames-rederive-btn svg {
    flex-shrink: 0;
    color: var(--color-arcade-orange, #ff8c00);
}
/* Locked state: filled accent so the lock reads as ON. */
.frames-lock-btn--on {
    background: rgba(255, 140, 0, 0.16);
    border-color: var(--color-arcade-orange, #ff8c00);
}
/* Grid-overlay lock button in the ON (locked) state. */
.frames-result-action--on {
    color: var(--color-arcade-orange, #ff8c00);
}
.frames-result-action--on i,
.frames-result-action--on svg {
    color: var(--color-arcade-orange, #ff8c00);
}
/* A LOCKED-but-stale badge reads as informational (muted), not action-needed. */
.frames-stale-badge--locked {
    opacity: 0.6;
}

/* ===========================================================================
   F2 — re-roll on EVERY frame: two-mode menu, NEW badge, single-candidate bar
   =========================================================================== */

/* Generic busy spinner for any re-roll affordance (grid overlay / expanded action). */
.frames-reroll-busy {
    pointer-events: none;
    opacity: 0.7;
}
.frames-reroll-busy i,
.frames-reroll-busy svg {
    animation: framesRebatchSpin 800ms linear infinite;
}

/* Candidates added by a re-roll get a small NEW pill (top-left of the thumb, clear of the ✓). */
.frames-new-badge {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 2;
    padding: 0 6px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-full, 9999px);
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.06em;
    color: #0b0f1a;
    background: rgba(250, 204, 21, 0.95);   /* amber = new / fresh */
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    pointer-events: none;
}
.frames-filmstrip-tile--new .frames-filmstrip-thumb {
    border-color: rgba(250, 204, 21, 0.6);
}

/* T0.3 (temporal-shift): candidates added by a Shift Start get a small T0 pill — mirrors the
   re-roll NEW pill, sky-toned to read as "temporal / t0". from_shift is never from_reroll, so the
   two pills never occupy the same tile. */
.frames-t0-badge {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 2;
    padding: 0 6px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-full, 9999px);
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.06em;
    color: #f8fafc;
    background: rgba(56, 189, 248, 0.95);   /* sky = temporal / t0 */
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    pointer-events: none;
}
.frames-filmstrip-tile--t0 .frames-filmstrip-thumb {
    border-color: rgba(56, 189, 248, 0.6);
}

/* Single-candidate (early-accepted) expanded view: a slim re-roll/lock bar (no filmstrip yet). */
.frames-filmstrip--bar {
    align-items: center;
}
.frames-reroll-hint {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 12px;
    color: var(--color-text-tertiary, #94a3b8);
}

/* The two-mode re-roll popover (body-mounted; positioned inline via JS). */
.frames-reroll-menu {
    position: fixed;
    z-index: 10050;
    width: 268px;
    padding: var(--space-2);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    background: var(--color-bg-secondary, #1e293b);
    border: 1px solid var(--color-border-strong, rgba(255, 255, 255, 0.16));
    border-radius: var(--radius-lg, 12px);
    box-shadow: var(--shadow-xl, 0 18px 50px rgba(0, 0, 0, 0.55));
    transform-origin: top center;
    animation: framesRerollMenuIn 160ms cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes framesRerollMenuIn {
    from { opacity: 0; transform: translateY(-6px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.frames-reroll-opt {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    text-align: left;
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-tertiary, #334155);
    border: 1px solid var(--color-border-default, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    transition: background 120ms ease-out, border-color 120ms ease-out;
}
.frames-reroll-opt:hover {
    background: var(--color-bg-primary, #0f172a);
    border-color: var(--color-arcade-orange, #ff8c00);
}
.frames-reroll-opt i,
.frames-reroll-opt svg {
    flex: 0 0 auto;
    color: var(--color-arcade-orange, #ff8c00);
}
.frames-reroll-opt-text {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.frames-reroll-opt-text strong { font-size: 13px; font-weight: 600; }
.frames-reroll-opt-text small { font-size: 11px; color: var(--color-text-tertiary, #94a3b8); }
.frames-reroll-opt--primary {
    justify-content: center;
    background: rgba(255, 140, 0, 0.16);
    border-color: var(--color-arcade-orange, #ff8c00);
    font-size: 13px;
    font-weight: 600;
}
.frames-reroll-opt--primary:hover {
    background: rgba(255, 140, 0, 0.26);
}
.frames-reroll-sep {
    height: 1px;
    margin: var(--space-1) 0;
    background: var(--color-border-default, rgba(255, 255, 255, 0.1));
}
.frames-reroll-guide {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.frames-reroll-guide-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-tertiary, #94a3b8);
}
.frames-reroll-note {
    width: 100%;
    resize: vertical;
    min-height: 48px;
    padding: var(--space-2);
    font-size: 13px;
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-primary, #0f172a);
    border: 1px solid var(--color-border-default, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-md, 8px);
}
.frames-reroll-note:focus {
    outline: none;
    border-color: var(--color-arcade-orange, #ff8c00);
}
.frames-reroll-note--empty {
    border-color: rgba(248, 113, 113, 0.8);
}
.frames-reroll-note::placeholder {
    font-size: 13px;
    color: var(--color-text-tertiary, #94a3b8);
    opacity: 0.8;
}

/* Themed <select>s inside the re-roll / Shift Start popovers (shift window + recast dropdowns) —
   native appearance stripped, dark theme + custom chevron to match the menu shell. */
.frames-shift-window,
.frames-recast-select {
    width: 100%;
    padding: var(--space-2) 32px var(--space-2) var(--space-3);
    font-size: 13px;
    color: var(--color-text-primary, #f1f5f9);
    background-color: var(--color-bg-primary, #0f172a);
    border: 1px solid var(--color-border-default, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-md, 8px);
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    transition: border-color 120ms ease-out;
}
.frames-shift-window:hover,
.frames-recast-select:hover {
    border-color: var(--color-border-strong, rgba(255, 255, 255, 0.16));
}
.frames-shift-window:focus,
.frames-recast-select:focus {
    outline: none;
    border-color: var(--color-arcade-orange, #ff8c00);
}
.frames-shift-window option,
.frames-recast-select option {
    background: var(--color-bg-secondary, #1e293b);
    color: var(--color-text-primary, #f1f5f9);
}
.frames-recast-select:disabled {
    cursor: not-allowed;
}
.frames-shift-cost {
    font-size: 11px;
    color: var(--color-text-tertiary, #94a3b8);
}
@media (prefers-reduced-motion: reduce) {
    .frames-reroll-menu { animation: none; }
}

/* Per-shot recast section (spec 2026-06-08) — one dropdown per present label at the top of the
   re-roll menu. Master/people = interactive; derived/people = [data-disabled="1"] (dimmed, with a
   hint). Plain CSS (no Tailwind utilities) — no build:css needed. */
.frames-recast {
    margin: 0 0 10px;
    padding: 8px 10px;
    border: 1px solid var(--color-border-default, rgba(255, 255, 255, 0.1));
    border-radius: var(--radius-md, 8px);
    background: rgba(255, 255, 255, 0.02);
}
.frames-recast-title {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-tertiary, #94a3b8);
    margin-bottom: 6px;
}
.frames-recast-hint { font-size: 11px; opacity: .6; margin-bottom: 6px; }
.frames-recast-row { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.frames-recast-label { font-size: 12px; min-width: 84px; opacity: .85; }
.frames-recast-select { flex: 1; min-width: 0; }
.frames-recast[data-disabled="1"] { opacity: .55; }

/* =====================================================================================
   studioConfirm() — design-system confirm modal (utils/confirm-modal.js)
   Mirrors the Frames plan-review gate's visual language (.frames-plan-panel) at a tighter
   520px so it reads as a focused decision. Reused app-wide; built for the Frames §3 P0 pass.
   ===================================================================================== */
.studio-confirm {
    position: fixed;
    inset: 0;
    z-index: calc(var(--z-modal) + 10);   /* above the gate modal (it invokes studioConfirm) */
    display: flex !important;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out;
}
.studio-confirm.hidden { display: none !important; }   /* beat Tailwind's !important .hidden */
.studio-confirm.open { opacity: 1; pointer-events: auto; }

.studio-confirm-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(2, 6, 23, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: pointer;
}

.studio-confirm-panel {
    position: relative;
    width: 100%;
    max-width: 520px;
    display: flex;
    flex-direction: column;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    transform: scale(0.96) translateY(8px);
    transition: transform 220ms cubic-bezier(0.34, 1.4, 0.64, 1);
}
.studio-confirm.open .studio-confirm-panel { transform: scale(1) translateY(0); }

/* -------- Header -------- */
.studio-confirm-header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-6) var(--space-4);
    background: radial-gradient(120% 140% at 0% 0%, rgba(255, 140, 0, 0.07) 0%, transparent 55%);
}
.studio-confirm-icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: var(--radius-lg);
    color: var(--color-accent);
    background: var(--color-accent-subtle);
    border: 1px solid var(--color-border-accent);
}
.studio-confirm-icon--danger {
    color: var(--color-error);
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
}
.studio-confirm-header-text { flex: 1; min-width: 0; padding-top: 4px; }
.studio-confirm-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    line-height: var(--line-height-tight, 1.25);
}

/* Cost chip — borrows the prominent .frames-cost-chip--total treatment so money reads as money. */
.studio-confirm-cost {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    font-variant-numeric: tabular-nums;
    color: var(--color-accent);
    background: linear-gradient(135deg, rgba(255, 140, 0, 0.16) 0%, rgba(45, 212, 191, 0.14) 100%);
    border: 1px solid var(--color-border-accent);
    border-radius: var(--radius-lg);
    white-space: nowrap;
}
.studio-confirm-cost i, .studio-confirm-cost svg { color: var(--color-accent-light); }

/* -------- Body -------- */
.studio-confirm-body { padding: 0 var(--space-6) var(--space-2); }
.studio-confirm-text {
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal, 1.5);
    color: var(--color-text-secondary);
}
.studio-confirm-hint {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-normal, 1.5);
    color: var(--color-text-muted);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
}
.studio-confirm-hint i, .studio-confirm-hint svg { flex-shrink: 0; margin-top: 1px; color: var(--color-text-disabled); }

/* -------- Footer -------- */
.studio-confirm-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-6) var(--space-5);
}
.studio-confirm-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 96px;
    padding: var(--space-2) var(--space-5);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    cursor: pointer;
    transition: background 140ms ease, color 140ms ease, border-color 140ms ease, transform 80ms ease;
}
.studio-confirm-btn:active { transform: translateY(1px); }
.studio-confirm-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.studio-confirm-btn--cancel {
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border-color: var(--color-border-default);
}
.studio-confirm-btn--cancel:hover { color: var(--color-text-primary); background: var(--color-bg-secondary); }

.studio-confirm-btn--confirm {
    color: #fff;
    background: var(--color-accent);
    box-shadow: var(--shadow-accent);
}
.studio-confirm-btn--confirm:hover { background: var(--color-accent-hover); }

.studio-confirm-btn--danger { background: var(--color-error); box-shadow: none; }
.studio-confirm-btn--danger:hover { background: #dc2626; }
/* On a red confirm, give focus a light ring (orange-on-red fails contrast). */
.studio-confirm-btn--danger:focus-visible { outline-color: #fff; }

/* -------- Responsive + reduced motion -------- */
@media (max-width: 560px) {
    .studio-confirm-panel { max-width: min(100%, 95vw); }
    .studio-confirm-header { flex-wrap: wrap; }
    .studio-confirm-cost { order: 3; }
    .studio-confirm-footer { flex-direction: column-reverse; align-items: stretch; }
    .studio-confirm-btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
    .studio-confirm { transition: none; }
    .studio-confirm-panel { transition: none; transform: none; }
    .studio-confirm-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* ============================================================
   Character Identity Fidelity — anchor gallery, fidelity toggle,
   refine v2 plan + before/after diff
   ============================================================ */
.identity-gallery { display: flex; flex-wrap: wrap; gap: .5rem; margin: .5rem 0; }
.identity-gallery .anchor { position: relative; width: 96px; }
.identity-gallery .anchor img { width: 96px; height: 96px; object-fit: cover; border-radius: .375rem; display: block; }
.identity-gallery .anchor.canonical { outline: 2px solid var(--arcade-orange, #ff7a18); outline-offset: 1px; }
.identity-gallery .anchor .remove { position: absolute; top: 2px; right: 2px; display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 9999px; background: rgba(0, 0, 0, .65); color: #fff; cursor: pointer; line-height: 0; }
.identity-gallery .anchor .remove:hover { background: rgba(0, 0, 0, .85); }
.identity-gallery .anchor .anchor-badge { position: absolute; bottom: 2px; left: 2px; padding: 1px 4px; font-size: 9px; line-height: 1.3; border-radius: .25rem; background: var(--arcade-orange, #ff7a18); color: #1a1a1a; font-weight: 600; }
.identity-toggle { display: flex; align-items: center; gap: .5rem; margin: .5rem 0; flex-wrap: wrap; }
.identity-toggle small { color: #9ca3af; flex-basis: 100%; }
.refine-plan { margin: .5rem 0; padding: .5rem .75rem; border-radius: .375rem; background: rgba(255,255,255,.05); white-space: pre-wrap; font-size: .8125rem; color: #e5e7eb; }
.refine-diff { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; align-items: start; margin: .5rem 0; }
.refine-diff figure { margin: 0; }
.refine-diff figcaption { font-size: .75rem; color: #9ca3af; margin-bottom: .25rem; }
.refine-diff img { width: 100%; border-radius: .375rem; }
.refine-score { grid-column: 1 / -1; text-align: center; font-weight: 600; }

/* ============================================================================
   Frames — Render Clips (Seedance 2.0), design spec §9. NEW `.frames-clip-*`
   classes ONLY (Lesson #20 — shared looks are re-implemented on the same
   token system, never double-classed onto another component's JS hooks).
   Visual language mirrors the frames family: elevated panels, quiet chips
   (dark glass + hairline border), the single accent, generous negative space.
   ============================================================================ */

/* --- Grid-overlay quick actions row -----------------------------------------
   The card overlay's `.frames-result-action` buttons were each absolutely
   pinned to the SAME corner (the migrated result-card block near the end of this
   file) — every button after the first was unreachable. The new
   `.frames-result-actions` wrapper owns the corner and lays them out as a compact
   row; the inner override (0,2,0) beats the legacy absolute rule (0,1,0). */
.frames-result-actions {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    display: flex;
    align-items: center;
    gap: 6px;
    z-index: 3;
}
.frames-result-actions .frames-result-action {
    position: static;
    top: auto;
    right: auto;
}

/* ---------- Review-bay hierarchy: source frames recede once clips exist ------
   Before any clip is rendered the stills grid is the working surface. The moment
   clips land, they become the hero and the (already-reviewed) source frames drop
   to a compact, labeled reference filmstrip so the two zones stop competing. */
.frames-source-eyebrow { display: none; }
.frames-has-clips .frames-source-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-muted, #94a3b8);
}
.frames-source-eyebrow i,
.frames-source-eyebrow svg { width: 14px; height: 14px; color: var(--color-text-muted, #94a3b8); }
.frames-source-eyebrow-count { font-variant-numeric: tabular-nums; opacity: 0.8; }

/* ---------------------- Reload-resume "last board" card ---------------------
   Shown on a clean canvas (top of the empty state) when a durable pointer to the
   director's last board with real content survives a page reload. Deliberately
   SECONDARY — a quiet raised surface that never competes with the primary
   "start a board" controls: muted uppercase eyebrow, ellipsized title, muted
   meta, a ghost Dismiss and an arcade-orange Reopen. Tokens mirror the
   neighboring `.frames-clip-card` / `.frames-source-eyebrow` rules. */
.frames-resume-card {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding: var(--space-4) var(--space-5);
    text-align: left;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    transition: border-color 160ms ease-out, box-shadow 160ms ease-out;
}
.frames-resume-card:hover {
    border-color: var(--color-border-strong, #334155);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.38);
}
.frames-resume-body {
    min-width: 0;                 /* let the title ellipsize inside the flex row */
    flex: 1 1 220px;
}
.frames-resume-eyebrow {
    display: block;
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-text-muted, #94a3b8);
}
.frames-resume-title {
    margin-top: 2px;
    font-size: 14px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.frames-resume-meta {
    margin-top: 2px;
    font-size: 12px;
    color: var(--color-text-muted, #94a3b8);
    font-variant-numeric: tabular-nums;
}
.frames-resume-actions {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}
.frames-resume-dismiss,
.frames-resume-open {
    height: 32px;
    padding: 0 var(--space-4);
    font-size: 12px;
    font-weight: var(--font-weight-semibold, 600);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out;
}
.frames-resume-dismiss {
    color: var(--color-text-secondary, #cbd5e1);
    background: transparent;
    border: 1px solid var(--color-border-default);
}
.frames-resume-dismiss:hover {
    color: var(--color-text-primary, #f1f5f9);
    border-color: var(--color-border-strong, #334155);
}
.frames-resume-open {
    color: #fff;
    background: var(--color-accent);
    border: 1px solid var(--color-accent);
}
.frames-resume-open:hover { background: rgba(255, 140, 0, 0.85); }
.frames-resume-dismiss:focus-visible,
.frames-resume-open:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
    .frames-resume-card,
    .frames-resume-dismiss,
    .frames-resume-open { transition: none; }
    .frames-resume-card:hover { box-shadow: none; }
}

/* §5e plan-bible banner (T15) — the plan's stamped Story Bible has been deleted. An
   amber warning notice above the results grid (component CSS, not Tailwind utilities). */
.frames-plan-bible-banner {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding: var(--space-3) var(--space-4);
    text-align: left;
    background: rgba(245, 158, 11, 0.08);
    border: 1px solid rgba(245, 158, 11, 0.42);
    border-left-width: 3px;
    border-radius: var(--radius-lg);
}
.frames-plan-bible-banner-icon {
    flex-shrink: 0;
    margin-top: 1px;
    color: #f59e0b;
}
.frames-plan-bible-banner-body {
    min-width: 0;
    flex: 1 1 auto;
}
.frames-plan-bible-banner-title {
    font-size: 13px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
}
.frames-plan-bible-banner-meta {
    margin-top: 2px;
    font-size: 12px;
    line-height: 1.45;
    color: var(--color-text-secondary, #cbd5e1);
}
.frames-plan-bible-banner-dismiss {
    flex-shrink: 0;
    height: 30px;
    padding: 0 var(--space-3);
    font-size: 12px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-secondary, #cbd5e1);
    background: transparent;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 160ms ease-out, color 160ms ease-out;
}
.frames-plan-bible-banner-dismiss:hover {
    color: var(--color-text-primary, #f1f5f9);
    border-color: var(--color-border-strong, #334155);
}
.frames-plan-bible-banner-dismiss:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
    .frames-plan-bible-banner-dismiss { transition: none; }
}

/* Compact auto-fill thumbnail track. !important beats Tailwind's important:true
   `grid-cols-*` / `gap-*` utilities (CLAUDE.md) — without it the demotion silently
   loses to the utility classes on the element. */
.frames-has-clips #frames-results-grid {
    grid-template-columns: repeat(auto-fill, 132px) !important;
    gap: var(--space-3) !important;
    justify-content: start;
}
.frames-has-clips #frames-results-grid > * {
    opacity: 0.72;
    transition: opacity 160ms ease-out;
}
.frames-has-clips #frames-results-grid > *:hover { opacity: 1; }
/* The heavy per-card overlay actions belong to full-size review; on the demoted
   strip a still is view/expand-only (click to open for lock / re-roll). */
.frames-has-clips #frames-results-grid .frames-result-actions { display: none; }

/* Give the clips a stronger divider + more air below the source strip. */
.frames-has-clips .frames-clip-section {
    margin-top: var(--space-8, 2rem);
    padding-top: var(--space-6, 1.5rem);
}

/* ===========================================================================
   Result-card base styles — MIGRATED VERBATIM (design §7) from the former
   preview.html inline <style>. Kept AFTER the last .frames-result-* /
   .frames-has-clips rule so the old "injected later from preview.html, later
   wins" cascade position is preserved (e.g. the locked-state hover overlay and
   the pending-overlay tie). Do NOT move this block above those rules.
   =========================================================================== */
.frames-result-card {
    position: relative;
    border-radius: 0.75rem;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.2s;
    border: 2px solid transparent;
    /* P1a — driven by the plan AR (--frames-cell-aspect set on the grid); 16/9 fallback. */
    aspect-ratio: var(--frames-cell-aspect, 16/9);
}

.frames-result-card:hover {
    border-color: rgb(255 140 0);
    transform: scale(1.02);
}

.frames-result-card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.frames-result-overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgb(0 0 0 / 0.8), transparent 50%);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 0.75rem;
    opacity: 0;
    transition: opacity 0.2s;
}

.frames-result-card:hover .frames-result-overlay {
    opacity: 1;
}

.frames-result-label {
    font-size: 0.75rem;
    font-weight: 500;
    color: white;
}

.frames-result-action {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgb(255 140 0);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    cursor: pointer;
    transition: all 0.2s;
}

.frames-result-action:hover {
    transform: scale(1.1);
    background: rgb(255 160 40);
}

/* --------------------------- Clips section shell --------------------------- */
.frames-clip-section {
    margin-top: var(--space-6);
    padding-top: var(--space-5);
    border-top: 1px solid var(--color-border-default);
}
.frames-clip-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}
.frames-clip-section-title {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: 14px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
}
.frames-clip-section-title i,
.frames-clip-section-title svg {
    color: var(--color-accent);
}
.frames-clip-section-count {
    font-size: 12px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted, #94a3b8);
    font-variant-numeric: tabular-nums;
}
.frames-clip-play-board-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 32px;
    padding: 0 var(--space-3);
    font-size: 12px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 160ms ease-out, background 160ms ease-out;
}
.frames-clip-play-board-btn:hover:not(:disabled) {
    border-color: var(--color-accent);
}
.frames-clip-play-board-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.frames-clip-play-board-btn:disabled { opacity: 0.45; cursor: default; }
.frames-clip-play-board-btn--active {
    border-color: var(--color-accent);
    background: rgba(255, 140, 0, 0.12);
}
.frames-clip-play-board-btn i,
.frames-clip-play-board-btn svg { color: var(--color-accent); }

/* One-time expectation copy — a quiet informational band, not a toast. */
.frames-clip-expectation {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
    font-size: 12px;
    line-height: 1.5;
    color: var(--color-text-secondary, #cbd5e1);
    background: rgba(255, 140, 0, 0.06);
    border: 1px solid rgba(255, 140, 0, 0.18);
    border-radius: var(--radius-lg);
}
.frames-clip-expectation i,
.frames-clip-expectation svg {
    flex-shrink: 0;
    margin-top: 1px;
    color: var(--color-accent);
}
.frames-clip-expectation strong { color: var(--color-text-primary, #f1f5f9); }
.frames-clip-expectation-dismiss {
    margin-left: auto;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    color: var(--color-text-muted, #94a3b8);
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    cursor: pointer;
}
.frames-clip-expectation-dismiss:hover { color: var(--color-text-primary, #f1f5f9); }

/* --------------------- Clips = the hero, once rendered --------------------- */
/* A generous responsive grid (not a scroll strip): for a spot's handful of
   clips a wrapping grid reads as the deliverable with nothing hidden off-edge. */
.frames-clip-strip {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
    gap: var(--space-4);
    padding-bottom: var(--space-1);
}

.frames-clip-card {
    display: flex;
    flex-direction: column;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: border-color 160ms ease-out, transform 160ms ease-out, box-shadow 160ms ease-out;
}
.frames-clip-card:hover {
    border-color: var(--color-border-strong, #334155);
    transform: translateY(-2px);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.38);
}
@media (prefers-reduced-motion: reduce) {
    .frames-clip-card { transition: border-color 160ms ease-out; }
    .frames-clip-card:hover { transform: none; }
}
.frames-clip-card--refused,
.frames-clip-card--failed { border-color: rgba(248, 113, 113, 0.35); }
.frames-clip-card--stale { border-color: rgba(255, 140, 0, 0.35); }

.frames-clip-media {
    position: relative;
    aspect-ratio: var(--frames-cell-aspect, 16 / 9);
    background: #0b0f1a;
}
.frames-clip-video,
.frames-clip-poster {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}
.frames-clip-poster--dim { opacity: 0.45; }
.frames-clip-poster--empty {
    background: linear-gradient(135deg, var(--color-bg-secondary), var(--color-bg-tertiary));
}

/* Chips (top-left of the media): STALE / escalation L{n} / duration — the same
   glass treatment as `.frames-alt-badge`, re-declared under the clip namespace. */
.frames-clip-chips {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 5px;
    pointer-events: none;
}
.frames-clip-chip {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 7px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.02em;
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
    background: rgba(8, 12, 22, 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--radius-full, 9999px);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
}
.frames-clip-chip--stale {
    color: var(--color-warning-text);
    border-color: rgba(245, 158, 11, 0.55);
}
.frames-clip-chip--shield { color: #c7d2fe; }

/* In-flight overlay: spinner + the live WS stage. */
.frames-clip-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    font-size: 12px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary, #cbd5e1);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    background: rgba(8, 12, 22, 0.35);
}
.frames-clip-spinner {
    width: 22px;
    height: 22px;
    border: 2px solid rgba(255, 255, 255, 0.18);
    border-top-color: var(--color-accent);
    border-radius: var(--radius-full);
    animation: framesClipSpin 800ms linear infinite;
}
@keyframes framesClipSpin { to { transform: rotate(360deg); } }

.frames-clip-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
}
.frames-clip-label {
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary, #cbd5e1);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.frames-clip-icon-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    color: var(--color-text-muted, #94a3b8);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: color 160ms ease-out, background 160ms ease-out;
}
.frames-clip-icon-btn:hover {
    color: var(--color-text-primary, #f1f5f9);
    background: rgba(255, 255, 255, 0.06);
}
.frames-clip-icon-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
}

/* Track C §D1 — the "previous take" switcher: a chip that opens a thumb-less menu
   of shelved takes (+ the current selection as the checked row). No thumbnails =
   no per-take signing pass (INV5). */
.frames-clip-takes {
    position: relative;
    flex-shrink: 0;
    margin-left: auto;
}
.frames-clip-takes-chip {
    cursor: pointer;
    border: 1px solid var(--color-border-default);
    background: rgba(255, 255, 255, 0.04);
    color: var(--color-text-secondary, #cbd5e1);
}
.frames-clip-takes-chip:hover {
    color: var(--color-text-primary, #f1f5f9);
    background: rgba(255, 255, 255, 0.08);
}
.frames-clip-takes-chip:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
}
.frames-clip-takes-menu {
    position: absolute;
    right: 0;
    bottom: calc(100% + var(--space-1));
    z-index: 20;
    min-width: 140px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-1);
    background: var(--color-surface-raised, #1e293b);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.frames-clip-take-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-1) var(--space-2);
    font-size: 11px;
    color: var(--color-text-secondary, #cbd5e1);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-align: left;
    transition: color 140ms ease-out, background 140ms ease-out;
}
.frames-clip-take-row:hover {
    color: var(--color-text-primary, #f1f5f9);
    background: rgba(255, 255, 255, 0.06);
}
.frames-clip-take-row.is-current {
    color: var(--color-text-primary, #f1f5f9);
    cursor: default;
}
.frames-clip-take-row.is-current .frames-clip-take-meta::before {
    content: "";
}
.frames-clip-take-meta { white-space: nowrap; }

/* Director-language state note (stale / refused / failed) under the media. */
.frames-clip-note {
    padding: var(--space-2) var(--space-3) var(--space-3);
    border-top: 1px solid var(--color-border-default);
    font-size: 11px;
    line-height: 1.5;
    color: var(--color-text-secondary, #cbd5e1);
}
.frames-clip-note p { margin: 0 0 var(--space-2); }
.frames-clip-note--refused p,
.frames-clip-note--failed p { color: var(--color-error-text); }
.frames-clip-note--stale p { color: var(--color-warning-text); }
.frames-clip-note-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* Shared small button (strip notes + player bar + modal footer secondary).
   Joins the round's 32px secondary control scale (design §7) — was 28px/11px. */
.frames-clip-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 var(--space-3);
    font-size: 13px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-secondary, #1e293b);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 160ms ease-out, background 160ms ease-out;
}
.frames-clip-btn:hover:not(:disabled) { border-color: var(--color-accent); }
.frames-clip-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.frames-clip-btn:disabled { opacity: 0.5; cursor: default; }
.frames-clip-btn i, .frames-clip-btn svg { color: var(--color-accent); flex-shrink: 0; }
.frames-clip-btn--quiet {
    background: transparent;
}

/* ------------------------------- Play board -------------------------------- */
.frames-clip-player {
    margin-bottom: var(--space-4);
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.frames-clip-player-stage {
    position: relative;
    aspect-ratio: var(--frames-cell-aspect, 16 / 9);
    max-height: 60vh;
    background: #05070d;
}
.frames-clip-player-video {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: contain;
}
.frames-clip-player-gap {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    text-align: center;
    padding: var(--space-4);
}
.frames-clip-player-gap-title {
    font-size: 13px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
}
.frames-clip-player-gap-reason {
    font-size: 12px;
    color: var(--color-text-muted, #94a3b8);
}
/* Track C §D4: a rendered TEXT CARD's still, held as a timed poster in the Play
   board (kind:'still-hold'). Fills the stage, contained, no chrome. */
.frames-clip-player-hold-img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--radius-sm, 4px);
}
.frames-clip-player-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-top: 1px solid var(--color-border-default);
}
.frames-clip-player-caption {
    font-size: 12px;
    color: var(--color-text-secondary, #cbd5e1);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---------------------------- Render Clips modal ---------------------------
   Standard fixed-overlay modal shell (fixed overlay, blurred backdrop,
   spring-in panel) on the clip namespace. (Still a real modal — only the
   Frames plan/bible surfaces were de-modaled to in-canvas stage panels.) */
.frames-clip-modal {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out;
}
.frames-clip-modal.open {
    opacity: 1;
    pointer-events: auto;
}
.frames-clip-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(2, 6, 23, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: pointer;
}
.frames-clip-panel {
    position: relative;
    width: 100%;
    max-width: 860px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    transform: scale(0.96) translateY(8px);
    transition: transform 220ms cubic-bezier(0.34, 1.4, 0.64, 1);
}
.frames-clip-modal.open .frames-clip-panel {
    transform: scale(1) translateY(0);
}

.frames-clip-header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-border-default);
    background:
        radial-gradient(120% 140% at 0% 0%, rgba(255, 140, 0, 0.07) 0%, transparent 55%);
}
.frames-clip-header-icon {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    color: var(--color-accent);
    background: rgba(255, 140, 0, 0.1);
    border: 1px solid rgba(255, 140, 0, 0.25);
    border-radius: var(--radius-lg);
}
.frames-clip-header-text { flex: 1; min-width: 0; }
.frames-clip-title {
    margin: 0;
    font-size: 16px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-text-primary, #f1f5f9);
}
.frames-clip-subtitle {
    margin: 2px 0 0;
    font-size: 12px;
    color: var(--color-text-muted, #94a3b8);
}
.frames-clip-close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    color: var(--color-text-muted, #94a3b8);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
}
.frames-clip-close:hover {
    color: var(--color-text-primary, #f1f5f9);
    background: rgba(255, 255, 255, 0.06);
}
.frames-clip-close:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
}

/* Global controls band. */
.frames-clip-controls {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-5);
    border-bottom: 1px solid var(--color-border-default);
}
.frames-clip-control {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.frames-clip-control-label {
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted, #94a3b8);
}
.frames-clip-seg {
    display: inline-flex;
    background: var(--color-bg-secondary, #1e293b);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    padding: 2px;
    gap: 2px;
}
.frames-clip-seg-btn {
    height: 26px;
    padding: 0 10px;
    font-size: 12px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary, #cbd5e1);
    background: transparent;
    border: none;
    border-radius: calc(var(--radius-md) - 2px);
    cursor: pointer;
    transition: background 160ms ease-out, color 160ms ease-out;
}
.frames-clip-seg-btn:hover:not(:disabled):not(.frames-clip-seg-btn--active) {
    color: var(--color-text-primary, #f1f5f9);
}
.frames-clip-seg-btn--active {
    color: #0b0f1a;
    background: var(--color-accent);
    font-weight: var(--font-weight-semibold, 600);
}
.frames-clip-seg-btn:disabled { opacity: 0.35; cursor: default; }
.frames-clip-seg-btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
}
.frames-clip-select {
    height: 30px;
    padding: 0 var(--space-2);
    font-size: 12px;
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-secondary, #1e293b);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
}
.frames-clip-select:hover { border-color: var(--color-border-strong); }
.frames-clip-select:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
}
.frames-clip-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--color-text-secondary, #cbd5e1);
    cursor: pointer;
    user-select: none;
}
.frames-clip-toggle input {
    accent-color: var(--color-accent);
    width: 14px;
    height: 14px;
    cursor: pointer;
}
.frames-clip-smart-note {
    flex-basis: 100%;
    margin: 0;
    font-size: 11px;
    color: #ffd9ad;
}
.frames-clip-chunk-note {
    margin: 0 0 var(--space-2);
    font-size: 11px;
    color: var(--color-text-muted, #94a3b8);
}

/* Scrollable rows body. */
.frames-clip-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--space-3) var(--space-5);
}
.frames-clip-rows {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.frames-clip-empty {
    padding: var(--space-5);
    text-align: center;
    font-size: 12px;
    color: var(--color-text-muted, #94a3b8);
}
.frames-clip-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-2);
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
}
.frames-clip-row:hover { background: rgba(255, 140, 0, 0.04); }
.frames-clip-row-check {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    padding-top: var(--space-2);
    cursor: pointer;
}
.frames-clip-row-check input {
    accent-color: var(--color-accent);
    width: 15px;
    height: 15px;
    cursor: pointer;
}
.frames-clip-row-thumb {
    flex-shrink: 0;
    width: 96px;
    aspect-ratio: var(--frames-cell-aspect, 16 / 9);
    object-fit: cover;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-default);
    background: #0b0f1a;
}
.frames-clip-row-thumb--empty {
    background: linear-gradient(135deg, var(--color-bg-secondary), var(--color-bg-tertiary));
}
.frames-clip-row-main { flex: 1; min-width: 0; }
.frames-clip-row-shot {
    display: flex;
    align-items: center;
    gap: var(--space-2, 8px);
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary, #cbd5e1);
    margin-bottom: var(--space-1);
    min-width: 0;
}
/* T16: the label ellipsizes; the authored badge + live authoring pill stay whole. */
.frames-clip-row-shot-label {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* B5: delivered-row markers in the Render Clips modal — a re-render re-bills the
   shot, so it must be a VISIBLE, opt-in choice (delivered-current rows start
   UNCHECKED and de-emphasised; stale rows start checked with a "re-render" tag). */
.frames-clip-row-tag {
    display: inline-flex;
    align-items: center;
    margin-bottom: var(--space-1);
    padding: 1px 8px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.02em;
    border-radius: var(--radius-full, 9999px);
    border: 1px solid transparent;
}
.frames-clip-row-tag--done {
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.12);
    border-color: rgba(148, 163, 184, 0.3);
}
.frames-clip-row-tag--stale {
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border-color: rgba(245, 158, 11, 0.55);
}

/* ── Track C §D2: multi-still CLUSTER clips — the per-master "include coverage"
   toggle (fold this master's coverage children into ONE continuity clip, billed
   as one clip) and the dimmed state of a child ABSORBED into a checked cluster
   (its still rides the master's clip; its own solo checkbox is disabled). */
.frames-clip-cluster {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1, 4px);
    margin-bottom: var(--space-1);
    padding: 2px 8px 2px 4px;
    font-size: 11px;
    font-weight: var(--font-weight-medium, 500);
    color: var(--color-text-secondary, #cbd5e1);
    background: rgba(99, 102, 241, 0.10);
    border: 1px solid rgba(99, 102, 241, 0.30);
    border-radius: var(--radius-full, 9999px);
    cursor: pointer;
    user-select: none;
}
.frames-clip-cluster:hover {
    background: rgba(99, 102, 241, 0.16);
    border-color: rgba(99, 102, 241, 0.45);
}
.frames-clip-cluster input {
    width: 13px;
    height: 13px;
    accent-color: rgb(129, 140, 248);
    cursor: pointer;
}
.frames-clip-row--in-cluster {
    opacity: 0.55;
}
.frames-clip-row--in-cluster .frames-clip-row-cost {
    color: rgb(129, 140, 248);
    font-style: italic;
}

/* ── T16: clip-authoring surface in the Render Clips modal ──────────────────
   The "Authored" badge (this row renders from its director-authored prompt), the
   live per-slot authoring pill (frames_author_progress WS: Directing…/Writing…/
   Authored/Kept deterministic), and the stale-authored re-author affordance note
   (the deterministic prompt is prefilled; the actionable 1cr button lands in T17). */
.frames-author-badge,
.frames-author-pill {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    padding: 1px 8px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.02em;
    border-radius: var(--radius-full, 9999px);
    border: 1px solid transparent;
    white-space: nowrap;
}
.frames-author-badge {
    color: var(--color-info-text);
    background: var(--color-info-bg);
    border-color: rgba(59, 130, 246, 0.5);
}
.frames-author-pill {
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.12);
    border-color: rgba(148, 163, 184, 0.3);
}
/* FIX-3: honest signal that an active cluster master renders on the deterministic
   path (its authored prompt is not used). Shown by _repriceClipModal in place of
   the suppressed "Authored" badge; a quiet muted caption, not a loud badge. */
.frames-cluster-authored-note {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    font-size: 10px;
    font-style: italic;
    color: var(--color-text-muted);
    white-space: nowrap;
}
.frames-author-pill--done {
    color: var(--color-success-text);
    background: var(--color-success-bg);
    border-color: rgba(16, 185, 129, 0.5);
}
.frames-author-pill--dropped {
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.08);
    border-color: rgba(148, 163, 184, 0.25);
}
.frames-author-stale-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2, 8px);
    margin-bottom: var(--space-1);
    padding: 6px 10px;
    font-size: 11px;
    line-height: 1.4;
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border: 1px solid rgba(245, 158, 11, 0.4);
    border-radius: var(--radius-md, 8px);
}
.frames-author-stale-note i,
.frames-author-stale-note svg {
    flex: 0 0 auto;
    margin-top: 1px;
    color: var(--color-warning);
}

/* ── C3 T17: author-clips trigger, per-slot re-roll affordance, handoff badge ──
   The toolbar "Author clips" chip reuses .btn-secondary; these style the per-slot
   re-roll affordance in the render modal (an inline guidance input + a 1cr button),
   the "Continuity check" handoff badge (modal row + grid overlay), and the grid
   authoring pill (same base .frames-author-pill; a grid variant sits in the
   overlay). */
.frames-author-reroll {
    display: flex;
    align-items: center;
    gap: var(--space-2, 8px);
    margin-bottom: var(--space-1);
}
.frames-author-guidance {
    flex: 1 1 auto;
    min-width: 0;
    padding: 4px 8px;
    font-size: 11px;
    color: var(--color-text-primary);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md, 8px);
}
.frames-author-guidance:focus {
    outline: none;
    border-color: rgba(255, 140, 0, 0.6);
    background: rgba(255, 140, 0, 0.06);
}
.frames-author-guidance::placeholder { color: var(--color-text-muted); }
.frames-author-reroll-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-info-text);
    background: var(--color-info-bg);
    border: 1px solid rgba(59, 130, 246, 0.5);
    border-radius: var(--radius-full, 9999px);
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, border-color 0.15s;
}
.frames-author-reroll-btn:hover:not(:disabled) {
    background: rgba(59, 130, 246, 0.24);
    border-color: rgba(59, 130, 246, 0.75);
}
.frames-author-reroll-btn:disabled { opacity: 0.5; cursor: default; }
.frames-author-reroll-btn i,
.frames-author-reroll-btn svg { flex: 0 0 auto; width: 14px; height: 14px; }

/* "Continuity check" handoff badge — on a modal row (inline pill, same family as the
   Authored badge) and on a grid card overlay (frames-author-handoff--grid). */
.frames-author-handoff {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    padding: 1px 8px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.02em;
    border-radius: var(--radius-full, 9999px);
    white-space: nowrap;
    /* "Continuity check" is a soft-attention meaning = warn. Retires the lone
       purple (the only purple in the app) into the shared warn family. */
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border: 1px solid rgba(245, 158, 11, 0.55);
}
.frames-author-handoff--grid {
    position: relative;
    z-index: 2;
    margin-left: var(--space-2, 8px);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
}
/* Grid overlay authoring pill: reuses .frames-author-pill; float it beside the label. */
.frames-author-pill--grid {
    margin-left: var(--space-2, 8px);
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
}

.frames-clip-row--rendered { opacity: 0.72; }
.frames-clip-row--rendered:hover { opacity: 1; }
.frames-clip-row-prompt {
    width: 100%;
    resize: vertical;
    min-height: 44px;
    padding: var(--space-2);
    font-size: 12px;
    line-height: 1.45;
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-secondary, #1e293b);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
}
.frames-clip-row-prompt:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 1px;
}
.frames-clip-row-side {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--space-2);
}
.frames-clip-row-duration {
    height: 28px;
    padding: 0 var(--space-2);
    font-size: 11px;
    color: var(--color-text-primary, #f1f5f9);
    background: var(--color-bg-secondary, #1e293b);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
}
.frames-clip-row-cost {
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--color-accent-light, #ffb054);
    font-variant-numeric: tabular-nums;
}

/* Skipped nodes — muted, honest, with the reason copy. */
.frames-clip-skipped {
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: 1px dashed var(--color-border-default);
}
.frames-clip-skipped-head {
    font-size: 11px;
    font-weight: var(--font-weight-semibold, 600);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted, #94a3b8);
    margin-bottom: var(--space-2);
}
.frames-clip-skipped-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    padding: 3px 0;
    font-size: 11px;
}
.frames-clip-skipped-shot {
    color: var(--color-text-muted, #94a3b8);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.frames-clip-skipped-reason {
    flex-shrink: 0;
    color: var(--color-text-secondary, #cbd5e1);
}

/* Footer: live total + CTA. */
.frames-clip-footer {
    padding: var(--space-3) var(--space-5) var(--space-4);
    border-top: 1px solid var(--color-border-default);
}
.frames-clip-footer-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.frames-clip-total {
    font-size: 12px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary, #cbd5e1);
    font-variant-numeric: tabular-nums;
}
.frames-clip-footer-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.frames-clip-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 34px;
    padding: 0 var(--space-4);
    font-size: 12px;
    font-weight: var(--font-weight-semibold, 600);
    color: #0b0f1a;
    background: var(--color-accent);
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    box-shadow: var(--shadow-accent, 0 4px 20px rgba(255, 140, 0, 0.25));
    transition: background 160ms ease-out;
}
.frames-clip-cta:hover:not(:disabled) { background: var(--color-accent-hover, #ff9d2e); }
.frames-clip-cta:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.frames-clip-cta:disabled { opacity: 0.5; cursor: default; box-shadow: none; }

/* Narrow viewports: rows stack; the side controls move under the prompt. */
@media (max-width: 640px) {
    .frames-clip-row { flex-wrap: wrap; }
    .frames-clip-row-side {
        flex-direction: row;
        align-items: center;
        width: 100%;
        justify-content: flex-end;
    }
    .frames-clip-card { flex-basis: 260px; }
}

@media (prefers-reduced-motion: reduce) {
    .frames-clip-modal { transition: none; }
    .frames-clip-panel { transition: none; transform: none; }
    .frames-clip-modal-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
    .frames-clip-spinner { animation: none; border-top-color: var(--color-accent); }
}

/* ==================== CINEMATIC FRAMES — STORY BIBLE INTAKE (C1 T19) ==============
   The collapsed "Add source material" expander that sits under the Concept box. It
   reuses the panel's existing form language (.form-label / .form-input / .btn-*); these
   rules only add the expander affordance, the sub-labels, the C2 "coming soon" chip, and
   the authoring placeholder strip that the WS reducer (frames-bible.js) drives until T20
   ships the full editor. */

/* Small field caption reused across the intake body (script / library / notes). */
.form-sublabel {
    display: block;
    font-size: 0.75rem;
    line-height: 1rem;
    color: rgb(100 116 139);
    margin-bottom: 0.25rem;
}

.frames-bible-intake-toggle {
    background: transparent;
    border: none;
    padding: 0;
    cursor: pointer;
}
.frames-bible-intake-toggle #frames-bible-chevron {
    transition: transform 150ms ease;
}
.frames-bible-intake.is-open .frames-bible-intake-toggle #frames-bible-chevron {
    transform: rotate(90deg);
}

/* Multi-selects in the intake body: keep them compact and readable. */
.frames-bible-intake-body select[multiple] {
    padding: 0.35rem 0.4rem;
}

/* Deck Intake D1 — the one-box upload (deck / script-only / board-only PDF) that
   replaced the separate Script + Storyboard boxes. No layout of its own beyond the
   intake body's `space-y-3`; the escape hatches get a link-style low-emphasis button
   (NOT `.btn-ghost` — that class is sized for icon-only 24px buttons, too small for
   these text labels). */
.frames-bible-deck-hatch-btn {
    background: transparent;
    border: none;
    padding: 0;
    font-size: 0.75rem;
    line-height: 1rem;
    color: rgb(148 163 184);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}
.frames-bible-deck-hatch-btn:hover {
    color: rgb(226 232 240);
}

/* CTA promotion: when the disclosure hierarchy promotes the bible CTA, the "Generate
   shot list" link dims so the primary action reads first (frames-bible.js sets the
   classes; no behaviour changes, only emphasis). */
#generate-shotlist-btn.is-demoted {
    opacity: 0.55;
}
#frames-bible-author-btn.is-promoted {
    box-shadow: 0 0 0 2px rgba(255, 140, 0, 0.35);
}

/* ── Mandate C — intake "one calm flow" ─────────────────────────────────────
   One consistent optional affordance (replaces three ad-hoc "(optional)" spans),
   an inline duration/pace field on the --space grid, the secondary "Refine"
   enhancer group (hairline-separated rows, no standalone dividers), and the
   subordinate footer run-options tier. */
.frames-optional-tag {
    font-size: var(--font-size-xs);
    color: var(--color-text-disabled);
    font-weight: var(--font-weight-normal);
    text-transform: none;
    letter-spacing: normal;
}

/* Duration / Pace: label + select as one inline unit; the select sizes to content
   (not the .form-select default width:100%) so the row stays compact and on-grid. */
.frames-inline-field {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.frames-inline-field .form-select {
    width: auto;
}

/* design §7 BROKEN #2 — the duration/pace row's helper ("1 credit · writes the shot list
   below") forced sidebar horizontal overflow @1024 (scrollWidth 333 > clientWidth 308). Let
   that row wrap and the helper soft-wrap so the panel never scrolls sideways. Scoped via :has
   to the row that directly contains the inline fields (no controls.html edit available). */
div:has(> .frames-inline-field) { flex-wrap: wrap; }
.frames-optional-tag.ml-auto { white-space: normal; }

/* design §7 BROKEN #1 — the sticky cost/run footer is the last child of the scrolling
   #controls-panel, so its semi-transparent blurred background ghosted OVER the Refine
   selects at most scroll positions. Scope to the Frames panel (its footer uniquely carries
   #generate-frames-btn): make it a clean opaque bar and reserve scroll runway above it so the
   last real control clears the bar at rest. Overrides the layout.css base (later + more
   specific), never edits it. */
.controls-footer:has(#generate-frames-btn) {
    background-color: var(--color-bg-secondary, #0f172a);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    margin-top: var(--space-6);
}

/* Refine (optional): the three enhancer sections, moved below the primary flow and
   visibly secondary. One umbrella head; rows separated by an internal hairline. */
.frames-intake-refine,
/* Cast & Locations (design §A1) — a first-class sibling of the Refine group; it shares the
   eyebrow + row-separator language via GROUPED selectors (Lesson #20: never borrow another
   component's JS-hook class — group the styling instead). */
.frames-declare {
    margin-bottom: var(--space-5);
}
.frames-intake-refine-head,
.frames-declare-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-4);
}
.frames-declare-head i,
.frames-declare-head svg { color: var(--color-accent-light); flex-shrink: 0; }
.frames-intake-refine-row,
.frames-declare-block {
    margin-bottom: 0;
}
.frames-intake-refine-row + .frames-intake-refine-row,
.frames-declare-block + .frames-declare-block {
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-border-subtle);
}

/* Footer run-options: advanced toggles as a subordinate tier below the cost card
   and above the primary Generate Frames action. */
.frames-run-options {
    margin-bottom: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border-default);
}
.frames-run-options-eyebrow {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-2);
}

/* Authoring placeholder strip — per-pass status lines from the reducer. */
.frames-bible-authoring {
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 8px;
    padding: 0.6rem 0.75rem;
    background: rgba(255, 255, 255, 0.02);
}
.frames-bible-authoring-passes .frames-bible-pass {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.6875rem;
    color: rgb(148 163 184);
}
.frames-bible-authoring-passes .frames-bible-pass .frames-bible-pass-dot {
    width: 6px;
    height: 6px;
    border-radius: 999px;
    flex-shrink: 0;
    background: rgb(100 116 139);
}
.frames-bible-authoring-passes .frames-bible-pass.is-streaming .frames-bible-pass-dot {
    background: var(--color-accent, rgb(255 140 0));
    animation: frames-bible-pulse 1.2s ease-in-out infinite;
}
.frames-bible-authoring-passes .frames-bible-pass.is-complete .frames-bible-pass-dot {
    background: rgb(34 197 94);
}
.frames-bible-authoring-passes .frames-bible-pass.is-failed .frames-bible-pass-dot {
    background: rgb(239 68 68);
}
.frames-bible-authoring-passes .frames-bible-pass.is-complete,
.frames-bible-authoring-passes .frames-bible-pass.is-streaming {
    color: rgb(203 213 225);
}

@keyframes frames-bible-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .frames-bible-authoring-passes .frames-bible-pass.is-streaming .frames-bible-pass-dot {
        animation: none;
    }
    .frames-bible-intake-toggle #frames-bible-chevron { transition: none; }
}

/* =========================================================================
   Story Bible editor gate (C1 Task 20) — the full-screen director surface.
   Mirrors the coverage-plan review gate's visual language (grouped selectors,
   Lesson #20): the root renders as an in-canvas stage panel (de-modaled
   2026-07-12; the old `.frames-plan-modal` overlay is gone) and reuses the
   header/footer/close classes, so ONLY the editor-specific layout lives here.
   ========================================================================= */

/* Wide panel — renders as an in-canvas stage panel (de-modaled 2026-07-12; the
   old .frames-plan-modal overlay is gone) that owns its own show/hide + transition. */
.frames-bible-editor-panel {
    position: relative;
    width: min(1080px, 94vw);
    max-width: 1080px;
    height: 88vh;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    transform: scale(0.96) translateY(8px);
    transition: transform 220ms cubic-bezier(0.34, 1.4, 0.64, 1);
}

/* Header status stat pills (ready / writing / to-fix). */
.frames-bible-editor-status {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    /* FW-6: the three stat pills' natural width can exceed the header room at MAX panel
       width — wrap onto a second row instead of clipping the chrome. */
    flex-wrap: wrap;
    row-gap: var(--space-2);
    min-width: 0;
}

.frames-bible-stat {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    padding: 3px 8px;
    border-radius: var(--radius-full);
    white-space: nowrap;
}

.frames-bible-stat i,
.frames-bible-stat svg { width: 13px; height: 13px; flex-shrink: 0; }

.frames-bible-stat--ready { color: #22c55e; background: rgba(34, 197, 94, 0.12); }
.frames-bible-stat--streaming { color: var(--color-accent-light); background: rgba(255, 140, 0, 0.12); }
.frames-bible-stat--failed { color: #f87171; background: rgba(248, 113, 113, 0.12); }

/* -------------------- Body: rail + main -------------------- */
.frames-bible-editor-body {
    display: flex;
    flex: 1;
    min-height: 0;
}

.frames-bible-rail {
    width: 264px;
    flex-shrink: 0;
    overflow-y: auto;
    padding: var(--space-3);
    display: flex;
    flex-direction: column;
    gap: 2px;
    border-right: 1px solid var(--color-border-default);
    background: rgba(15, 23, 42, 0.35);
}

.frames-bible-rail-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    width: 100%;
    text-align: left;
    padding: var(--space-2) var(--space-3);
    border: 1px solid transparent;
    border-radius: var(--radius-lg);
    background: transparent;
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}

.frames-bible-rail-item:hover { background: rgba(255, 140, 0, 0.06); }

.frames-bible-rail-item--active {
    background: var(--color-bg-tertiary);
    border-color: var(--color-border-accent);
    color: var(--color-text-primary);
}

.frames-bible-rail-item--disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.frames-bible-rail-item--disabled:hover { background: transparent; }

.frames-bible-rail-name {
    flex: 1;
    min-width: 0;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.frames-bible-rail-meta {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* Approve / lock status pills (display-only in T20; interactive in T21). */
.frames-bible-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: var(--radius-full);
}
.frames-bible-pill i, .frames-bible-pill svg { width: 11px; height: 11px; }
.frames-bible-pill--approved { color: #22c55e; background: rgba(34, 197, 94, 0.15); }
.frames-bible-pill--locked { color: var(--color-accent-light); background: rgba(255, 140, 0, 0.15); }

/* gen_state chip (per rail row). */
.frames-bible-genchip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 6px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: var(--radius-full);
    white-space: nowrap;
}
.frames-bible-genchip i, .frames-bible-genchip svg { width: 11px; height: 11px; flex-shrink: 0; }

/* Detected script-format annotation (audit G6) — a neutral chip beside the attached
 * script name. Borrows the genchip palette but is sentence-case (no uppercase), since
 * the label is director language, not a state token. */
/* Shared NEUTRAL pill base. The Cast & Locations scope badges/chips (design §A1 / §6)
   reuse this family via GROUPED selectors (Lesson #20 — never borrow a JS-hook class for
   styling; group the styling and keep hooks separate). Modifiers below set the accents. */
.frames-bible-source-format,
.frames-loc-badge,
.frames-scope-chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;   /* icon + label (editor source strip; harmless on the icon-less intake chip) */
    padding: 1px 6px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    border-radius: var(--radius-full);
    white-space: nowrap;
    /* Detected-format annotation reads as the shared NEUTRAL state chip. */
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.12);
}
.frames-bible-source-format i,
.frames-bible-source-format svg,
.frames-loc-badge i, .frames-loc-badge svg,
.frames-scope-chip i, .frames-scope-chip svg { width: 11px; height: 11px; flex-shrink: 0; }

/* "Main location" reads as the ACCENT pill (it is the one wired location); "Bible source"
   stays neutral. Both are non-interactive badges. */
.frames-loc-badge { flex-shrink: 0; }
.frames-loc-badge--main {
    color: var(--color-accent-light);
    background: rgba(255, 122, 24, .12);
}

/* The per-row "Bible only" scope chip is an interactive toggle: neutral when off, accent
   when active. Disabled = the bible owns the driven set (takeover) or the master toggle is
   off (every row implicitly bible-only). */
.frames-scope-chip {
    border: 1px solid transparent;
    cursor: pointer;
    text-transform: none;
    letter-spacing: normal;
}
.frames-scope-chip.is-active {
    color: var(--color-accent-light);
    background: rgba(255, 122, 24, .12);
    border-color: var(--color-border-accent);
}
.frames-scope-chip:hover:not([disabled]) { border-color: var(--color-border-accent); }
.frames-scope-chip[disabled] { cursor: default; opacity: 0.6; }

/* Layout — the scope chip sits under each cast row's picker; the locations row 1 keeps its
   "Main location" badge inline with the SceneSelector; rows 2+ are badge · select · remove.
   The sidebar rows use their OWN `frames-loc-row1`/`frames-loc-row2` classes — deliberately
   NOT the plan-review gate's `.frames-loc-row` (which is styled + reveal-animated at ~:9714/
   :9908). Double-classing with the gate class re-fired that reveal animation on every sidebar
   mutation (Lesson #20). Both sidebar variants share flex/align/gap via this grouped selector. */
.frames-cast-scope { margin-top: 6px; }
.frames-loc-row1,
.frames-loc-row2 {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* G4 — the broken-bind ROLLUP chip in the status strip (a clickable stat that jumps to
   the first broken row) + the per-row BROKEN badge (a --broken modifier on the shared
   review-badge sev family). Both read as an error state. */
.frames-bible-stat--broken {
    color: var(--color-error-text);
    background: var(--color-error-bg);
    border: none;
    font-family: inherit;
    cursor: pointer;
    transition: filter var(--transition-fast);
}
.frames-bible-stat--broken:hover { filter: brightness(1.12); }
.frames-bible-review-badge--broken { color: var(--color-error-text); background: var(--color-error-bg); }
/* Draft is the RESTING state: 12 identical filled pills down the rail were pure
   noise. Draft reads as quiet text; the active states (streaming/complete/failed)
   keep their filled pills so change is what draws the eye. */
.frames-bible-genchip--draft { color: var(--color-text-disabled); background: transparent; }
.frames-bible-genchip--streaming { color: var(--color-accent-light); background: rgba(255, 140, 0, 0.14); }
.frames-bible-genchip--complete { color: #22c55e; background: rgba(34, 197, 94, 0.14); }
.frames-bible-genchip--failed { color: #f87171; background: rgba(248, 113, 113, 0.14); }
.frames-bible-genchip--blocked { color: #94a3b8; background: rgba(148, 163, 184, 0.14); }

/* -------------------- Main pane -------------------- */
.frames-bible-main {
    flex: 1;
    min-width: 0;
    overflow-y: auto;
    padding: var(--space-5) var(--space-6);
    outline: none;
}

/* Reading measure: on a wide canvas the section content (and especially the
   inline row-edit form) stretched edge-to-edge. Cap the director-read column;
   full-width surfaces (mapcheck tables, agency view) keep their own widths. */
.frames-bible-section-head,
.frames-bible-rollup,
.frames-bible-claims,
.frames-bible-rows {
    max-width: 880px;
}

.frames-bible-section-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--color-border-default);
}

.frames-bible-section-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
}

.frames-bible-section-kind {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-disabled);
    background: var(--color-bg-tertiary);
    padding: 2px 8px;
    border-radius: var(--radius-full);
}

.frames-bible-rollup {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    font-style: italic;
    margin-bottom: var(--space-4);
}
.frames-bible-rollup i, .frames-bible-rollup svg { color: var(--color-accent-light); flex-shrink: 0; }

/* Claims — flowing paragraphs with a right-margin provenance chip. */
.frames-bible-claims {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.frames-bible-claim {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
    color: var(--color-text-primary);
}
.frames-bible-claim-text { flex: 1; min-width: 0; }

/* Provenance chip (claim / row right margin). Recessed dark so it stays legible on
   BOTH surfaces it rides: bare claims on the pane AND rows on bg-tertiary cards. */
.frames-bible-prov-chip {
    flex-shrink: 0;
    align-self: flex-start;
    margin-top: 1px;
    font-size: 10px;
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
    background: rgba(15, 23, 42, 0.45);
    border: 1px solid rgba(148, 163, 184, 0.15);
    border-radius: var(--radius-full);
    padding: 1px 7px;
}
.frames-bible-prov-chip--user { color: var(--color-accent-light); border-color: var(--color-border-accent); }
.frames-bible-prov-chip--script { color: #38bdf8; }
.frames-bible-prov-chip--inferred { color: var(--color-text-disabled); }

/* Rows — a read-only two-line row list. */
.frames-bible-rows {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.frames-bible-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3);
    /* Elevation over outline: bg-secondary matched the pane behind it, so each row
       read as a hard-edged empty frame. A one-step-lighter surface + hairline
       border reads as a soft card and kills the boxes-on-boxes feel. */
    border: 1px solid rgba(148, 163, 184, 0.08);
    border-radius: var(--radius-lg);
    background: var(--color-bg-tertiary);
}
.frames-bible-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.frames-bible-row-primary { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-text-primary); }
.frames-bible-row-secondary { font-size: var(--font-size-xs); color: var(--color-text-muted); }

/* -------------------- Agency (read-only beat-sheet) view (Track B T14) --------------------
   The header toggle swaps the director main pane for a calm, read-only agency read: the
   spot logline, then a numbered beat list (who's on screen · the line · the cut out). A raw
   markdown/prose string falls back to an escaped <pre>. Dark-only (no light theme). */
.frames-bible-agency { max-width: 68ch; }
.frames-bible-agency-logline {
    font-size: var(--font-size-base);
    line-height: var(--line-height-relaxed);
    color: var(--color-text-primary);
    padding-bottom: var(--space-4);
    margin-bottom: var(--space-4);
    border-bottom: 1px solid var(--color-border-default);
}
.frames-bible-agency-prose {
    white-space: pre-wrap;
    word-break: break-word;
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-relaxed);
    color: var(--color-text-primary);
    margin: 0;
}
.frames-bible-agency-beats {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: 0;
    padding: 0;
}
.frames-bible-agency-beat {
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border-default);
    border-left: 2px solid var(--color-border-accent);
    border-radius: var(--radius-lg);
    background: var(--color-bg-secondary);
}
.frames-bible-agency-beat-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.frames-bible-agency-beat-idx {
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-disabled);
}
.frames-bible-agency-cast { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.frames-bible-agency-name {
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border-radius: var(--radius-full);
    padding: 1px 8px;
}
.frames-bible-agency-transition {
    margin-left: auto;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-accent-light);
}
.frames-bible-agency-dialogue {
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
    color: var(--color-text-primary);
}
.frames-bible-agency-dialogue--silent { color: var(--color-text-disabled); font-style: italic; }

/* ---------------------------------------------------------------------------
   Frame-map checkpoint (C4 Track B T11) — the render↔board review table inside the
   bible editor. Dark-only (the app has no light theme). NEW `.frames-mapcheck-*`
   JS-hook classes only; the pill + styled-select bases are grouped into the shared
   `.frames-loc-*` / `.frames-cast-*` families above (Lesson #20 — never double-classed).
--------------------------------------------------------------------------- */
/* Rail: the "Coverage maps" subhead + per-plan meta (stale flag / confirm count / slots). */
.frames-mapcheck-rail-subhead {
    margin: var(--space-3) var(--space-2) var(--space-1);
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border-default);
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-disabled);
}
.frames-mapcheck-rail-subhead i, .frames-mapcheck-rail-subhead svg { opacity: 0.7; flex-shrink: 0; }
.frames-mapcheck-rail-count {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    color: var(--color-text-muted);
}
.frames-mapcheck-rail-stale { display: inline-flex; color: var(--color-warning-text); }
.frames-mapcheck-rail-confirm {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border-radius: var(--radius-full);
}

/* Pane header staleness chip (F9) + the summary legend row. */
.frames-mapcheck-stale-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    font-size: 11px;
    font-weight: var(--font-weight-semibold);
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border: 1px solid var(--color-warning-border, var(--color-border-default));
    border-radius: var(--radius-full);
}
.frames-mapcheck-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}
.frames-mapcheck-legend-item { display: inline-flex; align-items: center; gap: 5px; }

/* The table + one row per render slot (slot · thumbs · match · controls). */
.frames-mapcheck-table { display: flex; flex-direction: column; gap: var(--space-2); }
.frames-mapcheck-row {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    background: var(--color-bg-secondary);
}
.frames-mapcheck-slot {
    min-width: 22px;
    text-align: center;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-muted);
}
.frames-mapcheck-thumbs { display: inline-flex; align-items: center; gap: 4px; }
.frames-mapcheck-thumb {
    width: 52px;
    height: 32px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border-default);
    background: var(--color-bg-tertiary);
}
.frames-mapcheck-thumb--empty {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-disabled);
}
.frames-mapcheck-thumb--board { border-style: dashed; }
.frames-mapcheck-match { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.frames-mapcheck-match-label {
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.frames-mapcheck-match-meta { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.frames-mapcheck-conf { font-size: 11px; color: var(--color-text-muted); }

/* Pills: CONFIRM reuses the --sev (warning) family; crossing reads as info. */
.frames-mapcheck-pill--confirm {
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border-color: var(--color-warning-border, transparent);
}
.frames-mapcheck-pill--crossing {
    color: var(--color-info);
    background: var(--color-info-bg);
    border-color: var(--color-info-border);
}

/* Controls: the ACTION + target selects (compact override of the grouped select base). */
.frames-mapcheck-controls { display: inline-flex; align-items: center; gap: 6px; justify-self: end; }
.frames-mapcheck-action,
.frames-mapcheck-target {
    flex: 0 0 auto;
    min-width: 118px;
    max-width: 172px;
    padding: 5px 26px 5px 9px;
    font-size: var(--font-size-xs);
}
.frames-mapcheck-target--hidden { display: none; }

/* Narrow panes: wrap the controls under the row so nothing overflows. */
@media (max-width: 720px) {
    .frames-mapcheck-row { grid-template-columns: auto 1fr; }
    .frames-mapcheck-controls { grid-column: 1 / -1; justify-self: stretch; }
    .frames-mapcheck-action, .frames-mapcheck-target { flex: 1 1 auto; max-width: none; }
}

/* Block — the style exemplar quote card. */
.frames-bible-block {
    display: flex;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-left: 3px solid var(--color-border-accent);
    border-radius: var(--radius-lg);
    background: var(--color-bg-secondary);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-relaxed);
    font-style: italic;
}
.frames-bible-block i, .frames-bible-block svg { color: var(--color-accent-light); opacity: 0.7; flex-shrink: 0; }

/* Empty + failed/blocked states. */
.frames-bible-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-8) var(--space-4);
    color: var(--color-text-disabled);
    text-align: center;
    font-size: var(--font-size-sm);
}
.frames-bible-empty i, .frames-bible-empty svg { opacity: 0.5; }

.frames-bible-state {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    font-size: var(--font-size-sm);
}
.frames-bible-state-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.frames-bible-state-text strong { color: var(--color-text-primary); }
.frames-bible-state-text span { color: var(--color-text-muted); font-size: var(--font-size-xs); }
.frames-bible-state--failed { border-color: rgba(248, 113, 113, 0.4); background: rgba(248, 113, 113, 0.08); }
.frames-bible-state--failed > i, .frames-bible-state--failed > svg { color: #f87171; flex-shrink: 0; }
.frames-bible-state--blocked > i, .frames-bible-state--blocked > svg { color: var(--color-text-disabled); flex-shrink: 0; }

/* Shimmer skeleton for a streaming section. */
.frames-bible-shimmer { display: flex; flex-direction: column; gap: var(--space-3); }
.frames-bible-shimmer-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-bottom: var(--space-1);
}
.frames-bible-shimmer-bar {
    height: 12px;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg,
        var(--color-bg-tertiary) 25%, var(--color-bg-secondary) 37%, var(--color-bg-tertiary) 63%);
    background-size: 400% 100%;
    animation: frames-bible-shimmer 1.4s ease infinite;
}
@keyframes frames-bible-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* Finalize button turns green once the bible is finalized. */
.frames-bible-editor-footer .btn-secondary.is-done { color: #22c55e; }

/* =========================================================================
   Deck Intake D1 review gate (Task 10) — the ONE gate between a triaged deck
   and routing. Reuses the bible-editor gate's stage-panel/header/footer
   chrome (`.frames-plan-panel`, `.frames-bible-editor-panel`,
   `.frames-plan-header`, `.frames-plan-footer`, `.frames-bible-editor-footer`) —
   ONLY the gate-specific body content (page thumb grid + cast/venue groups) is
   new here, scoped under `.frames-bible-editor-panel` per the shared surface.
   ========================================================================= */

.frames-bible-editor-panel .frames-deck-gate-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--space-5) var(--space-6);
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.frames-bible-editor-panel .frames-deck-gate-group-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: var(--space-3);
}

.frames-bible-editor-panel .frames-deck-gate-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: var(--space-3);
}

.frames-bible-editor-panel .frames-deck-gate-thumb {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: rgba(15, 23, 42, 0.35);
}

.frames-bible-editor-panel .frames-deck-gate-thumb img {
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    display: block;
    background: var(--color-bg-tertiary);
}

.frames-bible-editor-panel .frames-deck-gate-thumb-empty {
    width: 100%;
    aspect-ratio: 3 / 4;
    background: var(--color-bg-tertiary);
}

.frames-bible-editor-panel .frames-deck-gate-thumb-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2);
}

.frames-bible-editor-panel .frames-deck-gate-thumb-page {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    flex-shrink: 0;
}

.frames-bible-editor-panel .frames-deck-gate-select {
    min-width: 0;
    flex: 1;
    font-size: 11px;
    padding: 2px 4px;
    border-radius: var(--radius-sm);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    color: var(--color-text-primary);
}

/* Cast/Locations groups are VISIBLE but UNROUTED in D1 (R18) — a quieter, read-only
   chip row rather than the editable thumb grid above. */
.frames-bible-editor-panel .frames-deck-gate-group-rows {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.frames-bible-editor-panel .frames-deck-gate-chip {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    background: rgba(148, 163, 184, 0.12);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    padding: 3px 10px;
}

.frames-bible-editor-panel .frames-deck-gate-footer .frames-plan-footer-lead {
    font-weight: var(--font-weight-medium);
}

/* -------------------------------------------------------------------------
   R4 (2026-07-11) — the in-gate script-conflict resolver. Sits between the
   gate body and the footer when the deck routes script pages AND the bible
   already carries a script (or a 409 forced it). Amber-tinted advisory with
   two btn-secondary btn-sm choices (replace vs keep-as-notes).
   ------------------------------------------------------------------------- */
.frames-deck-gate-conflict {
    margin: 8px 0; padding: 8px 10px; border-radius: 6px;
    background: rgba(245, 158, 11, 0.08); border: 1px solid rgba(245, 158, 11, 0.35);
}
.frames-deck-gate-conflict-title {
    display: flex; align-items: center; gap: 6px;
    font-size: 12px; color: #fbbf24; margin-bottom: 6px;
}
.frames-deck-gate-conflict-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* -------------------------------------------------------------------------
   Deck Style Fidelity D1 (design §2f, C18 honesty surface) — the PRE-route
   zero-capture warning, live at the Breakdown gate under the Pages grid.
   Same amber-advisory language as the R4 script-conflict banner above (no
   actions here — it's informational, the remedies are "reclassify a page" /
   "use the Campaign look slot", both done elsewhere in the UI).
   ------------------------------------------------------------------------- */
.frames-deck-gate-style-warning {
    display: flex; align-items: center; gap: 6px;
    margin-top: 10px; padding: 8px 10px; border-radius: 6px;
    background: rgba(245, 158, 11, 0.08); border: 1px solid rgba(245, 158, 11, 0.35);
    font-size: 12px; color: #fbbf24;
}
.frames-deck-gate-style-warning i { flex-shrink: 0; }

/* -------------------------------------------------------------------------
   Deck Intake D2 — the Cast section (talent leg, spec §4c). One titled block
   per detected role group, a card per person: headshot crop, name, tape
   link, include checkbox. ALL checked by default (the ACTUAL cast, not
   options). A `.is-created` card (already a library Character from a prior
   route pass — R21) renders muted with a ✓ badge and a disabled checkbox.
   ------------------------------------------------------------------------- */

.frames-bible-editor-panel .frames-deck-gate-cast-role {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.frames-bible-editor-panel .frames-deck-gate-cast-role + .frames-deck-gate-cast-role {
    margin-top: var(--space-4);
}

.frames-bible-editor-panel .frames-deck-gate-cast-role-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
}

.frames-bible-editor-panel .frames-deck-gate-cast-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--space-3);
}

.frames-bible-editor-panel .frames-deck-gate-person-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: rgba(15, 23, 42, 0.35);
}

.frames-bible-editor-panel .frames-deck-gate-person-card.is-created {
    border-color: var(--color-success-border, var(--color-border-default));
    opacity: 0.85;
}

.frames-bible-editor-panel .frames-deck-gate-person-photo {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    display: block;
    border-radius: var(--radius-sm);
    background: var(--color-bg-tertiary);
}

.frames-bible-editor-panel .frames-deck-gate-person-photo-empty {
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-sm);
    background: var(--color-bg-tertiary);
}

.frames-bible-editor-panel .frames-deck-gate-person-name {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.frames-bible-editor-panel .frames-deck-gate-person-tape {
    font-size: var(--font-size-xs);
    color: var(--color-accent);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.frames-bible-editor-panel .frames-deck-gate-person-tape:hover {
    text-decoration: underline;
}

.frames-bible-editor-panel .frames-deck-gate-person-include {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    cursor: pointer;
}

.frames-bible-editor-panel .frames-deck-gate-person-card.is-created .frames-deck-gate-person-include {
    cursor: default;
}

.frames-bible-editor-panel .frames-deck-gate-person-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    color: var(--color-success-text, var(--color-success));
    font-weight: var(--font-weight-medium);
}

/* ============================================================================
   Cinematic Frames — de-modaled stage panel (canvas redesign §4.3/§4.5, M15).
   The deck gate renders as an in-canvas STAGE, not an overlay. Its panel KEEPS
   .frames-plan-panel / .frames-bible-editor-panel / .frames-deck-gate-panel so every
   scoped child rule above keeps applying — these STANDALONE rules (lesson #34: never
   appended into a grouped selector) are 2-class compounds SCOPED to the deck gate
   (Tasks 6/7 ship their own scoped resets; a bare .frames-stage-panel sizing rule is
   FORBIDDEN — it would defeat the Sources cards' width cap by source order) and:
     • undo the modal card box (fixed max-width/height, floating shadow);
     • reset the transform that ONLY `.frames-plan-modal.open …` used to clear
       (that reset no longer fires once .frames-plan-modal is dropped);
     • let the CANVAS own the scroll — the gate body flows to content instead of
       being a flex:1 internal scroller (which can collapse to 0 in an auto-height
       panel via the min-height:0 flexbox gotcha).
   ============================================================================ */
.frames-stage-panel.frames-deck-gate-panel {
    position: relative;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: none;
    transform: none;
    box-shadow: none;
}

.frames-stage-panel .frames-deck-gate-body {
    flex: 0 1 auto;
    overflow: visible;
}

/* ============================================================================
   Cinematic Frames — Bible editor DE-MODALED into the Bible stage (§4.3 / M16).
   Standalone rules (lesson #34): NOT appended into any grouped selector; placed
   AFTER every `.frames-bible-editor-panel` rule above so they win by specificity
   AND source order over the base modal sizing + the `.frames-plan-modal.open …`
   transform-undo (which no longer matches — the root dropped `.frames-plan-modal`).
   Scoped to `.frames-bible-editor` so a generic `.frames-stage-panel` from the
   sibling de-modal tasks (5/7) can coexist without collision.
   ============================================================================ */

/* The Bible stage grows to fill the canvas; its mount + the de-modaled panel stretch
   so the 3-column editor keeps its own internal scroll (was a fixed 88vh overlay).
   `.hidden` (Tailwind !important) still wins when the stage/root is hidden. */
#frames-stage-bible {
    flex: 1;
    min-height: 0;
    padding: 0;
}
#frames-bible-editor-container {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}
.frames-stage-panel.frames-bible-editor {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}
/* Reset the floating-modal panel chrome: no scale/offset transform (its undo rule no
   longer matches), full width/height, no border/radius/shadow — it IS the stage now. */
.frames-stage-panel.frames-bible-editor .frames-bible-editor-panel {
    transform: none;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: none;
    flex: 1;
    min-height: 0;
    border: none;
    border-radius: 0;
    box-shadow: none;
}

/* ============================================================================
   Story Bible editor — RED-PEN layer (C1 Task 21)
   Claim spans + Confirm/Strike/Edit popover, per-section Rewrite, tabular row
   editors, and the right-side review rail. Chip colors ride ONE token table
   (provenanceChipColor in frames-bible.js → these custom props) so the palette
   lives in a single place.
   ============================================================================ */

/* The seven provenance chip color tokens (one per PROVENANCE_SOURCES value). */
:root {
    --frames-bible-chip-concept: #a78bfa;   /* violet — the director's own concept */
    --frames-bible-chip-script:  #38bdf8;   /* sky — lifted from the script page */
    --frames-bible-chip-board:   #f472b6;   /* pink — read from a storyboard */
    --frames-bible-chip-render:  #2dd4bf;   /* teal — carried from an earlier render */
    --frames-bible-chip-library: #fbbf24;   /* amber — matched from the asset library */
    --frames-bible-chip-inferred:#94a3b8;   /* slate — inferred / low-confidence */
    --frames-bible-chip-user:    var(--color-accent-light);   /* orange — your confirmed edit */
}

/* -------------------- Editable claim spans + gutter -------------------- */
/* The gutter is ALWAYS reserved (fixed min-width) so a state badge / provenance
   chip appearing on a claim never reflows the prose beside it. */
.frames-bible-claim-gutter {
    flex-shrink: 0;
    display: inline-flex;
    align-items: flex-start;
    gap: 4px;
    min-width: 64px;
    justify-content: flex-end;
    margin-top: 1px;
}

.frames-bible-claim-text--btn {
    display: inline;
    text-align: left;
    white-space: normal;
    background: none;
    border: none;
    padding: 1px 3px;
    margin: -1px -3px;
    border-radius: var(--radius-sm);
    font: inherit;
    color: inherit;
    cursor: text;
    transition: background var(--transition-fast), box-shadow var(--transition-fast);
}
.frames-bible-claim-text--btn:hover { background: rgba(255, 140, 0, 0.08); }
.frames-bible-claim-text--btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--color-border-accent);
    background: rgba(255, 140, 0, 0.06);
}

.frames-bible-claim--confirmed .frames-bible-claim-text { color: var(--color-text-primary); }
.frames-bible-claim--struck .frames-bible-claim-text {
    text-decoration: line-through;
    color: var(--color-text-disabled);
    opacity: 0.7;
}

.frames-bible-claim-state {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    border-radius: var(--radius-full);
    color: #22c55e;
    background: rgba(34, 197, 94, 0.15);
}
.frames-bible-claim-state i, .frames-bible-claim-state svg { width: 10px; height: 10px; }
.frames-bible-claim-state--struck { color: #f87171; background: rgba(248, 113, 113, 0.15); }

/* Jump-flash when a review card targets a claim (1200ms, reduced-motion safe). */
.frames-bible-flash { animation: frames-bible-flash 1.2s ease; }
@keyframes frames-bible-flash {
    0%   { background: rgba(255, 140, 0, 0.28); box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.25); }
    100% { background: transparent; box-shadow: 0 0 0 3px transparent; }
}

/* -------------------- Section head: Rewrite affordance -------------------- */
.frames-bible-section-head-spacer { flex: 1; }
.frames-bible-rewrite-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.frames-bible-rewrite-btn:hover {
    color: var(--color-accent-light);
    border-color: var(--color-border-accent);
    background: rgba(255, 140, 0, 0.08);
}
.frames-bible-rewrite-btn i, .frames-bible-rewrite-btn svg { width: 14px; height: 14px; }

/* -------------------- Inline editors (rewrite / claim / row) -------------------- */
.frames-bible-edit-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-3);
}
.frames-bible-rewrite-hint {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-bottom: var(--space-3);
}
.frames-bible-rewrite-hint i, .frames-bible-rewrite-hint svg { color: var(--color-accent-light); flex-shrink: 0; margin-top: 1px; }
.frames-bible-rewrite-input,
.frames-bible-claim-edit-input {
    width: 100%;
    resize: vertical;
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
}
.frames-bible-claim-edit { display: flex; flex-direction: column; }

/* -------------------- Tabular row editors -------------------- */
.frames-bible-row-gutter {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}
.frames-bible-row-pills { display: inline-flex; gap: 3px; }
.frames-bible-rowpill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-default);
    background: var(--color-bg-tertiary);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.frames-bible-rowpill i, .frames-bible-rowpill svg { width: 14px; height: 14px; }
.frames-bible-rowpill:hover { color: var(--color-text-primary); border-color: var(--color-border-strong); }
.frames-bible-rowpill--confirm.is-on { color: #22c55e; border-color: rgba(34, 197, 94, 0.5); background: rgba(34, 197, 94, 0.12); }
.frames-bible-rowpill--strike.is-on { color: #f87171; border-color: rgba(248, 113, 113, 0.5); background: rgba(248, 113, 113, 0.12); }
.frames-bible-rowpill--edit:hover { color: var(--color-accent-light); border-color: var(--color-border-accent); }

.frames-bible-row--confirmed { border-color: rgba(34, 197, 94, 0.35); }
.frames-bible-row--struck { opacity: 0.6; }
.frames-bible-row--struck .frames-bible-row-primary { text-decoration: line-through; color: var(--color-text-disabled); }

.frames-bible-row--editing { flex-direction: column; align-items: stretch; gap: var(--space-3); }
.frames-bible-row-fields { display: flex; flex-direction: column; gap: var(--space-3); }
.frames-bible-row-field { display: flex; flex-direction: column; gap: 4px; }
.frames-bible-row-field-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
}
.frames-bible-row-field .form-input,
.frames-bible-row-field .form-select { width: 100%; font-size: var(--font-size-sm); }
.frames-bible-row-field textarea.form-input { resize: vertical; }

/* -------------------- Claim popover (extends the shared kebab popover) -------------------- */
.frames-bible-claim-popover { min-width: 200px; }

/* -------------------- Review rail (right column) -------------------- */
.frames-bible-review-rail {
    flex-shrink: 0;
    width: 300px;
    border-left: 1px solid var(--color-border-default);
    /* The SAME recessed wash as .frames-bible-rail — the two side rails frame the
       main pane symmetrically instead of reading as three different surfaces. */
    background: rgba(15, 23, 42, 0.35);
    overflow-y: auto;
    padding: var(--space-4);
}
.frames-bible-review-rail.is-empty { display: none; }

.frames-bible-review-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-secondary);
    margin-bottom: var(--space-3);
}
.frames-bible-review-head i, .frames-bible-review-head svg { color: var(--color-accent-light); }

.frames-bible-review-list { display: flex; flex-direction: column; gap: var(--space-3); }

.frames-bible-review-card {
    border: 1px solid rgba(148, 163, 184, 0.08);
    border-left-width: 3px;
    border-radius: var(--radius-lg);
    background: var(--color-bg-tertiary);
    padding: var(--space-3);
}
/* Reconciliation card rules ride the unified 5-state language: conflict=high,
   dropped=warn, divergent=info, new=ok — the same tokens the finding cards use. */
.frames-bible-review-card--conflict { border-left-color: var(--color-error); }
.frames-bible-review-card--dropped { border-left-color: var(--color-warning); }
.frames-bible-review-card--divergent { border-left-color: var(--color-info); }
.frames-bible-review-card--new { border-left-color: var(--color-success); }

.frames-bible-review-card-head {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: var(--space-2);
}
.frames-bible-review-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 7px;
    font-size: 10px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: var(--radius-full);
}
.frames-bible-review-badge i, .frames-bible-review-badge svg { width: 11px; height: 11px; }
.frames-bible-review-badge--conflict { color: var(--color-error-text); background: var(--color-error-bg); }
.frames-bible-review-badge--dropped { color: var(--color-warning-text); background: var(--color-warning-bg); }
.frames-bible-review-badge--divergent { color: var(--color-info-text); background: var(--color-info-bg); }
.frames-bible-review-badge--new { color: var(--color-success-text); background: var(--color-success-bg); }

/* C2 T14 — verifier-finding cards (P7). The card is severity-styled so a finalize-blocking
   HIGH finding reads as the most urgent (red border + faint red wash), medium amber, low
   slate. The base --finding class only holds the fallback left-border; the --sev-* variant
   wins the color. */
.frames-bible-review-card--finding { border-left-color: var(--color-text-muted); }
/* HIGH: the solid error LEFT rule + the red HIGH badge carry the urgency. A full
   red border made the card the loudest frame on the canvas and fought the accent
   CTAs — every severity now shares the one calm card language (left rule only). */
.frames-bible-review-card--sev-high { border-left-color: var(--color-error); }
.frames-bible-review-card--sev-medium { border-left-color: var(--color-warning); }
.frames-bible-review-card--sev-low { border-left-color: var(--color-text-muted); }

/* Badge labels: the saturated-500 text failed AA (~2.5:1). The -text tints land ~5:1. */
.frames-bible-review-badge--sev-high { color: var(--color-error-text); background: var(--color-error-bg); }
.frames-bible-review-badge--sev-medium { color: var(--color-warning-text); background: var(--color-warning-bg); }
.frames-bible-review-badge--sev-low { color: var(--color-text-muted); background: rgba(148, 163, 184, 0.12); }

/* Finding evidence + proposed fix lines. Grouped so the shared type-scale lives in one
   place; the fix reads at primary-text weight (it's the actionable red-pen). */
.frames-bible-review-evidence,
.frames-bible-review-fix {
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
    line-height: var(--line-height-normal);
    margin-bottom: var(--space-1);
}
.frames-bible-review-fix { color: var(--color-text-primary); }
.frames-bible-review-fieldlabel {
    display: inline-block;
    margin-right: 6px;
    font-size: 9px;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text-muted);
}

.frames-bible-review-section {
    font-size: 10px;
    color: var(--color-text-muted);
    background: var(--color-bg-secondary);
    padding: 1px 7px;
    border-radius: var(--radius-full);
}
.frames-bible-review-jump {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-left: auto;
    padding: 2px 7px;
    font-size: 10px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    background: transparent;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}
.frames-bible-review-jump:hover { color: var(--color-accent-light); border-color: var(--color-border-accent); }
.frames-bible-review-jump i, .frames-bible-review-jump svg { width: 11px; height: 11px; }

.frames-bible-review-text {
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    line-height: var(--line-height-normal);
    margin-bottom: var(--space-1);
}
.frames-bible-review-summary {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    font-style: italic;
    margin-bottom: var(--space-2);
}
.frames-bible-review-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

/* Per-card decisions read GHOST, not filled: a rail of pending suggestions was a
   wall of solid-orange Accepts competing with the footer's real commit CTAs. The
   accent tint keeps the affordance; hover restores the full-strength button. */
.frames-bible-review-card .btn-primary {
    background: rgba(255, 122, 24, 0.10);
    color: var(--color-accent-light);
    border: 1px solid rgba(255, 122, 24, 0.35);
    box-shadow: none;
}
.frames-bible-review-card .btn-primary:hover {
    background: var(--color-accent);
    color: #fff;
    border-color: var(--color-accent);
}
.frames-bible-review-card .btn-secondary {
    background: transparent;
    border-color: transparent;
    color: var(--color-text-muted);
}
.frames-bible-review-card .btn-secondary:hover {
    background: rgba(148, 163, 184, 0.10);
    color: var(--color-text-secondary);
}

@media (prefers-reduced-motion: reduce) {
    .frames-bible-shimmer-bar { animation: none; }
    .frames-bible-editor-panel { transition: none; }
    .frames-bible-flash { animation: none; }
    .frames-bible-claim-text--btn { transition: none; }
}

/* ============================================================================
   Story Bible editor — FINALIZE / VERSION + AMBIENT STALENESS + CAST TAKEOVER
   (C1 Task 22). The version chip + history popover in the header, the persistent
   staleness rail + Re-generate CTA above the footer, the dismissible finalize
   violations card, and the "Driven by Story Bible" cast banner in Maintain Cast.
   ============================================================================ */

/* -------------------- Header version chip + history popover -------------------- */
.frames-bible-version-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: var(--space-2);
    padding: 2px 8px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: .01em;
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: 999px;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.frames-bible-version-chip:hover {
    color: var(--color-text-primary);
    border-color: var(--color-border-accent);
}
.frames-bible-version-chip--finalized {
    color: #22c55e;
    border-color: rgba(34, 197, 94, .4);
    background: rgba(34, 197, 94, .1);
}
.frames-bible-version-caret { opacity: .7; }

/* T14 — the header AGENCY-view toggle (a pill beside the version chip). Mirrors the
   version-chip pill; the --on state reads in the accent so the read-only agency view
   is visibly engaged. */
.frames-bible-view-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: var(--space-2);
    padding: 2px 8px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: .01em;
    color: var(--color-text-secondary);
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: 999px;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.frames-bible-view-toggle i, .frames-bible-view-toggle svg { width: 12px; height: 12px; flex-shrink: 0; }
.frames-bible-view-toggle:hover { color: var(--color-text-primary); border-color: var(--color-border-accent); }
.frames-bible-view-toggle--on {
    color: var(--color-accent-light);
    border-color: var(--color-border-accent);
    background: rgba(255, 140, 0, .1);
}

.frames-bible-version-menu {
    min-width: 200px;
    max-width: 320px;
    padding: var(--space-1);
}
/* C4 T13 — the verify / match / scan truth picker (reuses .frames-node-popover +
   .frames-menu-* chrome). One row per truth source (board crops / each live plan). */
.frames-bible-truth-picker {
    min-width: 220px;
    max-width: 340px;
    padding: var(--space-1);
}
.frames-bible-truth-picker .frames-bible-picker-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.frames-bible-version-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 6px 10px;
    font-size: 12px;
    border-radius: var(--radius-sm);
}
.frames-bible-version-row-v { font-weight: 700; color: var(--color-text-primary); }
.frames-bible-version-row-status {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--color-bg-tertiary);
    color: var(--color-text-muted);
}
.frames-bible-version-row-status--finalized { color: #22c55e; background: rgba(34, 197, 94, .12); }
.frames-bible-version-row-label { color: var(--color-text-muted); font-style: italic; }

/* -------------------- Ambient staleness rail (⚖ design §10) -------------------- */
/* T22 was a single row; C4 T12 grows a per-plan blast-radius LEDGER beneath it, so
   the strip is a column (head + optional ledger) and the head keeps the old row. */
.frames-bible-staleness {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border-top: 1px solid var(--color-border-default);
    background: var(--color-warning-bg);   /* warn wash — a calm, now-perceptible "needs attention" */
}
.frames-bible-staleness.hidden { display: none; }
.frames-bible-staleness-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}
.frames-bible-staleness-body {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 500;
    color: var(--color-text-secondary);
    min-width: 0;
}
.frames-bible-staleness-body i, .frames-bible-staleness-body svg { color: #fbbf24; flex-shrink: 0; }
.frames-bible-staleness-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.frames-bible-staleness-cta { flex-shrink: 0; }

/* -------------------- C4 T12: blast-radius ledger (per-plan downstream) -------------------- */
.frames-bible-ledger-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--color-text-secondary);
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color .15s ease, background .15s ease;
}
.frames-bible-ledger-toggle:hover { color: var(--color-text-primary); background: rgba(255, 255, 255, .06); }
.frames-bible-ledger-toggle i, .frames-bible-ledger-toggle svg { flex-shrink: 0; color: #fbbf24; }
.frames-bible-ledger-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    border-top: 1px solid var(--color-border-default);
    padding-top: var(--space-2);
}
.frames-bible-ledger-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 6px 8px;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-bg-tertiary);
}
.frames-bible-ledger-name {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    flex: 1 1 auto;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-primary);
}
.frames-bible-ledger-name i, .frames-bible-ledger-name svg { flex-shrink: 0; opacity: .7; }
.frames-bible-ledger-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frames-bible-ledger-meta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    font-size: 11px;
    color: var(--color-text-muted);
}
.frames-bible-ledger-affected { flex-shrink: 0; }
.frames-bible-ledger-cr {
    flex-shrink: 0;
    font-weight: 600;
    color: #fca5a5;
    padding: 1px 6px;
    border-radius: var(--radius-sm);
    background: rgba(239, 68, 68, .12);
}
.frames-bible-ledger-cr--free { color: var(--color-text-muted); background: var(--color-bg-secondary); font-weight: 500; }
.frames-bible-ledger-cta { flex-shrink: 0; }
@media (max-width: 640px) {
    .frames-bible-ledger-row { flex-wrap: wrap; }
    .frames-bible-ledger-cta { margin-left: auto; }
}

/* -------------------- Finalize violations card (dismissible) -------------------- */
.frames-bible-violations {
    margin: 0 var(--space-4) var(--space-3);
    padding: var(--space-3);
    border: 1px solid rgba(239, 68, 68, .4);
    border-radius: var(--radius-md);
    background: rgba(239, 68, 68, .08);
}
.frames-bible-violations.hidden { display: none; }
.frames-bible-violations-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}
.frames-bible-violations-title {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 700;
    color: #f87171;
}
.frames-bible-violations-dismiss {
    display: inline-flex;
    padding: 2px;
    color: var(--color-text-muted);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color .15s ease, background .15s ease;
}
.frames-bible-violations-dismiss:hover { color: var(--color-text-primary); background: var(--color-bg-tertiary); }
.frames-bible-violations-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.frames-bible-violation-row {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    font-size: 12px;
    color: var(--color-text-secondary);
}
.frames-bible-violation-tag {
    flex-shrink: 0;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: #fca5a5;
    padding: 1px 6px;
    border-radius: var(--radius-sm);
    background: rgba(239, 68, 68, .12);
}
.frames-bible-violation-msg { min-width: 0; }

/* -------------------- Maintain Cast: "Driven by Story Bible" banner -------------------- */
.frames-cast-bible-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: 8px 10px;
    border: 1px solid var(--color-border-accent);
    border-radius: var(--radius-md);
    background: rgba(255, 122, 24, .08);
}
.frames-cast-bible-banner.hidden { display: none; }
.frames-cast-bible-banner-text {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-accent-light);
    min-width: 0;
}
.frames-cast-bible-banner-text i, .frames-cast-bible-banner-text svg { flex-shrink: 0; }
.frames-cast-bible-unlink {
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--color-text-secondary);
    padding: 3px 10px;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}
.frames-cast-bible-unlink:hover { color: var(--color-text-primary); border-color: var(--color-border-accent); }

@media (prefers-reduced-motion: reduce) {
    .frames-bible-version-chip,
    .frames-bible-violations-dismiss,
    .frames-cast-bible-unlink { transition: none; }
}

/* ============================================================================
   Board-Locked Coverage (T8, storyboard-fidelity round)
   The Sources shot-list card gains a "Board-locked coverage" toggle + summary
   when the active Story Bible carries an extracted storyboard; the summary is
   mirrored (informational) atop the Coverage stage. Panel chips ride the Dailies
   grid + single view. Component classes only — dark-only, matches the badge/banner
   language already used across .frames-*. Injected by cinematic-frames.js.
   ============================================================================ */
.frames-board-panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}
.frames-board-panel.hidden { display: none; }

/* Toggle row — a title/sub stack on the left, a pure-CSS switch on the right. */
.frames-board-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: 10px 12px;
    border: 1px solid var(--color-border-accent);
    border-radius: var(--radius-md);
    background: rgba(255, 122, 24, 0.06);
    cursor: pointer;
}
.frames-board-toggle-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.frames-board-toggle-title {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text-primary);
}
.frames-board-toggle-title svg { width: 16px; height: 16px; color: var(--color-accent); flex-shrink: 0; }
.frames-board-toggle-sub { font-size: var(--font-size-xs); color: var(--color-text-muted); }

/* The switch — a styled checkbox (no Tailwind peer utilities, no extra span). */
.frames-board-toggle-input {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex-shrink: 0;
    width: 38px;
    height: 22px;
    margin: 0;
    border-radius: var(--radius-full);
    background: var(--color-bg-tertiary);
    cursor: pointer;
    transition: background 0.15s ease;
}
.frames-board-toggle-input::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.3));
    transition: transform 0.15s ease;
}
.frames-board-toggle-input:checked { background: var(--color-accent); }
.frames-board-toggle-input:checked::after { transform: translateX(16px); }
.frames-board-toggle-input:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Summary — mapped/total readout + LOUD overflow / desync chips + add-from-panel. */
.frames-board-summary { display: flex; flex-direction: column; gap: var(--space-2); }
.frames-board-summary.hidden { display: none; }
.frames-board-stat {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}
.frames-board-stat strong { color: var(--color-text-primary); font-variant-numeric: tabular-nums; }
.frames-board-stat svg { width: 14px; height: 14px; color: var(--color-accent); flex-shrink: 0; }

.frames-board-alert {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    font-size: var(--font-size-xs);
    line-height: 1.4;
}
.frames-board-alert svg { width: 14px; height: 14px; flex-shrink: 0; margin-top: 1px; }
.frames-board-alert--over {
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border: 1px solid var(--color-warning-border);
}
.frames-board-alert--over svg { color: var(--color-warning); }
.frames-board-alert--warn {
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border: 1px solid var(--color-warning-border);
    font-weight: 600;
}
.frames-board-alert--warn svg { color: var(--color-warning); }

.frames-board-adds { display: flex; flex-wrap: wrap; gap: 6px; }
.frames-board-add {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px 3px 7px;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.frames-board-add svg { width: 12px; height: 12px; }
.frames-board-add:hover:not(:disabled) {
    color: var(--color-text-primary);
    border-color: var(--color-border-accent);
    background: rgba(255, 140, 0, 0.12);
}
.frames-board-add:disabled { opacity: 0.4; cursor: not-allowed; }

/* Coverage-stage mirror — a slim informational strip above the plan review. */
.frames-board-coverage-strip {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    width: 100%;
    max-width: 880px;
    margin: 0 auto var(--space-4);
    padding: 12px 14px;
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    background: var(--color-bg-secondary);
}
.frames-board-coverage-strip.hidden { display: none; }

/* Panel chip — a tiny storyboard thumb + "board 12A". Grid overlay + single-view button. */
.frames-board-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    padding: 3px 8px 3px 3px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--radius-full);
    background: rgba(8, 12, 22, 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
}
.frames-board-chip img {
    width: 22px;
    height: 22px;
    border-radius: var(--radius-full);
    object-fit: cover;
    flex-shrink: 0;
}
.frames-board-chip-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.frames-result-overlay .frames-board-chip { align-self: flex-start; margin-top: 4px; }

.frames-board-chip--single {
    cursor: pointer;
    padding-right: 10px;
    border-color: var(--color-border-strong);
    transition: border-color 0.15s ease, background 0.15s ease;
}
.frames-board-chip--single svg { width: 14px; height: 14px; opacity: 0.8; }
.frames-board-chip--single:hover { border-color: var(--color-border-accent); background: rgba(8, 12, 22, 0.85); }

.frames-board-single { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); margin-top: var(--space-4); }
.frames-board-single.hidden { display: none; }

.frames-board-compare {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3);
    width: 100%;
}
.frames-board-compare.hidden { display: none; }
.frames-board-compare-cell {
    margin: 0;
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-bg-primary);
}
.frames-board-compare-cell img {
    display: block;
    width: 100%;
    height: auto;
    max-height: 48vh;
    object-fit: contain;
    background: #000;
}
.frames-board-compare-cell figcaption {
    padding: 6px 10px;
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--color-text-muted);
    text-align: center;
}

@media (prefers-reduced-motion: reduce) {
    .frames-board-toggle-input,
    .frames-board-toggle-input::after,
    .frames-board-add,
    .frames-board-chip--single { transition: none; }
}

/* Staged-source chips — story-bible intake box (2026-07-11) */
.frames-staged-chips:empty { display: none; }
.frames-staged-chip {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 6px; border-radius: 4px;
    background: rgba(148, 163, 184, 0.12);
    border: 1px solid rgba(148, 163, 184, 0.25);
    font-size: 11px; color: #cbd5e1; max-width: 220px;
}
.frames-staged-chip-kind { color: #f59e0b; font-weight: 600; text-transform: uppercase; font-size: 9px; }
.frames-staged-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frames-staged-chip-remove {
    background: none; border: none; color: #94a3b8; cursor: pointer;
    font-size: 13px; line-height: 1; padding: 0 2px;
}
.frames-staged-chip-remove:hover { color: #f87171; }

/* ============================================================================
   Cinematic Frames canvas redesign — workflow-rail A11Y polish (Task 9, spec §3).
   AUDIT-ADD (only-missing): the Step 7 audit found the rail render task (Tasks 2–3)
   ALREADY painted `.frames-rail-slab:focus-visible` (see :~9511) AND a reduced-motion
   guard neutralizing the running-lamp pulse (`.frames-rail-lamp--running { animation:
   none; }`, see :~9558). Per only-add-missing, those are NOT re-declared here — only
   the two genuinely-missing rules are appended. Standalone rules (lesson #34), at
   end-of-file so they follow every rail/stage family:
     • keyboard-visible focus ring on the ensemble chips (the slab ring already exists;
       `:focus-visible` out-specifies the single-class base — no !important needed);
     • reduced-motion neutralizes the active-slab transition (the lamp pulse is already
       covered; `transition: none` carries !important so it wins regardless of how the
       transition was applied by the rail task).
   ============================================================================ */
.frames-rail-chip:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .frames-rail-slab { transition: none !important; }
}

/* =============================================================================================
   ===== SCS ===== Studio Component System — foundations (P0c, Task 6)
   =============================================================================================
   Self-contained. Everything below is NEW and namespaced `.scs-*` / `@keyframes scs-*`; it
   overrides nothing above it and nothing above it targets these selectors, so this section can
   be moved or deleted as a unit. Later SCS phases APPEND here — never interleave with V1 blocks.

   House rules enforced in this section (V2 spec §3.1, grep-checkable in review):
     1. NO `transition: all`      — named properties only, so reduced-motion + the zero-duration
                                    contract are exact and nothing animates by accident.
     2. NO literal colors         — tokens only (the one documented exception is the select
                                    chevron: an SVG data URI cannot read a custom property).
     3. NO Tailwind `transition-*` / `animate-*` in SCS markup — `important: true` makes those
                                    utilities !important, and they would silently beat this file.
     4. All keyframes `scs-*`     — the `fadeIn` ×4 / `spin` ×5 collision class cannot recur.
     5. One physics, everywhere   — hover = tint at --motion-fast (+ translateY(-1px) on raised
                                    CTAs only); press = scale(0.98); disabled = opacity .45 +
                                    cursor:not-allowed + hover suppressed via :hover:not(:disabled);
                                    focus = :focus-visible 2px --accent outline, 2px offset, on
                                    EVERY interactive element.
   Modifier ordering inside each family is load-bearing: VARIANT modifiers are declared before
   SIZE modifiers, so `.scs-btn--primary.scs-btn--sm` resolves to the small height (equal
   specificity → last declaration wins).
   ============================================================================================= */

/* ---------------------------------------------------------------------------------------------
   Button — `.scs-btn` [+ --primary | --quiet | --danger | --icon] [+ --sm | --lg | --full]
   Ported from `.frames-toolbar-btn` (:107-160), the only button in the app authored as a state
   matrix. Additions over the donor: press transform, token-driven motion, a press color for
   filled variants, and a disabled opacity of .45 (the system value; the donor used .5).
   --------------------------------------------------------------------------------------------- */
.scs-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    height: 32px;
    padding: 0 12px;
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    line-height: 1;
    white-space: nowrap;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-default);
    background: transparent;
    color: var(--color-text-secondary);
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
    transition: background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out),
                transform var(--motion-fast) var(--ease-out);
}
.scs-btn i,
.scs-btn svg { width: 16px; height: 16px; flex-shrink: 0; }

.scs-btn:hover:not(:disabled) {
    background: var(--color-bg-hover);
    border-color: var(--color-border-strong);
    color: var(--color-text-primary);
}
.scs-btn:active:not(:disabled) {
    background: var(--color-bg-press);
    transform: scale(0.98);
}
.scs-btn:disabled,
.scs-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
}
.scs-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* --primary: the ONE terminal action per surface. Raised CTA → the only variant that lifts. */
.scs-btn--primary {
    height: 36px;
    padding: 0 16px;
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-on);
    font-weight: var(--font-weight-semibold);
}
.scs-btn--primary:hover:not(:disabled) {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: var(--accent-on);
    transform: translateY(-1px);
}
.scs-btn--primary:active:not(:disabled) {
    background: var(--accent-press);
    border-color: var(--accent-press);
    /* translateY(0) is explicit so the lift unwinds in the same declaration as the press. */
    transform: translateY(0) scale(0.98);
}

/* --quiet: the lowest tier. No border weight at rest; the border is the hover affordance. */
.scs-btn--quiet {
    color: var(--color-text-muted);
    border-color: transparent;
}
.scs-btn--quiet:hover:not(:disabled) {
    border-color: var(--color-border-default);
}

/* --danger: destructive, tinted rather than filled. `--color-error-text` is the palette's
   documented AA-passing on-dark label (tokens.css:34-37); a filled #ef4444 with white text is
   3.78:1 — AA-Large only. A filled destructive CTA can be added when a flow actually needs the
   weight; nothing in P0c/P1 does. */
.scs-btn--danger {
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
    color: var(--color-error-text);
}
.scs-btn--danger:hover:not(:disabled) {
    background: var(--color-error-bg);
    border-color: var(--color-error);
    color: var(--color-error-text);
}
.scs-btn--danger:focus-visible {
    outline-color: var(--color-error);
}

/* --icon: square; the icon is the whole label, so it needs an accessible name from the markup
   (aria-label / title). Sizes below keep width == height. */
.scs-btn--icon {
    width: 32px;
    padding: 0;
}

/* Size modifiers — declared AFTER the variants on purpose (see section header). */
.scs-btn--sm { height: 28px; padding: 0 10px; font-size: 12px; }
.scs-btn--lg { height: 36px; padding: 0 16px; }
.scs-btn--icon.scs-btn--sm { width: 28px; padding: 0; }
.scs-btn--icon.scs-btn--lg { width: 36px; padding: 0; }
.scs-btn--full { width: 100%; }

/* ---------------------------------------------------------------------------------------------
   Field — `.scs-field` wrapper + input / textarea / select / checkbox / toggle.
   Checkboxes and toggles are styled here from `appearance: none` — there is NO
   @tailwindcss/forms plugin installed (tailwind.config.js `plugins: []`), which is why the 18
   `form-checkbox`-idiom inputs in V1 markup render as unstyled OS boxes. SCS never depends on it.
   --------------------------------------------------------------------------------------------- */
.scs-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
}
.scs-field-label {
    display: block;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.scs-field-hint {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}
.scs-field-error {
    font-size: var(--font-size-xs);
    color: var(--color-error-text);
}
/* Horizontal row for controls whose label sits beside them (checkbox, toggle). */
.scs-field-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
.scs-field-row .scs-field-label { text-transform: none; letter-spacing: 0; cursor: pointer; }

.scs-input,
.scs-textarea,
.scs-select {
    width: 100%;
    min-width: 0;
    font-family: inherit;
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    /* The focus ring below fully replaces the UA outline — never drop one without the other. */
    outline: none;
    transition: border-color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out),
                background-color var(--motion-fast) var(--ease-out);
}
.scs-input,
.scs-select { height: 32px; padding: 0 var(--space-3); }
.scs-textarea {
    min-height: 88px;
    padding: var(--space-2) var(--space-3);
    line-height: var(--line-height-normal);
    resize: vertical;
}
.scs-input::placeholder,
.scs-textarea::placeholder { color: var(--color-text-disabled); }

.scs-input:hover:not(:disabled),
.scs-textarea:hover:not(:disabled),
.scs-select:hover:not(:disabled) { border-color: var(--color-border-hover); }

/* Text fields ring on ANY focus (mouse included) — a caret with no ring reads as broken.
   :focus-visible is added too so the keyboard case is never weaker than the pointer case. */
.scs-input:focus,
.scs-textarea:focus,
.scs-select:focus,
.scs-input:focus-visible,
.scs-textarea:focus-visible,
.scs-select:focus-visible {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--color-accent-muted);
}
.scs-input:disabled,
.scs-textarea:disabled,
.scs-select:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.scs-select {
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    padding-right: 30px;
    /* DOCUMENTED EXCEPTION to rule 2: an SVG data URI cannot read a custom property. The stroke
       is #94a3b8 == --color-text-muted; change both together. Identical chevron to .form-select
       (:526) so a native select next to an SCS one never shows two different arrows. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
}

/* --- Checkbox (self-styled, no plugin) --- */
.scs-checkbox {
    appearance: none;
    -webkit-appearance: none;
    flex-shrink: 0;
    display: inline-grid;
    place-content: center;
    width: 18px;
    height: 18px;
    margin: 0;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out);
}
.scs-checkbox::before {
    content: "";
    width: 11px;
    height: 11px;
    transform: scale(0);
    transform-origin: bottom left;
    /* Checkmark drawn by clipping a filled box — no icon font, no image request. The fill is an
       INSET box-shadow rather than a background-color on purpose: Windows High Contrast Mode
       strips background colors but keeps box-shadows, so the tick survives forced-colors. */
    box-shadow: inset 1em 1em var(--accent-on);
    clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
    transition: transform var(--motion-fast) var(--ease-out);
}
.scs-checkbox:checked {
    background: var(--accent);
    border-color: var(--accent);
}
.scs-checkbox:checked::before { transform: scale(1); }
.scs-checkbox:indeterminate {
    background: var(--accent);
    border-color: var(--accent);
}
.scs-checkbox:indeterminate::before {
    transform: scale(1);
    clip-path: polygon(0 38%, 100% 38%, 100% 62%, 0 62%);
}
.scs-checkbox:hover:not(:disabled) { border-color: var(--color-border-hover); }
.scs-checkbox:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.scs-checkbox:disabled { opacity: 0.45; cursor: not-allowed; }

/* --- Toggle (a checkbox that reads as a switch; same input, different affordance) --- */
.scs-toggle {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex-shrink: 0;
    width: 38px;
    height: 22px;
    margin: 0;
    background: var(--color-bg-tertiary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out);
}
.scs-toggle::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: var(--radius-full);
    background: var(--color-text-secondary);
    transition: transform var(--motion-fast) var(--ease-out),
                background-color var(--motion-fast) var(--ease-out);
}
.scs-toggle:checked {
    background: var(--accent);
    border-color: var(--accent);
}
/* 36px inner width − 2px inset − 16px thumb − 2px start = 16px of travel. */
.scs-toggle:checked::after {
    transform: translateX(16px);
    background: var(--accent-on);
}
.scs-toggle:hover:not(:disabled) { border-color: var(--color-border-hover); }
.scs-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.scs-toggle:disabled { opacity: 0.45; cursor: not-allowed; }

/* ---------------------------------------------------------------------------------------------
   Segment — one segmented control. Contract: `aria-pressed` on each button AND one `--active`
   class, period (V2 spec §3.1). Both selectors below are grouped so a consumer that sets only
   one of them still renders correctly — but components must set BOTH: the class paints, the
   attribute is what assistive tech reads.
   --------------------------------------------------------------------------------------------- */
.scs-segment {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
}
.scs-segment-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 28px;
    padding: 0 12px;
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    line-height: 1;
    white-space: nowrap;
    color: var(--color-text-muted);
    background: transparent;
    border: none;
    border-radius: calc(var(--radius-md) - 2px);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out);
}
.scs-segment-btn i,
.scs-segment-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
/* Both state selectors are excluded, not just the class — a consumer that sets only the attribute
   is out of contract, but it must not also get a hover repaint on the selected item. */
.scs-segment-btn:hover:not(:disabled):not(.scs-segment-btn--active):not([aria-pressed="true"]) {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}
.scs-segment-btn--active,
.scs-segment-btn[aria-pressed="true"] {
    background: var(--accent-soft);
    color: var(--accent);
    /* inset ring instead of a border so the button never changes size when it activates */
    box-shadow: inset 0 0 0 1px var(--color-border-accent);
}
.scs-segment-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.scs-segment-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.scs-segment--full { display: flex; width: 100%; }
.scs-segment--full .scs-segment-btn { flex: 1 1 0; min-width: 0; }

/* ---------------------------------------------------------------------------------------------
   Overlay — `.scs-overlay` > `.scs-overlay-backdrop` + `.scs-overlay-panel`.
   Reveal mechanics are owned by scs/overlay.js: rAF-gated `.scs-open` add, the same class removed
   on exit (symmetric, CSS-owned), and an exit that reads the COMPUTED duration below rather than
   assuming one — so reduced-motion (0ms) removes the node immediately and can never strand it.
   No `!important` on display: unlike `.studio-confirm` (which toggles `.hidden` on a singleton),
   SCS overlays are created and destroyed, so Tailwind's `!important .hidden` is never in play.
   --------------------------------------------------------------------------------------------- */
.scs-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-6);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-fast) var(--ease-out);
}
.scs-overlay.scs-open {
    opacity: 1;
    pointer-events: auto;
}
.scs-overlay-backdrop {
    position: absolute;
    inset: 0;
    background: var(--color-bg-scrim);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: pointer;
}
.scs-overlay-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 520px;
    max-height: 100%;
    overflow: hidden;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    transform: scale(0.96) translateY(8px);
    /* The one spring in the system — overlay panels only. */
    transition: transform var(--motion-gentle) var(--ease-spring);
}
.scs-overlay.scs-open .scs-overlay-panel { transform: scale(1) translateY(0); }
.scs-overlay-panel:focus { outline: none; }
.scs-overlay-header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-6) var(--space-4);
}
.scs-overlay-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    line-height: var(--line-height-tight);
}
.scs-overlay-body {
    padding: 0 var(--space-6) var(--space-5);
    overflow-y: auto;
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
}
.scs-overlay-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-6) var(--space-5);
    border-top: 1px solid var(--color-border-subtle);
}

/* ---------------------------------------------------------------------------------------------
   Popover + Chip — the deck's anchored surface.
   `.scs-popover` is ALWAYS portaled to document.body by scs/popover.js and positioned `fixed`
   from the anchor's rect. That is not a preference: the console deck creates a stacking context
   (z-index) and its backdrop-filter makes it the containing block for fixed descendants, so a
   popover left inside the deck would be both clipped and mispositioned.
   Cascade order below is load-bearing: base → placement variant → `.scs-open`. All three are
   (0,2,0); the open state must be declared LAST or the entry transform never unwinds. (Same
   class of trap as the `.frames-toolbar-overflow` comment at :163-168.)
   --------------------------------------------------------------------------------------------- */
.scs-popover {
    position: fixed;
    top: 0;
    left: 0;
    z-index: var(--z-popover);
    min-width: 200px;
    max-width: min(360px, calc(100vw - 16px));
    max-height: calc(100vh - 16px);
    overflow-y: auto;
    padding: var(--space-2);
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    pointer-events: none;
    transform: translateY(-4px);
    transition: opacity var(--motion-base) var(--ease-out),
                transform var(--motion-base) var(--ease-out);
}
.scs-popover[data-placement^="top"] { transform: translateY(4px); }   /* enters upward */
.scs-popover.scs-open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}
.scs-popover:focus { outline: none; }
.scs-popover-title {
    padding: var(--space-1) var(--space-2) var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-text-muted);
}

.scs-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    max-width: 100%;
    padding: 0 10px;
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    line-height: 1;
    white-space: nowrap;
    color: var(--color-text-secondary);
    background: transparent;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out);
}
.scs-chip i,
.scs-chip svg { width: 14px; height: 14px; flex-shrink: 0; }
.scs-chip-label { color: var(--color-text-muted); }
.scs-chip-value {
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
}
.scs-chip:hover:not(:disabled) {
    background: var(--color-bg-hover);
    border-color: var(--color-border-strong);
    color: var(--color-text-primary);
}
/* Open == active: the chip is the popover's anchor, so aria-expanded IS the state. */
.scs-chip[aria-expanded="true"],
.scs-chip--active {
    background: var(--accent-soft);
    border-color: var(--color-border-active);
    color: var(--color-text-primary);
}
.scs-chip:disabled { opacity: 0.45; cursor: not-allowed; }
.scs-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------------------------------------------------------------------------------------------
   Spinner — the only SCS animation that runs unattended, so it is the only one that needs a
   reduced-motion fallback rather than a stop (a frozen spinner reads as a hung app).
   --------------------------------------------------------------------------------------------- */
@keyframes scs-spin { to { transform: rotate(360deg); } }
.scs-spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    border: 2px solid var(--color-border-strong);
    border-top-color: var(--accent);
    border-radius: var(--radius-full);
    animation: scs-spin 700ms var(--ease-linear) infinite;
}

/* ---------------------------------------------------------------------------------------------
   Notify — toast exit (X5) + the assertive announce region  (P0c, Task 7)

   `.scs-toast-exit` is added by `dismissToast()` (studio-app.js) and is the ONLY thing that takes
   a toast off screen: both the auto-dismiss timer and the close button route through it. The
   keyframe name deliberately differs from the entry animation (`slideIn`, :775) — re-assigning the
   SAME name is precisely the X5 bug (a finished animation is updated in place, never re-triggered),
   so the exit never played.

   Geometry mirrors `slideIn` exactly (translateX 0 → 100%, opacity 1 → 0) so entry and exit are
   symmetric; the duration is the system's `--motion-base` rather than the entry's legacy 300ms —
   exits are quicker than entries by design, and a token duration is what makes the reduced-motion
   contract exact (the block below zeroes it, `dismissToast` reads the COMPUTED duration and removes
   the node immediately at 0 instead of awaiting an `animationend` that may never fire).

   Specificity note: `.toast` (:764) declares the entry `animation` shorthand with the same weight,
   so the compound selector — not source order alone — is what guarantees the override.
   --------------------------------------------------------------------------------------------- */
@keyframes scs-toast-out {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(100%); }
}
.scs-toast-exit,
.toast.scs-toast-exit {
    animation: scs-toast-out var(--motion-base) var(--ease-out) forwards;
    pointer-events: none;   /* no second close-click can land mid-exit */
}

/* The screen-reader-only surface. Notify owns one assertive region here (errors must be announced
   even when the visual toast is suppressed by the stack cap); `clip` is kept alongside `clip-path`
   because it is the only variant some older screen-reader/browser pairs honour. */
.scs-visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------------------------------------
   Skeleton + state detail — the shell's honest loading surface  (P0c, Tasks 8+9)

   Rendered by the loader into `#preview-panel` (and the control column) for the whole fetch
   window. It replaced a window in which the PREVIOUS tab's rendered output stayed on screen under
   the new tab's title — which reads as "the click did nothing" and earns a second click.

   Shape-of-the-content, not a spinner: the blocks below are sized like the media card and the
   fields that land in their place, so nothing jumps when the real fragment arrives. The shimmer is
   a background-position sweep (compositor-friendly, no layout) and it is the only SCS animation
   besides the spinner that runs unattended — under reduced motion it becomes a flat tint rather
   than a frozen gradient.
   --------------------------------------------------------------------------------------------- */
@keyframes scs-skeleton-sweep {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

.scs-skeleton {
    /* The base tint reads as "surface, not content" against both the stage gradient and the
       control column; the sweep is one step brighter, never accent-colored (a skeleton must not
       look interactive). */
    background-color: var(--color-bg-hover);
    background-image: linear-gradient(
        90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.06) 50%,
        transparent 100%
    );
    background-size: 200% 100%;
    background-repeat: no-repeat;
    border-radius: var(--radius-md);
    animation: scs-skeleton-sweep 1600ms var(--ease-linear) infinite;
}

.scs-skeleton-stage {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.scs-skeleton-media {
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-xl);
}

.scs-skeleton-meta {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.scs-skeleton-line { height: 12px; border-radius: var(--radius-full); }
.scs-skeleton-line--wide  { width: 45%; }
.scs-skeleton-line--short { width: 25%; }
.scs-skeleton-line--label { width: 35%; height: 10px; }

.scs-skeleton-controls {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
}

.scs-skeleton-block { height: 96px; }
.scs-skeleton-field { height: 32px; }
.scs-skeleton-cta   { height: 40px; border-radius: var(--radius-lg); margin-top: var(--space-2); }

/* The FloatingPanel minimize pill is CSS-positioned (`bottom: 16px`, :8975) while the panel's
   parking spots are computed in JS. Both have to clear the console deck or the pill lands behind
   it — this is the CSS half of `getConsoleClearance()` (floating-panel.js). Scoped to the shell's
   console-layout flag, so it is inert on every V1 tab. */
.scs-console-layout #preview-panel .floating-adjustment-pill {
    bottom: calc(16px + var(--console-clearance)) !important;
}

/* The technical reason under an honest error state: present, quiet, never the headline. */
.scs-state-detail {
    margin-top: var(--space-2);
    max-width: 340px;
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-normal);
    color: var(--color-text-disabled);
    word-break: break-word;
}

/* ---------------------------------------------------------------------------------------------
   THE reduced-motion block. One block, app-wide by construction: zeroing the tokens disables
   every SCS transition at once, including ones written by later phases, because SCS CSS is not
   allowed to hardcode a duration. Companion contract in JS: scs/overlay.js reads the computed
   duration and removes immediately at 0 (generation-bar.js:99-101 is the prior art), so nothing
   waits on a `transitionend` that will never fire.
   Resting transforms are neutralized explicitly — with 0ms durations they would otherwise paint
   one frame in their entry position and snap. Note `.scs-checkbox::before` is deliberately NOT
   reset: its scale(0) is the UNCHECKED state, not entry motion.
   --------------------------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    :root {
        --motion-fast: 0ms;
        --motion-base: 0ms;
        --motion-gentle: 0ms;
        --motion-slow: 0ms;
        --motion-stagger: 0ms;
    }
    .scs-overlay-panel,
    .scs-overlay.scs-open .scs-overlay-panel { transform: none; }
    .scs-overlay-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
    .scs-popover,
    .scs-popover[data-placement^="top"],
    .scs-popover.scs-open { transform: none; }
    .scs-btn:active:not(:disabled),
    .scs-btn--primary:hover:not(:disabled),
    .scs-btn--primary:active:not(:disabled) { transform: none; }
    .scs-spinner { animation-duration: 2400ms; }
    /* A skeleton must still read as "loading" without motion — the flat tint stays, the sweep
       goes. (Contrast with the spinner, which is slowed rather than stopped: a frozen spinner
       reads as a hung app, a frozen shimmer just reads as a placeholder.) */
    .scs-skeleton { animation: none; background-image: none; }
}


/* ============================================================
   SCS COMPONENT STYLES — folded from scs-fragments/ by the controller
   (Track 2 Wave A; one subsection per component, append-only)
   ============================================================ */

/* ---- scs-fragment: character-picker.css ---- */
/* ---------------------------------------------------------------------------------------------
   CharacterPicker — `select-row` density (P1a, Task 13; V2 spec §3.11)
   FRAGMENT: appended verbatim into the SCS section of components.css by the controller. It obeys
   that section's house rules — tokens only, no `transition: all`, no Tailwind `transition-*` /
   `animate-*` in the markup, focus rings on every interactive element (the select and the clear
   button inherit theirs from `.scs-select` / `.scs-btn`), and no hardcoded durations so THE
   reduced-motion block zeroes this family with everything else.

   The row is a 2-column grid: a fixed 40px identity thumb, then everything that can wrap.
   The label / control / note stack keeps a constant height whether or not a character is picked
   (the badge and the clear button occupy the control row only when there is something to clear,
   and the note collapses while empty), so choosing one does not shift the rows below it.
   --------------------------------------------------------------------------------------------- */
.scs-charpick {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* `hidden` is toggled in JS on elements this file gives a `display` to. An author rule beats the
   UA's `[hidden] { display: none }` regardless of specificity, so it has to be restated here —
   otherwise the clear button and the empty portrait would both stay on screen. */
.scs-charpick [hidden] {
    display: none;
}

.scs-charpick-row {
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr);
    gap: var(--space-3);
    align-items: start;
}

/* --- identity thumb --------------------------------------------------------------------------
   The portrait chain resolves in JS (`portrait || thumbnail || placeholder`); this only paints
   whichever of the two children the component un-hides. */
.scs-charpick-thumb {
    position: relative;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    /* Aligns the thumb with the SELECT, not with the label above it. */
    margin-top: 18px;
    overflow: hidden;
    border-radius: var(--radius-md);
    background: var(--color-bg-tertiary);
    box-shadow: inset 0 0 0 1px var(--color-border-subtle);
    transition: box-shadow var(--motion-fast) var(--ease-out);
}
/* A filled slot rings in accent — the one glance that says "this row is set". */
.scs-charpick-thumb[data-scs-empty="0"] {
    box-shadow: inset 0 0 0 1px var(--color-border-accent);
}
.scs-charpick-portrait {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.scs-charpick-thumb-icon {
    width: 18px;
    height: 18px;
    color: var(--color-text-disabled);
}
.scs-charpick-thumb[data-scs-empty="0"] .scs-charpick-thumb-icon {
    display: none;
}

/* --- label / control / note stack ----------------------------------------------------------- */
.scs-charpick-main {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}
.scs-charpick-label {
    display: block;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    cursor: pointer;
}
.scs-charpick-control {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}
.scs-charpick-select {
    flex: 1 1 auto;
    min-width: 0;
}

/* --- type badge ------------------------------------------------------------------------------
   Reads the same word the option text carries, so the row still says what kind of character this
   is once the select is collapsed to its value. `person` stays neutral: it is the default type
   and an accent on every row would spend the accent on nothing. */
.scs-charpick-badge {
    flex: 0 0 auto;
    padding: 0 var(--space-2);
    height: 20px;
    display: inline-flex;
    align-items: center;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: 1;
    white-space: nowrap;
    border-radius: var(--radius-full);
    background: var(--color-bg-hover);
    color: var(--color-text-secondary);
}
.scs-charpick-badge[data-type="animated_character"] {
    background: var(--accent-soft);
    color: var(--accent);
}
.scs-charpick-badge[data-type="subject"] {
    background: var(--color-info-bg);
    color: var(--color-info-text);
}

.scs-charpick-clear {
    flex: 0 0 auto;
}

/* --- the honesty line ------------------------------------------------------------------------
   Says why a selection disappeared (deleted / unshared / already in the other slot). It is a
   `role="status"` region that is always in the DOM and collapses while empty, so an assistive
   technology observes a stable node instead of one that appears and vanishes. */
.scs-charpick-note {
    margin: 0;
    font-size: var(--font-size-xs);
    line-height: var(--line-height-normal);
    color: var(--color-warning-text);
}
.scs-charpick-note:empty {
    display: none;
}

.scs-charpick-hint {
    margin: 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}
.scs-charpick-hint:empty {
    display: none;
}

/* --- error state -----------------------------------------------------------------------------
   Distinct from "no characters yet" on purpose: telling a user with forty characters that they
   have none is the lie this bar exists to prevent. Retry re-runs the store's forced revalidate. */
.scs-charpick-error {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-error-border);
    border-radius: var(--radius-md);
    background: var(--color-error-bg);
    color: var(--color-error-text);
    font-size: var(--font-size-xs);
}
.scs-charpick-error-text {
    flex: 1 1 auto;
    min-width: 0;
}

/* ---- scs-fragment: source-well.css ---- */
/* =============================================================================================
   SCS fragment — SourceWell  (P1a, Task 13b · spec §3.6, V1 §3.2 Row A ①)

   FRAGMENT FILE. Authored standalone so six concurrent Wave-A writers don't race on one file; the
   controller concatenates it into the `===== SCS =====` section of `static/studio/css/components.css`
   after the wave. It is APPEND-ONLY there: everything below is namespaced `.scs-well-*` /
   `@keyframes scs-well-*`, overrides nothing, and is targeted by nothing above it.

   House rules of that section, all honoured here (grep-checkable):
     1. no `transition: all` — named properties only, so the reduced-motion contract is exact
     2. no literal colors — tokens only
     3. no Tailwind `transition-*` / `animate-*` in the markup (component-authored DOM, no utilities,
        which is also why no rule here needs `!important` despite `important: true`)
     4. all keyframes `scs-*`
     5. one physics: hover = tint at --motion-fast · press = scale(0.98) · disabled = opacity .45
        · focus = :focus-visible 2px --accent outline at 2px offset on EVERY interactive element
     6. no hardcoded z integers — the × paints above the chip through DOM order (a positioned
        sibling declared after a static one), not through a z-index

   Geometry is the spec's: 44px tiles. Everything else is subordinate to that number.
   ============================================================================================= */

.scs-well {
    display: flex;
    align-items: center;
    min-width: 0;
    outline: none;              /* programmatic focus target (tabIndex -1) — never a visible stop */
}

.scs-well-track {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--space-2);
    min-width: 0;
    /* Deliberately NOT `overflow: hidden`: the component budgets its own width with the `+n`
       overflow tile, and clipping here would amputate focus rings and the corner ×. */
}

.scs-well-slot {
    position: relative;
    display: flex;
    align-items: center;
    min-width: 0;
    flex: 0 1 auto;
}

/* ---------------------------------------------------------------------------------------------
   The chip — 44px, portrait-led. Reads as "a thing that is loaded", not as a button that acts.
   --------------------------------------------------------------------------------------------- */
.scs-well-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 44px;
    max-width: 200px;
    min-width: 0;
    padding: 0 var(--space-3) 0 6px;
    font-family: inherit;
    text-align: left;
    background: var(--color-bg-hover);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
    transition: background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                transform var(--motion-fast) var(--ease-out);
}
.scs-well-chip:hover:not(:disabled) {
    background: var(--color-bg-press);
    border-color: var(--color-border-strong);
}
.scs-well-chip:active:not(:disabled) { transform: scale(0.98); }
.scs-well-chip:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.scs-well-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Thumb: the fastest read in the strip. The icon underneath is both the no-thumb placeholder and
   the expired-signed-URL fallback (the JS flips `data-thumb="failed"` on the slot). */
.scs-well-thumb {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    background: var(--color-bg-press);
    border-radius: var(--radius-sm);
}
.scs-well-thumb-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}
.scs-well-thumb-icon {
    width: 16px;
    height: 16px;
    color: var(--color-text-muted);
}
/* Present but silent while a real thumbnail is showing. */
.scs-well-thumb-img ~ .scs-well-thumb-icon { display: none; }
.scs-well-slot[data-thumb="failed"] .scs-well-thumb-img { display: none; }
.scs-well-slot[data-thumb="failed"] .scs-well-thumb-icon { display: block; }

/* Kind badge — a 15px disc on the thumb's corner. Tinted from the palette's AA-tuned on-dark
   label colors so kinds are separable at a glance without inventing a new color family. */
.scs-well-kind-badge {
    position: absolute;
    right: -3px;
    bottom: -3px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    border-radius: var(--radius-full);
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    color: var(--color-text-muted);
}
.scs-well-kind-badge i,
.scs-well-kind-badge svg { width: 9px; height: 9px; }
.scs-well-slot[data-kind="character"] .scs-well-kind-badge { color: var(--color-info-text); }
.scs-well-slot[data-kind="scene"]     .scs-well-kind-badge { color: var(--color-success-text); }
.scs-well-slot[data-kind="media"]     .scs-well-kind-badge { color: var(--color-warning-text); }

.scs-well-chip-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-width: 0;
}
.scs-well-chip-label {
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    line-height: 1.15;
    color: var(--color-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.scs-well-chip-kind {
    font-size: 10px;
    font-weight: var(--font-weight-medium);
    line-height: 1.1;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------------------------
   Remove — a sibling button (never nested inside the chip: a button inside a button is invalid
   and gets flattened), revealed on hover AND on :focus-within so it is never a hidden keyboard
   target. On touch there is no hover, so it is simply always visible.
   --------------------------------------------------------------------------------------------- */
.scs-well-remove {
    position: absolute;
    top: -6px;
    right: -6px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-full);
    color: var(--color-text-muted);
    cursor: pointer;
    opacity: 0;
    transform: scale(0.85);
    transition: opacity var(--motion-fast) var(--ease-out),
                transform var(--motion-fast) var(--ease-out),
                background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out);
}
.scs-well-remove i,
.scs-well-remove svg { width: 11px; height: 11px; }
.scs-well-slot:hover .scs-well-remove,
.scs-well-slot:focus-within .scs-well-remove {
    opacity: 1;
    transform: scale(1);
}
.scs-well-remove:hover {
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
    color: var(--color-error-text);
}
.scs-well-remove:active { transform: scale(0.92); }
.scs-well-remove:focus-visible {
    opacity: 1;
    transform: scale(1);
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
@media (hover: none) {
    .scs-well-remove { opacity: 1; transform: scale(1); }
}

/* ---------------------------------------------------------------------------------------------
   Empty slot — the invitation. Dashed, quiet, same 44px so the strip's rhythm never jumps when a
   source lands. Inert (and looks it) when the host wired no `onOpen`.
   --------------------------------------------------------------------------------------------- */
.scs-well-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 44px;
    min-width: 44px;
    max-width: 160px;
    padding: 0 var(--space-3);
    font-family: inherit;
    font-size: 12px;
    font-weight: var(--font-weight-medium);
    line-height: 1;
    color: var(--color-text-muted);
    background: transparent;
    border: 1px dashed var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out);
}
.scs-well-ghost i,
.scs-well-ghost svg { width: 14px; height: 14px; flex-shrink: 0; }
.scs-well-ghost-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.scs-well-ghost:hover:not(:disabled) {
    background: var(--color-bg-hover);
    border-color: var(--color-border-strong);
    color: var(--color-text-primary);
}
.scs-well-ghost:disabled {
    opacity: 0.45;
    cursor: default;
}
.scs-well-ghost:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Overflow `+n` — a chip by construction, so it keeps the strip's height and focus behavior. */
.scs-well-chip--overflow {
    justify-content: center;
    min-width: 44px;
    max-width: none;
    padding: 0 var(--space-3);
}
.scs-well-overflow-count {
    font-size: 13px;
    font-weight: var(--font-weight-semibold);
    line-height: 1;
    color: var(--color-text-secondary);
}

/* ---------------------------------------------------------------------------------------------
   Entry motion — only for chips that ARRIVE (update()), never for the restore pass: re-activating
   a tab must not read as a user action. Token-driven, so the app-wide reduced-motion block zeroes
   it with everything else (a 0ms animation simply never plays).
   --------------------------------------------------------------------------------------------- */
@keyframes scs-well-chip-in {
    from { opacity: 0; transform: scale(0.94); }
    to   { opacity: 1; transform: scale(1); }
}
.scs-well-slot--enter {
    animation: scs-well-chip-in var(--motion-gentle) var(--ease-out) both;
}

/* Laptop widths: compress, never to bare icons (V1 §3.2's glanceability rule). The name survives;
   the kind line drops, because the badge and the accessible name still carry it. */
@media (max-width: 1279px) {
    .scs-well-chip { max-width: 150px; }
    .scs-well-chip-kind { display: none; }
    .scs-well-ghost { max-width: 120px; }
}

/* ---- scs-fragment: state-progress.css ---- */
/* =================================================================================================
   ===== SCS ===== StateSurface + Progress (simple profile)          (P1a, Task 12)
   =================================================================================================
   APPEND-READY FRAGMENT. This file is not loaded by the browser: the controller concatenates it
   into the `===== SCS =====` section of `static/studio/css/components.css` after the wave (six
   concurrent writers on one file would race). Nothing here is a Tailwind class, so no
   `npm run build:css` is required for it.

   House rules obeyed (same list as the SCS section header):
     1. NO `transition: all` — named properties only.
     2. NO literal colors — tokens only.
     3. NO Tailwind `transition-*` / `animate-*` in the markup these rules style.
     4. All keyframes `scs-*`.
     5. One physics: hover = tint at --motion-fast; press = scale(0.98); disabled = opacity .45;
        focus = :focus-visible 2px --accent outline — all of which arrive with `.scs-btn`, which
        the CTA and the Retry button reuse rather than re-style.

   REUSED, NOT REDECLARED (they already exist in the SCS section — do not duplicate on merge):
     `.scs-skeleton` + `.scs-skeleton-media` / `-meta` / `-line*`   the loading pane's blocks
     `.scs-visually-hidden`                                         the announce lines
     `.scs-state-detail`                                            the quiet technical reason
     `.scs-btn` + variants                                          CTA and Retry
   The pending/error CELL family (`.scs-take-cell*`) belongs to TakeGrid (Task 10) and is
   deliberately absent here: Progress renders those cells through TakeGrid's `renderTakeCell`, so
   styling them from this file would fork a system family (V2 invariant 9).
   ================================================================================================= */

/* -------------------------------------------------------------------------------------------------
   StateSurface — one triad, four panes, mutually exclusive BY CONSTRUCTION.

   The panes are siblings that all exist for the surface's whole life; `show()` toggles the
   `hidden` PROPERTY and the `.hidden` class on each. Both matter: the property is CSS-independent
   truth (it survives a stylesheet that never loaded and it is what jsdom tests read), the class is
   what Tailwind's `!important` display rule keys on. `[hidden]` is therefore restated below with
   `!important` — `tailwind.config.js` sets `important: true`, so a utility class on a pane would
   otherwise beat the attribute and paint two states at once, which is the exact class of bug this
   component exists to kill.
   ------------------------------------------------------------------------------------------------- */
.scs-state {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    min-height: 0;
    flex: 1 1 auto;
}

.scs-state-pane[hidden] {
    display: none !important;
}

/* Every visible pane enters the same way: a short, small rise. `both` fill means a zeroed
   duration (reduced motion) lands on the final frame immediately rather than flashing the
   entry frame — no resting transform to neutralize, which is why this is an animation and
   not a transition. */
@keyframes scs-state-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: none; }
}

.scs-state-pane {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    animation: scs-state-in var(--motion-gentle) var(--ease-out) both;
}

/* --- the set-dressed panes (empty + error): one centred card ------------------------------------ */
.scs-state-pane--empty,
.scs-state-pane--error {
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: var(--space-2);
    padding: var(--space-10) var(--space-6);
}

/* The figure is a soft disc behind the icon, not a bare glyph floating in space — it gives the
   empty state a centre of gravity at the size a stage demands. */
.scs-state-figure {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    margin-bottom: var(--space-2);
    border-radius: var(--radius-full);
    background: var(--color-bg-hover);
    border: 1px solid var(--color-border-subtle);
    color: var(--color-text-muted);
}

.scs-state-figure--error {
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
    color: var(--color-error-text);
}

.scs-state-icon,
.scs-state-figure svg {
    width: 30px;
    height: 30px;
    stroke-width: 1.5;
}

.scs-state-title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    color: var(--color-text-primary);
}

.scs-state-body {
    margin: 0;
    max-width: 42ch;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
    color: var(--color-text-muted);
}

.scs-state-body[hidden],
.scs-state-title[hidden],
.scs-state-detail[hidden] {
    display: none !important;
}

.scs-state-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

.scs-state-actions:empty {
    display: none;
}

/* --- loading pane: shape-of-the-content, never a spinner ---------------------------------------- */
.scs-state-pane--loading {
    justify-content: center;
    padding: var(--space-6);
}

.scs-state-skeleton {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    width: 100%;
    max-width: 640px;
    margin: 0 auto;
}

/* --- content pane: a pass-through box, so hosts lay out their own children --------------------- */
.scs-state-pane--content {
    display: flex;
    flex-direction: column;
    overflow: visible;
}

/* --- densities ---------------------------------------------------------------------------------
   `stage-card` is the P1a density and needs no overrides (the base above IS it). The other two are
   authored so the API's `setDensity()` is never a promise the CSS cannot keep: `rail-compact` is
   the 360px Rack column, `inline-strip` is a one-line status inside an existing row. -------------- */
.scs-state--rail-compact .scs-state-pane--empty,
.scs-state--rail-compact .scs-state-pane--error {
    padding: var(--space-6) var(--space-4);
    gap: var(--space-1);
}
.scs-state--rail-compact .scs-state-figure {
    width: 44px;
    height: 44px;
    margin-bottom: var(--space-1);
}
.scs-state--rail-compact .scs-state-icon,
.scs-state--rail-compact .scs-state-figure svg { width: 20px; height: 20px; }
.scs-state--rail-compact .scs-state-title { font-size: var(--font-size-sm); }
.scs-state--rail-compact .scs-state-body { font-size: var(--font-size-xs); max-width: 28ch; }
.scs-state--rail-compact .scs-state-actions { margin-top: var(--space-3); }

.scs-state--inline-strip .scs-state-pane--empty,
.scs-state--inline-strip .scs-state-pane--error {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    text-align: left;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
}
.scs-state--inline-strip .scs-state-figure {
    width: 28px;
    height: 28px;
    margin-bottom: 0;
    flex-shrink: 0;
}
.scs-state--inline-strip .scs-state-icon,
.scs-state--inline-strip .scs-state-figure svg { width: 16px; height: 16px; }
.scs-state--inline-strip .scs-state-title { font-size: var(--font-size-sm); }
.scs-state--inline-strip .scs-state-body { font-size: var(--font-size-xs); max-width: none; }
.scs-state--inline-strip .scs-state-detail { margin-top: 0; }
.scs-state--inline-strip .scs-state-actions { margin-top: 0; margin-left: auto; }

/* -------------------------------------------------------------------------------------------------
   Progress (simple profile) — the in-flight grid.

   Progress owns the SLOTS (identity + layout); TakeGrid's `renderTakeCell` owns what sits inside
   them. A slot keeps its square while its item is in flight and while the host paints the finished
   card into it, so nothing reflows at the moment a generation lands — the single most visible
   jank in the donor tabs.
   ------------------------------------------------------------------------------------------------- */
.scs-progress {
    display: block;
    width: 100%;
}

/* THE SAME TRACK RULE AS `.scs-take-cells` (:17770), deliberately duplicated rather than shared:
   the two grids are stacked in one column and a run finishing must not re-flow the surface. A cell
   is `minmax(--scs-take-min, 1fr)` in flight and `minmax(--scs-take-min, 1fr)` when finished, so
   the rectangle a user is watching is the rectangle the image lands in.
   `data-cols` is still written by the JS (it is the job's own count and screen readers read the
   announce line, not the grid) but it no longer decides the layout — auto-fill follows the
   container, which is what makes the two owners agree at every Stage width. */
.scs-progress-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--scs-take-min, 200px), 1fr));
    gap: var(--space-3);
    width: 100%;
}

/* The slot is the SHAPE. It reads the same custom property TakeGrid's cells read, WITH THE SAME
   FALLBACK, so an in-flight cell and a finished card are one rectangle at every aspect the deck
   can select — the hardcoded `1 / 1` that used to live here is exactly what center-cropped a 16:9
   run and reflowed the stage at the completion instant.

   The fallback was `1 / 1` here and `16 / 9` on `.scs-take-cell` (take-grid.css) through P1. That
   never showed on Image Gen, because `_paintAspect()` writes `--scs-take-aspect` onto `.ig-results`
   — the shared ancestor of BOTH hosts — so the two resolved the same value by coincidence rather
   than by construction. P2 mounts Progress in a second host; a host that does not set the property
   on a common ancestor would get a 1:1 slot wrapping a 16:9 cell. Aligned to `16 / 9`, which is
   also the value `.scs-take-grid` declares on itself. */
.scs-progress-slot {
    position: relative;
    min-width: 0;
    aspect-ratio: var(--scs-take-aspect, 16 / 9);
    border-radius: var(--radius-lg);
}

/* An emptied slot (item complete, host has not painted into it yet, or chose its own grid and has
   not called releaseSlot) must not read as a broken tile: no border, no fill, just reserved space. */
.scs-progress-slot[data-status="complete"]:empty {
    background: none;
    border: none;
}

/* The cell FILLS the slot instead of sizing itself. `.scs-take-cell` carries its own
   `aspect-ratio`, and a child that resolves its own height is a second shape authority — the two
   disagreed by exactly the slot's padding-box rounding and the grid jumped on completion. With
   both dimensions definite the child's `aspect-ratio` is inert by spec, so there is one shape
   authority (the slot) and nothing to drift.

   Anything a HOST paints into a slot (a custom `renderCell`, its own complete-card) takes the
   generic rule below; nothing competes with it. */
.scs-progress-slot > * {
    position: absolute;
    inset: 0;
}

/* THE CELL NEEDS THE COMPOUND FORM, and this is the whole ledgered defect.
   `.scs-progress-slot > *` is specificity (0,1,0) — and so is `.scs-take-cell`, which is folded
   400+ lines LATER in this file (take-grid.css). On equal specificity the later rule wins, so
   `.scs-take-cell { position: relative }` beat `position: absolute`, `inset: 0` was inert, and
   the cell kept resolving its own height: the rule READ as a fix and did nothing for the whole of
   P1. `.scs-take-cell` + the class Progress stamps on every cell it mounts is (0,2,0) and wins
   regardless of source order — which is what makes the slot the single shape authority in fact
   and not just in the comment above.

   It is deliberately NOT solved by moving the fragment or by `!important`: fold order is not a
   contract anyone can see from this rule, and `important: true` in tailwind.config.js means a
   Tailwind utility on a child would still out-rank an `!important` here. Specificity is the only
   half of the cascade that a file-reading test can prove — `state-progress.test.js` does. */
.scs-take-cell.scs-progress--fill {
    position: absolute;
    inset: 0;
}

/* ---- scs-fragment: take-actions-viewer.css ---- */
/* =============================================================================================
   SCS fragment — TakeActions (3 densities) + Viewer            (P1a / T11, spec §3.4 + §3.5)

   Concatenated into components.css after the wave; it may therefore assume the SCS section that
   precedes it (`.scs-btn`, `.scs-overlay*`, `.scs-popover*`, the `--motion-*` / `--z-*` / spacing
   tokens and THE one reduced-motion block that zeroes those tokens app-wide).

   Rules this file lives under:
   - no hardcoded z integers — `--z-*` only (the scale is pinned by a file-reading test);
   - no hardcoded durations — `--motion-*` only, so the app-wide reduced-motion block reaches
     every transition written here without naming them;
   - `!important` only where Tailwind's `important: true` utilities would otherwise win. That is
     exactly one place: `[hidden]`. Preflight's `[hidden]{display:none}` is (0,1,0), the same
     specificity as `.scs-viewer-arm`, so a later class rule would beat it and paint a "hidden"
     media arm. Same trap as `.studio-confirm.hidden`.
   ============================================================================================= */

/* ---------------------------------------------------------------------------------------------
   The action rail — one registry, three densities.
   --------------------------------------------------------------------------------------------- */
.scs-take-rail {
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

/* ── density: card ──────────────────────────────────────────────────────────────────────────
   A hover strip pinned to the cell's top-right. The host cell must establish a containing block
   (TakeCard is `position: relative`); the rail deliberately does not mutate its parent.
   Reveal is driven by the PARENT's hover through `:hover >` rather than by naming the card class,
   so this file has no dependency on TakeGrid's markup. */
.scs-take-rail--card {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    z-index: var(--z-base);
    padding: 3px;
    border-radius: var(--radius-lg);
    background: var(--color-bg-surface);   /* the shipped glassmorphism token */
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: var(--shadow-md);
    opacity: 0;
    transform: translateY(-4px);
    pointer-events: none;
    transition: opacity var(--motion-fast) var(--ease-out),
                transform var(--motion-fast) var(--ease-out);
}
:hover > .scs-take-rail--card,
.scs-take-rail--card:focus-within {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
/* Touch has no hover: the rail is permanent, or it is unreachable. */
@media (hover: none) {
    .scs-take-rail--card {
        opacity: 1;
        transform: none;
        pointer-events: auto;
    }
}
.scs-take-rail--card .scs-take-action {
    width: 28px;
    height: 28px;
    padding: 0;
    border: none;
    background: transparent;
}
.scs-take-rail--card .scs-take-action:hover:not(:disabled) {
    background: var(--color-bg-hover);
}

/* ── density: viewer ────────────────────────────────────────────────────────────────────────
   The keyboard-complete surface: every applicable action, visible label, no overflow menu.

   ⚠ CONCAT-ORDER-PROOFING (and a flag for the wave review): `take-grid.css` ALSO declares a bare
   `.scs-take-rail` — as an absolutely positioned, `opacity: 0` hover rail. Same specificity
   (0,1,0) as a lone `--viewer` modifier, so whichever fragment is concatenated LAST would win and
   the Viewer footer would vanish into a corner. The two non-card densities therefore state their
   own layout at (0,2,0). The real fix is one renderer for this family (invariant 9) — see the T11
   report §3; until that is reconciled, do NOT "simplify" these compound selectors. */
.scs-take-rail.scs-take-rail--viewer {
    position: static;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
    opacity: 1;
    transform: none;
    pointer-events: auto;
}
.scs-take-rail--viewer .scs-take-action-label {
    font-size: 13px;
    line-height: 1;
}

/* ── density: menu ──────────────────────────────────────────────────────────────────────────
   The `.` / context-menu popover body. */
.scs-take-rail.scs-take-rail--menu {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    min-width: 180px;
    opacity: 1;
    transform: none;
    pointer-events: auto;
}
.scs-take-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    height: 32px;
    padding: 0 var(--space-2);
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    line-height: 1;
    text-align: left;
    white-space: nowrap;
    color: var(--color-text-secondary);
    background: transparent;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out);
}
.scs-take-menu-item i,
.scs-take-menu-item svg { width: 15px; height: 15px; flex-shrink: 0; }
.scs-take-menu-item:hover:not(:disabled) {
    background: var(--color-bg-hover);
    color: var(--color-text-primary);
}
.scs-take-menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.scs-take-menu-item:disabled { opacity: 0.45; cursor: not-allowed; }
.scs-take-menu-item[aria-pressed="true"] { color: var(--accent); }

/* ── states shared by every density ─────────────────────────────────────────────────────────
   pressed (a favorited take, a live adjust session) · busy (an in-flight run) · disabled. */
.scs-take-action[aria-pressed="true"],
.scs-take-menu-item[aria-pressed="true"] i,
.scs-take-action[aria-pressed="true"] i,
.scs-take-action[aria-pressed="true"] svg {
    color: var(--accent);
}
.scs-take-action[aria-pressed="true"] svg { fill: currentColor; }
.scs-take-action[aria-busy="true"],
.scs-take-menu-item[aria-busy="true"] {
    opacity: 0.6;
    cursor: progress;
}
/* The busy pulse is the only unattended motion here, so — like the spinner — it is slowed under
   reduced motion rather than frozen, which would read as a stuck button. */
@keyframes scs-take-busy { 50% { opacity: 0.35; } }
.scs-take-action[aria-busy="true"] i,
.scs-take-action[aria-busy="true"] svg,
.scs-take-menu-item[aria-busy="true"] i,
.scs-take-menu-item[aria-busy="true"] svg {
    /* `--ease-linear` is the documented curve for indeterminate progress, which is what this is. */
    animation: scs-take-busy 900ms var(--ease-linear) infinite;
}
.scs-take-more[aria-expanded="true"] {
    background: var(--accent-soft);
    color: var(--color-text-primary);
}

/* Prompt overlay (View prompt) — an Overlay panel, so only its body is styled here. */
.scs-prompt-overlay .scs-overlay-panel { max-width: 620px; }
.scs-prompt-text {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    color: var(--color-text-primary);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-relaxed);
}
.scs-prompt-meta {
    margin: var(--space-3) 0 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* =============================================================================================
   Viewer — the single-media view.

   It is mounted INSIDE the stage container (not portaled), because the Adjust action opens
   FloatingPanel over `.scs-viewer-media` and the panel's clearance clamp only applies to a
   container inside `#preview-panel`. So it takes `--z-overlay`: above stage content, below the
   modal family (`--z-modal`) that its own View-prompt overlay uses, and it never has to fight the
   console deck because it does not cover it.
   ============================================================================================= */
.scs-viewer {
    position: absolute;
    inset: 0;
    z-index: var(--z-overlay);
    display: flex;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-base) var(--ease-out);
}
.scs-viewer.scs-open {
    opacity: 1;
    pointer-events: auto;
}
/* On a console-layout tab the stage reserves `--console-clearance` at the bottom for the deck.
   `inset: 0` resolves against the padding box, so without this the viewer would slide under the
   deck — and take the adjustment panel's parking spot with it. Gated on the body flag because the
   token is defined globally but only MEANS something on a console tab. */
.scs-console-layout .scs-viewer { bottom: var(--console-clearance); }

.scs-viewer-scrim {
    position: absolute;
    inset: 0;
    background: var(--color-bg-scrim);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.scs-viewer-panel {
    position: relative;
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-width: 0;
    padding: var(--space-4);
    gap: var(--space-3);
    /* THE expand. `--motion-slow` is the large-surface step (Storyboard's 400ms treatment
       generalised); three sibling tabs hard-cut today. */
    transform: scale(0.985);
    transition: transform var(--motion-slow) var(--ease-out);
}
.scs-viewer.scs-open .scs-viewer-panel { transform: scale(1); }
.scs-viewer-panel:focus { outline: none; }
.scs-viewer-panel:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -4px;
}

/* ── bar ────────────────────────────────────────────────────────────────────────────────── */
.scs-viewer-bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex: 0 0 auto;
    min-width: 0;
}
.scs-viewer-heading {
    flex: 1 1 auto;
    min-width: 0;
}
.scs-viewer-title {
    margin: 0;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    color: var(--color-text-primary);
    /* Two lines, then ellipsis: a 90-character excerpt must not push the media down. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.scs-viewer-meta {
    margin: 2px 0 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.scs-viewer-counter {
    flex: 0 0 auto;
    padding: 0 var(--space-2);
    font-size: var(--font-size-xs);
    font-variant-numeric: tabular-nums;   /* the counter must not reflow as it counts */
    color: var(--color-text-muted);
}

/* ── stage ──────────────────────────────────────────────────────────────────────────────── */
.scs-viewer-stage {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex: 1 1 auto;
    min-height: 0;
}
.scs-viewer-media {
    position: relative;                   /* FloatingPanel's containing block */
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
}
.scs-viewer-arm[hidden] { display: none !important; }
.scs-viewer-image,
.scs-viewer-video {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}
.scs-viewer-image { cursor: grab; }       /* it is a drag source for the storyboard */
.scs-viewer-image:active { cursor: grabbing; }
.scs-viewer-audio { width: min(520px, 100%); }
.scs-viewer-text,
.scs-viewer-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    max-width: 640px;
    padding: var(--space-6);
    text-align: center;
    background: var(--color-bg-elevated);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-xl);
}
.scs-viewer-text-body {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    text-align: left;
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-relaxed);
}
.scs-viewer-error i,
.scs-viewer-error svg {
    width: 28px;
    height: 28px;
    color: var(--color-text-muted);
}
.scs-viewer-error-title {
    margin: 0;
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
}
.scs-viewer-error-body {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

/* ── nav ────────────────────────────────────────────────────────────────────────────────── */
.scs-viewer-nav {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    background: var(--color-bg-surface);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.scs-viewer-nav i,
.scs-viewer-nav svg { width: 20px; height: 20px; }
/* Disabled at the bounds — visible, not removed: the affordance has to stay in the same place or
   the remaining arrow jumps under the cursor at the ends of the run. */
.scs-viewer-nav:disabled {
    opacity: 0.3;
    cursor: default;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

/* ── footer ─────────────────────────────────────────────────────────────────────────────── */
.scs-viewer-footer {
    display: flex;
    justify-content: center;
    flex: 0 0 auto;
    padding-top: var(--space-1);
}

/* Narrow stages: the nav buttons overlay the media instead of stealing width from it. */
@media (max-width: 900px) {
    .scs-viewer-panel { padding: var(--space-3); }
    .scs-viewer-nav {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        z-index: var(--z-base);
    }
    .scs-viewer-nav--prev { left: 0; }
    .scs-viewer-nav--next { right: 0; }
    .scs-viewer-media { width: 100%; }
}

/* ---------------------------------------------------------------------------------------------
   Reduced motion. The token block upstream already zeroes every duration; what remains is the
   resting TRANSFORMS, which at 0ms would paint one frame in their entry position and snap.
   --------------------------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .scs-take-rail--card,
    :hover > .scs-take-rail--card,
    .scs-take-rail--card:focus-within { transform: none; }
    .scs-take-rail.scs-take-rail--viewer,
    .scs-take-rail.scs-take-rail--menu { transform: none; }
    .scs-viewer-panel,
    .scs-viewer.scs-open .scs-viewer-panel { transform: none; }
    .scs-viewer-scrim { backdrop-filter: none; -webkit-backdrop-filter: none; }
    .scs-take-action[aria-busy="true"] i,
    .scs-take-action[aria-busy="true"] svg,
    .scs-take-menu-item[aria-busy="true"] i,
    .scs-take-menu-item[aria-busy="true"] svg { animation-duration: 2400ms; }
    @media (max-width: 900px) {
        .scs-viewer-nav { transform: translateY(-50%); }   /* positional, not entry motion */
    }
}

/* ---- scs-fragment: take-grid.css ---- */
/* =================================================================================================
   SCS — TakeGrid / TakeCard  (P1a, Task 10)

   FRAGMENT. The controller concatenates the P1 fragments into the `===== SCS =====` section at the
   END of components.css after the wave (six concurrent writers on one file would race). Nothing
   here depends on source order: every selector is `.scs-take-*`, nothing above it targets these
   names, and the one place specificity matters is called out inline.

   House rules from the SCS section header apply verbatim: no `transition: all`, no literal colors
   (tokens only), no Tailwind `transition-*`/`animate-*` in the markup, all keyframes `scs-*`, one
   physics (hover = tint at --motion-fast, press = scale(0.98), disabled = .45 + not-allowed, focus
   = :focus-visible 2px --accent outline offset 2).

   The visual language is the Frames result card (components.css:12651+) re-authored on tokens:
   uniform aspect cells, image-first with the label revealed on hover, an accent hairline that
   lights on hover/focus, and the action rail as a compact row in the top-right corner. What the
   donor did with hardcoded oranges, `transition: all 0.2s`, and an ordering trick, this does with
   tokens, named properties, and explicit specificity.
   ================================================================================================= */

.scs-take-grid {
    /* Component-local aliases. `--scs-take-stagger` exists so a grid can override its ramp inline
       (TakeGrid.mount's staggerMs) WITHOUT shadowing the `--motion-stagger` token for its subtree —
       an inline token override would survive the reduced-motion media query. */
    --scs-take-stagger: var(--motion-stagger);
    --scs-take-aspect: 16 / 9;
    --scs-take-min: 200px;

    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.scs-take-cells {
    display: grid;
    /* auto-fill, not fixed breakpoints: the grid lives in the Stage, whose width changes when the
       Rack opens. Column count follows the container, so opening the drawer re-flows instead of
       cropping. */
    grid-template-columns: repeat(auto-fill, minmax(var(--scs-take-min, 200px), 1fr));
    gap: var(--space-3);
}

/* -------------------------------------------------------------------------------------------------
   Cell — the identity element. One aspect for pending, error and complete, so a cell resolving
   from shimmer to image causes ZERO layout shift (the donor's `--frames-cell-aspect` lift).
   ------------------------------------------------------------------------------------------------- */
/* Every custom property below carries its own fallback: `Progress` (T12) renders these same cells
   into containers that are NOT a `.scs-take-grid`, and an undefined var makes the whole
   declaration invalid — a cell with no `aspect-ratio` collapses to zero height. */
.scs-take-cell {
    position: relative;
    aspect-ratio: var(--scs-take-aspect, 16 / 9);
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--color-bg-secondary);
}

/* --- pending ------------------------------------------------------------------------------------ */
@keyframes scs-take-shimmer {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

.scs-take-shimmer {
    position: absolute;
    inset: 0;
    background-color: var(--color-bg-secondary);
    background-image: linear-gradient(
        90deg,
        transparent 0%,
        var(--color-bg-hover) 50%,
        transparent 100%
    );
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: scs-take-shimmer 1600ms var(--ease-linear) infinite;
}

/* Bottom-anchored, never full-cell: the status line must not cover the shimmer (that is the whole
   signal that something is happening). It paints above the shimmer by TREE ORDER — both are
   positioned and neither takes a z-index, which is how an SCS surface stacks locally (bare z
   integers are banned; the token scale is for app-level surfaces, not for two layers inside one
   card). Consequence to respect in JS: `renderTakeCell` must keep appending the status line AFTER
   the shimmer. */
.scs-take-cell-status {
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    background: linear-gradient(to top, var(--color-bg-scrim), transparent);
    pointer-events: none;
}

/* The pulse dot — the smallest honest "still working" signal; it carries no percentage, because
   this pipeline has none to report (report b §0: Image Gen's wire is synchronous). */
@keyframes scs-take-pulse {
    0%, 100% { opacity: 0.35; transform: scale(0.8); }
    50%      { opacity: 1;    transform: scale(1.15); }
}

.scs-take-cell-status::before {
    content: '';
    width: 6px;
    height: 6px;
    flex-shrink: 0;
    border-radius: var(--radius-full);
    background: var(--accent);
    animation: scs-take-pulse 1200ms var(--ease-out) infinite;
}

/* --- error -------------------------------------------------------------------------------------- */
.scs-take-cell--error {
    background: var(--color-error-bg);
    box-shadow: inset 0 0 0 1px var(--color-error-border);
}

.scs-take-error {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3);
    text-align: center;
}

.scs-take-error-icon,
.scs-take-error .scs-take-error-icon {
    width: 20px;
    height: 20px;
    color: var(--color-error-text);
}

.scs-take-error-text {
    font-size: var(--font-size-xs);
    line-height: var(--line-height-normal);
    color: var(--color-error-text);
    /* Provider errors run long; clamp rather than let one cell grow a scrollbar. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

/* -------------------------------------------------------------------------------------------------
   Card — the complete state. A real <button>, so Enter/Space open the Viewer with platform
   semantics and :focus-visible is the browser's own.
   ------------------------------------------------------------------------------------------------- */
.scs-take-card {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 1px solid var(--color-border-subtle);
    border-radius: inherit;
    background: var(--color-bg-secondary);
    color: var(--color-text-primary);
    cursor: pointer;
    overflow: hidden;
    /* Named properties only — `transition: all` is banned in system CSS. */
    transition:
        border-color var(--motion-fast) var(--ease-out),
        transform var(--motion-base) var(--ease-out),
        box-shadow var(--motion-base) var(--ease-out);
}

.scs-take-media {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Legibility layer for the caption. Always painted (a caption over a bright image is unreadable
   without it) but weak, so the image stays the subject; it strengthens on hover with the label. */
.scs-take-scrim {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top, var(--color-bg-scrim) 0%, transparent 45%);
    opacity: 0.55;
    transition: opacity var(--motion-fast) var(--ease-out);
}

.scs-take-label {
    position: absolute;
    left: var(--space-3);
    right: var(--space-3);
    bottom: var(--space-2);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
    opacity: 0;
    transform: translateY(4px);
    transition:
        opacity var(--motion-fast) var(--ease-out),
        transform var(--motion-fast) var(--ease-out);
}

.scs-take-card:hover {
    border-color: var(--color-border-active);
    transform: scale(1.02);
    box-shadow: var(--shadow-lg);
}

.scs-take-card:active {
    transform: scale(0.99);
}

.scs-take-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-color: var(--color-border-active);
}

.scs-take-card:hover .scs-take-scrim,
.scs-take-card:focus-visible .scs-take-scrim { opacity: 1; }

/* THE PLAY AFFORDANCE (P2). A video Take that carried a poster rendered as a plain `<img>` —
   pixel-identical to a still, with nothing saying there was anything to play. The thumb stays an
   `<img>` on purpose (N `<video preload="metadata">` tiles is N range requests and N decoders for
   clips nobody is playing), so this badge is what makes the tile READ as a clip.

   Centred over the media and pointer-transparent: the card underneath is the button, and a second
   click target inside it would be a second thing to Tab to for the same action. */
.scs-take-play {
    position: absolute;
    top: 50%;
    left: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
    color: var(--color-text-primary);
    background: var(--color-bg-scrim);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-full);
    pointer-events: none;
    opacity: 0.85;
    transition: opacity var(--motion-fast) var(--ease-out),
                transform var(--motion-fast) var(--ease-out);
}

.scs-take-play i,
.scs-take-play svg { width: 18px; height: 18px; }

.scs-take-card:hover .scs-take-play,
.scs-take-card:focus-visible .scs-take-play {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.06);
}

.scs-take-card:hover .scs-take-label,
.scs-take-card:focus-visible .scs-take-label {
    opacity: 1;
    transform: translateY(0);
}

/* -------------------------------------------------------------------------------------------------
   Reveal — the ONE stagger implementation (retires four copy-pasted `setTimeout(i * 150)` sites).
   `both` fill matters: without it the card paints at full opacity for the length of its delay and
   then fades in from nothing, which is the flicker the copies all had.
   ------------------------------------------------------------------------------------------------- */
@keyframes scs-take-reveal {
    from { opacity: 0; transform: translateY(6px) scale(0.985); }
    to   { opacity: 1; transform: none; }
}

.scs-take-cell--reveal {
    animation: scs-take-reveal var(--motion-gentle) var(--ease-out) both;
    animation-delay: calc(var(--scs-stagger-index, 0) * var(--scs-take-stagger, var(--motion-stagger)));
}

/* -------------------------------------------------------------------------------------------------
   Action rail — NOT STYLED HERE, and that is the contract.

   `TakeActions` (take-actions-viewer.css) owns `.scs-take-rail` in all three densities; this file
   declared a second one and the two collided at equal specificity, so whichever fragment was
   concatenated last would have won (the Viewer footer landing in a corner). One renderer, one
   stylesheet, per invariant 9.

   What this file owes the rail is only the geometry it depends on, and `.scs-take-cell` already
   provides it: `position: relative` (the containing block `.scs-take-rail--card` pins to) and a
   hovered parent (its reveal is a `:hover >` on the direct parent — which is why the grid appends
   the rail element straight into the cell, with no wrapper). The `z-index` that used to live here
   was a bare `2`; z integers are banned in SCS surfaces and the rail now takes `var(--z-base)`
   from its own file.
   ------------------------------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------------------------------
   Badges — the injected `badges[]` slot plus the built-in "from another session" mark (§3.3's
   multi-user clause). Quiet by construction: glass chip, muted label, no accent — it is provenance,
   not a call to action.
   ------------------------------------------------------------------------------------------------- */
/* Same stacking rule as the status line: badges are appended after the card, so tree order puts
   them over the media without a z-index. The injected rail is appended after the badges and lands
   on top of both. */
.scs-take-badges {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    max-width: calc(100% - var(--space-12));
    pointer-events: none;
}

.scs-take-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    max-width: 100%;
    padding: 2px var(--space-2);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full);
    background: var(--color-bg-surface);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    line-height: var(--line-height-tight);
    color: var(--color-text-secondary);
}

.scs-take-badge i,
.scs-take-badge svg {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

.scs-take-badge-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scs-take-badge--quiet {
    color: var(--color-text-muted);
    border-color: var(--color-border-subtle);
}

/* An out-of-session cell is dimmed by a hair until the user touches it — present, clearly not part
   of what this window just produced. */
.scs-take-cell--foreign .scs-take-card { opacity: 0.88; }
.scs-take-cell--foreign .scs-take-card:hover,
.scs-take-cell--foreign .scs-take-card:focus-visible { opacity: 1; }

/* -------------------------------------------------------------------------------------------------
   Grouped run row (§4.1) — an in-place cross-tool run inside the host tab's grid.
   ------------------------------------------------------------------------------------------------- */
.scs-take-run {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.scs-take-run-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--color-border-subtle);
}

.scs-take-run-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    color: var(--accent);
}

.scs-take-run-label {
    margin: 0;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-secondary);
}

.scs-take-run-count {
    margin-left: auto;
    font-size: var(--font-size-xs);
    font-variant-numeric: tabular-nums;   /* the count must not jitter as it climbs */
    color: var(--color-text-muted);
}

/* -------------------------------------------------------------------------------------------------
   Reduced motion. The tokens are already zeroed globally by the SCS block in components.css, which
   covers every transition here. What still needs an explicit stop is the three KEYFRAME animations
   (a duration token does not reach them) — and the shimmer keeps its flat tint so a pending cell
   still reads as "placeholder" rather than as an empty box.
   ------------------------------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .scs-take-shimmer { animation: none; background-image: none; }
    .scs-take-cell-status::before { animation: none; opacity: 1; }
    .scs-take-cell--reveal { animation: none; }
    .scs-take-card:hover,
    .scs-take-card:active { transform: none; }
    .scs-take-label { transform: none; }
    /* `.scs-take-rail` is deliberately absent — TakeActions owns that class and its own
       reduced-motion block. */
}

/* ---- scs-fragment: image-gen-pilot.css ---- */
/* -------------------------------------------------------------------------------------------------
   ===== SCS ===== Image Gen pilot — deck body, stage, history strip           (P1a, Task 15)

   The SHELL owns the deck's chrome (`.scs-console*`, layout.css) and the rack's (`.scs-rack*`);
   the COMPONENTS own their own families (`.scs-well-*`, `.scs-charpick-*`, `.scs-take-*`,
   `.scs-state-*`, `.scs-progress-*`). What is left — and all this subsection contains — is the
   tab's own composition: how the well, the prompt and the CTA share Row A, how the chips share
   Row B, and how the stage stacks its history strip over the results.

   House rules held here: no literal colors, no `transition: all`, no hardcoded durations (the ONE
   reduced-motion block zeroes every token), no hardcoded z integers, and every selector prefixed
   `.ig-` so nothing can collide with a component family.
   ------------------------------------------------------------------------------------------------- */

/* ── Row A — the take ─────────────────────────────────────────────────────────────────────────── */

/* The well is content-sized: an empty well is three 44px invitations, and it must never take the
   room the prompt needs. */
.ig-well-host {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 40%;
}

/* The prompt is the deck's center of gravity — it takes every pixel the other two do not, and it
   never drops below the 400px the V1 width budget reserves for it. */
.ig-prompt-wrap {
    position: relative;
    display: flex;
    flex: 1 1 auto;
    align-items: flex-start;
    min-width: min(400px, 100%);
    padding: 0 var(--space-2);
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    transition: border-color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out);
}
.ig-prompt-wrap:focus-within {
    border-color: var(--color-border-active);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* One line at rest, growing to six (the JS writes the height; this owns the rhythm). `resize:none`
   because a hand-dragged textarea would break the deck's two-row grammar. */
.ig-prompt {
    flex: 1 1 auto;
    min-width: 0;
    /* border-box (Tailwind preflight) means padding eats the CONTENT box: a 22px box with 5px
       padding leaves 12px for a 22px line and clips the descenders. Rest height is one line PLUS
       the padding, and the six-line ceiling is computed the same way. */
    height: 32px;
    max-height: 142px;         /* 6 × 22px line + 10px padding */
    padding: 5px var(--space-2);
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: 22px;
    color: var(--color-text-primary);
    background: transparent;
    border: none;
    outline: none;
    resize: none;
    overflow-y: hidden;
    transition: box-shadow var(--motion-base) var(--ease-out);
}
.ig-prompt::placeholder { color: var(--color-text-disabled); }

/* Arrival + enhancement acknowledgements. Text that changed under the user's hands has to say so;
   these are the two places this tab writes the prompt itself. */
.ig-prompt--arrived { box-shadow: inset 0 0 0 2px var(--color-border-active); }
.ig-prompt--enhanced { box-shadow: inset 0 0 0 2px var(--color-success-border); }

.ig-enhance {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    align-self: center;
    height: 26px;
    padding: 0 10px;
    font-family: inherit;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    cursor: pointer;
    transition: color var(--motion-fast) var(--ease-out),
                background-color var(--motion-fast) var(--ease-out);
}
.ig-enhance i,
.ig-enhance svg { width: 13px; height: 13px; }
.ig-enhance:hover:not(:disabled) { color: var(--accent); background: var(--accent-soft); }
.ig-enhance:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ig-enhance:disabled { opacity: 0.5; cursor: progress; }
/* The system spinner treatment, not a second one: same keyframe, same 700ms, same `--ease-linear`
   as `.scs-spinner` (:16419). The hand-rolled `900ms linear` was both a hardcoded duration in a
   subsection whose header forbids them and — worse — invisible to the reduced-motion arm below,
   which only knew about `.scs-spinner`. */
.ig-enhance.is-busy i,
.ig-enhance.is-busy svg { animation: scs-spin 700ms var(--ease-linear) infinite; }

/* The one orange object. Its price lives inside it, so the number and the action are one target. */
.ig-cta {
    flex-shrink: 0;
    gap: var(--space-2);
}
.ig-cta-cost {
    font-variant-numeric: tabular-nums;   /* the price must not jitter as it changes */
    font-weight: var(--font-weight-medium);
    opacity: 0.85;
}
.ig-cta:disabled .ig-cta-cost { opacity: 1; }
.ig-cta--busy .ig-cta-icon { animation: scs-spin 700ms var(--ease-linear) infinite; }

/* SLOWED, NEVER STOPPED — the `.scs-spinner` contract (:16589), which these two now share. A
   frozen spinner reads as a hung app; at 2400ms it still says "working" without the motion.
   The ONE app-wide reduced-motion block cannot reach these, because a keyframe animation's
   duration is not a token it can zero — so the arm is stated here, next to the animations it
   governs, rather than duplicating the block. */
@media (prefers-reduced-motion: reduce) {
    .ig-enhance.is-busy i,
    .ig-enhance.is-busy svg,
    .ig-cta--busy .ig-cta-icon { animation-duration: 2400ms; }
}

/* ── Row B — the settings rail ────────────────────────────────────────────────────────────────── */

.ig-row-spacer { flex: 1 1 auto; min-width: var(--space-2); }
.ig-chip { flex-shrink: 0; }
.ig-clear { flex-shrink: 0; }

/* Chip popover panels park here while closed so their ids never leave the document.
   `display: none` UNCONDITIONALLY, not `[hidden]`: the store is never a visible surface — a panel
   is MOVED out of it into the popover and back — and an author `display` rule on this element
   would beat the UA's `[hidden] { display: none }` regardless of specificity, which is exactly how
   four settings panels ended up rendering inline in Row B during the first width measurement. */
.ig-panels { display: none; }
.ig-panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 220px;
    padding: var(--space-1);
}
.ig-panel .scs-select { width: 100%; }

/* Below ~1200px the CATEGORY label drops and the live VALUE stays. Compressing to bare icons would
   throw away exactly the glanceable state the chips exist for (V1 §3.2). */
@media (max-width: 1199px) {
    .ig-chip .scs-chip-label { display: none; }
    .ig-clear .ig-clear-label { display: none; }
    .ig-clear { width: 28px; padding: 0; justify-content: center; }
    .ig-enhance .ig-enhance-label { display: none; }
    .ig-enhance { width: 26px; padding: 0; justify-content: center; }
}

.ig-shortcuts {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 260px;
}
.ig-shortcut-row {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}
.ig-shortcut-row kbd {
    flex: 0 0 auto;
    min-width: 108px;
    font-family: inherit;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* ── The rack's own fields ────────────────────────────────────────────────────────────────────── */

.ig-rack-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    margin-top: var(--space-3);
}
.ig-rack-field .scs-input { width: 100%; }

.ig-notice {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-xs);
    line-height: 1.5;
    color: var(--color-warning-text);
    background: var(--color-warning-bg);
    border: 1px solid var(--color-warning-border);
    border-radius: var(--radius-md);
}
.ig-notice i,
.ig-notice svg { width: 14px; height: 14px; flex-shrink: 0; margin-top: 1px; }

/* ── The stage ────────────────────────────────────────────────────────────────────────────────── */

/* THE STAGE FILLS ITS PANEL. `#preview-panel` is a column flex container whose content box already
   ends above the deck (`#preview-panel.scs-stage { padding-bottom: var(--console-clearance) }`,
   layout.css:690), so `flex-grow: 1` here is the whole "between the header and the deck clearance"
   contract — the same one every full-height stage in the app resolves through its panel.
   `flex-shrink: 0` keeps the other half honest: a stage taller than the panel stays at its content
   height and `#preview-panel`'s own `overflow-y: auto` scrolls it, instead of the grid being
   squeezed to fit.

   This is load-bearing, not cosmetic. The Viewer mounts INSIDE this element (`openViewer` passes
   `_stageEl`) and takes `position: absolute; inset: 0`, so the stage's height IS the Viewer's
   height. While the stage was content-sized, a 1024×1024 result opened into an 89 px picture —
   smaller than the card it was opened from, and a different size depending on how many cards were
   behind it (P1a gate finding F-2).

   `position: relative` is DECLARED, not left to `viewer.js`'s static-position fallback
   (viewer.js:264): a containing block this layout depends on belongs in the stylesheet, where it
   can be read, not in an inline style written by whichever component happens to mount first. */
.ig-stage {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
    gap: var(--space-5);
    width: 100%;
    max-width: 1120px;      /* the deck's own width: results and controls share one column */
    margin: 0 auto;
}

/* ONE CLEARANCE, CLAIMED ONCE. `.scs-console-layout .scs-viewer { bottom: var(--console-clearance) }`
   (:17536) is written for a Viewer whose containing block is `#preview-panel`'s PADDING box, where
   the deck really does overlay the bottom 132px. This stage lives INSIDE that padding, so the same
   rule would subtract the clearance a second time and give back a band 132px shorter than the
   surface it covers. The `.scs-console-layout` prefix is carried so this wins on specificity (0,3,0
   vs 0,2,0) rather than on the order the fragments happen to be concatenated in. */
.scs-console-layout .ig-stage > .scs-viewer { bottom: 0; }

/* RE-HOMED to the top of the stage. `absolute bottom-4` put it under a 3-image grid — and now
   under the deck. */
.ig-history {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--color-border-subtle);
}
.ig-history-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
}
.ig-history-title {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}
.ig-history-all {
    font-family: inherit;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    background: none;
    border: none;
    cursor: pointer;
    transition: color var(--motion-fast) var(--ease-out);
}
.ig-history-all:hover { color: var(--color-text-primary); }
.ig-history-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ig-history-items {
    display: flex;
    gap: var(--space-3);
    overflow-x: auto;
    padding-bottom: var(--space-1);
}
/* A history entry is a real button now (it opens the viewer), so it needs the button reset that
   `.history-item` — written for a `<div>` — never had. */
.ig-history-item {
    flex-shrink: 0;
    padding: 0;
    background: none;
    cursor: pointer;
}
.ig-history-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The surface takes whatever the history strip leaves, so `StateSurface`'s own `flex: 1 1 auto`
   (:17103) has a definite box to resolve against: its empty and error panes are authored
   `justify-content: center` for a stage-sized card, and in a content-height host that centring had
   nothing to centre in. `min-height: 0` because the content pane holds a scrollable grid — without
   it the automatic minimum size of a flex item would push the stage past its panel. */
.ig-surface {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
}

/* Two owners, one visual grid: Progress paints the in-flight cells, TakeGrid the finished Takes.
   They are stacked, and because completion moves every index in a single tick the seam is only
   ever visible during a partial run — where it is the honest picture (finished above, failed
   below).

   `--scs-take-aspect` is set on this wrapper by `_paintAspect()` and INHERITS into Progress's
   slots (`.scs-progress-slot` reads it at :17291). It does NOT reach TakeGrid's cells, because
   `.scs-take-grid` declares the same property on itself (:17757) and a declared value beats an
   inherited one — so `_paintAspect()` writes the grid root INLINE as well. Two writes, one shape;
   see the method's own docblock for why one is not enough. */
.ig-results {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    width: 100%;
}
.ig-grid-host:empty,
.ig-progress-host:empty { display: none; }

/* ---- scs-fragment: director-action.css ---- */
/* ==============================================================================================
   `director-variations` — the portable-takes confirm dialog (P1b, T17).

   Everything here sits INSIDE an SCS `Overlay`, so the reveal, the backdrop, the Tab trap and the
   Escape layer are already owned (`.scs-overlay*` at :16255). What this block adds is the dialog's
   own anatomy: a source thumbnail in the header, a column of labelled segmented groups, and a
   footer that carries the price on the left and the two decisions on the right.

   The choices are inline `.scs-segment` groups on purpose, NOT popovers: an Overlay's Tab trap
   owns `panelEl` and `Popover` portals to `document.body`, so popover controls inside an overlay
   are keyboard-unreachable (`overlay.js:27-33`). This is the arrangement that note prescribes.

   No motion is declared here at all — the panel's own spring and the segment buttons' hover
   transitions come from the primitives, which already carry the reduced-motion contract.
   ============================================================================================== */

/* Wider than the 520px default: five labelled control rows read as a form, not a prompt. */
.scs-overlay-panel.scs-dirvar { max-width: 560px; }

.scs-dirvar .scs-overlay-header { align-items: center; }

/* A 1:1 crop of the source. Decorative — the header text names the take — so `alt=""`. */
.scs-dirvar-thumb {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border-default);
    background: var(--color-bg-primary);
}
.scs-dirvar-headtext { min-width: 0; }
.scs-dirvar-sub {
    margin-top: var(--space-1);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    line-height: var(--line-height-normal);
    /* One line, ellipsised: a 110-char excerpt must never push the controls off screen. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scs-dirvar-fields {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}
.scs-dirvar-field {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
}
/* `.scs-segment` is inline-flex and would overflow with eight aspect ratios in it; the two groups
   that can exceed the panel width wrap instead of scrolling, because a segmented control that
   scrolls hides options the user is being asked to choose between. */
.scs-dirvar-seg--wrap { flex-wrap: wrap; }

.scs-dirvar-field .scs-field-hint { margin: 0; }
/* An empty hint is the resolved state — no reserved gap for a line that is not there. */
.scs-dirvar-field .scs-field-hint:empty { display: none; }

/* The footer carries money, so it is two-sided: the quote reads first, the decisions sit right. */
.scs-overlay-footer.scs-dirvar-foot {
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
}
.scs-dirvar-status {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 200px;
}
.scs-dirvar-price {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    /* Tabular figures so the number does not jitter as the selection changes. */
    font-variant-numeric: tabular-nums;
}
/* The honest reason Run is disabled. Never a price, never a guess — see `openConfirm`'s repaint. */
.scs-dirvar-reason {
    font-size: var(--font-size-xs);
    line-height: var(--line-height-normal);
    color: var(--color-text-muted);
}
.scs-dirvar-reason:empty { display: none; }
.scs-dirvar-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}

/* ---- scs-fragment: scs-sheet.css ---- */
/* =============================================================================================
   SCS — ConsoleDock extension sheet (P2)

   The deck's surface for a flow too rich for a chip (V1 spec §3.2): Video's reference tray, its
   frame pair. It RISES FROM the deck rather than replacing the stage, which is the whole reason it
   is not an Overlay — the user is still looking at the media the flow is about.

   Geometry mirrors the deck exactly (same max-width, same horizontal inset, same radius family) so
   the two read as one column of chrome rather than as two unrelated panels. It is a SIBLING of the
   deck inside `#console-dock`, so it inherits that container's `pointer-events: auto` rule and is
   unaffected by the deck's own minimize transform.

   ⚠ THIS BLOCK DEPENDS ON `#console-dock { flex-direction: column }` (layout.css). Every
   declaration below — `margin-bottom` as the gap ABOVE the deck, the shared `max-width`, the whole
   "rises from" reading — is a column statement. Under the flex default (`row`) the sheet and the
   deck are two items on one line and both shrink: measured at 1440, sheet x=272 w=560 beside a
   deck squeezed 1052→592. The direction is pinned by a file-level assertion in
   `console-dock-sheet.test.js` for exactly that reason; jsdom can see neither.

   Motion is the overlay-PANEL treatment — `--motion-gentle` with `--ease-spring` (tokens.css:172,
   "overlay PANELS only") — because that is what this is: a panel arriving, not a control changing
   state. The exit is the same class removed, and `console-dock.js` reads the COMPUTED duration
   before detaching, so reduced motion (where the tokens are zeroed) removes it on the same tick
   instead of stranding it for 220ms of nothing.
   ============================================================================================= */

.scs-sheet {
    position: relative;
    z-index: var(--z-sheet);
    display: flex;
    flex-direction: column;
    /* CENTER: the dock's cross axis is horizontal now. `flex-end` here would pin the sheet to the
       right edge while the deck it belongs to sits centred — the same axis flip that moved the
       restore pill. */
    align-self: center;
    width: 100%;
    max-width: 1120px;                       /* the deck's own max-width (layout.css:581) */
    max-height: min(62vh, 560px);            /* never taller than the media it belongs to */
    margin-bottom: var(--space-2);
    background: var(--color-bg-surface);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-2xl);
    box-shadow: var(--shadow-xl);
    /* The entry state. `.is-open` is added one frame later (console-dock.js), which is what gives
       the transition a "from" to animate out of. */
    transform: translateY(12px);
    opacity: 0;
    transition: transform var(--motion-gentle) var(--ease-spring),
                opacity var(--motion-base) var(--ease-out);
}

.scs-sheet.is-open {
    transform: translateY(0);
    opacity: 1;
}

.scs-sheet:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.scs-sheet-head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border-subtle);
}

.scs-sheet-title {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 13px;
    font-weight: var(--font-weight-semibold);
    letter-spacing: 0.01em;
    color: var(--color-text-primary);
    /* A tray title is authored data; long ones truncate rather than pushing the close control
       off the edge of a surface whose only other exit is a key. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scs-sheet-close {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    color: var(--color-text-muted);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background-color var(--motion-fast) var(--ease-out),
                color var(--motion-fast) var(--ease-out);
}

.scs-sheet-close i,
.scs-sheet-close svg { width: 15px; height: 15px; }
.scs-sheet-close:hover { background: var(--color-bg-hover); color: var(--color-text-primary); }
.scs-sheet-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The body scrolls, the head does not: a tray with nine reference slots must not push its own
   close control out of reach. */
.scs-sheet-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--space-4);
}

@media (prefers-reduced-motion: reduce) {
    /* The tokens are already zeroed app-wide; the transform is not a token, so the entry state
       is neutralised here too — otherwise a sheet would appear 12px low and stay there. */
    .scs-sheet { transform: none; }
}

/* ---- scs-fragment: upload-zone.css ---- */
/* =============================================================================================
   SCS — UploadZone (P2, spec §3.7)

   One surface for the 27 the app hand-rolls. The zone IS a button (Enter/Space open the picker
   through the platform), the constraints line is a real paragraph the button is described by, and
   the busy state is the shared `.upload-busy-overlay` from `utils/upload-feedback.js` — an APPENDED
   child, never an innerHTML swap, because the file input lives inside this root and a swap would
   silently kill the picker path.

   The drop affordance is a dashed border that becomes solid accent on `[data-dragging]`. The state
   is set by a COUNTED dragenter/dragleave pair in the JS: `dragleave` fires when the pointer
   crosses into the icon or the hint, so an uncounted handler flickers the highlight off inside its
   own zone.
   ============================================================================================= */

.scs-upload {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}

.scs-upload-zone {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    min-height: 72px;
    padding: var(--space-3) var(--space-4);
    font-family: inherit;
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    text-align: center;
    background: var(--color-bg-secondary);
    border: 1px dashed var(--color-border-default);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: color var(--motion-fast) var(--ease-out),
                border-color var(--motion-fast) var(--ease-out),
                background-color var(--motion-fast) var(--ease-out);
}

.scs-upload-zone:hover:not(:disabled) {
    color: var(--color-text-primary);
    border-color: var(--color-border-strong);
    background: var(--color-bg-hover);
}

.scs-upload-zone:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A disabled zone must LOOK unavailable, not merely refuse: an enabled-looking control that eats
   clicks is the same lie as a dead drop zone. */
.scs-upload-zone:disabled { opacity: 0.5; cursor: not-allowed; }

.scs-upload-icon { width: 18px; height: 18px; flex-shrink: 0; }
.scs-upload-label { min-width: 0; }

/* The drop target is the whole root — zone AND hint — so a pointer that drifts onto the
   constraints line does not read as "left the zone". */
.scs-upload[data-dragging="true"] .scs-upload-zone {
    color: var(--color-text-primary);
    border-style: solid;
    border-color: var(--accent);
    background: var(--color-bg-hover);
}

.scs-upload-hint {
    margin: 0;
    padding: 0 var(--space-1);
    font-size: 11px;
    line-height: 1.4;
    color: var(--color-text-muted);
}

/* Never `display: none` on the input: a hidden-by-display input is unfocusable in some engines and
   `.click()` on it is ignored. `hidden` + the off-screen box keeps it a real, clickable control. */
.scs-upload-input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* ---- scs-fragment: progress-streaming.css ---- */
/* =============================================================================================
   SCS — Progress, STREAMING profile (P2)

   The job-level chrome the simple profile has no honest content for: the provider's own stage
   text, an elapsed clock, and a stall line. It sits ABOVE the cell grid, so a stage change never
   moves a cell, and it is a fixed-height row for the same reason — text arriving and leaving must
   not reflow the media the user is watching.

   The elapsed value is tabular so the digits do not dance once a second; that is the whole reason
   `font-variant-numeric` is here and not a preference.

   There is deliberately NO progress bar and NO ring. `progress.js`'s header states why: a
   percentage the pipeline never sends is a lie with a stroke-dashoffset, and elapsed is the honest
   substitute — it claims nothing about what is left.
   ============================================================================================= */

.scs-progress-stream {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    min-height: 20px;
    margin-bottom: var(--space-2);
}

.scs-progress-stage {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--color-text-secondary);
    /* Provider stage text is arbitrary length; it truncates rather than wrapping the row into
       two lines and shifting the grid down mid-run. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scs-progress-elapsed {
    flex-shrink: 0;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--color-text-muted);
}

/* The stall line is a REPORT, not a warning: it is styled like the muted stage text, not like an
   error. The run is fine — it is just quiet — and painting it as a failure would teach users to
   cancel healthy generations. */
.scs-progress-stall {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
    font-size: 12px;
    line-height: 1.5;
    color: var(--color-text-muted);
}

.scs-progress-stall::before {
    content: "";
    flex-shrink: 0;
    width: 6px;
    height: 6px;
    border-radius: var(--radius-full);
    background: var(--color-text-muted);
    animation: scs-progress-stall-pulse 2400ms var(--ease-in-out-legacy) infinite;
}

@keyframes scs-progress-stall-pulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    /* Slowed, never stopped — the system treatment for an unattended animation
       (scs-fragment-house-rules.test.js:97-107). A pulse that stops reads as "the run stopped". */
    .scs-progress-stall::before { animation-duration: 4800ms; }
}

/* ---- scs-fragment: video-deck.css ---- */
/* =============================================================================================
   ===== SCS ===== Video deck, stage, sheets                                          (P2, T5)

   The SHELL owns the deck's chrome (`.scs-console*`, layout.css), the rack's (`.scs-rack*`) and
   the sheet's (`.scs-console-sheet`, the `scs-sheet.css` fragment); the COMPONENTS own their own
   families (`.scs-well-*`, `.scs-take-*`, `.scs-state-*`, `.scs-progress-*`, `.scs-upload-*`,
   `.scs-segment*`). What is left — and all this subsection contains — is Video's own composition:
   how the well, the prompt and the CTA share Row A, how the four-mode segment leads Row B, how the
   three sheets lay their contents out, and how the stage stacks history over results.

   House rules held here: no literal colors, no `transition: all`, no hardcoded durations, no
   hardcoded z integers, and every selector prefixed `.vid-` so nothing can collide with a
   component family.
   ============================================================================================= */

/* ── Row A — the take ─────────────────────────────────────────────────────────────────────── */

.vid-well-host {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 34%;
    border-radius: var(--radius-lg);
}

/* An arrival must be SEEN. Ten of the eleven "send to video" producers used to land with no
   visible change at all, so the well says so once, briefly, and then gets out of the way. */
.vid-well--arrived {
    box-shadow: 0 0 0 2px var(--accent-soft);
    transition: box-shadow var(--motion-gentle) var(--ease-out);
}

.vid-prompt-wrap {
    position: relative;
    display: flex;
    flex: 1 1 auto;
    align-items: flex-start;
    min-width: min(380px, 100%);
    padding: 0 var(--space-2);
    background: var(--color-bg-primary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-lg);
    transition: border-color var(--motion-fast) var(--ease-out),
                box-shadow var(--motion-fast) var(--ease-out);
}
.vid-prompt-wrap:focus-within {
    border-color: var(--color-border-active);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* One line at rest, growing to six (the JS writes the height; this owns the rhythm).
   `border-box` means padding eats the CONTENT box, so the rest height is one line PLUS the
   padding and the ceiling is computed the same way — otherwise the last line clips. */
.vid-prompt {
    flex: 1 1 auto;
    min-width: 0;
    height: 32px;
    max-height: 142px;
    padding: 5px var(--space-2);
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: 22px;
    color: var(--color-text-primary);
    background: transparent;
    border: 0;
    resize: none;
    outline: none;
}
.vid-prompt::placeholder { color: var(--color-text-muted); }

.vid-enhance {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    flex-shrink: 0;
    align-self: center;
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-accent);
    background: transparent;
    border: 0;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: color var(--motion-fast) var(--ease-out),
                background-color var(--motion-fast) var(--ease-out);
}
.vid-enhance:hover:not(:disabled) { background: var(--accent-soft); }
.vid-enhance:disabled { opacity: 0.55; cursor: default; }
.vid-enhance i { width: 14px; height: 14px; }
.vid-enhance.is-busy i { animation: scs-spin 700ms var(--ease-linear) infinite; }

.vid-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    white-space: nowrap;
}
.vid-cta-icon { width: 16px; height: 16px; }
.vid-cta-cost { font-size: var(--font-size-xs); opacity: 0.85; }
.vid-cta--busy .vid-cta-icon { animation: scs-spin 700ms var(--ease-linear) infinite; }

/* ── Row B — the mode segment + the settings rail ─────────────────────────────────────────── */

.vid-mode-host { display: flex; flex: 0 0 auto; }

.vid-chip[hidden] { display: none; }

.vid-row-spacer { flex: 1 1 auto; }

.vid-panels { display: none; }

.vid-panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 220px;
}

.vid-slider-row { display: flex; flex-direction: column; gap: var(--space-1); }
.vid-slider { width: 100%; accent-color: var(--color-accent); }
.vid-slider-scale {
    display: flex;
    justify-content: space-between;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

/* ── The rack's engine pills ──────────────────────────────────────────────────────────────── */

.vid-rack-pills { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.vid-pill[hidden] { display: none; }

.vid-notice {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-2);
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}
.vid-notice i { width: 14px; height: 14px; flex-shrink: 0; margin-top: 2px; }

/* ── Sheets — source · keyframes · references ─────────────────────────────────────────────── */

.vid-sheet {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
}

/* The two keyframes are POSITIONAL — start and end — so they are laid out as a pair and never
   reflow into a stack that would make "the first one" a scroll position. */
.vid-frame-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
}
.vid-frame-cell { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.vid-frame-cell[data-focus="true"] {
    outline: 2px solid var(--color-border-active);
    outline-offset: var(--space-1);
    border-radius: var(--radius-lg);
}
.vid-frame-caption {
    margin: 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-secondary);
}

/* The V1 tray is gated by `#videoMultimodalPanel { display: none }` + `.active` (:9040-9053) —
   a MODE gate from the old layout, where the panel lived in the controls column and appeared when
   the Multimodal tab was selected. On the SCS deck the gate is the SHEET: the host exists only
   while the tray sheet is open, so "mounted" already means "active". Without this the panel was
   built, filled and never displayed — the mode shipped functionally headless.
   The id+class selector (1-1-0) is what outranks the V1 id rule; it stays scoped to the SCS host,
   so the V1 rule still governs the panel anywhere else it is mounted. */
#videoMultimodalPanel.vid-tray-host { display: block; }

.vid-tray-host { min-width: 0; }
.vid-tray-zones {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-2);
}

.vid-recent { display: flex; flex-direction: column; gap: var(--space-2); }
.vid-recent-title {
    margin: 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.vid-recent-items { display: flex; gap: var(--space-2); overflow-x: auto; padding-bottom: var(--space-1); }
.vid-recent-item {
    flex: 0 0 auto;
    width: 72px;
    height: 48px;
    padding: 0;
    overflow: hidden;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color var(--motion-fast) var(--ease-out);
}
.vid-recent-item:hover { border-color: var(--color-border-active); }
.vid-recent-item img { width: 100%; height: 100%; object-fit: cover; }

/* ── The stage ────────────────────────────────────────────────────────────────────────────── */

/* The stage IS the Viewer's box: `openViewer` mounts the Viewer inside `#video-stage` and the
   Viewer takes `position: absolute; inset: 0`, so the stage's height is the Viewer's height —
   the same F-2 geometry the Image Gen pilot fixed on `.ig-stage`. `flex: 1 0 auto` makes the
   stage GROW to `#preview-panel` (whose padding already ends above the deck) while `flex-shrink:
   0` lets a stage taller than the panel stay at content height and scroll. While the stage was
   content-sized, a finished clip expanded into a band the height of the take row. */
.vid-stage {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
    gap: var(--space-3);
    width: 100%;
}

/* ONE CLEARANCE, CLAIMED ONCE — the `.ig-stage` rule's twin. The app-wide
   `.scs-console-layout .scs-viewer { bottom: var(--console-clearance) }` is written for a Viewer
   whose containing block is `#preview-panel`'s padding box; this stage lives INSIDE that padding,
   so the same rule would subtract the clearance a second time. Prefix carried for specificity
   (0,3,0 over 0,2,0), not for scoping. */
.scs-console-layout .vid-stage > .scs-viewer { bottom: 0; }

.vid-history { display: flex; flex-direction: column; gap: var(--space-2); }
.vid-history[hidden] { display: none; }
.vid-history-head { display: flex; align-items: center; justify-content: space-between; }
.vid-history-title {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.vid-history-all {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: color var(--motion-fast) var(--ease-out);
}
.vid-history-all:hover { color: var(--color-text-primary); }
.vid-history-items { display: flex; gap: var(--space-2); overflow-x: auto; padding-bottom: var(--space-1); }
.vid-history-item {
    flex: 0 0 auto;
    width: 96px;
    height: 54px;
    padding: 0;
    overflow: hidden;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color var(--motion-fast) var(--ease-out);
}
.vid-history-item:hover { border-color: var(--color-border-active); }
.vid-history-item img { width: 100%; height: 100%; object-fit: cover; }

.vid-surface { flex: 1 1 auto; min-height: 0; }

/* The results sandwich: Progress owns the in-flight cells, TakeGrid owns the finished ones, and a
   completion moves one cell from the first to the second without swapping containers. Both read
   `--scs-take-aspect` from here. */
.vid-results { display: flex; flex-direction: column; gap: var(--space-3); min-height: 0; }
.vid-grid-host { min-height: 0; }
.vid-progress-host { min-height: 0; }

.vid-frame-tools { display: flex; justify-content: center; }
.vid-frame-tools[hidden] { display: none; }

/* ── The frame-selector modal, lifted onto the scale ──────────────────────────────────────── */

/* It ships AS-IS from the V1 tab (`components/video/preview.html`) and carried Tailwind's `z-50`
   — 150 BELOW the console deck (`--z-sticky: 200`). The deck therefore painted OVER the open
   modal and its Generate button, a paid action, was clickable through it. The utility could not
   simply be outranked: `important: true` compiles it to `z-index: 50 !important`, which no
   id-selector rule beats, so the class left the markup and the layer is declared here instead. */
#frame-selector-modal {
    z-index: var(--z-modal);
}

/* ── The full-page drop overlay ───────────────────────────────────────────────────────────── */

.vid-drop-overlay {
    position: absolute;
    inset: 0;
    z-index: var(--z-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-bg-overlay);
    border-radius: var(--radius-lg);
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--motion-fast) var(--ease-out);
}
.vid-drop-overlay.hidden { display: none; }
.vid-drop-overlay.active { opacity: 1; }
.vid-drop-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-6);
    text-align: center;
    background: var(--color-bg-secondary);
    border: 2px dashed var(--color-border-active);
    border-radius: var(--radius-xl);
}
.vid-drop-card i { width: 32px; height: 32px; color: var(--color-accent); }
.vid-drop-title { margin: 0; font-size: var(--font-size-base); color: var(--color-text-primary); }
.vid-drop-hint { margin: 0; font-size: var(--font-size-xs); color: var(--color-text-muted); }

@media (prefers-reduced-motion: reduce) {
    /* Slowed, never stopped — the system treatment for an unattended animation. A spinner that
       stops reads as "the run stopped". */
    .vid-enhance.is-busy i,
    .vid-cta--busy .vid-cta-icon { animation-duration: 2400ms; }
}
