dragonflight/services/premiere-plugin/css/styles.css

1120 lines
24 KiB
CSS
Raw Normal View History

/* Wild Dragon MAM Panel — Wild Dragon Design System */
/* OKLCH tokens aligned with web-ui/common.css */
:root {
--bg-deep: oklch(8% 0.011 266);
--bg-base: oklch(11% 0.010 266);
--bg-panel: oklch(15% 0.013 266);
--bg-surface: oklch(19% 0.014 266);
--bg-raised: oklch(24% 0.015 266);
--bg-hover: oklch(28% 0.015 266);
--accent: oklch(45% 0.20 266);
--accent-dim: oklch(56% 0.130 52);
--accent-subtle: oklch(55% 0.20 266 / 0.12);
--accent-border: oklch(55% 0.20 266 / 0.36);
--text-primary: oklch(94% 0.008 266);
--text-secondary: oklch(72% 0.014 266);
--text-tertiary: oklch(52% 0.012 266);
--text-disabled: oklch(38% 0.010 266);
--border-faint: oklch(22% 0.013 266);
--border: oklch(28% 0.015 266);
--border-strong: oklch(38% 0.018 266);
--status-green: oklch(70% 0.18 148);
--status-red: oklch(64% 0.22 25);
--status-blue: oklch(67% 0.16 245);
--status-yellow: oklch(80% 0.16 90);
--status-gray: oklch(58% 0.012 266);
--status-green-bg: oklch(70% 0.18 148 / 0.12);
--status-red-bg: oklch(64% 0.22 25 / 0.12);
--status-blue-bg: oklch(67% 0.16 245 / 0.12);
--status-yellow-bg: oklch(80% 0.16 90 / 0.12);
--signal-good: var(--status-green);
--signal-warn: var(--status-yellow);
--signal-bad: var(--status-red);
--signal-idle: var(--status-gray);
--sp-1: 4px;
--sp-2: 8px;
--sp-3: 12px;
--sp-4: 16px;
--sp-5: 20px;
--sp-6: 24px;
--sp-8: 32px;
--sp-12: 48px;
--sp-16: 64px;
--font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Consolas', 'Liberation Mono', monospace;
--text-xs: 11px;
--text-sm: 13px;
--text-base: 14px;
--text-md: 16px;
--r-sm: 4px;
--r-md: 6px;
--r-lg: 8px;
--t-fast: 150ms ease-out;
--t-normal: 250ms ease-out;
--shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
width: 100%;
height: 100%;
font-family: var(--font);
background: var(--bg-base);
color: var(--text-primary);
font-size: 12px;
-webkit-font-smoothing: antialiased;
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-deep); }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }
/* ================================================================
PANEL CONTAINER
================================================================ */
#panel-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
/* ================================================================
CONNECTION BAR
================================================================ */
.connection-bar {
background: var(--bg-panel);
border-bottom: 1px solid var(--border);
padding: var(--sp-3);
flex-shrink: 0;
}
.connection-controls {
display: flex;
gap: var(--sp-2);
align-items: center;
}
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
.connection-controls--stacked {
display: flex;
flex-direction: column;
gap: var(--sp-2);
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
}
.server-input-row {
display: flex;
align-items: center;
gap: var(--sp-2);
fix(premiere-plugin): v1.0.1 — actually load + connect under CEP 12 End-to-end debugging against a live Premiere Pro 2025 + auth-enabled mam-api surfaced four real bugs that made v1.0.0 install cleanly but never load, plus the missing auth flow. All four are fixed and the panel is verified connected (status dot green, Reconnect button shown, project list populated). - manifest.xml: a comment in the <Resources> block contained "--" (inside "--enable-nodejs"/"--mixed-context"), which is illegal per the XML spec. CEP 12's strict parser logged ERROR XPATH Double hyphen within comment and skipped the panel entirely. Comment rewritten without double hyphens. - manifest.xml: lacked the Version="X.Y" attribute on <ExtensionManifest> and used a non-standard AbstractionLayers/empty <ExtensionList/> structure. CEP rejected it with Unsupported Manifest version '' Manifest rewritten to the standard CSXS 7.0 schema (ExtensionList + DispatchInfoList + RequiredRuntimeList), matching the working AMPP panel template. - main.js: re-declared `const csInterface = new CSInterface()` at top level even though CSInterface.js already declared the same binding. CEP 12 shares script-realm lexical scope across <script> tags, so the second const threw Identifier 'csInterface' has already been declared The throw fired before setupEventListeners(), so the Connect button's click handler was never attached. This is the root cause of the original "clicking Connect does nothing" symptom; everything else was secondary. Removed the duplicate declaration; main.js now uses the binding from CSInterface.js. - No auth support against AUTH_ENABLED=true servers. mam-api supports Bearer tokens (POST /api/v1/tokens), so added: • API token input field (password-masked) next to Server URL • localStorage persistence on every keystroke • window.fetch monkey-patch that injects Authorization: Bearer <token> on every request whose URL starts with the configured server. Signed S3 download URLs are NOT touched. Drive-by fixes that came out of the same debugging pass: - Server URL input listener was 'change' (fires on blur); switched to 'input' so typing-then-clicking-Connect immediately commits. - restoreSettings() now strips trailing slashes from the stored URL so older saved values like 'http://host/' stop producing //api/v1 404s. - CSS selector `input[type="text"].server-url` didn't match the new password input → the token field was unstyled and effectively invisible. Generalized to `input.server-url`; restructured the connection bar into `.connection-controls--stacked` (flex column) of two `.server-input-row` rows so two input fields fit cleanly. - Build scripts now parse ExtensionBundleVersion from both element form (<ExtensionBundleVersion>X</...>) and attribute form (ExtensionBundleVersion="X"), since the manifest rewrite switched schemas. Version bumped 1.0.0 → 1.0.1. New artifacts committed at services/premiere-plugin/build/releases/v1.0.1/ (.exe 2 MB, .zxp 35 KB). v1.0.0 left in place so editors who downloaded it can verify they're on the broken version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:24:10 -04:00
}
.server-url {
flex: 1;
min-width: 0;
height: 28px;
padding: 0 var(--sp-2);
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--r-sm);
color: var(--text-primary);
font-size: var(--text-xs);
font-family: var(--font-mono);
outline: none;
transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.server-url:focus {
border-color: var(--accent-border);
box-shadow: 0 0 0 2px var(--accent-subtle);
}
.server-url::placeholder { color: var(--text-tertiary); }
.connect-btn { flex-shrink: 0; }
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--status-red);
flex-shrink: 0;
transition: background var(--t-fast), box-shadow var(--t-fast);
}
.status-indicator.connected {
background: var(--status-green);
box-shadow: 0 0 6px var(--status-green);
}
.status-indicator.connecting {
background: var(--status-yellow);
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
/* ================================================================
BUTTONS (design system patterns)
================================================================ */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--sp-1);
padding: 0 var(--sp-2);
height: 28px;
font-size: var(--text-xs);
font-weight: 500;
border: 1px solid transparent;
border-radius: var(--r-sm);
transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
white-space: nowrap;
line-height: 1;
flex-shrink: 0;
cursor: pointer;
font-family: var(--font);
}
.btn-sm {
height: 24px;
padding: 0 var(--sp-2);
font-size: 11px;
}
.btn-primary {
background: var(--accent);
color: oklch(11% 0.010 250);
border-color: var(--accent);
}
.btn-primary:hover:not(:disabled) {
background: oklch(52% 0.21 266);
border-color: oklch(52% 0.21 266);
}
.btn-primary:active:not(:disabled) {
background: oklch(40% 0.19 266);
}
.btn-secondary {
background: var(--bg-surface);
color: var(--text-primary);
border-color: var(--border-strong);
}
.btn-secondary:hover:not(:disabled) {
background: var(--bg-raised);
}
.btn-ghost {
background: transparent;
color: var(--text-secondary);
border-color: transparent;
}
.btn-ghost:hover:not(:disabled) {
background: var(--bg-hover);
color: var(--text-primary);
}
.btn-danger {
background: transparent;
color: var(--status-red);
border-color: oklch(62% 0.22 25 / 0.25);
}
.btn-danger:hover:not(:disabled) {
background: var(--status-red-bg);
}
.btn:disabled { opacity: 0.38; cursor: not-allowed; pointer-events: none; }
/* Legacy button compatibility */
button {
cursor: pointer;
font-family: var(--font);
}
button:disabled {
opacity: 0.38;
cursor: not-allowed;
pointer-events: none;
}
button.secondary {
background: var(--bg-surface);
color: var(--text-primary);
border: 1px solid var(--border-strong);
border-radius: var(--r-sm);
padding: 0 var(--sp-2);
height: 28px;
font-size: var(--text-xs);
font-weight: 500;
display: inline-flex;
align-items: center;
justify-content: center;
transition: background var(--t-fast);
}
button.secondary:hover:not(:disabled) {
background: var(--bg-raised);
}
/* ================================================================
SEARCH & FILTER
================================================================ */
.search-filter-area {
background: var(--bg-panel);
border-bottom: 1px solid var(--border);
padding: var(--sp-3);
flex-shrink: 0;
}
.search-bar {
display: flex;
gap: var(--sp-2);
margin-bottom: var(--sp-2);
}
.search-input {
flex: 1;
height: 30px;
padding: 0 var(--sp-3);
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--r-sm);
color: var(--text-primary);
font-size: var(--text-xs);
outline: none;
transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.search-input:focus {
border-color: var(--accent-border);
box-shadow: 0 0 0 2px var(--accent-subtle);
}
.search-input::placeholder { color: var(--text-tertiary); }
.filter-controls {
display: flex;
gap: var(--sp-2);
}
select {
flex: 1;
height: 28px;
padding: 0 24px 0 var(--sp-2);
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--r-sm);
color: var(--text-primary);
font-size: var(--text-xs);
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24'%3E%3Cpath fill='%23667788' d='m7 10 5 5 5-5z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 6px center;
cursor: pointer;
outline: none;
transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
select:focus {
border-color: var(--accent-border);
box-shadow: 0 0 0 2px var(--accent-subtle);
}
select option { background: var(--bg-surface); color: var(--text-primary); }
/* ================================================================
CHIP (design system)
================================================================ */
.chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 2px 8px;
height: 20px;
border-radius: 3px;
font-family: var(--font-mono);
font-size: 11px;
letter-spacing: 0.04em;
text-transform: uppercase;
background: var(--bg-surface);
color: var(--text-secondary);
border: 1px solid var(--border);
white-space: nowrap;
}
.chip-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.chip--good { color: var(--signal-good); border-color: oklch(70% 0.18 148 / 0.35); }
.chip--warn { color: var(--signal-warn); border-color: oklch(80% 0.16 90 / 0.35); }
.chip--bad { color: var(--signal-bad); border-color: oklch(64% 0.22 25 / 0.35); }
.chip--rec { color: var(--accent); border-color: var(--accent-border); }
/* ================================================================
SEQUENCE INFO BAR
================================================================ */
.seq-info-bar {
background: var(--bg-surface);
border-bottom: 1px solid var(--border);
padding: var(--sp-1) var(--sp-3);
flex-shrink: 0;
display: flex;
align-items: center;
gap: var(--sp-2);
min-height: 28px;
}
.seq-info-bar.hidden { display: none; }
.seq-info-label { flex-shrink: 0; }
.seq-info-name {
font-size: 11px;
font-weight: 500;
color: var(--text-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.seq-refresh-btn {
flex-shrink: 0;
font-size: 13px;
line-height: 1;
}
/* ================================================================
MAIN CONTENT AREA
================================================================ */
.content-area {
display: flex;
flex: 1;
gap: 0;
min-height: 0;
}
.asset-grid-container {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
border-right: 1px solid var(--border);
}
/* ================================================================
ASSET GRID
================================================================ */
.asset-grid {
flex: 1;
overflow-y: auto;
padding: var(--sp-3);
display: grid;
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
gap: var(--sp-3);
}
.asset-card {
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--r-md);
overflow: hidden;
cursor: pointer;
transition: border-color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
display: flex;
flex-direction: column;
height: 155px;
}
.asset-card:hover {
border-color: var(--accent-border);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
.asset-card.selected {
border-color: var(--accent);
background: var(--bg-panel);
box-shadow: 0 0 0 1px var(--accent-border);
}
.asset-thumbnail {
width: 100%;
aspect-ratio: 16 / 9;
background: var(--bg-deep);
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
color: var(--text-tertiary);
overflow: hidden;
flex-shrink: 0;
}
.asset-thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
}
.asset-info {
padding: var(--sp-2);
display: flex;
flex-direction: column;
gap: 3px;
flex: 1;
min-height: 0;
}
.asset-filename {
font-weight: 500;
font-size: 11px;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.asset-meta {
display: flex;
gap: var(--sp-1);
font-size: 10px;
color: var(--text-secondary);
font-family: var(--font-mono);
}
.asset-status-badge {
display: inline-flex;
align-items: center;
padding: 1px 6px;
border-radius: 100px;
font-size: 9px;
font-weight: 500;
letter-spacing: 0.04em;
text-transform: uppercase;
width: fit-content;
}
.status-badge.ready {
background: var(--status-green-bg);
color: var(--status-green);
}
.status-badge.processing {
background: var(--status-blue-bg);
color: var(--status-blue);
animation: pulse 1.5s ease-in-out infinite;
}
.status-badge.error {
background: var(--status-red-bg);
color: var(--status-red);
}
/* ================================================================
EMPTY STATE
================================================================ */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--sp-12) var(--sp-8);
text-align: center;
gap: var(--sp-2);
}
.empty-state-icon {
color: var(--text-tertiary);
margin-bottom: var(--sp-1);
}
.empty-state-icon svg {
width: 36px;
height: 36px;
}
.empty-state-title {
font-size: var(--text-sm);
font-weight: 500;
color: var(--text-secondary);
}
.empty-state-body {
font-size: var(--text-xs);
color: var(--text-tertiary);
max-width: 30ch;
line-height: 1.5;
}
/* ================================================================
DETAILS PANEL
================================================================ */
.details-panel {
width: 190px;
background: var(--bg-panel);
border-left: 1px solid var(--border);
padding: var(--sp-3);
display: flex;
flex-direction: column;
gap: var(--sp-2);
overflow-y: auto;
}
.details-panel.hidden { display: none; }
.details-header {
margin-bottom: var(--sp-1);
}
.details-header-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-tertiary);
}
.details-section {
display: flex;
flex-direction: column;
gap: 2px;
}
.details-label {
font-size: 9px;
font-weight: 500;
text-transform: uppercase;
color: var(--text-tertiary);
letter-spacing: 0.06em;
}
.details-value {
font-size: 11px;
color: var(--text-primary);
word-break: break-word;
}
.tags-list {
display: flex;
flex-wrap: wrap;
gap: var(--sp-1);
}
.tag {
display: inline-block;
background: var(--bg-surface);
border: 1px solid var(--border-faint);
color: var(--text-secondary);
padding: 2px 6px;
border-radius: 100px;
font-size: 9px;
font-family: var(--font-mono);
}
.divider {
height: 1px;
background: var(--border);
border: none;
}
/* ================================================================
PROGRESS INDICATOR
================================================================ */
.progress-container {
padding: var(--sp-2) var(--sp-3);
background: var(--bg-panel);
border-bottom: 1px solid var(--border);
display: none;
}
.progress-container.visible { display: block; }
.progress-label {
font-size: var(--text-xs);
margin-bottom: var(--sp-1);
color: var(--text-secondary);
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
.progress-bar {
width: 100%;
height: 3px;
background: var(--bg-hover);
border-radius: 2px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--accent);
width: 0%;
transition: width 300ms ease-out;
}
/* ================================================================
EXPORT PANEL (Push Timeline to MAM)
================================================================ */
.export-panel {
background: var(--bg-panel);
border-top: 1px solid var(--border);
padding: var(--sp-3);
flex-shrink: 0;
}
.export-panel.hidden { display: none; }
.export-panel-title {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--accent);
margin-bottom: var(--sp-2);
}
.export-panel input[type="text"],
.export-panel .input {
width: 100%;
height: 28px;
padding: 0 var(--sp-2);
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--r-sm);
color: var(--text-primary);
font-size: var(--text-xs);
margin-bottom: var(--sp-1);
outline: none;
transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.export-panel input[type="text"]:focus,
.export-panel .input:focus {
border-color: var(--accent-border);
box-shadow: 0 0 0 2px var(--accent-subtle);
}
.export-panel select {
width: 100%;
margin-bottom: var(--sp-2);
flex: none;
}
.export-clip-info {
font-size: var(--text-xs);
color: var(--text-secondary);
margin-bottom: var(--sp-2);
font-family: var(--font-mono);
}
.export-panel-actions {
display: flex;
gap: var(--sp-2);
}
.export-panel-actions .btn { flex: 1; }
/* ================================================================
ADVANCED SECTION
================================================================ */
.advanced-section {
background: var(--bg-panel);
border-bottom: 1px solid var(--border);
padding: var(--sp-2) var(--sp-3);
flex-shrink: 0;
}
.advanced-section-title {
font-size: 9px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-tertiary);
margin-bottom: var(--sp-1);
}
.advanced-row {
display: flex;
gap: var(--sp-2);
}
.advanced-row .btn { flex: 1; }
/* ================================================================
ACTION BAR
================================================================ */
.action-bar {
background: var(--bg-panel);
border-top: 1px solid var(--border);
padding: var(--sp-2) var(--sp-3);
flex-shrink: 0;
display: flex;
flex-direction: column;
gap: var(--sp-1);
}
.action-row {
display: flex;
gap: var(--sp-2);
}
.action-row .btn { flex: 1; }
/* ================================================================
SLIDE PANEL (design system pattern)
================================================================ */
.slide-overlay {
position: fixed;
inset: 0;
background: oklch(8% 0.010 250 / 0.65);
z-index: 80;
opacity: 0;
pointer-events: none;
transition: opacity var(--t-normal);
}
.slide-overlay.open { opacity: 1; pointer-events: all; }
.slide-panel {
position: fixed;
top: 0; right: 0; bottom: 0;
width: 420px;
background: var(--bg-panel);
border-left: 1px solid var(--border);
z-index: 90;
display: flex;
flex-direction: column;
transform: translateX(100%);
transition: transform var(--t-normal);
}
.slide-panel.open { transform: translateX(0); }
.slide-panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--sp-5);
height: 40px;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.slide-panel-title {
font-size: var(--text-sm);
font-weight: 500;
color: var(--text-primary);
}
.slide-panel-body {
flex: 1;
overflow-y: auto;
padding: var(--sp-5);
display: flex;
flex-direction: column;
gap: var(--sp-4);
}
.slide-panel-footer {
padding: var(--sp-3) var(--sp-5);
border-top: 1px solid var(--border);
display: flex;
justify-content: flex-end;
gap: var(--sp-2);
flex-shrink: 0;
}
/* ================================================================
PRESET CARDS (for FCP Conform)
================================================================ */
.preset-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--sp-2);
}
.preset-card {
padding: var(--sp-2) var(--sp-2);
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--r-md);
cursor: pointer;
transition: border-color var(--t-fast), background var(--t-fast);
}
.preset-card:hover {
border-color: var(--accent-border);
background: var(--bg-raised);
}
.preset-card.selected {
border-color: var(--accent);
background: var(--accent-subtle);
}
.preset-card-title {
font-size: var(--text-xs);
font-weight: 500;
color: var(--text-primary);
margin-bottom: 2px;
}
.preset-card-desc {
font-size: 10px;
color: var(--text-tertiary);
font-family: var(--font-mono);
}
/* ================================================================
CLIP LIST (for Hi-Res Relink)
================================================================ */
.clip-list-container {
flex: 1;
min-height: 0;
overflow-y: auto;
border: 1px solid var(--border);
border-radius: var(--r-md);
background: var(--bg-base);
}
.clip-list {
display: flex;
flex-direction: column;
}
.clip-list-item {
display: flex;
align-items: center;
gap: var(--sp-2);
padding: var(--sp-2) var(--sp-2);
border-bottom: 1px solid var(--border-faint);
transition: background var(--t-fast);
}
.clip-list-item:last-child { border-bottom: none; }
.clip-list-item:hover { background: var(--bg-surface); }
.clip-list-item-checkbox {
width: 14px;
height: 14px;
accent-color: var(--accent);
flex-shrink: 0;
cursor: pointer;
}
.clip-list-item-info {
flex: 1;
min-width: 0;
}
.clip-list-item-name {
font-size: var(--text-xs);
font-weight: 500;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.clip-list-item-meta {
font-size: 10px;
color: var(--text-tertiary);
font-family: var(--font-mono);
}
.clip-list-item-status {
flex-shrink: 0;
font-size: 9px;
font-weight: 500;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.clip-list-item-status.matched {
color: var(--status-green);
}
.clip-list-item-status.unmatched {
color: var(--text-disabled);
}
/* ================================================================
RELINK SUMMARY
================================================================ */
.relink-summary {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--sp-2);
padding: var(--sp-4);
text-align: center;
}
.relink-summary.hidden { display: none; }
.relink-summary-icon { color: var(--status-green); }
.relink-summary-text {
font-size: var(--text-sm);
font-weight: 500;
color: var(--text-primary);
}
.relink-summary-detail {
font-size: var(--text-xs);
color: var(--text-secondary);
font-family: var(--font-mono);
}
/* ================================================================
MESSAGE BANNERS
================================================================ */
.error-message {
background: var(--status-red-bg);
border: 1px solid oklch(64% 0.22 25 / 0.25);
color: var(--status-red);
padding: var(--sp-2) var(--sp-3);
border-radius: var(--r-sm);
font-size: var(--text-xs);
margin-bottom: var(--sp-2);
}
.success-message {
background: var(--status-green-bg);
border: 1px solid oklch(70% 0.18 148 / 0.25);
color: var(--status-green);
padding: var(--sp-2) var(--sp-3);
border-radius: var(--r-sm);
font-size: var(--text-xs);
margin-bottom: var(--sp-2);
}
.info-message {
background: var(--accent-subtle);
border: 1px solid var(--accent-border);
color: var(--accent);
padding: var(--sp-2) var(--sp-3);
border-radius: var(--r-sm);
font-size: var(--text-xs);
margin-bottom: var(--sp-2);
}
/* ================================================================
FORM GROUP (design system)
================================================================ */
.form-group {
display: flex;
flex-direction: column;
gap: var(--sp-1);
}
.form-label {
font-size: 10px;
font-weight: 500;
letter-spacing: 0.07em;
text-transform: uppercase;
color: var(--text-secondary);
}
.form-hint {
font-size: var(--text-xs);
color: var(--text-tertiary);
line-height: 1.5;
}
/* ================================================================
UTILITY
================================================================ */
.hidden { display: none !important; }
.loading { opacity: 0.6; pointer-events: none; }
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.truncate-lines-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.spinner {
display: inline-block;
width: 12px;
height: 12px;
border: 2px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* ================================================================
RESPONSIVE
================================================================ */
@media (max-width: 500px) {
.asset-grid {
grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
gap: var(--sp-2);
padding: var(--sp-2);
}
.details-panel {
width: 140px;
padding: var(--sp-2);
}
.asset-card { height: 145px; }
.slide-panel { width: 100%; }
}