1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-22 03:05:32 +02:00
archivr/frontend/src/styles.css
TheGeneralist e7104cf29d
fix(frontend): index-based stripes for root and child rows
Root rows: EntriesView passes rowIndex from entries.map to EntryRow,
which applies entry-row-outer--light/dark. Retires both nth-child stripe
blocks so skeleton rows can never shift the first real entry to dark.
Skeleton rows keep a :not(.entry-row-outer) nth-child fallback.

Child rows: colours changed from the warm root palette (paper-3/#f2ede5)
to cooler near-whites (#fafaf8/#f2f0ec) so children are visually distinct
from their parent row regardless of which stripe the parent sits on.
2026-07-21 14:07:14 +02:00

2981 lines
78 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600&family=Spectral:wght@500;600&display=swap');
:root {
color-scheme: light;
--ink: #20251f;
--muted: #6b6f66;
--muted-2: #8a8d83;
--paper: #f5f0e7;
--paper-2: #e9e1d2;
--paper-3: #fffaf0;
--line: #d2c6b5;
--line-soft: #e5dccd;
--accent: #8d3f30;
--accent-2: #b78342;
--link: #245f72;
--top: #141d18;
--field: #fffdf7;
--r: 3px;
--r2: 6px;
--r3: 10px;
--sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
--serif: "Spectral", Georgia, "Times New Roman", serif;
--display: "Cormorant Garamond", Georgia, serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
background: var(--paper);
color: var(--ink);
font-family: var(--sans);
font-size: 14px;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
button,
input,
select {
font: inherit;
}
/* ── Refined scrollbars ──────────────────────────────────────────────────── */
.workspace,
.context-rail {
scrollbar-width: thin;
scrollbar-color: var(--line) transparent;
}
.workspace::-webkit-scrollbar,
.context-rail::-webkit-scrollbar { width: 11px; height: 11px; }
.workspace::-webkit-scrollbar-track,
.context-rail::-webkit-scrollbar-track { background: transparent; }
.workspace::-webkit-scrollbar-thumb,
.context-rail::-webkit-scrollbar-thumb {
background: var(--line);
border-radius: 999px;
border: 3px solid transparent;
background-clip: padding-box;
}
.workspace::-webkit-scrollbar-thumb:hover,
.context-rail::-webkit-scrollbar-thumb:hover {
background: var(--muted-2);
background-clip: padding-box;
border: 3px solid transparent;
}
/* ── Topbar ──────────────────────────────────────────────────────────────── */
.topbar {
height: 58px;
display: grid;
grid-template-columns: auto auto 1fr auto auto;
align-items: center;
gap: 26px;
padding: 0 22px;
background: var(--top);
color: #efe6d6;
border-bottom: 3px solid var(--accent);
}
.brand {
font-family: var(--display);
font-weight: 600;
font-size: 30px;
line-height: 1;
letter-spacing: 0.01em;
color: #f4ead8;
}
/* Archive switcher */
.switcher {
position: relative;
display: inline-flex;
align-items: center;
}
.switcher select {
appearance: none;
-webkit-appearance: none;
border: 1px solid rgba(247, 238, 223, 0.20);
background: rgba(247, 238, 223, 0.06);
color: #f1e8d8;
font-family: var(--sans);
font-weight: 550;
font-size: 13.5px;
letter-spacing: 0.04em;
padding: 8px 32px 8px 15px;
cursor: pointer;
border-radius: 6px;
transition: background .15s ease, border-color .15s ease;
}
.switcher select:hover {
background: rgba(247, 238, 223, 0.11);
border-color: rgba(247, 238, 223, 0.34);
}
.switcher::after {
content: "";
position: absolute;
right: 15px;
top: 50%;
width: 6px; height: 6px;
margin-top: -5px;
border-right: 1.2px solid #b6ab98;
border-bottom: 1.2px solid #b6ab98;
transform: rotate(45deg);
pointer-events: none;
}
.nav { display: flex; gap: 22px; justify-content: flex-end; min-width: 0; }
.nav-link {
border: 0;
background: transparent;
color: #cdc1ad;
cursor: pointer;
padding: 6px 0;
font-size: 12.5px;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
position: relative;
}
.nav-link:hover { color: #f4ead8; }
.nav-link.is-active { color: #f4ead8; }
.nav-link.is-active::after {
content: "";
position: absolute;
left: 0; right: 0; bottom: -2px;
height: 1px;
background: var(--accent-2);
}
/* Capture button */
.capture-button {
display: inline-flex;
align-items: center;
gap: 8px;
position: relative;
overflow: hidden;
border: 0;
background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 88%, #fff) 0%, var(--accent) 55%);
color: #f7eddd;
padding: 10px 18px;
cursor: pointer;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.15em;
text-transform: uppercase;
border-radius: var(--r);
box-shadow: inset 0 1px 0 rgba(255, 245, 230, 0.16), 0 1px 2px rgba(20, 29, 24, 0.30);
transition: filter .18s ease, box-shadow .18s ease;
}
.capture-button:hover {
filter: brightness(0.93);
box-shadow: inset 0 1px 0 rgba(255, 245, 230, 0.12), 0 2px 6px rgba(20, 29, 24, 0.34);
}
.capture-button::before {
content: "";
position: absolute;
top: 0; bottom: 0; left: 0;
width: 45%;
background: linear-gradient(100deg, transparent 0%, rgba(255, 246, 232, 0.45) 50%, transparent 100%);
transform: translateX(-180%) skewX(-18deg);
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.capture-button:hover::before { animation: cap-sheen 0.7s ease; }
}
@keyframes cap-sheen {
from { transform: translateX(-180%) skewX(-18deg); }
to { transform: translateX(340%) skewX(-18deg); }
}
/* ── App shell ───────────────────────────────────────────────────────────── */
.app-shell {
height: calc(100vh - 58px);
display: grid;
grid-template-columns: minmax(0, 1fr) 340px;
}
.workspace { min-width: 0; overflow: auto; display: flex; flex-direction: column; }
/* ── View toggle ─────────────────────────────────────────────────────────── */
.view { display: none; }
.view.is-active { display: block; }
/* ── Search toolbar ──────────────────────────────────────────────────────── */
.toolbar {
position: sticky;
top: 0;
z-index: 3;
display: flex;
align-items: center;
gap: 16px;
padding: 12px 22px;
background: color-mix(in srgb, var(--paper) 88%, white);
border-bottom: 1px solid var(--line-soft);
}
.search-field {
position: relative;
flex: 1 1 auto;
min-width: 0;
display: flex;
align-items: center;
height: 42px;
background: var(--field);
border: 1px solid var(--line);
border-radius: 20px;
transition: border-color .15s ease, box-shadow .15s ease;
}
.search-field:focus-within {
border-color: var(--accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}
.search-field .ico { display: grid; place-items: center; width: 46px; height: 100%; color: var(--muted-2); flex-shrink: 0; }
.search-field .ico svg { width: 16px; height: 16px; }
.search-input {
flex: 1; min-width: 0; height: 100%;
border: 0; background: transparent; color: var(--ink);
padding: 0 6px 0 0; font-size: 14px; letter-spacing: 0.01em; outline: none;
}
.search-input::placeholder { color: var(--muted-2); }
.search-field .kbd {
margin-right: 12px;
display: inline-flex; align-items: center;
padding: 3px 7px;
font-size: 11px; color: var(--muted);
background: var(--paper-2);
border: 1px solid var(--line-soft);
border-radius: var(--r);
flex-shrink: 0;
}
.result-count {
flex-shrink: 0;
font-size: 13px;
color: var(--muted);
letter-spacing: 0.02em;
white-space: nowrap;
}
.result-count b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
/* Tag filter badge */
.tag-filter-badge {
display: inline-flex;
align-items: center;
gap: 4px;
background: var(--accent);
color: #fff;
border: 0;
border-radius: var(--r);
font-size: 12px;
padding: 2px 8px;
cursor: pointer;
margin-left: 8px;
}
.tag-filter-badge:hover { opacity: 0.85; }
/* ── Entry table ─────────────────────────────────────────────────────────── */
.entry-table { width: 100%; font-size: 12.5px; }
.entry-header-row {
display: flex;
align-items: stretch;
position: sticky;
top: 67px;
z-index: 2;
background: color-mix(in srgb, var(--paper) 92%, white);
border-bottom: 1px solid var(--line-soft);
color: var(--muted);
font-size: 10.5px;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.entry-header-row > div { padding: 9px 10px; flex-shrink: 0; font-weight: 600; display: flex; align-items: center; }
#entries-body > div {
display: flex;
align-items: center;
cursor: default;
border-bottom: 1px solid var(--line-soft);
}
#entries-body > div > div { padding: 7px 10px; flex-shrink: 0; overflow: hidden; }
/* Skeleton rows (no index class) fall back to nth-child; real rows use explicit classes. */
#entries-body > div:not(.entry-row-outer):nth-child(even) { background: #f2ede5; }
#entries-body > div:not(.entry-row-outer):nth-child(odd) { background: var(--paper-3); }
/* Index-based stripes for real entry rows — immune to skeleton sibling count. */
#entries-body > .entry-row-outer--light { background: var(--paper-3); }
#entries-body > .entry-row-outer--dark { background: #f2ede5; }
#entries-body > div.is-selected {
background: #eee2d2;
box-shadow: inset 0 0 0 2px var(--accent);
}
#entries-body > div.is-multi-selected {
background: #eee2d2;
box-shadow: inset 0 0 0 2px var(--accent);
}
.col-added { width: 162px; color: var(--muted); }
.col-title { flex: 1 1 0; min-width: 0; overflow: hidden; display: flex; align-items: center; gap: 0.42em; }
.col-type { width: 116px; }
.col-size { width: 100px; display: flex; flex-direction: column; justify-content: center; gap: 1px; }
.size-total { font-variant-numeric: tabular-nums; }
.size-cached-pct {
font-size: 10px;
color: var(--muted);
opacity: 0.8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.col-url { flex: 0 0 30%; min-width: 0; overflow: hidden; }
/* col-check is first-child but hidden on desktop — target col-added directly */
.entry-header-row .col-added,
#entries-body > div .col-added { padding-left: 22px; }
.entry-header-row > div:last-child,
#entries-body > div > div:last-child { padding-right: 22px; }
.entry-title { color: var(--link); font-weight: 700; min-width: 0; }
.entry-header-row > div { padding: 9px 10px; flex-shrink: 0; font-weight: 600; }
.source-icon { display: flex; align-items: center; justify-content: center; width: 1.05em; height: 1.05em; flex-shrink: 0; }
.source-icon > * { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.source-icon svg { width: 100%; height: 100%; }
.url-cell { color: #555b55; white-space: nowrap; text-overflow: ellipsis; word-break: break-all; }
#entries-body .url-cell:hover { overflow: visible; white-space: normal; }
.type-pill { display: inline-block; padding: 2px 6px; background: #d8e3df; color: #275a5f; border: 1px solid #bfd0ca; border-radius: var(--r); }
/* ── Multi-select checkbox column ───────────────────────────────────────── */
/* Hidden on desktop (pointer:fine); always visible on touch/mobile */
.col-check {
display: none;
width: 40px;
flex-shrink: 0;
align-items: center;
justify-content: center;
padding: 0 !important;
cursor: pointer;
}
.row-checkbox {
/* reset <button> UA styles */
-webkit-appearance: none;
appearance: none;
padding: 0;
border: 1.5px solid var(--line);
cursor: pointer;
/* visual checkbox */
display: block;
width: 17px;
height: 17px;
border-radius: 4px;
background: var(--paper-3);
transition: border-color .15s ease, background .15s ease;
position: relative;
flex-shrink: 0;
}
.row-checkbox.is-checked {
background: var(--accent);
border-color: var(--accent);
}
.row-checkbox.is-checked::after {
content: '';
position: absolute;
left: 4px;
top: 2px;
width: 5px;
height: 8px;
border: 2px solid #fff;
border-top: none;
border-left: none;
transform: rotate(45deg);
}
@media (pointer: coarse) {
.col-check { display: flex; }
.entry-header-row .col-added,
#entries-body > div .col-added { padding-left: 10px; }
}
/* ── Runs view (table) ───────────────────────────────────────────────────── */
#runs-view .entry-table {
border-collapse: collapse;
table-layout: auto;
}
#runs-view .entry-table th {
position: sticky;
top: 0;
z-index: 1;
text-align: left;
padding: 10px;
background: color-mix(in srgb, var(--paper) 92%, white);
color: var(--muted);
border-bottom: 1px solid var(--line-soft);
font-size: 10.5px;
text-transform: uppercase;
letter-spacing: 0.08em;
}
#runs-view .entry-table td {
padding: 10px;
border-bottom: 1px solid var(--line-soft);
vertical-align: top;
}
#runs-view .entry-table tr:nth-child(even) td { background: #f2ede5; }
#runs-view .entry-table tr:nth-child(odd) td { background: var(--paper-3); }
/* ── Context rail ────────────────────────────────────────────────────────── */
.context-rail {
border-left: 1px solid var(--line);
background: var(--paper);
padding: 20px 20px 32px;
overflow: auto;
}
.rail-eyebrow {
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--muted-2);
margin-bottom: 16px;
}
.rail-title {
display: block;
font-family: var(--sans);
font-weight: 700;
font-size: 15.5px;
line-height: 1.4;
color: var(--ink);
margin: 0 0 16px;
word-break: break-word;
}
/* original-url tile */
.url-tile {
display: flex;
align-items: center;
gap: 9px;
padding: 10px 12px;
background: var(--paper-3);
border: 1px solid var(--line);
border-radius: var(--r3);
margin-bottom: 20px;
text-decoration: none;
}
.url-tile:hover { background: var(--field); border-color: var(--accent); }
.url-tile .ico { color: var(--ink); flex-shrink: 0; display: grid; place-items: center; }
.url-tile .ico svg { width: 15px; height: 15px; }
.url-tile .u-text {
min-width: 0; flex: 1;
font-size: 12.5px; color: var(--link);
font-family: ui-monospace, "SF Mono", Menlo, monospace;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.url-tile .ext { color: var(--muted-2); flex-shrink: 0; }
.url-tile .ext svg { width: 13px; height: 13px; display: block; }
/* metadata ledger */
.meta-list { margin-bottom: 24px; border-top: 1px solid var(--line-soft); }
.meta-item {
display: grid;
grid-template-columns: 92px 1fr;
gap: 14px;
align-items: baseline;
padding: 9px 0;
border-bottom: 1px solid var(--line-soft);
}
.meta-k {
font-size: 10.5px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted-2);
}
.meta-v { font-size: 13.5px; color: var(--ink); word-break: break-word; line-height: 1.4; }
.meta-v.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; color: var(--muted); }
.rail-section { margin-bottom: 24px; }
.rail-section-heading {
display: flex; align-items: baseline; gap: 8px;
font-size: 10.5px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted-2);
margin-bottom: 9px;
padding-bottom: 8px;
border-bottom: 1px solid var(--line);
}
.rail-section-heading .num { color: var(--muted-2); font-weight: 600; }
/* artifacts */
.artifact-list { list-style: none; margin: 0; padding: 0; }
.artifact-link {
display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
padding: 7px 2px;
border-bottom: 1px solid var(--line-soft);
text-decoration: none;
}
.artifact-link:last-child { border-bottom: 0; }
.artifact-name { font-size: 13px; color: var(--link); min-width: 0; word-break: break-word; }
.artifact-link:hover .artifact-name { text-decoration: underline; }
.artifact-size { font-size: 11.5px; color: var(--muted-2); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.artifact-group { list-style: none; }
.artifact-group-header {
width: 100%; background: none; border: none; border-bottom: 1px solid var(--line-soft);
cursor: pointer; text-align: left; color: inherit; font: inherit;
}
.artifact-group-header:hover .artifact-name { text-decoration: underline; }
.artifact-group-chevron {
display: inline-block;
font-style: normal;
transition: transform 0.15s ease;
transform: rotate(0deg);
transform-origin: 45% 50%;
margin-right: 3px;
}
.artifact-group-chevron.open { transform: rotate(90deg); }
.artifact-group-body { padding-left: 14px; }
/* tags */
.tags-wrap { display: flex; flex-wrap: wrap; gap: 7px; margin: 0 0 12px; }
.tag-pill {
display: inline-flex; align-items: center; gap: 7px;
background: var(--paper-2);
border: 1px solid var(--line);
border-radius: var(--r);
font-size: 12px; padding: 4px 7px 4px 10px;
color: var(--ink);
}
.tag-pill .remove {
border: 0; background: transparent; cursor: pointer;
color: var(--muted-2); width: 15px; height: 15px;
display: grid; place-items: center; font-size: 13px; line-height: 1;
}
.tag-pill .remove:hover { color: var(--accent); }
.tags-empty { font-size: 13px; color: var(--muted); margin: 0 0 11px; }
.tag-input-wrap {
display: flex; align-items: center; gap: 8px;
background: var(--field);
border: 1px solid var(--line);
border-radius: var(--r2);
padding: 2px 2px 2px 11px;
transition: border-color .15s ease, box-shadow .15s ease;
}
.tag-input-wrap:focus-within {
border-color: var(--accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}
.tag-input-wrap .hash { color: var(--muted-2); font-size: 13px; }
.tag-input {
flex: 1; min-width: 0; border: 0; background: transparent;
color: var(--ink); font-size: 13px; padding: 6px 0; outline: none;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.tag-add-btn {
border: 0; background: var(--ink); color: var(--paper-3);
padding: 6px 13px; font-size: 11.5px; letter-spacing: 0.06em;
text-transform: uppercase; border-radius: var(--r);
cursor: pointer; white-space: nowrap;
}
.tag-add-btn:hover { background: #2c332b; }
/* collections in rail */
.coll-row {
display: flex; align-items: center; justify-content: space-between; gap: 12px;
padding: 9px 13px;
background: var(--field);
border: 1px solid var(--line);
border-radius: var(--r2);
margin-bottom: 6px;
transition: border-color .15s ease;
}
.coll-row:hover { border-color: var(--accent); }
.coll-name { font-size: 13px; color: var(--ink); font-weight: 500; }
.vis-badge {
display: inline-flex; align-items: center; gap: 6px;
font-size: 11px; color: var(--muted);
background: var(--paper-2); border: 1px solid var(--line-soft);
border-radius: 999px; padding: 3px 10px;
}
.vis-badge::before {
content: ""; width: 6px; height: 6px; border-radius: 50%;
background: var(--accent-2);
}
/* ── Bulk-action panel ───────────────────────────────────────────────────── */
.bulk-panel { padding-top: 2px; }
.bulk-count {
font-size: 13px;
color: var(--muted);
margin-bottom: 22px;
}
.bulk-count-num {
font-size: 22px;
font-weight: 700;
color: var(--ink);
line-height: 1;
margin-right: 4px;
}
.bulk-coll-row {
display: flex;
align-items: center;
gap: 8px;
}
.bulk-coll-select {
flex: 1;
min-width: 0;
height: 32px;
padding: 0 8px;
border: 1px solid var(--line);
border-radius: var(--r);
background: var(--field);
color: var(--ink);
font-size: 13px;
cursor: pointer;
outline: none;
transition: border-color .15s ease;
}
.bulk-coll-select:focus { border-color: var(--accent); }
.tag-add-btn:disabled { opacity: 0.45; cursor: default; }
/* ── Rail delete zone ───────────────────────────────────────────────────── */
.rail-delete-zone {
margin-top: 24px;
padding-top: 20px;
border-top: 1px solid var(--line-soft);
}
.rail-delete-btn {
width: 100%;
padding: 8px 14px;
background: none;
border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
color: var(--accent);
border-radius: var(--r);
cursor: pointer;
font-size: 12.5px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
transition: background 0.15s ease, border-color 0.15s ease;
}
.rail-delete-btn:hover {
background: color-mix(in srgb, var(--accent) 8%, transparent);
border-color: var(--accent);
}
.rail-rearchive-btn {
width: 100%;
padding: 6px 12px;
background: var(--surface-2, #2a2a2a);
color: var(--text, #e0e0e0);
border: 1px solid var(--border, #444);
border-radius: 4px;
cursor: pointer;
font-size: 13px;
}
.rail-rearchive-btn:hover:not(:disabled) {
background: var(--surface-3, #333);
}
.rail-rearchive-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* ── Capture dialog ──────────────────────────────────────────────────────── */
.capture-dialog {
border: 1px solid var(--line);
background: var(--paper);
padding: 0;
width: min(540px, calc(100vw - 32px));
border-radius: var(--r3);
box-shadow: 0 20px 60px rgba(20, 29, 24, 0.28);
}
.capture-dialog::backdrop {
background: rgba(20, 29, 24, 0.45);
}
.capture-dialog-inner {
padding: 28px;
}
.capture-dialog-title {
margin: 0;
font-size: 22px;
font-family: var(--display);
font-weight: 600;
}
.capture-label {
display: block;
font-size: 11px;
font-weight: 600;
margin-bottom: 6px;
color: var(--muted-2);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.capture-input {
width: 100%;
height: 44px;
border: 1px solid var(--line);
background: var(--field);
color: var(--ink);
padding: 0 14px;
font-size: 15px;
margin-bottom: 10px;
border-radius: var(--r2);
outline: none;
transition: border-color .15s ease, box-shadow .15s ease;
}
.capture-input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}
.form-field .capture-input { margin-bottom: 0; }
.capture-error {
color: var(--accent);
font-size: 13px;
margin-bottom: 10px;
min-height: 18px;
}
.capture-actions {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 18px;
}
.capture-submit {
border: 0;
background: var(--ink);
color: var(--paper);
padding: 13px 20px;
border-radius: var(--r2);
cursor: pointer;
font-weight: 600;
font-size: 15px;
width: 100%;
min-width: 220px;
letter-spacing: 0.01em;
}
.capture-submit:hover { opacity: 0.85; }
.capture-submit:disabled { opacity: 0.45; cursor: default; }
.capture-cancel {
border: 0;
background: none;
color: var(--muted);
padding: 7px 18px;
border-radius: var(--r);
cursor: pointer;
font-size: 13px;
text-align: center;
width: 100%;
}
.capture-cancel:hover { color: var(--ink); background: var(--paper-2); }
/* ── Capture advanced options ────────────────────────────────────────────── */
.capture-advanced { margin-top: 12px; }
.capture-advanced-toggle {
display: flex;
align-items: center;
gap: 5px;
background: none;
border: 0;
cursor: pointer;
color: var(--muted);
font-size: 12.5px;
padding: 4px 0;
border-radius: var(--r);
}
.capture-advanced-toggle:hover { color: var(--ink); }
.capture-chevron {
width: 14px; height: 14px;
flex-shrink: 0;
transition: transform 0.18s ease;
}
.capture-chevron--open { transform: rotate(180deg); }
.capture-advanced-panel {
margin-top: 8px;
padding: 10px 12px;
border: 1px solid var(--line);
border-radius: var(--r2);
background: var(--paper-2);
}
.capture-ext-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
cursor: default;
}
.capture-ext-label { flex: 1; min-width: 0; }
.capture-ext-name {
display: block;
font-size: 13px;
font-weight: 600;
color: var(--ink);
}
.capture-ext-desc {
display: block;
font-size: 11.5px;
color: var(--muted);
margin-top: 1px;
}
/* ── Capture dialog: header + multi-row ─────────────────────────────────── */
.capture-dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.capture-dialog-close {
flex-shrink: 0;
background: none;
border: 0;
cursor: pointer;
color: var(--muted);
width: 28px;
height: 28px;
display: grid;
place-items: center;
border-radius: var(--r);
padding: 0;
}
.capture-dialog-close svg { width: 14px; height: 14px; }
.capture-dialog-close:hover { background: var(--paper-2); color: var(--ink); }
.capture-rows {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 8px;
}
.capture-row {
display: flex;
flex-direction: column;
gap: 3px;
}
.capture-row-main {
display: flex;
align-items: center;
gap: 8px;
}
/* No bottom-margin on inputs inside rows; gap handles spacing */
.capture-row-main .capture-input { margin-bottom: 0; }
/* Quality selector shown for yt-dlp sources */
.capture-quality {
flex-shrink: 0;
height: 32px;
padding: 0 6px;
border: 1px solid var(--line);
border-radius: var(--r);
background: var(--paper);
color: var(--ink);
font-size: 12px;
cursor: pointer;
outline: none;
transition: border-color .15s;
}
.capture-quality:hover { border-color: var(--accent-2); }
.capture-quality:focus { border-color: var(--accent); }
.capture-quality:disabled { opacity: 0.5; cursor: default; }
/* Probing state: ellipsis shown while yt-dlp metadata is in flight */
.capture-quality-probing {
flex-shrink: 0;
font-size: 12px;
color: var(--muted);
padding: 0 4px;
letter-spacing: .05em;
}
/* "No video detected" note */
.capture-quality-hint {
flex-shrink: 0;
font-size: 12px;
color: var(--muted);
font-style: italic;
}
.capture-quality-hint--error { color: #c05000; font-style: normal; }
/* Status dot */
.cap-dot {
flex-shrink: 0;
width: 20px;
height: 20px;
border-radius: 50%;
display: grid;
place-items: center;
font-size: 10px;
font-weight: 700;
line-height: 1;
}
.cap-dot--idle { background: var(--paper-2); }
.cap-dot--running { background: #fdefd8; color: #8a4f10; }
.cap-dot--ok { background: #d8eddf; color: #235c35; }
.cap-dot--err { background: #f5ddd8; color: #8d3f30; }
/* Spinner inside the running dot */
.cap-spinner {
display: block;
width: 10px;
height: 10px;
border: 2px solid currentColor;
border-top-color: transparent;
border-radius: 50%;
animation: cap-spin 0.7s linear infinite;
}
@keyframes cap-spin { to { transform: rotate(360deg); } }
/* Per-row action buttons (remove / retry) */
.capture-row-action {
flex-shrink: 0;
background: none;
border: 0;
cursor: pointer;
color: var(--muted);
width: 28px;
height: 28px;
display: grid;
place-items: center;
border-radius: var(--r);
padding: 0;
}
.capture-row-action svg { width: 12px; height: 12px; }
.capture-row-action:hover { color: var(--accent); background: var(--paper-2); }
.capture-row-remove:hover { color: var(--accent); }
/* Inline error under a failed row */
.capture-row-error {
margin: 0;
padding-left: 28px; /* align past the status dot */
font-size: 12px;
color: var(--accent);
line-height: 1.45;
}
/* Add-another button */
.capture-add-row {
display: flex;
align-items: center;
gap: 7px;
width: 100%;
background: none;
border: 1px dashed var(--line);
border-radius: var(--r);
color: var(--muted);
font-size: 13px;
cursor: pointer;
padding: 7px 12px;
margin-top: 4px;
margin-bottom: 18px;
transition: border-color .15s, color .15s, background .15s;
}
.capture-add-row svg { width: 13px; height: 13px; flex-shrink: 0; }
.capture-add-row:hover { border-color: var(--accent-2); color: var(--ink); background: var(--paper-2); }
/* ── Toast stack ─────────────────────────────────────────────────────────── */
.toast-stack {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 9000;
display: flex;
flex-direction: column;
gap: 10px;
width: 340px;
max-width: calc(100vw - 32px);
pointer-events: none;
}
.toast {
pointer-events: auto;
background: var(--paper);
border: 1px solid var(--line);
border-radius: var(--r2);
box-shadow: 0 6px 24px rgba(20, 29, 24, 0.18), 0 1px 4px rgba(20, 29, 24, 0.1);
overflow: hidden;
animation: toast-slide-in 0.22s cubic-bezier(.22,.68,0,1.2);
}
@keyframes toast-slide-in {
from { opacity: 0; transform: translateY(10px) scale(0.97); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
.toast--error { border-left: 3px solid var(--accent); }
.toast--warning { border-left: 3px solid #e8a000; }
.toast--success { border-left: 3px solid #22a855; }
.toast-top {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 12px 12px 12px 14px;
}
.toast-icon {
flex-shrink: 0;
font-size: 13px;
font-weight: 700;
color: var(--accent);
margin-top: 2px;
}
.toast--success .toast-icon { color: #22a855; }
.toast--warning .toast-icon { color: #e8a000; }
.toast-body {
flex: 1;
min-width: 0;
}
.toast-headline {
display: block;
font-size: 13.5px;
font-weight: 600;
color: var(--ink);
line-height: 1.3;
}
.toast-locator {
display: block;
font-size: 12px;
color: var(--muted);
margin-top: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.toast-btns {
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.toast-view-btn {
background: none;
border: 1px solid var(--line);
color: var(--link);
font-size: 12px;
cursor: pointer;
padding: 3px 9px;
border-radius: var(--r);
white-space: nowrap;
}
.toast-view-btn:hover { background: var(--paper-2); border-color: var(--link); }
.toast-dismiss {
background: none;
border: 0;
cursor: pointer;
color: var(--muted);
font-size: 20px;
line-height: 1;
width: 24px;
height: 24px;
display: grid;
place-items: center;
border-radius: var(--r);
padding: 0;
}
.toast-dismiss:hover { color: var(--ink); background: var(--paper-2); }
.toast-error-detail {
margin: 0;
padding: 10px 14px 12px;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 11.5px;
line-height: 1.55;
color: var(--muted);
background: var(--paper-2);
border-top: 1px solid var(--line);
white-space: pre-wrap;
word-break: break-word;
max-height: 200px;
overflow-y: auto;
}
.toast-warning-detail {
margin: 0;
padding: 10px 14px 12px;
font-size: 12px;
line-height: 1.55;
color: var(--muted);
background: var(--paper-2);
border-top: 1px solid var(--line);
white-space: pre-wrap;
word-break: break-word;
}
.toast-ignore-btn { color: var(--muted); }
/* ── Extension toggle (pill switch) ─────────────────────────────────────── */
.ext-toggle {
flex-shrink: 0;
position: relative;
width: 44px;
height: 24px;
border-radius: 12px;
background: var(--line);
border: 0;
cursor: pointer;
transition: background 0.18s ease;
padding: 0;
}
.ext-toggle--sm { width: 36px; height: 20px; border-radius: 10px; }
.ext-toggle--on { background: var(--ink); }
.ext-toggle:disabled { opacity: 0.4; cursor: default; }
.ext-toggle-knob {
position: absolute;
top: 3px; left: 3px;
width: 18px; height: 18px;
border-radius: 50%;
background: var(--paper);
transition: transform 0.18s ease;
display: block;
box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.ext-toggle--sm .ext-toggle-knob { width: 14px; height: 14px; top: 3px; left: 3px; }
.ext-toggle--on .ext-toggle-knob { transform: translateX(20px); }
.ext-toggle--sm.ext-toggle--on .ext-toggle-knob { transform: translateX(16px); }
/* ── Extension card (Settings / Extensions tab) ──────────────────────────── */
.ext-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 12px;
}
.ext-card {
border: 1px solid var(--line);
border-radius: var(--r2);
padding: 16px 18px;
background: var(--paper);
}
.ext-card-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
}
.ext-card-info { flex: 1; min-width: 0; }
.ext-card-name {
display: block;
font-weight: 600;
font-size: 14px;
margin-bottom: 4px;
}
.ext-card-desc {
display: block;
font-size: 13px;
color: var(--muted);
line-height: 1.5;
}
.ext-card-hint {
display: block;
font-size: 12px;
color: #e8a000;
margin-top: 6px;
}
.ext-card-hint code { font-size: 11.5px; }
.form-hint { font-size: 13px; color: var(--muted); line-height: 1.55; margin: 0; }
/* ── Utility ─────────────────────────────────────────────────────────────── */
.muted { color: var(--muted); }
/* ── Admin view ──────────────────────────────────────────────────────────── */
.admin-view {
padding: 22px;
}
.admin-list {
display: grid;
gap: 10px;
max-width: 780px;
}
.admin-archive {
border: 1px solid var(--line);
background: var(--paper-3);
padding: 12px;
border-radius: var(--r2);
}
/* ── Tag tree ────────────────────────────────────────────────────────────── */
.tag-tree {
padding: 20px 22px;
max-width: 320px;
}
.tag-tree-header {
display: flex;
align-items: baseline;
gap: 10px;
margin-bottom: 14px;
border-bottom: 1px solid var(--line-soft);
padding-bottom: 10px;
}
.tag-tree-title {
font-size: 11px;
font-weight: 700;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.07em;
}
.tag-tree-active {
font-size: 12px;
color: var(--muted-2);
font-style: italic;
}
.tag-tree-list {
list-style: none;
margin: 0;
padding: 0;
}
.tag-children {
padding-left: 16px;
}
.tag-node-btn {
border: 0;
background: transparent;
color: var(--link);
cursor: pointer;
padding: 3px 0;
text-align: left;
font-size: 13px;
display: block;
width: 100%;
}
.tag-node-btn:hover { text-decoration: underline; }
.tag-node-btn.is-active { font-weight: 600; color: var(--ink); }
/* tag-node-row: flex row containing the name button + delete × */
.tag-node-row {
display: flex;
align-items: center;
gap: 4px;
}
.tag-node-row .tag-node-btn {
flex: 1 1 0;
min-width: 0;
display: flex;
align-items: center;
gap: 4px;
width: auto;
}
/* constrain the edit pencil so it doesn't inherit unconstrained SVG dimensions */
.tag-node-btn .edit-icon {
width: 0.75em;
height: 0.75em;
flex-shrink: 0;
vertical-align: -0.1em;
opacity: 0.35;
}
.tag-node-btn:hover .edit-icon { opacity: 0.65; }
/* delete × button next to tag name — small, unobtrusive */
.tag-node-delete {
flex-shrink: 0;
border: 0;
background: transparent;
color: var(--muted-2);
cursor: pointer;
padding: 0 3px;
font-size: 14px;
line-height: 1;
opacity: 0;
}
.tag-node-row:hover .tag-node-delete { opacity: 1; }
.tag-node-delete:hover { color: var(--accent); }
/* rename input inside the tag list */
.tag-rename-input {
font-size: 13px;
flex: 1 1 0;
min-width: 0;
padding: 2px 5px;
border: 1px solid var(--accent);
border-radius: var(--r);
background: var(--field);
color: var(--ink);
outline: none;
}
/* entry count badge next to tag name */
.tag-node-label { flex-shrink: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-node-count {
font-size: 11px;
color: var(--muted-2);
font-weight: 400;
flex-shrink: 0;
margin-left: 3px;
}
/* header action buttons (+ New, Move) */
.tag-tree-header { align-items: center; }
.tag-tree-actions { margin-left: auto; display: flex; gap: 4px; }
.tag-tree-action-btn {
font-size: 11px;
padding: 2px 7px;
border: 1px solid var(--line);
border-radius: var(--r);
background: transparent;
color: var(--muted);
cursor: pointer;
line-height: 1.5;
white-space: nowrap;
transition: background 0.1s, color 0.1s;
}
.tag-tree-action-btn:hover:not(:disabled) { background: var(--paper-2); color: var(--ink); }
.tag-tree-action-btn:disabled { opacity: 0.4; cursor: default; }
.tag-tree-action-btn--cancel { border-color: var(--accent); color: var(--accent); }
.tag-tree-action-btn--cancel:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.tag-tree-title--move { font-style: italic; color: var(--accent-2); }
/* move source-select mode: nodes act as clickable targets */
.tag-node-row--move-select .tag-node-btn { cursor: crosshair; color: var(--ink); }
.tag-node-row--move-select .tag-node-btn:hover {
background: color-mix(in srgb, var(--link) 10%, transparent);
text-decoration: none;
border-radius: var(--r);
}
/* ── Tag picker modal (create/move destination) ──────────────────────────── */
.tag-picker-backdrop {
position: fixed;
inset: 0;
z-index: 200;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.tag-picker-modal {
background: var(--paper);
border-radius: var(--r3);
box-shadow: 0 16px 56px rgba(0, 0, 0, 0.24);
width: 300px;
max-width: 100%;
display: flex;
flex-direction: column;
max-height: 60vh;
}
.tag-picker-header {
display: flex;
align-items: center;
padding: 12px 14px;
border-bottom: 1px solid var(--line);
flex-shrink: 0;
gap: 8px;
}
.tag-picker-title {
flex: 1;
font-size: 13px;
font-weight: 600;
color: var(--ink);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tag-picker-close {
width: 26px;
height: 26px;
border-radius: 50%;
border: none;
background: transparent;
color: var(--muted-2);
font-size: 18px;
line-height: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.tag-picker-close:hover { background: var(--paper-2); color: var(--ink); }
.tag-picker-body {
flex: 1;
min-height: 0;
overflow-y: auto;
padding: 8px 12px 12px;
}
.tag-picker-root-btn {
display: block;
width: 100%;
text-align: left;
padding: 5px 8px;
margin-bottom: 6px;
border: 1px dashed var(--line);
border-radius: var(--r);
background: transparent;
color: var(--muted);
font-size: 12px;
cursor: pointer;
}
.tag-picker-root-btn:hover { background: var(--paper-2); color: var(--ink); border-color: var(--muted-2); }
.tag-picker-tree { border-top: 1px solid var(--line-soft); padding-top: 6px; margin-top: 2px; }
.tag-picker-node-btn {
border: 0;
background: transparent;
color: var(--link);
cursor: pointer;
padding: 3px 6px;
text-align: left;
font-size: 13px;
display: block;
width: 100%;
border-radius: var(--r);
}
.tag-picker-node-btn:hover { background: var(--paper-2); text-decoration: none; }
.tag-picker-empty { font-size: 13px; color: var(--muted-2); margin: 6px 0 0; }
/* ── Collections page (sidebar layout) ──────────────────────────────────── */
.collections-view {
padding: 24px;
}
.collections-heading {
margin: 0 0 16px;
font-size: 22px;
font-family: var(--display);
font-weight: 600;
}
.collections-error {
color: var(--accent);
font-size: 13px;
margin-bottom: 8px;
}
.coll-dismiss {
background: none;
border: none;
cursor: pointer;
color: var(--accent);
font-size: 16px;
line-height: 1;
padding: 0 4px;
}
.collections-layout {
display: grid;
grid-template-columns: 220px 1fr;
gap: 0;
border: 1px solid var(--line);
border-radius: var(--r2);
min-height: 340px;
}
.collections-sidebar {
border-right: 1px solid var(--line);
overflow-y: auto;
}
/* Sidebar list rows — renamed from .coll-row to avoid conflict with rail card */
.coll-sidebar-row {
display: flex;
flex-direction: column;
width: 100%;
padding: 10px 14px;
border: none;
border-bottom: 1px solid var(--line-soft);
background: none;
cursor: pointer;
text-align: left;
gap: 2px;
}
.coll-sidebar-row:hover { background: var(--paper-2); }
.coll-sidebar-row.is-active {
background: var(--paper-2);
border-left: 3px solid var(--accent);
}
.coll-row-name {
font-size: 14px;
font-weight: 600;
color: var(--ink);
}
.coll-row-meta {
font-size: 11px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.coll-detail {
padding: 20px 24px;
display: flex;
flex-direction: column;
gap: 16px;
}
.coll-detail--empty {
justify-content: center;
align-items: center;
}
.coll-detail-header {
display: flex;
align-items: center;
gap: 12px;
}
.coll-detail-name {
margin: 0;
font-size: 18px;
font-family: var(--display);
font-weight: 600;
flex: 1;
}
.coll-detail-name--editable { cursor: pointer; }
.coll-detail-name--editable:hover { color: var(--link); }
.coll-edit-hint { font-size: 14px; opacity: 0.5; margin-left: 4px; }
.coll-rename-input {
flex: 1;
font-size: 16px;
font-family: var(--display);
border: 1px solid var(--line);
padding: 4px 8px;
background: var(--field);
color: var(--ink);
border-radius: var(--r);
}
.coll-delete-btn {
border: 1px solid var(--accent);
background: none;
color: var(--accent);
padding: 5px 12px;
font-size: 13px;
cursor: pointer;
border-radius: var(--r);
}
.coll-delete-btn:hover { background: var(--accent); color: var(--paper); }
.coll-detail-vis {
display: flex;
align-items: center;
gap: 10px;
}
.coll-vis-label {
font-size: 13px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.04em;
white-space: nowrap;
}
.coll-vis-select {
border: 1px solid var(--line);
background: var(--paper-3);
color: var(--ink);
padding: 4px 8px;
font-size: 13px;
border-radius: var(--r);
}
.coll-section-heading {
font-size: 11px;
font-weight: 700;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 8px;
}
.coll-entries-section { flex: 1; }
.coll-entries-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.coll-entry-row {
display: flex;
align-items: center;
gap: 10px;
padding: 7px 0;
border-bottom: 1px solid var(--line-soft);
}
.coll-entry-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.coll-entry-title {
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.coll-entry-kind {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.coll-entry-actions {
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.coll-entry-vis-select {
border: 1px solid var(--line);
background: var(--paper-3);
color: var(--ink);
padding: 3px 6px;
font-size: 12px;
border-radius: var(--r);
}
.coll-entry-remove {
border: none;
background: none;
cursor: pointer;
color: var(--muted);
font-size: 18px;
line-height: 1;
padding: 0 4px;
}
.coll-entry-remove:hover { color: var(--accent); }
.coll-add-entry-form {
border-top: 1px solid var(--line-soft);
padding-top: 12px;
}
.coll-add-entry-row {
display: flex;
gap: 8px;
align-items: center;
}
.coll-add-entry-input {
flex: 1;
border: 1px solid var(--line);
background: var(--paper-3);
color: var(--ink);
padding: 6px 10px;
font-size: 13px;
min-width: 0;
border-radius: var(--r);
}
.coll-add-btn {
border: none;
background: var(--ink);
color: var(--paper);
padding: 6px 14px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
white-space: nowrap;
border-radius: var(--r);
}
.coll-add-btn:hover { opacity: 0.85; }
.coll-add-btn:disabled { opacity: 0.45; cursor: default; }
/* old override — superseded by coll-create-details section below */
/* ── Auth loading state ─────────────────────────────────────────────────── */
.auth-loading {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: var(--muted);
font-size: 15px;
background: var(--paper);
}
/* ── User menu (topbar right) ───────────────────────────────────────────── */
.user-menu {
display: flex;
align-items: center;
gap: 14px;
padding-left: 6px;
flex-shrink: 0;
}
.user-name {
font-size: 12.5px;
color: var(--muted-2);
letter-spacing: 0.01em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 140px;
}
.logout-btn {
border: 1px solid rgba(255,255,255,0.18);
background: transparent;
color: #c8bfb0;
font-size: 12px;
padding: 4px 11px;
border-radius: var(--r);
cursor: pointer;
white-space: nowrap;
transition: background 0.15s, color 0.15s;
}
.logout-btn:hover { background: rgba(255,255,255,0.1); color: var(--paper); }
.logout-btn:disabled { opacity: 0.5; cursor: default; }
/* ── Login / Setup pages ─────────────────────────────────────────────────── */
.login-page,
.setup-page {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: var(--paper);
}
.login-card,
.setup-card {
width: 100%;
max-width: 360px;
padding: 40px 36px 44px;
background: var(--paper-3);
border: 1px solid var(--line);
border-radius: var(--r3);
box-shadow: 0 2px 20px rgba(20,29,24,0.07);
}
.login-brand,
.setup-brand {
font-family: var(--display);
font-size: 32px;
font-weight: 600;
color: var(--ink);
letter-spacing: -0.01em;
margin: 0 0 6px;
}
.login-tagline,
.setup-tagline {
font-size: 13px;
color: var(--muted);
margin: 0 0 28px;
}
.login-field,
.setup-field {
display: flex;
flex-direction: column;
gap: 5px;
margin-bottom: 14px;
}
.login-label,
.setup-label {
font-size: 11.5px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.login-input,
.setup-input {
width: 100%;
border: 1px solid var(--line);
background: var(--field);
color: var(--ink);
padding: 9px 11px;
font-size: 14px;
border-radius: var(--r2);
outline: none;
transition: border-color 0.15s;
}
.login-input:focus,
.setup-input:focus { border-color: var(--accent); }
.login-error,
.setup-error {
font-size: 13px;
color: var(--accent);
margin: 4px 0 8px;
}
.login-submit,
.setup-submit {
width: 100%;
margin-top: 8px;
border: none;
background: var(--top);
color: var(--paper);
font-size: 14px;
font-weight: 600;
padding: 11px 16px;
border-radius: var(--r2);
cursor: pointer;
letter-spacing: 0.02em;
transition: opacity 0.15s;
}
.login-submit:hover,
.setup-submit:hover { opacity: 0.85; }
.login-submit:disabled,
.setup-submit:disabled { opacity: 0.45; cursor: default; }
/* ── Shared sub-view tabs ────────────────────────────────────────────────── */
.view-tabs {
display: flex;
gap: 2px;
margin-bottom: 22px;
border-bottom: 1px solid var(--line-soft);
padding-bottom: 0;
}
.view-tab {
border: none;
background: none;
color: var(--muted);
font-size: 13px;
font-weight: 600;
padding: 7px 14px;
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
letter-spacing: 0.02em;
transition: color 0.12s;
text-transform: uppercase;
letter-spacing: 0.06em;
font-size: 11.5px;
}
.view-tab:hover { color: var(--ink); }
.view-tab.is-active { color: var(--ink); border-bottom-color: var(--accent); }
/* ── Shared form elements ────────────────────────────────────────────────── */
.form-section { margin-bottom: 32px; }
.form-section h2 {
font-size: 14px;
font-weight: 700;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
margin: 0 0 14px;
}
.form-row { display: flex; gap: 8px; margin-bottom: 10px; }
.form-field {
display: flex;
flex-direction: column;
gap: 5px;
margin-bottom: 12px;
}
.form-label {
font-size: 11.5px;
font-weight: 600;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.field-input {
border: 1px solid var(--line);
background: var(--field);
color: var(--ink);
padding: 8px 10px;
font-size: 13.5px;
border-radius: var(--r);
outline: none;
transition: border-color 0.15s;
min-width: 0;
}
.field-input:focus { border-color: var(--accent); }
.field-input--flex { flex: 1; }
.form-msg { font-size: 13px; margin: 6px 0; }
.form-msg--ok { color: var(--link); }
.form-msg--err { color: var(--accent); }
.btn-primary {
border: none;
background: var(--top);
color: var(--paper);
font-size: 13px;
font-weight: 600;
padding: 8px 16px;
border-radius: var(--r);
cursor: pointer;
white-space: nowrap;
}
.btn-primary:hover { opacity: 0.85; }
.btn-primary:disabled { opacity: 0.45; cursor: default; }
.btn-ghost {
border: 1px solid var(--line);
background: none;
color: var(--ink);
font-size: 13px;
padding: 7px 14px;
border-radius: var(--r);
cursor: pointer;
}
.btn-ghost:hover { background: var(--paper-2); }
.btn-danger {
border: 1px solid var(--accent);
background: none;
color: var(--accent);
font-size: 13px;
padding: 7px 14px;
border-radius: var(--r);
cursor: pointer;
}
.btn-danger:hover { background: var(--accent); color: var(--paper); }
/* ── Admin view overrides ────────────────────────────────────────────────── */
.admin-view h1 { font-family: var(--display); font-weight: 600; font-size: 26px; margin: 0 0 20px; }
.admin-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
margin-bottom: 28px;
}
.admin-table th {
text-align: left;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--muted);
padding: 8px 10px;
border-bottom: 1px solid var(--line);
background: var(--paper-2);
}
.admin-table th:first-child { padding-left: 16px; }
.admin-table td {
padding: 9px 10px;
border-bottom: 1px solid var(--line-soft);
color: var(--ink);
vertical-align: middle;
}
.admin-table td:first-child { padding-left: 16px; }
.admin-table tr:hover td { background: var(--paper-2); }
.admin-row-disabled td { opacity: 0.45; }
.admin-section { margin-bottom: 36px; max-width: 860px; }
.admin-section h2 {
font-size: 14px;
font-weight: 700;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
margin: 0 0 14px;
}
.admin-section h3 {
font-size: 13px;
font-weight: 700;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.05em;
margin: 22px 0 10px;
}
.admin-form { display: flex; flex-direction: column; gap: 8px; max-width: 480px; }
.admin-input {
border: 1px solid var(--line);
background: var(--field);
color: var(--ink);
padding: 8px 10px;
font-size: 13.5px;
border-radius: var(--r);
outline: none;
transition: border-color 0.15s;
}
.admin-input:focus { border-color: var(--accent); }
.admin-action-btn {
border: 1px solid var(--line);
background: none;
color: var(--ink);
font-size: 12px;
padding: 4px 10px;
border-radius: var(--r);
cursor: pointer;
white-space: nowrap;
}
.admin-action-btn:hover { border-color: var(--accent); color: var(--accent); }
.status-badge {
display: inline-block;
padding: 2px 8px;
border-radius: var(--r);
font-size: 11.5px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.status-active { background: #d8eddf; color: #235c35; border: 1px solid #b4d9be; }
.status-disabled { background: #ede8e0; color: var(--muted); border: 1px solid var(--line); }
/* ── Runs view improvements ──────────────────────────────────────────────── */
.run-status {
display: inline-block;
padding: 2px 8px;
border-radius: var(--r);
font-size: 11.5px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.run-status--completed { background: #d8eddf; color: #235c35; border: 1px solid #b4d9be; }
.run-status--failed { background: #f5ddd8; color: #8d3f30; border: 1px solid #e0b8b0; }
.run-status--in-progress { background: #fdefd8; color: #8a4f10; border: 1px solid #f0cfa0; }
/* Clickable failed run rows and expandable error detail */
.run-row--failed { cursor: pointer; }
.run-row--failed:hover td { background: #fdf0ed !important; }
.run-expand-hint {
margin-left: 6px;
font-size: 10px;
color: var(--accent);
vertical-align: middle;
}
.run-error-row td {
padding: 0 !important;
background: var(--paper-2) !important;
}
.run-error-detail {
margin: 0;
padding: 10px 16px 12px;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 11.5px;
line-height: 1.55;
color: var(--muted);
white-space: pre-wrap;
word-break: break-word;
max-height: 220px;
overflow-y: auto;
}
/* ── Token created banner ────────────────────────────────────────────────── */
.token-banner {
background: #d8eddf;
border: 1px solid #b4d9be;
padding: 12px 14px;
margin-bottom: 16px;
font-size: 13px;
border-radius: var(--r2);
}
.token-banner code {
word-break: break-all;
display: block;
margin-top: 6px;
padding: 6px 8px;
background: var(--field);
border: 1px solid var(--line);
border-radius: var(--r);
font-size: 12px;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.token-dismiss {
margin-top: 8px;
font-size: 12px;
border: 1px solid var(--line);
background: none;
cursor: pointer;
padding: 3px 8px;
border-radius: var(--r);
color: var(--muted);
}
.token-dismiss:hover { background: var(--paper-2); }
.token-row {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid var(--line);
background: var(--paper-3);
padding: 10px 12px;
border-radius: var(--r);
margin-bottom: 6px;
}
.token-row-info strong { font-size: 14px; display: block; }
.token-row-info .muted { font-size: 12px; margin-top: 2px; }
.token-create-row { display: flex; gap: 8px; margin-bottom: 16px; }
/* ── Instance settings checkboxes ───────────────────────────────────────── */
.checkbox-row {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 12px;
cursor: pointer;
font-size: 14px;
}
.checkbox-row input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent); }
/* ── Collections create details ─────────────────────────────────────────── */
.coll-create-details {
margin-top: 16px;
}
.coll-create-details summary {
font-weight: 600;
cursor: pointer;
font-size: 13px;
color: var(--link);
list-style: none;
display: flex;
align-items: center;
gap: 6px;
padding: 8px 12px;
border: 1px solid var(--line-soft);
border-radius: var(--r2);
background: var(--paper-3);
width: fit-content;
}
.coll-create-details summary:hover { background: var(--paper-2); }
.coll-create-details[open] summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.coll-create-form {
border: 1px solid var(--line-soft);
border-top: none;
padding: 14px;
border-radius: 0 0 var(--r2) var(--r2);
background: var(--paper-3);
display: flex;
flex-direction: column;
gap: 10px;
max-width: 440px;
}
/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
.topbar {
grid-template-columns: 1fr auto;
height: auto;
min-height: 58px;
padding: 12px;
}
.switcher,
.nav {
grid-column: 1 / -1;
}
.nav {
justify-content: flex-start;
overflow-x: auto;
}
.app-shell {
height: auto;
grid-template-columns: 1fr;
}
.context-rail {
border-left: 0;
border-top: 1px solid var(--line);
}
.entry-table { min-width: 860px; }
}
/* Inline title edit in ContextRail */
.rail-title--editable {
cursor: pointer;
}
.rail-title--editable:hover {
opacity: 0.75;
}
.rail-title--editable .edit-icon {
display: inline-block;
width: 0.75em;
height: 0.75em;
margin-left: 0.35em;
vertical-align: middle;
opacity: 0;
transition: opacity 0.1s;
flex-shrink: 0;
}
.rail-title--editable:hover .edit-icon {
opacity: 0.5;
}
.rail-title-input {
width: 100%;
font: inherit;
font-size: inherit;
font-weight: 600;
background: transparent;
border: none;
border-bottom: 1px solid currentColor;
color: inherit;
padding: 0;
margin: 0 0 8px;
outline: none;
}
/* ════════════════════════════════════════════════════════════════════
ENTRY PREVIEWS
════════════════════════════════════════════════════════════════════ */
.preview-panel {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
.preview-panel-loading,
.preview-panel-empty {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 8px;
color: var(--muted-2);
font-size: 14px;
text-align: center;
padding: 24px;
}
/* ── Video preview ────────────────────────────────────────────────── */
.preview-video-wrap {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
background: #0d0d0b;
min-height: 200px;
}
.preview-video-wrap video {
max-width: 100%;
max-height: 100%;
width: 100%;
display: block;
}
/* ── Iframe preview ───────────────────────────────────────────────── */
.preview-iframe-wrap {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
.preview-iframe-toolbar {
display: flex;
flex-direction: column;
gap: 2px;
padding: 6px 12px;
background: var(--paper-2);
border-bottom: 1px solid var(--line);
flex-shrink: 0;
/* never uppercase the toolbar text */
text-transform: none;
letter-spacing: normal;
}
.preview-iframe-toolbar span {
font-size: 11px;
color: var(--muted-2);
}
.preview-iframe-toolbar a {
margin-left: auto;
color: var(--link);
font-size: 12px;
text-decoration: none;
padding: 3px 8px;
border: 1px solid var(--line);
border-radius: var(--r2);
background: var(--field);
transition: border-color 0.12s;
}
.preview-iframe-toolbar a:hover {
border-color: var(--accent);
text-decoration: none;
}
.preview-iframe-wrap iframe {
flex: 1;
width: 100%;
border: none;
background: white;
min-height: 0;
}
/* ── Image preview ────────────────────────────────────────────────── */
.preview-image-wrap {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
background: var(--paper-2);
}
.preview-image-wrap img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: var(--r3);
cursor: zoom-in;
display: block;
box-shadow: 0 4px 24px rgba(0,0,0,0.1);
}
/* ── Tweet preview wrap ───────────────────────────────────────────── */
.preview-tweet-wrap {
flex: 1;
min-height: 0;
overflow-y: auto;
padding: 12px 16px;
background: var(--paper-2);
/* styled scrollbar matching the workspace rail */
scrollbar-width: thin;
scrollbar-color: var(--line) transparent;
}
.preview-tweet-wrap::-webkit-scrollbar { width: 8px; }
.preview-tweet-wrap::-webkit-scrollbar-track { background: transparent; }
.preview-tweet-wrap::-webkit-scrollbar-thumb {
background: var(--line);
border-radius: 999px;
border: 2px solid transparent;
background-clip: padding-box;
}
.preview-tweet-wrap::-webkit-scrollbar-thumb:hover {
background: var(--muted-2);
background-clip: padding-box;
border: 2px solid transparent;
}
/* ── Tweet card ───────────────────────────────────────────────────── */
.tw-card {
border: 1px solid var(--line);
border-radius: 12px;
padding: 16px;
background: var(--paper);
max-width: 560px;
margin: 0 auto 12px;
}
.tw-thread {
max-width: 560px;
margin: 0 auto;
}
.tw-thread-item {
display: flex;
gap: 0;
margin-bottom: 0;
}
.tw-thread-connector {
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
width: 52px;
padding-top: 2px;
}
.tw-thread-avatar-col {
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
}
.tw-thread-line {
width: 2px;
background: var(--line);
flex: 1;
min-height: 16px;
margin: 4px 0;
}
.tw-thread-body {
flex: 1;
min-width: 0;
padding: 0 0 16px 12px;
}
.tw-thread-body:last-child { padding-bottom: 0; }
.tw-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
flex-shrink: 0;
display: block;
}
.tw-avatar-ph {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--paper-2);
border: 1px solid var(--line);
flex-shrink: 0;
}
.tw-header {
display: flex;
align-items: baseline;
gap: 6px;
flex-wrap: wrap;
margin-bottom: 6px;
}
.tw-author-name { font-size: 14.5px; font-weight: 700; color: var(--ink); }
.tw-author-handle { font-size: 13px; color: var(--muted-2); }
.tw-dot { color: var(--muted-2); font-size: 13px; }
.tw-date { font-size: 13px; color: var(--muted-2); }
.tw-text {
font-size: 15px;
line-height: 1.65;
color: var(--ink);
white-space: pre-line;
word-break: break-word;
margin-bottom: 10px;
}
.tw-text a { color: var(--link); text-decoration: none; }
.tw-text a:hover { text-decoration: underline; }
.tw-stats {
display: flex;
gap: 20px;
color: var(--muted-2);
font-size: 13px;
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid var(--line-soft);
}
.tw-stats span { display: flex; align-items: center; gap: 4px; }
/* ── X Article styles ─────────────────────────────────────────────── */
.tw-article {
max-width: 598px;
margin: 0 auto;
}
.tw-article-cover {
width: 100%;
display: block;
object-fit: cover;
max-height: 380px;
}
.tw-article-meta { padding: 20px 16px 0; }
.tw-article-title {
font-size: 22px;
font-weight: 800;
letter-spacing: -0.3px;
color: var(--ink);
line-height: 1.3;
margin-bottom: 14px;
}
.tw-article-author-row {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 14px;
}
.tw-article-author-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.tw-article-author-sub { font-size: 13px; color: var(--muted-2); }
.tw-article-divider { border: none; border-top: 1px solid var(--line); margin: 0; }
.tw-article-body { padding: 8px 16px 60px; }
.tw-b-h1 {
font-size: 24px; font-weight: 800; letter-spacing: -0.3px;
color: var(--ink); line-height: 1.25; margin: 22px 0 10px;
}
.tw-b-h2 {
font-size: 19px; font-weight: 700; letter-spacing: -0.15px;
color: var(--ink); line-height: 1.3; margin: 20px 0 8px;
}
.tw-b-p { font-size: 16px; color: var(--ink); line-height: 1.72; margin-bottom: 14px; }
.tw-b-p:empty { display: none; }
.tw-b-spacer { height: 6px; display: block; }
.tw-b-blockquote {
border-left: 3px solid var(--line);
padding: 2px 14px;
margin: 14px 0;
color: var(--muted);
font-size: 16px;
line-height: 1.65;
}
.tw-b-hr { border: none; border-top: 1px solid var(--line); margin: 24px 0; }
.tw-b-img { width: 100%; display: block; border-radius: 10px; margin: 14px 0; }
.tw-b-ul, .tw-b-ol { margin: 10px 0 14px; padding-left: 26px; }
.tw-b-li { font-size: 16px; color: var(--ink); line-height: 1.65; margin-bottom: 6px; }
.tw-b-code {
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
font-size: 0.875em;
background: var(--paper-2);
padding: 2px 5px;
border-radius: 4px;
color: var(--ink);
}
.tw-b-pre {
background: var(--paper-2);
border: 1px solid var(--line);
border-radius: 8px;
padding: 14px 16px;
overflow-x: auto;
margin: 12px 0;
}
.tw-b-pre code {
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
font-size: 13px;
line-height: 1.6;
}
.tw-b-tweet-link {
display: flex;
align-items: center;
gap: 10px;
border: 1px solid var(--line);
border-radius: 10px;
padding: 12px 14px;
margin: 12px 0;
color: var(--muted);
font-size: 14px;
text-decoration: none;
background: var(--paper-3);
transition: background 0.12s;
}
.tw-b-tweet-link:hover { background: var(--field); }
.tw-b-tweet-link svg { flex-shrink: 0; color: var(--ink); }
/* ── Audio bar ────────────────────────────────────────────────────── */
.audio-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 72px;
background: var(--paper);
border-top: 1px solid var(--line);
display: flex;
align-items: center;
gap: 20px;
padding: 0 24px;
z-index: 100;
box-shadow: 0 -2px 16px rgba(0,0,0,0.08);
}
.audio-bar-info {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
flex: 0 0 200px;
}
.audio-bar-icon {
flex-shrink: 0;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.audio-bar-icon svg { width: 20px; height: 20px; }
.audio-bar-title {
font-size: 13px;
color: var(--ink);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
font-weight: 500;
}
.audio-bar-controls {
flex: 1;
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
}
.audio-bar-play-btn {
width: 38px;
height: 38px;
border-radius: 50%;
background: var(--accent);
color: var(--paper);
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: background 0.12s, transform 0.1s;
}
.audio-bar-play-btn:hover { background: var(--accent-2); }
.audio-bar-play-btn:active { transform: scale(0.93); }
.audio-bar-play-btn svg { width: 15px; height: 15px; }
.audio-bar-seek {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
gap: 8px;
}
.audio-bar-seek input[type="range"] {
flex: 1;
accent-color: var(--accent);
height: 4px;
cursor: pointer;
min-width: 0;
}
.audio-bar-time {
font-size: 11.5px;
color: var(--muted-2);
white-space: nowrap;
min-width: 80px;
text-align: right;
font-variant-numeric: tabular-nums;
}
.audio-bar-right {
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 10px;
}
.audio-bar-volume {
display: flex;
align-items: center;
gap: 6px;
}
.audio-bar-volume svg { width: 14px; height: 14px; color: var(--muted-2); flex-shrink: 0; }
.audio-bar-volume input[type="range"] {
width: 72px;
accent-color: var(--accent);
cursor: pointer;
}
.audio-bar-close {
width: 28px;
height: 28px;
border-radius: 50%;
border: none;
background: transparent;
color: var(--muted-2);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
padding: 0;
line-height: 1;
transition: background 0.12s, color 0.12s;
}
.audio-bar-close:hover { background: var(--field); color: var(--ink); }
/* ── Preview modal ────────────────────────────────────────────────── */
.preview-modal-backdrop {
position: fixed;
inset: 0;
z-index: 200;
background: rgba(0, 0, 0, 0.55);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.preview-modal {
background: var(--paper);
border-radius: 12px;
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.28);
width: 90vw;
max-width: 1100px;
max-height: 88vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* Full-height variant for iframe/PDF/video/image (needs explicit height
so flex children like <iframe style="flex:1"> have a concrete container). */
.preview-modal--full {
height: 88vh;
}
.preview-modal--full .preview-modal-body {
max-height: none;
}
.preview-modal-header {
display: flex;
align-items: center;
padding: 14px 18px;
border-bottom: 1px solid var(--line);
flex-shrink: 0;
gap: 12px;
}
.preview-modal-title {
flex: 1;
min-width: 0;
font-size: 14px;
font-weight: 600;
color: var(--ink);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.preview-modal-close {
width: 30px;
height: 30px;
border-radius: 50%;
border: none;
background: transparent;
color: var(--muted-2);
font-size: 20px;
line-height: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: background 0.12s, color 0.12s;
}
.preview-modal-close:hover { background: var(--field); color: var(--ink); }
.preview-modal-body {
flex: 1;
min-height: 0;
/* overflow: hidden — each child (tweet-wrap, video-wrap, iframe, image)
manages its own scroll. This also prevents the spurious scrollbar that
appears when a video's native controls briefly expand the layout. */
overflow: hidden;
display: flex;
flex-direction: column;
/* Cap so long threads/articles stay scrollable even when modal has no
fixed height (shrinks for short tweets). 52px ≈ header padding+border. */
max-height: calc(88vh - 52px);
}
/* Preview button in context rail */
.rail-preview-btn {
display: block;
width: 100%;
padding: 8px 12px;
margin-bottom: 16px;
background: var(--accent);
color: var(--paper);
border: none;
border-radius: var(--r3);
font-size: 13px;
font-weight: 600;
cursor: pointer;
text-align: center;
transition: background 0.12s;
}
.rail-preview-btn:hover { background: var(--accent-2); }
/* Open-in-new-tab button in preview modal header */
.preview-modal-newtab {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: var(--r2);
color: var(--muted-2);
text-decoration: none;
font-size: 16px;
flex-shrink: 0;
transition: background 0.12s, color 0.12s;
}
.preview-modal-newtab:hover { background: var(--field); color: var(--ink); }
/* Push content above the fixed AudioBar when it is visible */
body.has-audio-bar { padding-bottom: 56px; }
/* ── Skeleton entry row ─────────────────────────────────────────────────── */
@keyframes skeleton-shimmer {
0% { background-position: 200% center; }
100% { background-position: -200% center; }
}
.skeleton-cell {
display: inline-block;
border-radius: 3px;
background: linear-gradient(90deg, var(--paper-2) 25%, var(--line-soft) 50%, var(--paper-2) 75%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.8s ease-in-out infinite;
}
/* Row container — flex row matching #entries-body > div layout */
.skeleton-row {
display: flex;
align-items: center;
background: var(--paper-3);
}
.skeleton-row > div {
padding: 7px 10px;
flex-shrink: 0;
overflow: hidden;
}
.skeleton-row .col-added { padding-left: 22px; }
.skeleton-row > div:last-child { padding-right: 22px; }
@media (pointer: coarse) {
.skeleton-row .col-added { padding-left: 10px; }
}
/* ── Child entry expansion ───────────────────────────────────────────────── */
/* Outer wrapper: one block per entry-group so nth-child stays correct.
#entries-body > .entry-row-outer beats #entries-body > div on specificity
(id + class > id + element) so display:flex is safely overridden. */
#entries-body > .entry-row-outer {
display: block;
border-bottom: none;
}
/* Inner flex row: replicates the #entries-body > div row behaviour. */
#entries-body > .entry-row-outer > .entry-row-main {
display: flex;
align-items: center;
cursor: default;
border-bottom: 1px solid var(--line-soft);
/* Reset padding that #entries-body > div > div would otherwise apply. */
padding: 0;
flex-shrink: unset;
overflow: visible;
}
/* Column cells inside the inner row. */
#entries-body > .entry-row-outer > .entry-row-main > div {
padding: 7px 10px;
flex-shrink: 0;
overflow: hidden;
}
#entries-body > .entry-row-outer > .entry-row-main > div:last-child { padding-right: 22px; }
#entries-body > .entry-row-outer > .entry-row-main .col-added { padding-left: 22px; }
/* Selection: class lives on outer wrapper; background + stroke scoped to inner row
so expanded child entries don't inherit the selection highlight. */
#entries-body > .entry-row-outer.is-selected { background: unset; outline: none; box-shadow: none; }
#entries-body > .entry-row-outer.is-multi-selected { background: unset; outline: none; box-shadow: none; }
#entries-body > .entry-row-outer.is-selected > .entry-row-main {
background: #eee2d2;
box-shadow: inset 0 0 0 2px var(--accent);
}
#entries-body > .entry-row-outer.is-multi-selected > .entry-row-main {
background: #eee2d2;
box-shadow: inset 0 0 0 2px var(--accent);
}
/* URL overflow on hover only — explicit pointer, not selection. */
#entries-body > .entry-row-outer .url-cell:hover { overflow: visible; white-space: normal; }
/* child-entries container: reset the padding that #entries-body > div > div applies. */
#entries-body > .entry-row-outer > .child-entries {
display: block;
padding: 0;
flex-shrink: unset;
overflow: visible;
border-left: 2px solid var(--line-soft);
margin-left: 32px;
}
/* Each child row reuses the same .col-* flex widths as normal rows. */
.child-entry-row {
display: flex;
align-items: center;
cursor: default;
border-bottom: 1px solid var(--line-soft);
opacity: 0.88;
}
.child-entry-row:hover { opacity: 1; }
.child-entry-row:last-child { border-bottom: none; }
.child-entry-row--light { background: #fafaf8; }
.child-entry-row--dark { background: #f2f0ec; }
.child-entry-row.is-selected {
background: #eee2d2;
box-shadow: inset 0 0 0 2px var(--accent);
opacity: 1;
}
.child-entry-row.is-multi-selected {
background: #eee2d2;
box-shadow: inset 0 0 0 2px var(--accent);
opacity: 1;
}
.child-entry-row > div {
padding: 6px 10px;
flex-shrink: 0;
overflow: hidden;
}
.child-entry-row .col-added { padding-left: 22px; }
.child-entry-row > div:last-child { padding-right: 22px; }
/* Expand chevron button */
.entry-expand-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
flex-shrink: 0;
padding: 0;
margin-right: 2px;
background: none;
border: none;
cursor: pointer;
opacity: 0.45;
color: inherit;
transition: opacity 0.15s;
}
.entry-expand-btn:focus { outline: none; }
.entry-expand-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.entry-expand-btn::before {
content: '';
display: block;
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 6px solid currentColor;
transition: transform 0.15s;
}
.entry-expand-btn:hover { opacity: 1; }
.entry-expand-btn.is-expanded::before { transform: rotate(90deg); }
/* Child count badge next to title */
.child-count-badge {
display: inline-block;
margin-left: 5px;
padding: 0 5px;
font-size: 0.72em;
font-weight: 600;
background: color-mix(in srgb, var(--line-soft) 60%, transparent);
border-radius: 10px;
opacity: 0.75;
vertical-align: middle;
line-height: 1.6;
}
/* Loading placeholder inside child-entries */
.child-entries-loading {
padding: 8px 12px;
font-size: 0.85em;
opacity: 0.55;
}
/* ── Playlist quality expansion ──────────────────────────── */
.capture-playlist-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 0.75rem;
color: var(--muted);
background: none;
border: none;
cursor: pointer;
padding: 2px 6px;
}
.capture-playlist-toggle:hover { color: var(--text); }
.capture-playlist-toggle--left {
flex-shrink: 0;
padding: 2px 4px;
font-size: 0.7rem;
}
.capture-conflict-badge {
font-size: 0.7rem;
color: #c07000;
background: #fff3cd;
border: 1px solid #e0a000;
border-radius: 4px;
padding: 1px 6px;
margin-left: 6px;
}
.capture-playlist-items {
border-top: 1px solid var(--line-soft);
max-height: 320px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--line) transparent;
}
.capture-playlist-item {
display: flex;
align-items: center;
gap: 8px;
padding: 5px 10px 5px 14px;
font-size: 0.8rem;
border-bottom: 1px solid var(--line-soft);
border-left: 3px solid transparent;
}
.capture-playlist-item:last-of-type { border-bottom: none; }
.capture-playlist-item--conflict {
border-left-color: #c07000;
background: color-mix(in srgb, #c07000 6%, transparent);
}
.capture-playlist-item-title {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text);
opacity: 0.9;
}
.capture-item-quality {
font-size: 0.73rem;
padding: 2px 4px;
border: 1px solid var(--line);
border-radius: 3px;
background: var(--paper-3);
color: var(--text);
flex-shrink: 0;
}
.capture-playlist-conflict-badge {
font-size: 0.68rem;
font-weight: 600;
color: #c07000;
white-space: nowrap;
flex-shrink: 0;
}
.capture-playlist-item-remove {
flex-shrink: 0;
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
padding: 0;
border: none;
background: none;
color: var(--muted);
cursor: pointer;
border-radius: 3px;
opacity: 0.3;
transition: opacity 0.1s, color 0.1s;
}
.capture-playlist-item:hover .capture-playlist-item-remove,
.capture-playlist-item-remove:focus-visible { opacity: 1; }
.capture-playlist-item-remove:hover { color: #c04000; opacity: 1; }
@media (pointer: coarse) { .capture-playlist-item-remove { opacity: 1; } }
.capture-playlist-item-remove { font-size: 0.75rem; line-height: 1; }
.capture-sync-row {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
font-size: 0.78rem;
color: var(--muted);
border-top: 1px solid var(--line-soft);
cursor: pointer;
}
.capture-sync-row input[type=checkbox] { cursor: pointer; }