chrysopedia/frontend/src/pages/HighlightQueue.module.css
jlightner 160b1a8445 feat: Added public ShortPlayer page at /shorts/:token with video playba…
- "frontend/src/pages/ShortPlayer.tsx"
- "frontend/src/pages/ShortPlayer.module.css"
- "frontend/src/api/shorts.ts"
- "frontend/src/App.tsx"
- "frontend/src/pages/HighlightQueue.tsx"
- "frontend/src/pages/HighlightQueue.module.css"

GSD-Task: S01/T02
2026-04-04 10:35:56 +00:00

492 lines
10 KiB
CSS

/* ── Layout — reuses creator sidebar pattern ──────────────────────────────── */
.layout {
display: flex;
gap: 0;
min-height: 60vh;
}
.content {
flex: 1;
min-width: 0;
padding: 2rem;
}
.pageTitle {
margin: 0 0 0.25rem;
font-size: 1.25rem;
font-weight: 600;
color: var(--color-text-primary);
}
.subtitle {
margin: 0 0 1.5rem;
font-size: 0.875rem;
color: var(--color-text-muted);
}
/* ── Filter tabs ──────────────────────────────────────────────────────────── */
.filterTabs {
display: flex;
gap: 0.25rem;
margin-bottom: 1.5rem;
border-bottom: 1px solid var(--color-border);
padding-bottom: 0;
}
.filterTab {
padding: 0.5rem 1rem;
font-size: 0.8125rem;
font-weight: 600;
color: var(--color-text-muted);
background: none;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: color 0.15s, border-color 0.15s;
margin-bottom: -1px;
}
.filterTab:hover {
color: var(--color-text-secondary);
}
.filterTabActive {
color: var(--color-accent);
border-bottom-color: var(--color-accent);
}
/* ── Candidate cards ──────────────────────────────────────────────────────── */
.candidateList {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.candidateCard {
background: var(--color-bg-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 1rem 1.25rem;
transition: border-color 0.15s;
}
.candidateCard:hover {
border-color: var(--color-accent);
}
.candidateHeader {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.candidateTitle {
flex: 1;
min-width: 0;
font-size: 0.9375rem;
font-weight: 600;
color: var(--color-text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.candidateDuration {
font-size: 0.75rem;
font-variant-numeric: tabular-nums;
color: var(--color-text-muted);
white-space: nowrap;
}
/* ── Badges ────────────────────────────────────────────────────────────────── */
.badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.6875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.02em;
white-space: nowrap;
flex-shrink: 0;
}
.badgeCandidate {
background: var(--color-badge-pending-bg);
color: var(--color-badge-pending-text);
}
.badgeApproved {
background: var(--color-badge-approved-bg);
color: var(--color-badge-approved-text);
}
.badgeRejected {
background: var(--color-badge-rejected-bg);
color: var(--color-badge-rejected-text);
}
.shortsBadge {
background: var(--color-accent-subtle, rgba(0, 255, 209, 0.12));
color: var(--color-accent, #00ffd1);
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.6875rem;
font-weight: 600;
white-space: nowrap;
}
/* ── Composite score bar ──────────────────────────────────────────────────── */
.compositeScore {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.compositeLabel {
font-size: 0.75rem;
font-weight: 600;
color: var(--color-text-muted);
white-space: nowrap;
min-width: 3rem;
text-align: right;
}
.scoreBarTrack {
flex: 1;
height: 6px;
background: var(--color-bg-surface-hover, rgba(255, 255, 255, 0.06));
border-radius: 3px;
overflow: hidden;
}
.scoreBarFill {
height: 100%;
border-radius: 3px;
background: var(--color-accent);
transition: width 0.3s ease;
}
/* ── Score breakdown ──────────────────────────────────────────────────────── */
.breakdownSection {
margin-top: 0.75rem;
display: flex;
flex-direction: column;
gap: 0.375rem;
}
.breakdownRow {
display: flex;
align-items: center;
gap: 0.5rem;
}
.breakdownLabel {
font-size: 0.6875rem;
color: var(--color-text-muted);
min-width: 9rem;
text-align: right;
}
.breakdownBar {
flex: 1;
height: 4px;
background: var(--color-bg-surface-hover, rgba(255, 255, 255, 0.06));
border-radius: 2px;
overflow: hidden;
}
.breakdownBarFill {
height: 100%;
border-radius: 2px;
background: var(--color-accent);
opacity: 0.7;
transition: width 0.3s ease;
}
.breakdownValue {
font-size: 0.6875rem;
font-variant-numeric: tabular-nums;
color: var(--color-text-muted);
min-width: 2.5rem;
}
/* ── Action buttons ───────────────────────────────────────────────────────── */
.actions {
display: flex;
gap: 0.5rem;
margin-top: 0.75rem;
}
.actionBtn {
padding: 0.375rem 0.875rem;
border-radius: 6px;
font-size: 0.8125rem;
font-weight: 600;
border: 1px solid var(--color-border);
background: var(--color-bg-surface);
color: var(--color-text-secondary);
cursor: pointer;
transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.actionBtn:hover {
background: var(--color-accent-subtle);
color: var(--color-accent);
}
.actionBtn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.approveBtn {
background: var(--color-badge-approved-bg, rgba(34, 197, 94, 0.12));
color: var(--color-badge-approved-text, #22c55e);
border-color: transparent;
}
.approveBtn:hover {
background: rgba(34, 197, 94, 0.22);
color: #22c55e;
}
.rejectBtn {
background: var(--color-badge-rejected-bg, rgba(239, 68, 68, 0.12));
color: var(--color-badge-rejected-text, #ef4444);
border-color: transparent;
}
.rejectBtn:hover {
background: rgba(239, 68, 68, 0.22);
color: #ef4444;
}
.trimBtn {
composes: actionBtn;
}
/* ── Trim panel ───────────────────────────────────────────────────────────── */
.trimPanel {
margin-top: 0.75rem;
padding: 0.75rem 1rem;
background: var(--color-bg-surface-hover, rgba(255, 255, 255, 0.03));
border: 1px solid var(--color-border);
border-radius: 6px;
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.trimField {
display: flex;
align-items: center;
gap: 0.375rem;
}
.trimLabel {
font-size: 0.75rem;
font-weight: 600;
color: var(--color-text-muted);
}
.trimInput {
width: 5rem;
padding: 0.25rem 0.5rem;
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
border: 1px solid var(--color-border);
border-radius: 4px;
background: var(--color-bg-surface);
color: var(--color-text-primary);
}
.trimInput:focus {
outline: none;
border-color: var(--color-accent);
}
.trimActions {
display: flex;
gap: 0.375rem;
margin-left: auto;
}
/* ── States ────────────────────────────────────────────────────────────────── */
.loadingState {
text-align: center;
padding: 3rem 1rem;
color: var(--color-text-muted);
font-size: 0.875rem;
}
.emptyState {
text-align: center;
padding: 3rem 1rem;
color: var(--color-text-muted);
}
.emptyState h2 {
font-size: 1.125rem;
color: var(--color-text-secondary);
margin: 0 0 0.5rem;
}
.emptyState p {
font-size: 0.875rem;
margin: 0;
}
.errorState {
background: var(--color-error-bg, rgba(220, 38, 38, 0.1));
color: var(--color-error, #ef4444);
padding: 1rem;
border-radius: 8px;
font-size: 0.875rem;
}
/* ── Shorts section ────────────────────────────────────────────────────────── */
.shortsSection {
display: flex;
align-items: center;
gap: 0.5rem;
margin-top: 0.5rem;
padding: 0.5rem 0;
border-top: 1px solid var(--color-border);
}
.shortsLabel {
font-size: 0.6875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-muted);
white-space: nowrap;
}
.shortsBadges {
display: flex;
gap: 0.375rem;
flex-wrap: wrap;
align-items: center;
}
.shortItem {
display: inline-flex;
align-items: center;
gap: 0.25rem;
}
.shortBadge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.6875rem;
font-weight: 600;
white-space: nowrap;
}
.shortStatusPending {
background: var(--color-badge-pending-bg);
color: var(--color-badge-pending-text);
}
.shortStatusProcessing {
background: var(--color-accent-subtle, rgba(0, 255, 209, 0.12));
color: var(--color-accent, #00ffd1);
animation: pulse 1.5s ease-in-out infinite;
}
.shortStatusComplete {
background: var(--color-badge-approved-bg, rgba(34, 197, 94, 0.12));
color: var(--color-badge-approved-text, #22c55e);
}
.shortStatusFailed {
background: var(--color-badge-rejected-bg, rgba(239, 68, 68, 0.12));
color: var(--color-badge-rejected-text, #ef4444);
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
.downloadLink {
background: none;
border: none;
cursor: pointer;
color: var(--color-accent, #00ffd1);
font-size: 0.875rem;
font-weight: 700;
padding: 0 0.25rem;
line-height: 1;
transition: opacity 0.15s;
}
.downloadLink:hover {
opacity: 0.7;
}
.copiedFlash {
color: var(--color-badge-approved-text, #22c55e) !important;
}
.shortError {
color: var(--color-badge-rejected-text, #ef4444);
font-size: 0.75rem;
cursor: help;
}
.generateBtn {
background: var(--color-accent-subtle, rgba(0, 255, 209, 0.12));
color: var(--color-accent, #00ffd1);
border-color: transparent;
}
.generateBtn:hover {
background: rgba(0, 255, 209, 0.22);
}
/* ── Responsive ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
.layout {
flex-direction: column;
}
.content {
padding: 1.25rem;
}
.candidateHeader {
flex-wrap: wrap;
}
.breakdownLabel {
min-width: 6rem;
font-size: 0.625rem;
}
.trimPanel {
flex-direction: column;
align-items: flex-start;
}
.trimActions {
margin-left: 0;
}
}