Files
arr/web/src/style.css
T
Miguel Palhas 043ebffa1c feat(web): series and episodes in unified search
In-library hits now read as whatever they are: movies open the release
deck as before, series hits render display-only until issue 129's detail
view gives them a link target, and an episode hit reads as its series
plus SxxEyy plus the episode title. TMDB results show TV alongside film,
and the add panel filters roots by kind; a series adds the one §4.1
add-time choice, auto_track, stated plainly: future seasons are tracked
automatically, past seasons are not.
2026-08-23 18:00:54 +01:00

1366 lines
27 KiB
CSS

/* arr — master-control board.
Tokens mirror .impeccable/design.json; components consume tokens, never
literals. Committed dark: a control room is lit by its lamps. */
@font-face {
font-family: "Rajdhani";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("/fonts/rajdhani-600-latin.woff2") format("woff2");
}
@font-face {
font-family: "Rajdhani";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("/fonts/rajdhani-700-latin.woff2") format("woff2");
}
:root {
/* ground and panels */
--ground: oklch(0.14 0.01 250);
--panel: oklch(0.18 0.012 250);
--panel-raised: oklch(0.21 0.014 250);
--line: oklch(0.3 0.015 250);
--line-strong: oklch(0.42 0.02 250);
--highlight: oklch(1 0 0 / 4%);
/* ink */
--ink: oklch(0.93 0.008 250);
--ink-muted: oklch(0.72 0.015 250);
--ink-faint: oklch(0.58 0.015 250);
/* signal lamps */
--signal-ok: oklch(0.8 0.17 150);
--signal-warn: oklch(0.82 0.14 80);
--signal-fault: oklch(0.68 0.21 25);
--signal-idle: oklch(0.45 0.02 250);
/* the one interactive hue */
--accent: oklch(0.8 0.12 220);
--accent-bright: oklch(0.88 0.12 220);
/* dead lamp and pressed-control lowlight */
--lamp-off: oklch(0.3 0.012 250);
--lowlight: oklch(0 0 0 / 30%);
/* release verdicts (§9.3) — rejected is quiet slate, never fault red */
--verdict-eligible: oklch(0.8 0.17 150);
--verdict-waived: oklch(0.82 0.14 80);
--verdict-rejected: oklch(0.68 0.02 250);
/* score heat scale (issue #111) — one list-relative gradient from lowest
red to highest green; JS picks the stop, colour stays in tokens */
--score-0: oklch(0.68 0.19 25);
--score-1: oklch(0.7 0.185 46);
--score-2: oklch(0.72 0.175 67);
--score-3: oklch(0.75 0.165 88);
--score-4: oklch(0.77 0.16 108);
--score-5: oklch(0.79 0.165 129);
--score-6: oklch(0.8 0.17 150);
/* library status (§4.2) — informational, never a severity ramp:
activity in one violet family, satisfaction in neutrals */
--status-airing: oklch(0.78 0.14 305);
--status-incomplete: oklch(0.72 0.09 305);
--status-waiting: oklch(0.64 0.045 305);
--status-complete: oklch(0.85 0.01 250);
--status-ended: oklch(0.62 0.015 250);
/* type */
--font-label: system-ui, "Segoe UI", sans-serif;
--font-readout:
ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono", Menlo, Consolas, monospace;
--font-display: "Rajdhani", "Avenir Next Condensed", "Arial Narrow", sans-serif;
/* type scale */
--text-2xs: 0.6875rem;
--text-xs: 0.75rem;
--text-sm: 0.8125rem;
--text-base: 1rem;
--text-md: 1.0625rem;
--text-lg: 1.3125rem;
--text-xl: 1.625rem;
/* rhythm */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-6: 1.5rem;
--space-8: 2rem;
--space-12: 3rem;
--radius: 4px;
--ease-out: cubic-bezier(0.25, 1, 0.5, 1);
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
/* a scrollbar appearing must not reflow the rail's wrap */
html {
scrollbar-gutter: stable;
}
body {
min-height: 100dvh;
display: flex;
flex-direction: column;
background: var(--ground);
color: var(--ink);
font-family: var(--font-label);
font-size: var(--text-base);
line-height: 1.5;
}
.readout {
font-family: var(--font-readout);
font-size: var(--text-sm);
}
.dim {
color: var(--ink-muted);
}
/* ---- rails ---------------------------------------------------------- */
.rail {
display: flex;
align-items: center;
gap: var(--space-6);
padding: var(--space-3) var(--space-6);
border-bottom: 1px solid var(--line);
background: var(--panel);
box-shadow: inset 0 1px var(--highlight);
}
.rail-id {
display: flex;
align-items: center;
gap: var(--space-3);
}
.wordmark {
margin: 0;
font-family: var(--font-display);
font-size: var(--text-xl);
font-weight: 700;
letter-spacing: 0.1em;
line-height: 1;
}
.rail-verdict {
margin: 0;
flex: 1;
color: var(--ink-muted);
}
.rail-verdict[data-tone="ok"] {
color: var(--signal-ok);
}
.rail-verdict[data-tone="warn"] {
color: var(--signal-warn);
}
.rail-verdict[data-tone="fault"] {
color: var(--signal-fault);
}
.rail-meta {
display: flex;
align-items: center;
gap: var(--space-4);
}
/* ---- lamps ---------------------------------------------------------- */
.lamp {
--lamp: var(--signal-idle);
width: 0.625rem;
height: 0.625rem;
flex: none;
border-radius: 50%;
background: var(--lamp);
/* the panel's own device: a lit indicator, not a depth shadow */
box-shadow:
0 0 6px var(--lamp),
0 0 14px oklch(from var(--lamp) l c h / 35%);
transition: background 300ms var(--ease-out);
}
.lamp-big {
width: 0.875rem;
height: 0.875rem;
}
.lamp[data-state="ok"] {
--lamp: var(--signal-ok);
}
.lamp[data-state="unconfigured"] {
--lamp: var(--signal-warn);
}
.lamp[data-state="degraded"] {
--lamp: var(--signal-warn);
}
.lamp[data-state="unreachable"] {
--lamp: var(--signal-fault);
}
.lamp[data-state="probing"] {
--lamp: var(--signal-idle);
animation: lamp-probe 1.2s var(--ease-out) infinite alternate;
}
/* dead air: dark, no glow, no motion */
.lamp[data-state="off"] {
--lamp: var(--lamp-off);
box-shadow: none;
}
@keyframes lamp-probe {
from {
opacity: 0.45;
}
to {
opacity: 1;
}
}
/* power-up: lamps flicker on left to right, once, on first verdict */
@keyframes lamp-strike {
0% {
opacity: 0.2;
}
40% {
opacity: 1;
}
55% {
opacity: 0.35;
}
100% {
opacity: 1;
}
}
.board.powered .lamp {
animation: lamp-strike 420ms var(--ease-out) both;
animation-delay: calc(var(--strike, 0) * 120ms);
}
.board.powered .lamp[data-state="off"] {
animation: none;
}
@media (prefers-reduced-motion: reduce) {
.lamp[data-state="probing"],
.board.powered .lamp {
animation: none;
}
}
/* ---- board and chain ------------------------------------------------- */
.board {
width: 100%;
max-width: 68rem;
margin: 0 auto;
padding: var(--space-12) var(--space-6);
flex: 1;
display: flex;
align-items: center;
}
/* the deck swaps in over the board; flex would beat [hidden] otherwise */
.board[hidden] {
display: none;
}
.chain {
width: 100%;
}
.chain {
display: grid;
grid-template-columns: 1fr 2.5rem 1.2fr 2.5rem 1fr;
grid-template-areas:
"tmdb t1 master out sink"
"prow t2 master out sink";
align-items: center;
row-gap: var(--space-6);
}
.area-tmdb {
grid-area: tmdb;
}
.area-prowlarr {
grid-area: prow;
}
.area-t1 {
grid-area: t1;
}
.area-t2 {
grid-area: t2;
}
.area-master {
grid-area: master;
}
.area-out {
grid-area: out;
}
.area-transmission {
grid-area: sink;
}
/* ---- modules --------------------------------------------------------- */
.module {
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: inset 0 1px var(--highlight);
padding: var(--space-4) var(--space-4) var(--space-3);
}
.module-master {
background: var(--panel-raised);
border-color: var(--line-strong);
padding: var(--space-6) var(--space-4) var(--space-4);
}
.module-head {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--space-1) var(--space-2);
}
.module-name {
margin: 0;
font-family: var(--font-display);
font-size: var(--text-md);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
line-height: 1;
}
.module-master .module-name {
font-size: var(--text-lg);
}
.module-status {
margin-left: auto;
padding-left: var(--space-3);
color: var(--ink-muted);
}
.module-status[data-tone="ok"] {
color: var(--signal-ok);
}
.module-status[data-tone="warn"] {
color: var(--signal-warn);
}
.module-status[data-tone="fault"] {
color: var(--signal-fault);
}
.module-role {
margin: var(--space-2) 0 0;
font-size: var(--text-2xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--ink-muted);
}
.module-detail {
margin: var(--space-1) 0 0;
font-size: var(--text-xs);
color: var(--ink-muted);
min-height: 1.2em;
}
/* ---- bus traces ------------------------------------------------------ */
.bus {
display: grid;
align-content: center;
justify-items: center;
}
.bus-trace {
--trace: var(--line-strong);
width: 100%;
height: 0.5rem;
display: block;
transition: filter 300ms var(--ease-out);
}
.bus-trace line {
stroke: var(--trace);
stroke-width: 1;
}
.bus-arrow {
fill: var(--trace);
}
.bus-trace[data-tone="ok"] {
--trace: var(--signal-ok);
}
.bus-trace[data-tone="warn"] {
--trace: var(--signal-warn);
}
.bus-trace[data-tone="fault"] {
--trace: var(--signal-fault);
}
/* ---- controls -------------------------------------------------------- */
.control {
min-height: 2.75rem;
padding: 0 var(--space-4);
font-family: var(--font-readout);
font-size: var(--text-sm);
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--accent);
background: var(--panel-raised);
border: 1px solid var(--line-strong);
border-radius: var(--radius);
box-shadow: inset 0 1px var(--highlight);
cursor: pointer;
transition:
border-color 150ms var(--ease-out),
color 150ms var(--ease-out);
}
.control:hover {
border-color: var(--accent);
color: var(--accent-bright);
}
.control:active {
box-shadow: inset 0 1px var(--lowlight);
}
.control:disabled {
color: var(--ink-faint);
border-color: var(--line);
cursor: default;
}
/* the engaged view control stays lit while its surface is up */
.control[aria-pressed="true"] {
border-color: var(--accent);
color: var(--accent-bright);
}
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ---- unified search (§9.2) ------------------------------------------- */
.rail-search {
position: relative;
flex: 1;
max-width: 30rem;
display: flex;
align-items: center;
}
.search-input {
width: 100%;
min-height: 2.75rem;
padding: 0 var(--space-8) 0 var(--space-3);
color: var(--ink);
background: var(--ground);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: inset 0 1px var(--lowlight);
caret-color: var(--accent);
transition: border-color 150ms var(--ease-out);
}
.search-input::placeholder {
color: var(--ink-faint);
opacity: 1;
}
.search-input:hover {
border-color: var(--line-strong);
}
.search-input:focus {
border-color: var(--accent);
outline: none;
}
.search-hint {
position: absolute;
right: var(--space-3);
padding: 0 var(--space-1);
font-size: var(--text-2xs);
color: var(--ink-faint);
border: 1px solid var(--line);
border-radius: var(--radius);
pointer-events: none;
}
/* ---- search deck ------------------------------------------------------ */
.deck {
width: 100%;
max-width: 68rem;
margin: 0 auto;
padding: var(--space-8) var(--space-6) var(--space-12);
flex: 1;
}
.deck-status {
margin: 0 0 var(--space-4);
color: var(--ink-muted);
}
.deck-status[data-tone="fault"] {
color: var(--signal-fault);
}
/* a sweep in flight borrows the rail's probing-lamp idiom, inline */
.deck-status .lamp {
display: inline-block;
margin-right: var(--space-2);
vertical-align: baseline;
}
.deck-group {
margin: 0 0 var(--space-8);
}
.deck-head {
display: flex;
align-items: baseline;
gap: var(--space-3);
padding: 0 var(--space-1) var(--space-2);
border-bottom: 1px solid var(--line);
}
/* the engraved micro-label is the heading itself, not a kicker */
.deck-label {
margin: 0;
font-size: var(--text-2xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--ink-muted);
}
.deck-count {
font-size: var(--text-xs);
color: var(--ink-faint);
}
.deck-rows {
margin: 0;
padding: 0;
list-style: none;
}
.row {
display: flex;
align-items: baseline;
flex-wrap: wrap;
gap: var(--space-1) var(--space-3);
width: 100%;
padding: var(--space-2) var(--space-1);
border-bottom: 1px solid oklch(from var(--line) l c h / 45%);
text-align: left;
}
.row-id {
display: inline-flex;
align-items: baseline;
gap: var(--space-2);
min-width: 0;
}
/* titles are names: the display face, per the Readout Rule in design.json */
.row-title {
font-family: var(--font-display);
font-size: var(--text-md);
font-weight: 600;
letter-spacing: 0.02em;
color: var(--ink);
}
.row-year {
font-size: var(--text-xs);
}
.row-chips {
display: inline-flex;
align-items: center;
gap: var(--space-1);
margin-left: auto;
}
.chip {
display: inline-flex;
align-items: center;
gap: var(--space-1);
min-height: 1.375rem;
padding: 0 var(--space-2);
background: var(--panel-raised);
border: 1px solid var(--line);
border-radius: var(--radius);
font-family: var(--font-readout);
font-size: var(--text-xs);
color: var(--ink-muted);
}
.chip[data-verdict="eligible"] {
color: var(--verdict-eligible);
border-color: oklch(from var(--verdict-eligible) l c h / 45%);
}
/* the dashed border is the visible mark of a relaxed rule */
.chip[data-verdict="waived"] {
color: var(--verdict-waived);
border-style: dashed;
border-color: oklch(from var(--verdict-waived) l c h / 55%);
}
/* rejected is the policy working, never fault red */
.chip[data-verdict="rejected"] {
color: var(--verdict-rejected);
}
.chip[data-movie-state="available"] {
color: var(--ink);
}
/* library status (§4.2): informational, never a severity ramp — activity in
the channel-violet family, satisfaction in neutrals; the word is always
present, so the state survives with colour removed */
.chip[data-status="airing"] {
color: var(--status-airing);
border-color: oklch(from var(--status-airing) l c h / 45%);
}
.chip[data-status="incomplete"] {
color: var(--status-incomplete);
}
.chip[data-status="waiting"] {
color: var(--status-waiting);
}
.chip[data-status="complete"] {
color: var(--status-complete);
}
.chip[data-status="ended"] {
color: var(--status-ended);
}
/* a TMDB row is the affordance: the whole row opens the add flow */
.row-tmdb {
font: inherit;
background: none;
border: 0;
border-bottom: 1px solid oklch(from var(--line) l c h / 45%);
cursor: pointer;
transition: background 150ms var(--ease-out);
}
.row-tmdb:hover:not(:disabled),
.row-tmdb:focus-visible {
background: var(--panel);
}
.row-tmdb:disabled {
cursor: default;
}
.row-add {
font-size: var(--text-xs);
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--accent);
}
.row-overview {
flex-basis: 100%;
overflow: hidden;
font-size: var(--text-xs);
color: var(--ink-faint);
white-space: nowrap;
text-overflow: ellipsis;
}
/* an episode hit's title sits beside its SxxEyy chip: a name, not a readout */
.row-sub {
font-size: var(--text-sm);
color: var(--ink-muted);
}
/* ---- add flow (inline, root and policy pre-filled) -------------------- */
.add-panel {
margin: 0 0 var(--space-2);
padding: var(--space-3) var(--space-3) var(--space-3);
background: var(--panel);
border: 1px solid var(--line);
border-top: 0;
border-radius: 0 0 var(--radius) var(--radius);
box-shadow: inset 0 1px var(--highlight);
}
.add-roots {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
gap: var(--space-2);
}
.root-option {
display: grid;
gap: var(--space-1);
padding: var(--space-2) var(--space-3);
font: inherit;
text-align: left;
color: var(--ink);
background: var(--panel-raised);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: inset 0 1px var(--highlight);
cursor: pointer;
transition: border-color 150ms var(--ease-out);
}
.root-option:hover {
border-color: var(--line-strong);
}
.root-option[aria-pressed="true"] {
border-color: var(--accent);
}
.root-audience {
font-family: var(--font-display);
font-size: var(--text-md);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
line-height: 1;
}
.root-policy,
.root-path {
font-size: var(--text-xs);
}
.add-actions {
display: flex;
align-items: center;
gap: var(--space-3);
margin: var(--space-3) 0 0;
}
/* the one series-level add-time question (§4.1): the choice and what it does */
.add-autotrack {
display: grid;
justify-content: start;
gap: var(--space-1);
margin: var(--space-3) 0 0;
}
.add-note {
margin: 0;
font-size: var(--text-xs);
color: var(--ink-muted);
}
.add-note[data-tone="fault"] {
color: var(--signal-fault);
}
.add-done {
margin: 0;
color: var(--verdict-eligible);
}
/* ---- release deck (§9.3) ---------------------------------------------- */
.releases-head {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--space-2) var(--space-3);
margin: 0 0 var(--space-6);
}
.releases-id {
flex: 1;
min-width: 0;
display: flex;
align-items: baseline;
gap: var(--space-2);
}
.releases-title {
margin: 0;
font-family: var(--font-display);
font-size: var(--text-lg);
font-weight: 700;
letter-spacing: 0.04em;
line-height: 1.1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.releases-year {
font-size: var(--text-xs);
}
/* ---- removal confirmation (§7.4, issue 104) --------------------------- */
/* remove is not the deck's errand: it reads as a quiet control until the
operator reaches for it, and never competes with the sweep */
.control-quiet {
color: var(--ink-muted);
border-color: var(--line);
}
.control-quiet:hover,
.control-quiet[aria-expanded="true"] {
color: var(--accent-bright);
border-color: var(--accent);
}
.remove-panel {
margin: 0 0 var(--space-6);
}
.remove-body {
display: grid;
gap: var(--space-2);
padding: var(--space-3);
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: inset 0 1px var(--highlight);
}
/* armed is a state, not a toggle: it is amber whenever files are on disk to
delete */
.remove-body[data-armed="true"] {
border-color: oklch(from var(--signal-warn) l c h / 55%);
}
.remove-evidence,
.remove-path,
.remove-note {
margin: 0;
font-size: var(--text-xs);
}
/* the folder is evidence: it wraps rather than truncating, because a path
the operator cannot read whole is not a confirmation */
.remove-path {
color: var(--ink-muted);
overflow-wrap: anywhere;
white-space: pre-line;
}
.remove-note {
color: var(--ink-muted);
}
.remove-note[data-tone="warn"] {
color: var(--signal-warn);
}
.remove-note[data-tone="fault"] {
color: var(--signal-fault);
}
.remove-actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin: var(--space-1) 0 0;
}
.remove-body[data-armed="true"] .remove-actions .control:first-child {
color: var(--signal-warn);
border-color: oklch(from var(--signal-warn) l c h / 55%);
}
.remove-body[data-armed="true"] .remove-actions .control:first-child:hover:not(:disabled) {
border-color: var(--signal-warn);
}
.bucket-head {
align-items: center;
}
.bucket-toggle {
margin-left: auto;
min-height: 2.75rem;
padding: 0 var(--space-2);
font-size: var(--text-xs);
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--accent);
background: none;
border: 0;
cursor: pointer;
transition: color 150ms var(--ease-out);
}
.bucket-toggle:hover {
color: var(--accent-bright);
}
/* fixed-width mono columns: chips and header labels share rem widths, so
the pseudo-table survives font-size differences and flex wrapping alike */
.cw {
display: inline-block;
flex: none;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
line-height: 1.25rem;
}
.cw-score {
width: 4.5rem;
text-align: right;
}
.cw-res {
width: 4rem;
}
.cw-src {
width: 4.5rem;
}
.cw-hdr {
width: 6rem;
}
.cw-aud {
width: 7.5rem;
}
.cw-size {
width: 4.5rem;
text-align: right;
}
.cw-seed {
width: 3.5rem;
text-align: right;
}
/* §9.3: headers never wrap — the narrow-deck block below sheds columns
instead */
.colhead {
display: flex;
gap: var(--space-1);
padding: var(--space-2) var(--space-1) 0;
}
.colhead .cw {
padding: 0 var(--space-2);
border: 1px solid transparent;
font-family: var(--font-readout);
font-size: var(--text-2xs);
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--ink-faint);
}
.rel {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--space-1) var(--space-2);
padding: var(--space-2) var(--space-1);
border-bottom: 1px solid oklch(from var(--line) l c h / 45%);
}
/* the line is plain content now — grab is its own control */
.rel-line {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--space-1);
}
/* §9.3: the release name is secondary — evidence, not the primary key */
.rel-name {
flex-basis: 100%;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: var(--text-xs);
color: var(--ink-faint);
}
.rel-none {
padding: var(--space-2) var(--space-1);
font-size: var(--text-xs);
border-bottom: 1px solid oklch(from var(--line) l c h / 45%);
}
.rel-note {
font-size: var(--text-xs);
color: var(--ink-muted);
}
.rel-note[data-tone="fault"] {
color: var(--signal-fault);
}
/* score heat: data-score is the list-relative stop, 0 lowest … 6 highest */
.rel-line .cw-score[data-score="0"] {
color: var(--score-0);
border-color: oklch(from var(--score-0) l c h / 45%);
}
.rel-line .cw-score[data-score="1"] {
color: var(--score-1);
border-color: oklch(from var(--score-1) l c h / 45%);
}
.rel-line .cw-score[data-score="2"] {
color: var(--score-2);
border-color: oklch(from var(--score-2) l c h / 45%);
}
.rel-line .cw-score[data-score="3"] {
color: var(--score-3);
border-color: oklch(from var(--score-3) l c h / 45%);
}
.rel-line .cw-score[data-score="4"] {
color: var(--score-4);
border-color: oklch(from var(--score-4) l c h / 45%);
}
.rel-line .cw-score[data-score="5"] {
color: var(--score-5);
border-color: oklch(from var(--score-5) l c h / 45%);
}
.rel-line .cw-score[data-score="6"] {
color: var(--score-6);
border-color: oklch(from var(--score-6) l c h / 45%);
}
/* ---- library view (§4.2) ---------------------------------------------- */
.rail-nav {
flex: none;
}
/* the library's master line: total readout left, the one §4.2 toggle right */
.library-bar {
margin: 0 0 var(--space-6);
}
/* the toggle's own padding would inset its text past the chip column's
right rag; drop it so SATISFIED sits flush with the chips below */
.library-bar .bucket-toggle {
padding: 0;
}
/* ---- attention queues (§5.2 + §5.7) ------------------------------------ */
/* the badge is a signal, not a control: amber attention on the cyan word */
.nav-count {
margin-left: var(--space-2);
font-size: var(--text-xs);
color: var(--signal-warn);
}
.queue-note {
margin: var(--space-2) var(--space-1) 0;
font-size: var(--text-xs);
color: var(--ink-faint);
}
/* like .rel: the line expands to fill, the action is its own control */
.queue-item {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: var(--space-1) var(--space-3);
padding: var(--space-2) var(--space-1);
border-bottom: 1px solid oklch(from var(--line) l c h / 45%);
}
.queue-item .queue-line {
flex: 1;
min-width: 0;
width: auto;
padding: 0;
border-bottom: 0;
}
.queue-empty {
padding: var(--space-2) var(--space-1);
font-size: var(--text-xs);
border-bottom: 1px solid oklch(from var(--line) l c h / 45%);
}
.queue-feedback {
font-size: var(--text-xs);
color: var(--ink-muted);
}
.queue-feedback[data-tone="fault"] {
color: var(--signal-fault);
}
/* ---- manual intake ---------------------------------------------------- */
.intake .module-detail {
overflow-wrap: anywhere;
}
/* ---- small screens --------------------------------------------------- */
@media (max-width: 46rem) {
.rail {
flex-wrap: wrap;
gap: var(--space-3) var(--space-4);
}
.rail-verdict {
flex-basis: 100%;
order: 3;
}
.rail-search {
order: 4;
flex-basis: 100%;
max-width: none;
}
/* deterministic first row: identity, views, then meta pushed right —
never re-wrapped by content or scrollbar changes */
.rail-nav {
order: 2;
}
.rail-meta {
order: 2;
margin-left: auto;
}
.deck {
padding: var(--space-6) var(--space-4) var(--space-8);
}
.row-chips {
margin-left: 0;
flex-basis: 100%;
}
.releases-id {
order: -1;
flex-basis: 100%;
}
/* the line shrinks rather than wrapping, so the grab control never
leaves the row — the release name absorbs the squeeze via ellipsis */
.rel-grab {
margin-left: auto;
}
/* same wrap on a queue entry: the one click drops below its line */
.queue-item .queue-line {
flex-basis: 100%;
}
.queue-allow {
margin-left: auto;
}
.board {
padding: var(--space-6) var(--space-4);
}
.chain {
grid-template-columns: 1fr;
grid-template-areas:
"tmdb"
"prow"
"t1"
"master"
"out"
"sink";
row-gap: var(--space-4);
}
/* one junctioned trace on the stacked chain; the second is redundant */
.area-t2 {
display: none;
}
.bus {
height: 2.25rem;
justify-content: center;
}
.bus svg {
transform: rotate(90deg);
transform-origin: center;
width: 2.25rem;
height: 0.5rem;
}
}
/* ---- narrow deck (§9.3 at phone widths) ------------------------------- */
/* the full seven-column line is 36rem; under 40rem it cannot fit, so hdr
and audio leave the line and the five surviving columns tighten —
aligned, never wrapped, never scrolled */
@media (max-width: 40rem) {
.colhead .cw,
.rel-line .chip {
padding: 0 var(--space-1);
}
.cw-hdr,
.cw-aud {
display: none;
}
.cw-score {
width: 3rem;
}
.cw-res {
width: 3rem;
}
.cw-src {
width: 3.5rem;
}
.cw-size {
width: 3rem;
}
.cw-seed {
width: 2.5rem;
}
}
/* ---- settings (issue #116) -------------------------------------------- */
/* rows follow the queues pattern: line, then an action pair */
.settings-row-actions {
display: flex;
gap: var(--space-2);
margin: var(--space-1) 0 var(--space-2);
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
gap: var(--space-3);
align-items: end;
}
.field {
display: grid;
gap: var(--space-1);
}
.field-label {
font-size: var(--text-2xs);
text-transform: uppercase;
letter-spacing: 0.12em;
}
.form-input {
min-height: 2.25rem;
width: 100%;
padding: 0 var(--space-2);
color: var(--ink);
font-family: var(--font-readout);
font-size: var(--text-xs);
background: var(--ground);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: inset 0 1px var(--lowlight);
caret-color: var(--accent);
transition: border-color 150ms var(--ease-out);
}
.form-input:hover {
border-color: var(--line-strong);
}
.form-input:focus {
border-color: var(--accent);
outline: none;
}
.form-input:disabled {
color: var(--ink-faint);
border-color: var(--line);
}
select.form-input {
appearance: none;
}
.form-input[data-invalid] {
border-color: var(--signal-fault);
}
/* one resolution's size band: label, floor, target, penalty on a line */
.band-line {
display: flex;
align-items: center;
gap: var(--space-2);
}
.band-line .field-label {
width: 3.5rem;
}
.band-num {
width: 4.5rem;
}