diff --git a/services/web-ui/public/styles-rest.css b/services/web-ui/public/styles-rest.css new file mode 100644 index 0000000..78904db --- /dev/null +++ b/services/web-ui/public/styles-rest.css @@ -0,0 +1,807 @@ +/* ========== Projects ========== */ +.projects-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); + gap: 14px; +} +.project-card { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + overflow: hidden; + cursor: pointer; + transition: transform 120ms, border 80ms; +} +.project-card:hover { + transform: translateY(-2px); + border-color: var(--border-stronger); +} +.project-thumb-grid { + display: grid; + grid-template-columns: 2fr 1fr; + grid-template-rows: 1fr 1fr; + gap: 2px; + aspect-ratio: 16 / 9; + background: var(--bg-2); +} +.project-thumb-grid .project-thumb-cell:first-child { grid-row: span 2; } +.project-thumb-cell { position: relative; overflow: hidden; background: var(--bg-2); } +.project-thumb-cell .thumb-svg { width: 100%; height: 100%; } +.project-card-body { padding: 12px 14px; } +.project-meta { + display: flex; gap: 6px; + font-size: 11.5px; color: var(--text-3); + margin-top: 4px; +} +.project-bar { + margin-top: 10px; + display: flex; + height: 4px; + border-radius: 99px; + overflow: hidden; + background: var(--bg-3); + gap: 1px; +} + +/* ========== Upload ========== */ +.field-label { + font-size: 10.5px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--text-4); + display: block; + margin-bottom: 6px; +} +.select-faux, .field-input { + height: 34px; + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-sm); + padding: 0 10px; + display: flex; align-items: center; gap: 8px; + color: var(--text-1); + font-size: 12.5px; + width: 100%; + cursor: pointer; +} +.field-input { font-size: 12.5px; outline: 0; } +.field-input:focus { border-color: var(--accent); background: var(--bg-2); } +.field-input.select { justify-content: space-between; } + +.dropzone { + background: var(--bg-1); + border: 1.5px dashed var(--border-stronger); + border-radius: var(--r-lg); + padding: 40px 24px; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + cursor: pointer; + transition: background 120ms, border 120ms; +} +.dropzone:hover { background: var(--bg-2); border-color: var(--accent); } +.dropzone-formats { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; justify-content: center; } +.upload-row { + display: flex; align-items: center; gap: 12px; + padding: 12px 14px; + border-bottom: 1px solid var(--border); +} +.upload-row:last-child { border-bottom: 0; } + +/* ========== Recorders ========== */ +.recorders-list { display: flex; flex-direction: column; gap: 10px; } +.recorder-row { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + padding: 12px; + display: grid; + grid-template-columns: 220px 1fr 380px auto; + align-items: center; + gap: 16px; + transition: border 80ms; +} +.recorder-row:hover { border-color: var(--border-stronger); } +.recorder-row.recording { border-color: rgba(255,59,48,0.25); } +.recorder-row.error { border-color: rgba(255,91,91,0.25); } +.recorder-preview { + height: 56px; + border-radius: var(--r-sm); + background: var(--bg-2); + overflow: hidden; + position: relative; +} +.recorder-empty { + height: 100%; + display: grid; place-items: center; + color: var(--text-3); +} +.recorder-audio-prev { + height: 100%; + display: flex; align-items: center; gap: 10px; + padding: 0 12px; +} +.recorder-audio-prev .waveform { flex: 1; height: 80%; } +.recorder-info { min-width: 0; display: flex; flex-direction: column; gap: 4px; } +.recorder-sub { + font-size: 11.5px; + color: var(--text-3); + display: flex; gap: 6px; +} +.recorder-sub.mono { font-family: var(--font-mono); font-size: 11px; } +.recorder-stats { + display: grid; + grid-template-columns: 90px 90px 1fr; + gap: 12px; +} +.recorder-stat .stat-label { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.06em; + font-weight: 600; + color: var(--text-4); + margin-bottom: 3px; +} +.recorder-stat .stat-val { font-size: 12.5px; } +.recorder-actions { display: flex; align-items: center; gap: 4px; } +.rec-dot { + width: 8px; height: 8px; + border-radius: 50%; + background: currentColor; +} + +/* ========== Capture / DeckLink ========== */ +.decklink-card { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + overflow: hidden; +} +.decklink-head { + padding: 14px 16px; + display: flex; justify-content: space-between; align-items: center; + border-bottom: 1px solid var(--border); +} +.decklink-body { + padding: 24px; + display: grid; + grid-template-columns: 60px 1fr; + gap: 20px; + align-items: stretch; + background: + radial-gradient(ellipse at top, rgba(91,124,250,0.05), transparent 60%), + var(--bg-0); +} +.decklink-card-face { + background: linear-gradient(180deg, #1c1f28, #0d0e13); + border: 1px solid var(--border-strong); + border-radius: 6px; + display: flex; flex-direction: column; + justify-content: space-between; + padding: 12px 6px; + position: relative; +} +.decklink-label { + writing-mode: vertical-rl; + transform: rotate(180deg); + font-family: var(--font-mono); + font-size: 8.5px; + letter-spacing: 0.12em; + color: var(--text-3); + text-align: center; + margin: 0 auto; +} +.decklink-leds { + display: flex; gap: 6px; + justify-content: center; +} +.decklink-led { + width: 6px; height: 6px; + border-radius: 50%; + background: rgba(255,255,255,0.1); +} +.decklink-led.on { + background: var(--success); + box-shadow: 0 0 6px var(--success); +} +.bnc-ports { display: flex; flex-direction: column; gap: 10px; } +.bnc-port { + display: grid; + grid-template-columns: 32px 1fr auto; + align-items: center; + gap: 12px; + padding: 10px; + background: var(--bg-2); + border: 1px solid var(--border); + border-radius: var(--r-sm); + text-align: left; + cursor: pointer; + position: relative; + transition: background 80ms, border 80ms; +} +.bnc-port:hover { border-color: var(--border-stronger); } +.bnc-port.active { background: var(--bg-3); } +.bnc-port.active.live::before { + content: ""; + position: absolute; + left: 0; top: 0; bottom: 0; + width: 2px; + background: var(--success); +} +.bnc-port.recording::before { background: var(--live); } +.bnc-port.active { box-shadow: inset 0 0 0 1px var(--accent); border-color: var(--accent); } +.bnc-connector { + width: 32px; height: 32px; + border-radius: 50%; + background: radial-gradient(circle, #1a1d24, #0a0c11); + display: grid; place-items: center; + border: 1.5px solid var(--border-stronger); + position: relative; +} +.bnc-pin { + width: 6px; height: 6px; + background: linear-gradient(135deg, #6b7280, #2a2f3a); + border-radius: 50%; +} +.bnc-ring { + position: absolute; + inset: 4px; + border: 1px dashed rgba(255,255,255,0.08); + border-radius: 50%; +} +.bnc-port.live .bnc-pin { background: linear-gradient(135deg, #FFC857, #C8862D); box-shadow: 0 0 8px rgba(255,200,87,0.4); } +.bnc-port.recording .bnc-pin { background: linear-gradient(135deg, #FF5C5C, #C8362D); box-shadow: 0 0 8px rgba(255,92,92,0.5); } +.bnc-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; } +.bnc-num { font-size: 12.5px; font-weight: 600; } +.bnc-label { font-size: 11px; color: var(--text-2); } +.bnc-sig { font-size: 10.5px; color: var(--text-3); } +.bnc-port.live .bnc-sig { color: var(--success); } +.bnc-rec { + width: 10px; height: 10px; + border-radius: 50%; + background: var(--live); + animation: pulse 1.2s ease-in-out infinite; +} +.bnc-signal-bar { + grid-column: 2 / 4; + height: 3px; + background: var(--bg-3); + border-radius: 99px; + overflow: hidden; + margin-top: 4px; +} +.bnc-signal-fill { + height: 100%; + background: linear-gradient(90deg, var(--success), var(--warning), var(--danger)); + background-size: 200% 100%; + background-position: 0% 0; + transition: width 200ms; +} +.decklink-foot { + padding: 10px 16px; + border-top: 1px solid var(--border); + display: flex; gap: 20px; + font-size: 11.5px; + color: var(--text-3); +} +.decklink-foot strong { color: var(--text-1); font-weight: 600; } + +.capture-detail { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + padding: 16px; +} +.capture-detail.empty { + display: flex; flex-direction: column; + align-items: center; justify-content: center; + padding: 80px 24px; + color: var(--text-3); +} +.capture-preview { + position: relative; + aspect-ratio: 16 / 9; + border-radius: var(--r-md); + overflow: hidden; + background: #000; +} +.capture-overlay-meters { + position: absolute; + right: 8px; top: 8px; + display: flex; gap: 4px; +} +.capture-tc { + position: absolute; + bottom: 8px; right: 8px; + background: rgba(0,0,0,0.7); + padding: 3px 8px; + border-radius: 3px; + font-family: var(--font-mono); + font-size: 11px; + color: white; +} +.capture-stats { + margin-top: 16px; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; +} +.capture-stat { + background: var(--bg-2); + border: 1px solid var(--border); + border-radius: var(--r-sm); + padding: 8px 10px; +} +.capture-stat-label { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.06em; + font-weight: 600; + color: var(--text-4); +} +.capture-stat-value { font-size: 13px; margin-top: 2px; } + +/* ========== Monitors ========== */ +.monitors-grid { + display: grid; + gap: 10px; + background: var(--bg-2); + border-radius: var(--r-lg); + padding: 10px; +} +.monitor-tile { + position: relative; + aspect-ratio: 16 / 9; + background: #000; + border-radius: var(--r-sm); + overflow: hidden; + border: 1px solid var(--border); + display: flex; flex-direction: column; + cursor: pointer; +} +.monitor-tile.audio { background: linear-gradient(135deg, hsl(180 30% 12%), hsl(200 25% 6%)); } +.monitor-tile-label { + position: absolute; + bottom: 0; left: 0; right: 0; + padding: 8px 10px; + background: linear-gradient(180deg, transparent, rgba(0,0,0,0.8)); + display: flex; align-items: center; gap: 6px; +} +.monitor-tile-label .name { + color: white; + font-size: 11.5px; + font-weight: 500; +} +.monitor-tile-label .time { + margin-left: auto; + color: white; + font-family: var(--font-mono); + font-size: 10.5px; +} + +/* ========== Jobs ========== */ +.jobs-stats { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 12px; +} +.job-row { + display: grid; + grid-template-columns: 20px 110px 1fr 90px 200px 70px 80px 90px; + align-items: center; + gap: 12px; + padding: 10px 16px; + border-bottom: 1px solid var(--border); + font-size: 12.5px; +} +.job-row:last-child { border-bottom: 0; } +.job-row.head { + font-size: 10.5px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--text-4); +} +.job-progress-wrap { + display: flex; align-items: center; gap: 8px; +} +.job-progress-bar { + flex: 1; + height: 5px; + background: var(--bg-3); + border-radius: 99px; + overflow: hidden; + position: relative; +} +.job-progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--accent), #7C9EFF); + background-size: 200% 100%; + animation: shimmer 2s linear infinite; + transition: width 300ms; +} + +/* ========== Editor ========== */ +.editor-shell { + display: flex; flex-direction: column; + height: 100%; + background: var(--bg-0); +} +.editor-topbar { + height: 44px; + border-bottom: 1px solid var(--border); + padding: 0 14px; + display: flex; align-items: center; gap: 10px; +} +.editor-body { + flex: 1; + display: grid; + grid-template-columns: 240px 1fr 240px; + min-height: 0; +} +.editor-bins, .editor-insp { background: var(--bg-1); border-right: 1px solid var(--border); overflow-y: auto; } +.editor-insp { border-right: 0; border-left: 1px solid var(--border); } +.editor-bin-item { + display: flex; align-items: center; gap: 8px; + padding: 6px; + border-radius: var(--r-sm); + cursor: pointer; +} +.editor-bin-item:hover { background: var(--hover); } +.editor-bin-thumb { width: 48px; aspect-ratio: 16/9; border-radius: 3px; overflow: hidden; background: var(--bg-2); flex-shrink: 0; } +.editor-viewer { background: #000; display: flex; flex-direction: column; } +.editor-canvas { + flex: 1; + position: relative; + background: #050608; + display: grid; place-items: center; + overflow: hidden; + max-height: 50vh; +} +.editor-canvas .thumb-svg { width: 100%; height: 100%; } +.editor-transport { + height: 44px; + display: flex; align-items: center; gap: 8px; + padding: 0 14px; + background: var(--bg-1); + border-top: 1px solid var(--border); +} +.editor-timeline { + background: var(--bg-0); + border-top: 1px solid var(--border); + height: 240px; + display: flex; flex-direction: column; + position: relative; + overflow: hidden; +} +.editor-timeline-head { + height: 32px; + display: flex; align-items: center; + padding: 0 12px; + gap: 8px; + border-bottom: 1px solid var(--border); +} +.timeline-ruler { + height: 22px; + display: flex; + padding-left: 40px; + border-bottom: 1px solid var(--border); + background: var(--bg-1); +} +.ruler-tick { + flex: 1; + border-left: 1px solid var(--border); + font-size: 9.5px; + color: var(--text-4); + padding: 4px 4px 0; +} +.timeline-track { + display: grid; + grid-template-columns: 40px 1fr; + align-items: stretch; + height: 42px; + border-bottom: 1px solid var(--border); +} +.timeline-track-label { + background: var(--bg-1); + display: grid; place-items: center; + font-size: 10.5px; + font-family: var(--font-mono); + font-weight: 600; + color: var(--text-3); + border-right: 1px solid var(--border); +} +.timeline-track-lane { + position: relative; + background: + repeating-linear-gradient(90deg, transparent 0 49px, rgba(255,255,255,0.02) 49px 50px); +} +.clip { + position: absolute; + top: 4px; bottom: 4px; + border-radius: 3px; + overflow: hidden; + display: flex; align-items: center; + cursor: pointer; + border: 1px solid rgba(0,0,0,0.3); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.15); +} +.clip-label { + position: absolute; + left: 6px; top: 3px; + font-size: 10px; + font-weight: 600; + color: white; + z-index: 2; + text-shadow: 0 1px 1px rgba(0,0,0,0.4); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.clip-film { display: flex; flex: 1; height: 100%; } +.clip-film-cell { flex: 1; overflow: hidden; } +.clip-film-cell .thumb-svg { width: 100%; height: 100%; } +.clip.audio { background: var(--success) !important; } +.clip-wave { width: 100%; height: 100%; padding: 4px; opacity: 0.6; } +.clip-wave .waveform { width: 100%; height: 100%; } +.timeline-playhead { + position: absolute; + top: 32px; bottom: 0; + width: 1.5px; + background: var(--live); + pointer-events: none; + z-index: 5; +} +.timeline-playhead::before { + content: ""; + position: absolute; + top: -4px; left: 50%; + width: 10px; height: 10px; + background: var(--live); + transform: translateX(-50%) rotate(45deg); +} + +/* ========== Admin tables ========== */ +.user-row, .token-row, .container-row { + display: grid; + align-items: center; + gap: 12px; + padding: 12px 16px; + border-bottom: 1px solid var(--border); + font-size: 12.5px; +} +.user-row { grid-template-columns: 1.5fr 100px 1.5fr 120px 40px; } +.token-row { grid-template-columns: 1.4fr 1.4fr 110px 110px 100px 40px; } +.container-row { grid-template-columns: 1.4fr 1.4fr 140px 140px 100px 1.4fr 110px; } +.user-row.head, .token-row.head, .container-row.head { + font-size: 10.5px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--text-4); +} +.user-row:last-child, .token-row:last-child, .container-row:last-child { border-bottom: 0; } +.token-row.revoked { opacity: 0.5; } + +/* ========== Cluster ========== */ +.cluster-canvas { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + overflow: hidden; +} + +/* ========== Settings ========== */ +.settings-nav { + display: flex; flex-direction: column; gap: 2px; + position: sticky; top: 0; +} +.settings-nav-item { + display: flex; align-items: center; gap: 8px; + padding: 0 10px; + height: 32px; + border-radius: var(--r-sm); + color: var(--text-2); + font-size: 12.5px; + cursor: pointer; +} +.settings-nav-item:hover { background: var(--hover); color: var(--text-1); } +.settings-nav-item.active { background: var(--accent-soft); color: var(--accent-text); } +.settings-card { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + overflow: hidden; +} +.settings-card-head { + padding: 16px; + display: flex; align-items: flex-start; gap: 12px; + border-bottom: 1px solid var(--border); +} +.settings-card-icon { + width: 36px; height: 36px; + border-radius: var(--r-sm); + background: var(--accent-soft); + color: var(--accent); + display: grid; place-items: center; + flex-shrink: 0; +} +.settings-card-body { padding: 16px; display: flex; flex-direction: column; gap: 12px; } +.field { display: flex; flex-direction: column; gap: 4px; } +.field-input-wrap { display: flex; gap: 6px; align-items: center; } +.checkbox-row { + display: flex; align-items: center; gap: 8px; + font-size: 12.5px; color: var(--text-1); + cursor: pointer; +} +.checkbox-row input { accent-color: var(--accent); } + +/* ========== Tokens parody ========== */ +.token-hero { + display: grid; + grid-template-columns: 2fr 1fr; + gap: 14px; + margin-bottom: 16px; +} +.token-burn-card, .token-actual-card { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + padding: 18px 20px; + position: relative; + overflow: hidden; +} +.token-burn-card { + background: + radial-gradient(ellipse at top right, rgba(255,91,91,0.12), transparent 60%), + var(--bg-1); + border-color: rgba(255,91,91,0.18); +} +.token-actual-card { + background: + radial-gradient(ellipse at bottom left, rgba(45,212,168,0.10), transparent 60%), + var(--bg-1); + border-color: rgba(45,212,168,0.18); +} +.token-card-label { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; + font-weight: 700; + color: var(--text-4); + margin-bottom: 8px; +} +.token-counter { + display: flex; align-items: baseline; gap: 12px; +} +.token-flame { font-size: 32px; line-height: 1; } +.token-big { + font-size: 48px; + font-weight: 700; + letter-spacing: -0.03em; + font-variant-numeric: tabular-nums; + background: linear-gradient(180deg, #FF9D6B, #FF5B5B); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + line-height: 1.05; +} +.token-rate { + font-size: 12px; + display: flex; align-items: baseline; + font-family: var(--font-mono); +} +.token-actual-amount { + display: flex; align-items: baseline; gap: 0; + color: var(--success); + margin-bottom: 8px; +} + +.token-comparison { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + padding: 0 0 12px; + margin-bottom: 16px; + overflow: hidden; +} +.token-compare-chart { + padding: 0 16px; +} +.token-compare-legend { + display: flex; gap: 24px; + padding: 8px 0 0; + font-size: 12px; + color: var(--text-2); +} +.token-compare-legend .dot { + display: inline-block; + width: 10px; height: 10px; + border-radius: 50%; + margin-right: 6px; + vertical-align: middle; +} + +.token-grid { + display: grid; + grid-template-columns: 1fr 1.4fr; + gap: 14px; +} +.token-event { + display: flex; align-items: center; gap: 12px; + padding: 10px 14px; + border-bottom: 1px solid var(--border); +} +.token-event:last-child { border-bottom: 0; } +.token-event.fresh { animation: tokenFresh 800ms ease; } +@keyframes tokenFresh { + 0% { background: rgba(255,91,91,0.15); transform: translateX(-4px); } + 100% { background: transparent; transform: none; } +} +.token-tiers { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; +} +.token-tier { + background: var(--bg-1); + border: 1px solid var(--border); + border-radius: var(--r-lg); + padding: 16px 14px; + display: flex; flex-direction: column; + gap: 6px; + position: relative; +} +.token-tier.popular { + border-color: var(--accent); + background: linear-gradient(180deg, var(--accent-soft) 0%, var(--bg-1) 40%); + box-shadow: 0 0 24px rgba(91,124,250,0.10); +} +.token-tier-badge { + position: absolute; + top: -8px; right: 12px; + background: var(--accent); + color: white; + font-size: 9.5px; + font-weight: 700; + letter-spacing: 0.06em; + padding: 3px 8px; + border-radius: 99px; +} +.token-tier-name { + font-size: 13px; + font-weight: 700; + letter-spacing: -0.01em; +} +.token-tier-desc { + font-size: 11px; + color: var(--text-3); + min-height: 32px; + line-height: 1.4; +} +.token-tier-price { + margin-top: 6px; + display: flex; align-items: baseline; +} +.token-tier-tokens { + font-size: 11px; + color: var(--text-3); + padding-top: 4px; + border-top: 1px solid var(--border); +} + +.token-footnote { + margin-top: 20px; + padding: 14px 16px; + background: var(--warning-soft); + border: 1px solid rgba(245,166,35,0.2); + border-radius: var(--r-md); + display: flex; gap: 12px; + font-size: 12.5px; + color: var(--text-2); + line-height: 1.55; +} +.token-footnote svg { color: var(--warning); flex-shrink: 0; margin-top: 2px; } +.token-footnote strong { color: var(--warning); }