diff --git a/services/web-ui/public/css/common.css b/services/web-ui/public/css/common.css index b6ff469..66e1af6 100644 --- a/services/web-ui/public/css/common.css +++ b/services/web-ui/public/css/common.css @@ -1,925 +1,787 @@ -/* Wild Dragon MAM - Common Styles */ +/* ================================================================ + WILD DRAGON MAM — Design System + Broadcast control register. Amber accent. Deep slate. + ================================================================ */ + +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap'); + +/* ================================================================ + TOKENS + ================================================================ */ -/* Color Palette - CSS Custom Properties */ :root { - --color-bg-primary: #0f0f1e; - --color-bg-secondary: #1a1a2e; - --color-bg-tertiary: #16213e; - --color-bg-hover: #252d48; + /* Background scale */ + --bg-base: oklch(11% 0.010 250); + --bg-panel: oklch(15.5% 0.012 250); + --bg-surface: oklch(20% 0.014 250); + --bg-raised: oklch(25% 0.015 250); + --bg-hover: oklch(29% 0.015 250); - --color-accent-primary: #e94560; - --color-accent-light: #ff5a7e; - --color-accent-dark: #d63050; + /* Accent — amber tally light */ + --accent: oklch(76% 0.178 52); + --accent-dim: oklch(56% 0.130 52); + --accent-subtle: oklch(76% 0.178 52 / 0.10); + --accent-border: oklch(76% 0.178 52 / 0.30); - --color-text-primary: #f0f0f0; - --color-text-secondary: #b0b0b0; - --color-text-tertiary: #808080; + /* Text */ + --text-primary: oklch(93% 0.008 250); + --text-secondary: oklch(62% 0.012 250); + --text-tertiary: oklch(44% 0.010 250); - --color-border: #2a3050; - --color-border-light: #3a4060; + /* Borders */ + --border: oklch(27% 0.014 250); + --border-strong: oklch(36% 0.016 250); - --color-status-ingesting: #f59e0b; - --color-status-processing: #3b82f6; - --color-status-ready: #10b981; - --color-status-error: #ef4444; - --color-status-archived: #6b7280; + /* Status colours */ + --status-green: oklch(68% 0.18 148); + --status-red: oklch(62% 0.22 25); + --status-blue: oklch(65% 0.16 245); + --status-amber: var(--accent); + --status-gray: oklch(44% 0.010 250); - --color-success: #10b981; - --color-warning: #f59e0b; - --color-danger: #ef4444; - --color-info: #3b82f6; + --status-green-bg: oklch(68% 0.18 148 / 0.10); + --status-red-bg: oklch(62% 0.22 25 / 0.10); + --status-blue-bg: oklch(65% 0.16 245 / 0.10); + --status-amber-bg: oklch(76% 0.178 52 / 0.10); - --spacing-xs: 4px; - --spacing-sm: 8px; - --spacing-md: 16px; - --spacing-lg: 24px; - --spacing-xl: 32px; + /* Spacing — 4pt base */ + --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; - --radius-sm: 4px; - --radius-md: 8px; - --radius-lg: 12px; + /* Typography */ + --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; + --text-xs: 11px; + --text-sm: 13px; + --text-base: 14px; + --text-md: 16px; + --text-lg: 18px; + --text-xl: 22px; - --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Helvetica Neue', sans-serif; + /* Radius */ + --r-sm: 4px; + --r-md: 6px; + --r-lg: 8px; - --transition-fast: 150ms ease-out; - --transition-normal: 250ms ease-out; + /* Shell dimensions */ + --sidebar-w: 220px; + --topbar-h: 48px; + + /* Z-index scale */ + --z-dropdown: 40; + --z-overlay: 80; + --z-panel: 90; + --z-toast: 200; + + /* Transitions */ + --t-fast: 150ms ease-out; + --t-normal: 250ms ease-out; } -/* Reset and Base Styles */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html { - scroll-behavior: smooth; - font-size: 16px; -} +/* ================================================================ + RESET + ================================================================ */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } +html { height: 100%; font-size: 16px; } body { - background-color: var(--color-bg-primary); - color: var(--color-text-primary); - font-family: var(--font-family); - line-height: 1.5; - letter-spacing: 0.3px; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + height: 100%; + font-family: var(--font); + font-size: var(--text-base); + color: var(--text-primary); + background: var(--bg-base); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + line-height: 1.5; + font-optical-sizing: auto; } +a { color: inherit; text-decoration: none; } +button { cursor: pointer; font-family: inherit; font-size: inherit; } +input, select, textarea { font-family: inherit; } +img { display: block; max-width: 100%; } +svg { display: block; flex-shrink: 0; } -/* Typography */ -h1, h2, h3, h4, h5, h6 { - font-weight: 600; - line-height: 1.2; - letter-spacing: -0.5px; -} +/* ================================================================ + SHELL LAYOUT + ================================================================ */ -h1 { - font-size: 2rem; -} - -h2 { - font-size: 1.5rem; -} - -h3 { - font-size: 1.25rem; -} - -h4 { - font-size: 1.1rem; -} - -p { - margin-bottom: var(--spacing-md); -} - -a { - color: var(--color-accent-primary); - text-decoration: none; - transition: color var(--transition-fast); -} - -a:hover { - color: var(--color-accent-light); -} - -/* Scrollbar Styling */ -::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -::-webkit-scrollbar-track { - background: var(--color-bg-secondary); -} - -::-webkit-scrollbar-thumb { - background: var(--color-bg-tertiary); - border-radius: var(--radius-sm); - border: 2px solid var(--color-bg-secondary); -} - -::-webkit-scrollbar-thumb:hover { - background: var(--color-border-light); -} - -/* Header Bar */ -.header { - display: flex; - align-items: center; - justify-content: space-between; - height: 60px; - background-color: var(--color-bg-secondary); - border-bottom: 1px solid var(--color-border); - padding: 0 var(--spacing-lg); - gap: var(--spacing-lg); - position: sticky; - top: 0; - z-index: 100; -} - -.header-logo { - display: flex; - align-items: center; - gap: var(--spacing-sm); - font-size: 1.1rem; - font-weight: 700; - letter-spacing: 1px; - text-transform: uppercase; - color: var(--color-text-primary); -} - -.header-logo-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 28px; - height: 28px; - background: linear-gradient(135deg, var(--color-accent-primary), var(--color-accent-light)); - border-radius: var(--radius-sm); - font-weight: 800; - font-size: 0.9rem; -} - -.header-nav { - display: flex; - gap: var(--spacing-lg); - align-items: center; -} - -.nav-item { - padding: var(--spacing-sm) var(--spacing-md); - color: var(--color-text-secondary); - transition: all var(--transition-fast); - cursor: pointer; - border-bottom: 2px solid transparent; - font-size: 0.95rem; - font-weight: 500; -} - -.nav-item:hover { - color: var(--color-text-primary); -} - -.nav-item.active { - color: var(--color-accent-primary); - border-bottom-color: var(--color-accent-primary); -} - -/* Layout Container */ -.app-container { - display: flex; - flex-direction: column; - height: 100vh; - overflow: hidden; -} - -.main-content { - display: flex; - flex: 1; - overflow: hidden; +.shell { + display: flex; + height: 100vh; + overflow: hidden; } .sidebar { - width: 280px; - background-color: var(--color-bg-secondary); - border-right: 1px solid var(--color-border); - overflow-y: auto; - padding: var(--spacing-md); - flex-shrink: 0; + width: var(--sidebar-w); + flex-shrink: 0; + display: flex; + flex-direction: column; + background: var(--bg-panel); + border-right: 1px solid var(--border); + overflow-y: auto; + overflow-x: hidden; } -.content-area { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; +.main { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + overflow: hidden; } -.content-main { - flex: 1; - overflow-y: auto; - padding: var(--spacing-lg); +/* ================================================================ + SIDEBAR + ================================================================ */ + +.sidebar-brand { + display: flex; + align-items: center; + gap: var(--sp-3); + height: var(--topbar-h); + padding: 0 var(--sp-4); + border-bottom: 1px solid var(--border); + flex-shrink: 0; } -/* Sidebar Sections */ -.sidebar-section { - margin-bottom: var(--spacing-lg); +.sidebar-brand-mark { + width: 22px; + height: 22px; + background: var(--accent); + border-radius: var(--r-sm); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: oklch(11% 0.010 250); } -.sidebar-section-title { - font-size: 0.85rem; - font-weight: 700; - color: var(--color-text-tertiary); - text-transform: uppercase; - letter-spacing: 0.5px; - margin-bottom: var(--spacing-sm); - padding: 0 var(--spacing-sm); +.sidebar-brand-name { + font-size: var(--text-sm); + font-weight: 500; + color: var(--text-primary); + letter-spacing: 0.05em; + text-transform: uppercase; + white-space: nowrap; } -.sidebar-item { - padding: var(--spacing-sm) var(--spacing-md); - margin-bottom: var(--spacing-xs); - background-color: transparent; - border: 1px solid transparent; - border-radius: var(--radius-md); - color: var(--color-text-secondary); - cursor: pointer; - font-size: 0.95rem; - transition: all var(--transition-fast); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; +.sidebar-nav { + flex: 1; + padding: var(--sp-3) 0; + display: flex; + flex-direction: column; + gap: 1px; } -.sidebar-item:hover { - background-color: var(--color-bg-hover); - border-color: var(--color-border-light); - color: var(--color-text-primary); +.sidebar-section-label { + padding: var(--sp-4) var(--sp-4) var(--sp-2); + font-size: 10px; + font-weight: 500; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--text-tertiary); } -.sidebar-item.active { - background-color: var(--color-bg-tertiary); - border-color: var(--color-accent-primary); - color: var(--color-accent-primary); +.nav-item { + display: flex; + align-items: center; + gap: var(--sp-3); + padding: var(--sp-2) var(--sp-4); + color: var(--text-secondary); + font-size: var(--text-sm); + font-weight: 400; + transition: color var(--t-fast), background var(--t-fast); + white-space: nowrap; + overflow: hidden; } -.sidebar-tree { - padding-left: var(--spacing-md); +.nav-item:hover { + color: var(--text-primary); + background: var(--bg-hover); } -.sidebar-tree-item { - padding: var(--spacing-xs) var(--spacing-sm); - margin-bottom: var(--spacing-xs); - font-size: 0.9rem; - color: var(--color-text-tertiary); - border-left: 2px solid var(--color-border); - border-radius: 0; - cursor: pointer; - transition: all var(--transition-fast); +.nav-item.active { + color: var(--accent); + background: var(--accent-subtle); + font-weight: 500; } -.sidebar-tree-item:hover { - color: var(--color-text-secondary); - border-left-color: var(--color-accent-primary); +.nav-item svg { + width: 15px; + height: 15px; + opacity: 0.7; + flex-shrink: 0; } -.sidebar-tree-item.active { - color: var(--color-accent-primary); - border-left-color: var(--color-accent-primary); +.nav-item.active svg { opacity: 1; } + +.sidebar-footer { + padding: var(--sp-4); + border-top: 1px solid var(--border); + flex-shrink: 0; } -/* Panels and Cards */ -.panel { - background-color: var(--color-bg-tertiary); - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - padding: var(--spacing-md); +/* ================================================================ + TOPBAR + ================================================================ */ + +.topbar { + height: var(--topbar-h); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 var(--sp-6); + background: var(--bg-panel); + border-bottom: 1px solid var(--border); + flex-shrink: 0; + gap: var(--sp-4); } -.panel-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--spacing-md); - padding-bottom: var(--spacing-md); - border-bottom: 1px solid var(--color-border); +.topbar-left { + display: flex; + align-items: center; + gap: var(--sp-3); + min-width: 0; } -.panel-title { - font-size: 1.1rem; - font-weight: 600; - color: var(--color-text-primary); +.topbar-right { + display: flex; + align-items: center; + gap: var(--sp-2); + flex-shrink: 0; } -.panel-action { - font-size: 0.9rem; - color: var(--color-accent-primary); - cursor: pointer; - transition: color var(--transition-fast); +.page-title { + font-size: var(--text-md); + font-weight: 500; + color: var(--text-primary); + white-space: nowrap; } -.panel-action:hover { - color: var(--color-accent-light); +.topbar-sep { + color: var(--text-tertiary); + font-size: var(--text-sm); + flex-shrink: 0; } -.card { - background-color: var(--color-bg-tertiary); - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - padding: 0; - overflow: hidden; - transition: all var(--transition-normal); - cursor: pointer; +/* ================================================================ + PAGE CONTENT + ================================================================ */ + +.page-content { + flex: 1; + overflow-y: auto; + padding: var(--sp-6); } -.card:hover { - border-color: var(--color-accent-primary); - box-shadow: 0 8px 24px rgba(233, 69, 96, 0.15); - transform: translateY(-2px); +.page-content::-webkit-scrollbar { width: 5px; } +.page-content::-webkit-scrollbar-track { background: transparent; } +.page-content::-webkit-scrollbar-thumb { + background: var(--border-strong); + border-radius: 3px; } -.card-thumbnail { - position: relative; - width: 100%; - padding-bottom: 62.5%; - background-color: var(--color-bg-primary); - overflow: hidden; -} +/* ================================================================ + BUTTONS + ================================================================ */ -.card-thumbnail img { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - object-fit: cover; -} - -.card-content { - padding: var(--spacing-md); -} - -.card-title { - font-size: 0.95rem; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: var(--spacing-xs); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.card-meta { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: var(--spacing-sm); -} - -.card-duration { - font-size: 0.85rem; - color: var(--color-text-tertiary); -} - -.card-status { - display: inline-block; -} - -/* Buttons */ .btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--spacing-sm); - padding: var(--spacing-sm) var(--spacing-md); - border: none; - border-radius: var(--radius-md); - font-size: 0.95rem; - font-weight: 600; - cursor: pointer; - transition: all var(--transition-fast); - text-decoration: none; - white-space: nowrap; - user-select: none; - font-family: var(--font-family); -} - -.btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.btn-primary { - background-color: var(--color-accent-primary); - color: white; -} - -.btn-primary:hover:not(:disabled) { - background-color: var(--color-accent-light); - box-shadow: 0 4px 12px rgba(233, 69, 96, 0.3); -} - -.btn-primary:active:not(:disabled) { - background-color: var(--color-accent-dark); -} - -.btn-secondary { - background-color: var(--color-bg-tertiary); - color: var(--color-text-primary); - border: 1px solid var(--color-border); -} - -.btn-secondary:hover:not(:disabled) { - background-color: var(--color-bg-hover); - border-color: var(--color-accent-primary); -} - -.btn-ghost { - background-color: transparent; - color: var(--color-text-secondary); - border: 1px solid transparent; -} - -.btn-ghost:hover:not(:disabled) { - color: var(--color-text-primary); - border-color: var(--color-border-light); + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--sp-2); + padding: 0 var(--sp-3); + height: 32px; + font-size: var(--text-sm); + font-weight: 500; + border: 1px solid transparent; + border-radius: var(--r-md); + transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast); + white-space: nowrap; + line-height: 1; + flex-shrink: 0; } .btn-sm { - padding: var(--spacing-xs) var(--spacing-sm); - font-size: 0.85rem; + height: 26px; + padding: 0 var(--sp-2); + font-size: var(--text-xs); + gap: var(--sp-1); + border-radius: var(--r-sm); } .btn-lg { - padding: var(--spacing-md) var(--spacing-lg); - font-size: 1.05rem; - min-height: 44px; + height: 40px; + padding: 0 var(--sp-5); + font-size: var(--text-base); + border-radius: var(--r-lg); } -.btn-icon { - padding: var(--spacing-sm); - border-radius: var(--radius-md); -} +.btn svg { width: 14px; height: 14px; flex-shrink: 0; } +.btn-sm svg { width: 12px; height: 12px; } +.btn-lg svg { width: 16px; height: 16px; } + +.btn-primary { + background: var(--accent); + color: oklch(11% 0.010 250); + border-color: var(--accent); +} +.btn-primary:hover { background: oklch(80% 0.178 52); border-color: oklch(80% 0.178 52); } +.btn-primary:active { background: oklch(70% 0.178 52); } + +.btn-secondary { + background: var(--bg-surface); + color: var(--text-primary); + border-color: var(--border-strong); +} +.btn-secondary:hover { background: var(--bg-raised); } + +.btn-ghost { + background: transparent; + color: var(--text-secondary); + border-color: transparent; +} +.btn-ghost:hover { 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 { background: var(--status-red-bg); } + +.btn-record { + background: var(--status-red); + color: oklch(98% 0.005 25); + border-color: var(--status-red); + font-variant-numeric: tabular-nums; +} +.btn-record:hover { background: oklch(68% 0.22 25); } +.btn-record.active { background: oklch(55% 0.22 25); box-shadow: 0 0 0 3px oklch(62% 0.22 25 / 0.25); } + +.btn:disabled { opacity: 0.38; cursor: not-allowed; pointer-events: none; } + +/* ================================================================ + FORM CONTROLS + ================================================================ */ -/* Form Elements */ .form-group { - margin-bottom: var(--spacing-md); + display: flex; + flex-direction: column; + gap: var(--sp-2); +} + +.form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--sp-4); } .form-label { - display: block; - margin-bottom: var(--spacing-sm); - font-size: 0.9rem; - font-weight: 600; - color: var(--color-text-secondary); - text-transform: uppercase; - letter-spacing: 0.3px; + font-size: var(--text-xs); + font-weight: 500; + letter-spacing: 0.07em; + text-transform: uppercase; + color: var(--text-secondary); } -.form-input, -.form-select, -.form-textarea { - width: 100%; - padding: var(--spacing-sm) var(--spacing-md); - background-color: var(--color-bg-primary); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - color: var(--color-text-primary); - font-family: var(--font-family); - font-size: 0.95rem; - transition: all var(--transition-fast); -} - -.form-input:focus, -.form-select:focus, -.form-textarea:focus { - outline: none; - border-color: var(--color-accent-primary); - background-color: var(--color-bg-secondary); - box-shadow: 0 0 0 3px rgba(233, 69, 96, 0.1); -} - -.form-input::placeholder { - color: var(--color-text-tertiary); -} - -.form-select { - cursor: pointer; - appearance: none; - background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%23b0b0b0' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E"); - background-position: right var(--spacing-sm) center; - background-repeat: no-repeat; - background-size: 1.5em 1.5em; - padding-right: 2.5rem; -} - -.form-textarea { - resize: vertical; - min-height: 100px; - font-family: 'Courier New', monospace; +.form-hint { + font-size: var(--text-xs); + color: var(--text-tertiary); + line-height: 1.5; } .form-error { - margin-top: var(--spacing-xs); - font-size: 0.85rem; - color: var(--color-status-error); + font-size: var(--text-xs); + color: var(--status-red); } -/* Status Badges */ +.input, +input[type="text"], +input[type="number"], +input[type="email"], +input[type="password"], +input[type="url"] { + width: 100%; + height: 34px; + padding: 0 var(--sp-3); + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--r-md); + color: var(--text-primary); + font-size: var(--text-sm); + transition: border-color var(--t-fast), box-shadow var(--t-fast); + outline: none; +} + +input[type="text"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="password"]:focus, +input[type="url"]:focus, +.input:focus { border-color: var(--accent-border); box-shadow: 0 0 0 3px var(--accent-subtle); } + +input::placeholder { color: var(--text-tertiary); } + +select { + width: 100%; + height: 34px; + padding: 0 28px 0 var(--sp-3); + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--r-md); + color: var(--text-primary); + font-size: var(--text-sm); + 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'%3E%3Cpath fill='%23667788' d='m7 10 5 5 5-5z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 8px 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 3px var(--accent-subtle); } +select option { background: var(--bg-surface); color: var(--text-primary); } + +textarea { + width: 100%; + padding: var(--sp-2) var(--sp-3); + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--r-md); + color: var(--text-primary); + font-size: var(--text-sm); + resize: vertical; + line-height: 1.5; + outline: none; + transition: border-color var(--t-fast); +} +textarea:focus { border-color: var(--accent-border); box-shadow: 0 0 0 3px var(--accent-subtle); } + +/* Toggle */ +.toggle { + display: flex; + align-items: center; + gap: var(--sp-3); + cursor: pointer; +} +.toggle-track { + position: relative; + width: 34px; + height: 18px; + background: var(--bg-hover); + border: 1px solid var(--border-strong); + border-radius: 9px; + transition: background var(--t-fast), border-color var(--t-fast); + flex-shrink: 0; +} +.toggle-track::after { + content: ''; + position: absolute; + width: 12px; height: 12px; + border-radius: 50%; + background: var(--text-tertiary); + top: 2px; left: 2px; + transition: transform var(--t-fast), background var(--t-fast); +} +.toggle input { position: absolute; opacity: 0; width: 0; height: 0; } +.toggle input:checked ~ .toggle-track { background: var(--accent); border-color: var(--accent); } +.toggle input:checked ~ .toggle-track::after { transform: translateX(16px); background: oklch(11% 0.010 250); } +.toggle-label { font-size: var(--text-sm); color: var(--text-secondary); } + +/* ================================================================ + BADGES + ================================================================ */ + .badge { - display: inline-flex; - align-items: center; - gap: var(--spacing-xs); - padding: 4px 10px; - border-radius: 20px; - font-size: 0.8rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.3px; + display: inline-flex; + align-items: center; + gap: var(--sp-1); + padding: 2px 7px; + border-radius: 100px; + font-size: var(--text-xs); + font-weight: 500; + letter-spacing: 0.04em; + white-space: nowrap; } -.badge-ingesting { - background-color: rgba(245, 158, 11, 0.2); - color: var(--color-status-ingesting); +.badge-recording { background: var(--status-amber-bg); color: var(--status-amber); } +.badge-idle { background: oklch(25% 0.014 250); color: var(--text-secondary); } +.badge-processing{ background: var(--status-blue-bg); color: var(--status-blue); } +.badge-ready { background: var(--status-green-bg); color: var(--status-green); } +.badge-error { background: var(--status-red-bg); color: var(--status-red); } +.badge-ingesting { background: var(--status-amber-bg); color: var(--status-amber); } +.badge-archived { background: oklch(25% 0.014 250); color: var(--text-tertiary); } + +.badge-sdi { background: var(--status-blue-bg); color: var(--status-blue); } +.badge-srt { background: var(--status-green-bg); color: var(--status-green); } +.badge-rtmp { background: var(--accent-subtle); color: var(--accent); } + +/* ================================================================ + STATUS DOTS + ================================================================ */ + +.status-dot { + display: inline-block; + width: 7px; height: 7px; + border-radius: 50%; + flex-shrink: 0; +} +.status-dot--recording { background: var(--accent); animation: pulse-amber 2s ease-out infinite; } +.status-dot--ready { background: var(--status-green); } +.status-dot--error { background: var(--status-red); } +.status-dot--processing { background: var(--status-blue); } +.status-dot--idle { background: var(--bg-hover); border: 1px solid var(--border-strong); } + +@keyframes pulse-amber { + 0% { box-shadow: 0 0 0 0 oklch(76% 0.178 52 / 0.8); } + 60% { box-shadow: 0 0 0 5px oklch(76% 0.178 52 / 0); } + 100% { box-shadow: 0 0 0 0 oklch(76% 0.178 52 / 0); } } -.badge-processing { - background-color: rgba(59, 130, 246, 0.2); - color: var(--color-status-processing); +/* ================================================================ + DIVIDER + ================================================================ */ + +.divider { height: 1px; background: var(--border); border: none; } + +/* ================================================================ + EMPTY STATE + ================================================================ */ + +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--sp-16) 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: 40px; height: 40px; } +.empty-state-title { font-size: var(--text-md); font-weight: 500; } +.empty-state-body { font-size: var(--text-sm); color: var(--text-secondary); max-width: 34ch; line-height: 1.6; } +.empty-state-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-2); } + +/* ================================================================ + TOASTS + ================================================================ */ + +.toast-container { + position: fixed; + bottom: var(--sp-6); + right: var(--sp-6); + display: flex; + flex-direction: column; + gap: var(--sp-2); + z-index: var(--z-toast); + pointer-events: none; +} +.toast { + display: flex; + align-items: flex-start; + gap: var(--sp-3); + padding: var(--sp-3) var(--sp-4); + background: var(--bg-raised); + border: 1px solid var(--border-strong); + border-radius: var(--r-lg); + font-size: var(--text-sm); + min-width: 260px; + max-width: 360px; + pointer-events: all; + animation: toast-in 180ms ease-out; +} +.toast-icon { flex-shrink: 0; margin-top: 1px; } +.toast-icon svg { width: 15px; height: 15px; } +.toast-body { flex: 1; } +.toast-title { font-weight: 500; color: var(--text-primary); } +.toast-msg { font-size: var(--text-xs); color: var(--text-secondary); margin-top: 2px; } +.toast--success .toast-icon { color: var(--status-green); } +.toast--error .toast-icon { color: var(--status-red); } +.toast--info .toast-icon { color: var(--status-blue); } +.toast--warning .toast-icon { color: var(--accent); } + +@keyframes toast-in { + from { opacity: 0; transform: translateY(6px); } + to { opacity: 1; transform: translateY(0); } } -.badge-ready { - background-color: rgba(16, 185, 129, 0.2); - color: var(--color-status-ready); +/* ================================================================ + SLIDE PANEL + ================================================================ */ + +.slide-overlay { + position: fixed; + inset: 0; + background: oklch(8% 0.010 250 / 0.65); + z-index: var(--z-overlay); + 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: 460px; + background: var(--bg-panel); + border-left: 1px solid var(--border); + z-index: var(--z-panel); + 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-6); + height: var(--topbar-h); + border-bottom: 1px solid var(--border); + flex-shrink: 0; +} +.slide-panel-title { font-size: var(--text-base); font-weight: 500; } + +.slide-panel-body { + flex: 1; + overflow-y: auto; + padding: var(--sp-6); + display: flex; + flex-direction: column; + gap: var(--sp-5); } -.badge-error { - background-color: rgba(239, 68, 68, 0.2); - color: var(--color-status-error); +.slide-panel-footer { + padding: var(--sp-4) var(--sp-6); + border-top: 1px solid var(--border); + display: flex; + justify-content: flex-end; + gap: var(--sp-2); + flex-shrink: 0; } -.badge-archived { - background-color: rgba(107, 114, 128, 0.2); - color: var(--color-status-archived); +/* ================================================================ + DATA TABLE + ================================================================ */ + +.data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--text-sm); + font-variant-numeric: tabular-nums; +} +.data-table th { + text-align: left; + padding: var(--sp-2) var(--sp-3); + font-size: 11px; + font-weight: 500; + letter-spacing: 0.07em; + text-transform: uppercase; + color: var(--text-tertiary); + border-bottom: 1px solid var(--border); + white-space: nowrap; +} +.data-table td { + padding: var(--sp-3); + border-bottom: 1px solid var(--border); + vertical-align: middle; + color: var(--text-primary); +} +.data-table tr:last-child td { border-bottom: none; } +.data-table tbody tr:hover td { background: var(--bg-surface); } + +/* ================================================================ + TABS + ================================================================ */ + +.tabs { display: flex; border-bottom: 1px solid var(--border); gap: 0; } +.tab { + padding: var(--sp-2) var(--sp-4); + font-size: var(--text-sm); + font-weight: 400; + color: var(--text-secondary); + border: none; + border-bottom: 2px solid transparent; + margin-bottom: -1px; + background: none; + cursor: pointer; + transition: color var(--t-fast), border-color var(--t-fast); + border-radius: 0; + white-space: nowrap; +} +.tab:hover { color: var(--text-primary); } +.tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 500; } + +/* ================================================================ + PROGRESS BAR + ================================================================ */ + +.progress-bar { height: 3px; background: var(--bg-hover); border-radius: 2px; overflow: hidden; } +.progress-fill { height: 100%; background: var(--accent); border-radius: 2px; transition: width 300ms ease-out; } +.progress-fill--success { background: var(--status-green); } +.progress-fill--error { background: var(--status-red); } + +/* ================================================================ + INFO BANNER (inline connection info etc.) + ================================================================ */ + +.info-banner { + display: flex; + align-items: flex-start; + gap: var(--sp-3); + padding: var(--sp-3) var(--sp-4); + background: var(--accent-subtle); + border: 1px solid var(--accent-border); + border-radius: var(--r-md); + font-size: var(--text-xs); + color: var(--accent); + line-height: 1.5; +} +.info-banner svg { width: 14px; height: 14px; flex-shrink: 0; margin-top: 1px; } +.info-banner code { + font-family: 'SF Mono', 'Consolas', 'Menlo', monospace; + font-size: 11px; + opacity: 0.9; } -.badge::before { - content: ''; - display: inline-block; - width: 6px; - height: 6px; - border-radius: 50%; - background-color: currentColor; -} +/* ================================================================ + SEGMENT (conditional field groups) + ================================================================ */ -/* Grid Layout */ -.grid { - display: grid; - gap: var(--spacing-lg); -} +.conditional-fields { display: flex; flex-direction: column; gap: var(--sp-5); } +.conditional-fields:empty { display: none; } -.grid-2 { - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); -} +/* ================================================================ + UTILITY + ================================================================ */ -.grid-3 { - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); -} - -.grid-4 { - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); -} - -/* Search Bar */ -.search-bar { - display: flex; - align-items: center; - gap: var(--spacing-sm); - padding: 0 var(--spacing-md); - background-color: var(--color-bg-secondary); - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - margin-bottom: var(--spacing-lg); - height: 44px; - transition: all var(--transition-fast); -} - -.search-bar:focus-within { - border-color: var(--color-accent-primary); - background-color: var(--color-bg-tertiary); - box-shadow: 0 0 0 3px rgba(233, 69, 96, 0.1); -} - -.search-bar input { - flex: 1; - background: transparent; - border: none; - color: var(--color-text-primary); - font-size: 0.95rem; -} - -.search-bar input:focus { - outline: none; -} - -.search-bar input::placeholder { - color: var(--color-text-tertiary); -} - -.search-icon { - color: var(--color-text-tertiary); -} - -/* Bottom Bar / Status Bar */ -.status-bar { - display: flex; - align-items: center; - justify-content: space-between; - height: 50px; - background-color: var(--color-bg-secondary); - border-top: 1px solid var(--color-border); - padding: 0 var(--spacing-lg); - gap: var(--spacing-lg); - flex-shrink: 0; -} - -.status-item { - display: flex; - align-items: center; - gap: var(--spacing-sm); - font-size: 0.9rem; - color: var(--color-text-secondary); -} - -.status-indicator { - display: inline-block; - width: 8px; - height: 8px; - border-radius: 50%; - background-color: var(--color-status-ready); -} - -.status-indicator.disconnected { - background-color: var(--color-status-error); -} - -/* Recording Indicator */ -.recording-indicator { - display: inline-flex; - align-items: center; - gap: var(--spacing-sm); - padding: 4px 10px; - background-color: rgba(239, 68, 68, 0.2); - border-radius: 20px; - font-size: 0.85rem; - color: var(--color-status-error); - font-weight: 600; -} - -.recording-dot { - display: inline-block; - width: 8px; - height: 8px; - border-radius: 50%; - background-color: var(--color-status-error); - animation: pulse 1s infinite; -} - -@keyframes pulse { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } -} - -/* Modal/Overlay */ -.modal-overlay { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.6); - z-index: 1000; - animation: fadeIn var(--transition-normal); -} - -.modal-overlay.active { - display: flex; - align-items: center; - justify-content: center; -} - -.modal { - background-color: var(--color-bg-secondary); - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - max-width: 600px; - width: 90%; - max-height: 90vh; - overflow-y: auto; - animation: slideUp var(--transition-normal); - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4); -} - -.modal-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-lg); - border-bottom: 1px solid var(--color-border); -} - -.modal-title { - font-size: 1.25rem; - font-weight: 700; - color: var(--color-text-primary); -} - -.modal-close { - background: none; - border: none; - color: var(--color-text-secondary); - font-size: 1.5rem; - cursor: pointer; - padding: 0; - width: 32px; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - transition: all var(--transition-fast); -} - -.modal-close:hover { - color: var(--color-text-primary); -} - -.modal-body { - padding: var(--spacing-lg); -} - -.modal-footer { - display: flex; - justify-content: flex-end; - gap: var(--spacing-md); - padding: var(--spacing-lg); - border-top: 1px solid var(--color-border); - background-color: var(--color-bg-tertiary); -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes slideUp { - from { - transform: translateY(20px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -/* Responsive */ -@media (max-width: 768px) { - .main-content { - flex-direction: column; - } - - .sidebar { - width: 100%; - border-right: none; - border-bottom: 1px solid var(--color-border); - max-height: 150px; - overflow-x: auto; - display: flex; - gap: var(--spacing-lg); - padding: var(--spacing-md); - } - - .sidebar-section { - margin-bottom: 0; - white-space: nowrap; - } - - .grid-2 { - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); - } - - .header { - flex-wrap: wrap; - height: auto; - padding: var(--spacing-md); - } - - .header-nav { - width: 100%; - order: 3; - } -} - -@media (max-width: 480px) { - :root { - font-size: 14px; - } - - .header { - padding: var(--spacing-sm); - } - - .content-main { - padding: var(--spacing-md); - } - - .grid-2 { - grid-template-columns: 1fr; - } - - .modal { - width: 95%; - } -} - -/* Utilities */ -.hidden { - display: none !important; -} - -.visible { - display: block !important; -} - -.flex { - display: flex; -} - -.flex-col { - flex-direction: column; -} - -.gap-sm { - gap: var(--spacing-sm); -} - -.gap-md { - gap: var(--spacing-md); -} - -.gap-lg { - gap: var(--spacing-lg); -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.mt-sm { margin-top: var(--spacing-sm); } -.mt-md { margin-top: var(--spacing-md); } -.mt-lg { margin-top: var(--spacing-lg); } - -.mb-sm { margin-bottom: var(--spacing-sm); } -.mb-md { margin-bottom: var(--spacing-md); } -.mb-lg { margin-bottom: var(--spacing-lg); } - -.p-sm { padding: var(--spacing-sm); } -.p-md { padding: var(--spacing-md); } -.p-lg { padding: var(--spacing-lg); } - -.opacity-50 { - opacity: 0.5; -} - -.opacity-75 { - opacity: 0.75; -} - -.cursor-pointer { - cursor: pointer; -} - -.truncate { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.no-wrap { - white-space: nowrap; -} +.monospace { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum'; } +.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.text-xs { font-size: var(--text-xs); } +.text-sm { font-size: var(--text-sm); } +.text-secondary { color: var(--text-secondary); } +.text-tertiary { color: var(--text-tertiary); } +.text-accent { color: var(--accent); } +.text-error { color: var(--status-red); } +.text-success { color: var(--status-green); } +.flex { display: flex; } +.flex-col { display: flex; flex-direction: column; } +.items-center { align-items: center; } +.gap-2 { gap: var(--sp-2); } +.gap-3 { gap: var(--sp-3); } +.gap-4 { gap: var(--sp-4); } +.mt-1 { margin-top: var(--sp-1); } +.mt-2 { margin-top: var(--sp-2); } +.mt-4 { margin-top: var(--sp-4); } +.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }