/* Wild Dragon MAM Panel — Wild Dragon Design System */ /* OKLCH tokens aligned with web-ui/common.css */ :root { /* Background scale */ --bg-deep: oklch(8% 0.011 32); --bg-base: oklch(11% 0.010 32); --bg-panel: oklch(15% 0.013 32); --bg-surface: oklch(19% 0.014 32); --bg-raised: oklch(24% 0.015 32); --bg-hover: oklch(28% 0.015 32); /* Accent */ --accent: oklch(62% 0.22 32); --accent-hover: oklch(68% 0.22 32); --accent-bright: oklch(76% 0.20 32); --accent-subtle: oklch(62% 0.22 32 / 0.12); --accent-border: oklch(62% 0.22 32 / 0.36); /* Text */ --text-primary: oklch(94% 0.008 32); --text-secondary: oklch(72% 0.014 32); --text-tertiary: oklch(56% 0.012 32); --text-disabled: oklch(38% 0.010 32); /* Borders */ --border-faint: oklch(22% 0.013 32); --border: oklch(28% 0.015 32); --border-strong: oklch(38% 0.018 32); /* Signals (primary) */ --signal-good: oklch(70% 0.18 148); --signal-bad: oklch(64% 0.22 25); --signal-warn: oklch(80% 0.16 90); --signal-idle: oklch(58% 0.012 32); --signal-info: oklch(67% 0.16 245); /* Signal backgrounds */ --signal-good-bg: oklch(70% 0.18 148 / 0.12); --signal-bad-bg: oklch(64% 0.22 25 / 0.12); --signal-warn-bg: oklch(80% 0.16 90 / 0.12); --signal-info-bg: oklch(67% 0.16 245 / 0.12); /* Signal hover variants */ --signal-good-hover: oklch(74% 0.18 148); --signal-bad-hover: oklch(68% 0.22 25); --signal-warn-hover: oklch(84% 0.16 90); /* Status aliases — backwards compat for main.js */ --status-green: var(--signal-good); --status-red: var(--signal-bad); --status-blue: var(--signal-info); --status-yellow: var(--signal-warn); --status-gray: var(--signal-idle); --status-green-bg: var(--signal-good-bg); --status-red-bg: var(--signal-bad-bg); --status-blue-bg: var(--signal-info-bg); --status-yellow-bg: var(--signal-warn-bg); /* Spacing */ --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; /* Typography */ --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; /* Radii */ --r-sm: 4px; --r-md: 6px; --r-lg: 8px; /* Transitions (legacy) */ --t-fast: 150ms ease-out; --t-normal: 250ms ease-out; /* Motion */ --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --dur-fast: 120ms; --dur-normal: 180ms; --dur-slide: 240ms; /* Elevation + surface extras */ --shadow: 0 4px 12px rgba(0, 0, 0, 0.3); --thumb-black: oklch(0% 0 32); --overlay: oklch(8% 0.010 32 / 0.65); /* Z-index layers */ --z-dropdown: 40; --z-overlay: 80; --z-panel: 90; --z-toast: 200; } * { 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; } .connection-controls--stacked { display: flex; flex-direction: column; gap: var(--sp-2); } .server-input-row { display: flex; align-items: center; gap: var(--sp-2); } .server-url { flex: 1; min-width: 0; height: 32px; padding: 0 var(--sp-2); background: var(--bg-deep); 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-visible { 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(--signal-bad); flex-shrink: 0; transition: background var(--t-fast), box-shadow var(--t-fast); } .status-indicator.connected { background: var(--signal-good); box-shadow: 0 0 6px var(--signal-good); } .status-indicator.connecting { background: var(--signal-warn); 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-3); height: 32px; font-size: var(--text-sm); font-weight: 500; border: 1px solid transparent; border-radius: var(--r-sm); transition: background var(--dur-fast) var(--ease-out-quart), border-color var(--dur-fast) var(--ease-out-quart), color var(--dur-fast) var(--ease-out-quart); white-space: nowrap; line-height: 1; flex-shrink: 0; cursor: pointer; font-family: var(--font); } .btn:focus-visible { outline: 2px solid var(--accent-subtle); outline-offset: 1px; } .btn:active:not(:disabled) { opacity: 0.85; transition: opacity 60ms; } .btn-sm { height: 28px; padding: 0 var(--sp-2); font-size: 11px; } .btn-lg { height: 36px; padding: 0 var(--sp-4); font-size: var(--text-sm); } .btn-icon { width: 28px; height: 28px; padding: 0; } .btn-primary { background: var(--accent); color: oklch(11% 0.010 32); border-color: var(--accent); } .btn-primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); } .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: var(--signal-bad); color: oklch(98% 0.005 25); border-color: var(--signal-bad); } .btn-danger:hover:not(:disabled) { background: var(--signal-bad-hover); border-color: var(--signal-bad-hover); } .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: 32px; font-size: var(--text-sm); 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: 32px; padding: 0 var(--sp-3); background: var(--bg-deep); 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-visible { 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: 32px; padding: 0 24px 0 var(--sp-2); background: var(--bg-deep); 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-visible { 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: 18px; border-radius: 3px; font-family: var(--font); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; background: var(--bg-surface); color: var(--text-secondary); white-space: nowrap; } .chip-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; } .chip--good { color: var(--signal-good); background: var(--signal-good-bg); } .chip--warn { color: var(--signal-warn); background: var(--signal-warn-bg); } .chip--bad { color: var(--signal-bad); background: var(--signal-bad-bg); } .chip--rec { color: var(--accent); background: var(--accent-subtle); } /* ================================================================ 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; } /* ================================================================ TAB NAVIGATION ================================================================ */ .tab-nav { display: flex; background: var(--bg-panel); border-bottom: 1px solid var(--border); flex-shrink: 0; } .tab-btn { flex: 1; height: 36px; background: transparent; border: none; border-bottom: 2px solid transparent; color: var(--text-secondary); font-family: var(--font); font-size: var(--text-xs); font-weight: 600; display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2); cursor: pointer; transition: all var(--t-fast); } .tab-btn:hover { color: var(--text-primary); background: var(--bg-hover); } .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); background: var(--bg-surface); } .tab-btn .badge { background: var(--bg-raised); color: var(--text-secondary); font-size: 10px; font-family: var(--font); padding: 1px 6px; border-radius: 10px; font-weight: normal; } .tab-btn.active .badge { background: var(--accent-subtle); color: var(--accent); } /* ================================================================ 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-faint); border-radius: var(--r-md); overflow: hidden; cursor: pointer; transition: border-color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast), filter var(--t-fast); display: flex; flex-direction: column; } .asset-card:hover { border-color: var(--accent-border); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.2); filter: brightness(1.04); } .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(--thumb-black); 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; height: 18px; padding: 0 6px; border-radius: 100px; font-family: var(--font); font-size: 9px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; width: fit-content; } .status-badge.ready { background: var(--signal-good-bg); color: var(--signal-good); } .status-badge.live, .status-badge.recording { background: var(--signal-bad-bg); color: var(--signal-bad); font-weight: bold; } .status-badge.ingesting, .status-badge.promoting, .status-badge.processing { background: var(--signal-info-bg); color: var(--signal-info); animation: pulse 1.5s ease-in-out infinite; } .status-badge.idle { background: var(--signal-warn-bg); color: var(--signal-warn); } .status-badge.error { background: var(--signal-bad-bg); color: var(--signal-bad); } /* ================================================================ 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-3); } .empty-state-icon { color: var(--text-tertiary); margin-bottom: var(--sp-2); } .empty-state-icon svg { width: 36px; height: 36px; } .empty-state-title { font-size: var(--text-sm); font-weight: 600; color: var(--text-secondary); } .empty-state-body { font-size: var(--text-xs); color: var(--text-tertiary); max-width: 30ch; line-height: 1.6; } /* ================================================================ 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-3); 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: 3px; } .details-label { font-size: 9px; font-weight: 600; text-transform: uppercase; color: var(--text-tertiary); letter-spacing: 0.07em; } .details-value { font-size: var(--text-xs); 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 var(--dur-slide) var(--ease-out-quart); } /* ================================================================ 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-3); } .export-panel input[type="text"], .export-panel .input { width: 100%; height: 32px; padding: 0 var(--sp-2); background: var(--bg-deep); border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text-primary); font-size: var(--text-xs); margin-bottom: var(--sp-2); outline: none; transition: border-color var(--t-fast), box-shadow var(--t-fast); } .export-panel input[type="text"]:focus-visible, .export-panel .input:focus-visible { border-color: var(--accent-border); box-shadow: 0 0 0 2px var(--accent-subtle); } .export-panel select { width: 100%; margin-bottom: var(--sp-3); 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-2); } .advanced-row { display: flex; gap: var(--sp-2); } .advanced-row .btn { flex: 1; } /* ================================================================ ACTION BAR ================================================================ */ .action-bar { background: var(--bg-deep); border-top: 1px solid var(--border); padding: var(--sp-2) var(--sp-3); flex-shrink: 0; display: flex; flex-direction: column; gap: var(--sp-2); } .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: var(--overlay); z-index: var(--z-overlay); opacity: 0; pointer-events: none; transition: opacity var(--dur-slide) var(--ease-out-quart); } .slide-overlay.open { opacity: 1; pointer-events: all; } .slide-panel { position: fixed; top: 0; right: 0; bottom: 0; width: 460px; background: var(--bg-panel); border-left: 1px solid var(--border); z-index: var(--z-panel); display: flex; flex-direction: column; overflow: hidden; transform: translateX(100%); transition: transform var(--dur-slide) var(--ease-out-expo); } .slide-panel.open { transform: translateX(0); } .slide-panel-header { display: flex; align-items: center; justify-content: space-between; padding: 0 18px; height: 52px; border-bottom: 1px solid var(--border-faint); flex-shrink: 0; } .slide-panel-title { font: 600 14px/1 var(--font); letter-spacing: -0.005em; color: var(--text-primary); } .slide-panel-body { flex: 1; min-height: 0; overflow-y: auto; padding: 18px; display: flex; flex-direction: column; gap: var(--sp-4); } .slide-panel-footer { padding: 14px 18px; background: var(--bg-deep); border-top: 1px solid var(--border-faint); 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-3); 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: 600; color: var(--text-primary); margin-bottom: 3px; } .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-3); 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: 600; letter-spacing: 0.06em; text-transform: uppercase; } .clip-list-item-status.matched { color: var(--signal-good); } .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(--signal-good); } .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(--signal-bad-bg); border: 1px solid oklch(64% 0.22 25 / 0.25); color: var(--signal-bad); padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm); font-size: var(--text-xs); line-height: 1.5; margin-bottom: var(--sp-2); } .success-message { background: var(--signal-good-bg); border: 1px solid oklch(70% 0.18 148 / 0.25); color: var(--signal-good); padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm); font-size: var(--text-xs); line-height: 1.5; 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); line-height: 1.5; 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: 600; 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); } .slide-panel { width: 100%; } }