/* ========================================================================== RSS Feed Dashboard — "Nightwire" palette -------------------------------------------------------------------------- Thesis: the dashboard has no house colour. One calm ink family carries the whole interface; the only saturated colour belongs to the sources (YouTube / Reddit / RT) and is used strictly as a signal — filter pills, card spines, chips, timestamps, feed health. Rule for every filled state: bright fill, deep ink type. ========================================================================== */ :root { color-scheme: dark; /* Ink ramp — cool indigo-slate, not black */ --bg: #0f1319; --surface: #161b24; --surface-2: #1e242f; --line: #262d3a; --line-2: #3a4351; --ink: #f1f3f7; --ink-soft: #a3adbd; --ink-faint: #828da1; --ink-deep: #0c1015; /* type that sits on a bright fill */ /* Source signals — the only chroma in the UI */ --youtube: #ff3b5c; --reddit: #ff7a2f; --rt: #1fcb93; /* Neutral interactive: the "All" tab, neutral pills, primary action */ --accent: var(--ink); --display: "Space Grotesk", system-ui, sans-serif; --body: "Plus Jakarta Sans", system-ui, -apple-system, sans-serif; --mono: "JetBrains Mono", ui-monospace, monospace; } ::selection { background: var(--ink); color: var(--ink-deep); } /* ---------- Shell ---------- */ .app-body { position: relative; min-height: 100vh; background-color: var(--bg); color: var(--ink); font-family: var(--body); -webkit-font-smoothing: antialiased; } /* One soft wash of panel light from the top edge. No coloured blobs, so the source hues stay the only chroma on screen. */ .app-body::before { content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none; background: radial-gradient(58rem 30rem at 50% -14%, rgba(241, 243, 247, 0.055), transparent 72%); } .site-header, main { position: relative; z-index: 1; } /* ---------- Header ---------- */ .site-header { position: sticky; top: 0; z-index: 20; background: rgba(15, 19, 25, 0.82); border-bottom: 1px solid var(--line); backdrop-filter: saturate(160%) blur(16px); -webkit-backdrop-filter: saturate(160%) blur(16px); } .brand { display: inline-flex; align-items: center; gap: 0.65rem; text-decoration: none; } /* Signal bars: three feeds, ascending strength, one per source hue. */ .brand-mark { width: 30px; height: 26px; border-radius: 9px; border: 1px solid var(--line); background: linear-gradient(var(--youtube), var(--youtube)) 6px bottom / 3px 8px no-repeat, linear-gradient(var(--reddit), var(--reddit)) 12px bottom / 3px 13px no-repeat, linear-gradient(var(--rt), var(--rt)) 18px bottom / 3px 18px no-repeat, var(--surface-2); box-shadow: 0 4px 14px -6px rgba(0, 0, 0, 0.65); } .brand-text { font-family: var(--display); font-weight: 700; font-size: 1.12rem; letter-spacing: -0.01em; color: var(--ink); } .brand-text em { font-style: normal; color: var(--ink-faint); } .header-meta { gap: 0.55rem; font-size: 0.76rem; color: var(--ink-soft); } .header-meta .sep { opacity: 0.4; } /* Desk is live — neutral pulse, so it is never confused with a source. */ .pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--ink); animation: pulse 2.2s ease-out infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(241, 243, 247, 0.32); } 70% { box-shadow: 0 0 0 9px rgba(241, 243, 247, 0); } 100% { box-shadow: 0 0 0 0 rgba(241, 243, 247, 0); } } /* Three wires — one segment per source, page-coloured gaps between them. */ .wire-rail { height: 3px; background: linear-gradient(90deg, var(--youtube) 0, var(--youtube) calc(33.333% - 1px), var(--bg) calc(33.333% - 1px), var(--bg) calc(33.333% + 1px), var(--reddit) calc(33.333% + 1px), var(--reddit) calc(66.666% - 1px), var(--bg) calc(66.666% - 1px), var(--bg) calc(66.666% + 1px), var(--rt) calc(66.666% + 1px)); } /* ---------- Filter pills ---------- */ .filter-pills { gap: 0.5rem; scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; } .filter-pill { --pill: var(--accent); display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.42rem 0.95rem; border-radius: 999px; border: 1px solid var(--line); background: rgba(255, 255, 255, 0.04); color: var(--ink); font-weight: 600; font-size: 0.86rem; text-decoration: none; white-space: nowrap; transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease; } .filter-pill .pill-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pill); transition: background 0.15s ease; } .filter-pill:hover { transform: translateY(-1px); background: rgba(255, 255, 255, 0.07); border-color: var(--line-2); color: var(--ink); } .filter-pill.active { background: var(--pill); border-color: transparent; color: var(--ink-deep); box-shadow: 0 8px 20px -10px color-mix(in srgb, var(--pill) 75%, transparent); } .filter-pill.active .pill-dot { background: currentColor; opacity: 0.8; } .refresh-chip { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.32rem 0.7rem; border-radius: 999px; border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-soft); font-size: 0.72rem; font-weight: 500; } /* ---------- Time range ---------- */ .toolbar-label { font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); padding-right: 0.15rem; } .range-pills { gap: 0.35rem; scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; } .range-pill { display: inline-flex; align-items: center; padding: 0.32rem 0.75rem; border-radius: 999px; border: 1px solid var(--line); background: rgba(255, 255, 255, 0.04); color: var(--ink-soft); font-size: 0.78rem; font-weight: 600; text-decoration: none; white-space: nowrap; transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; } .range-pill:hover { color: var(--ink); border-color: var(--line-2); background: rgba(255, 255, 255, 0.07); transform: translateY(-1px); } .range-pill.active { background: var(--ink); border-color: transparent; color: var(--ink-deep); box-shadow: 0 8px 20px -10px rgba(241, 243, 247, 0.45); } /* ---------- Cards ---------- */ .feed-card { --src: var(--accent); position: relative; border: 1px solid var(--line); border-top: 4px solid var(--src); border-radius: 18px; background: linear-gradient(180deg, color-mix(in srgb, var(--src) 8%, transparent), transparent 34%), var(--surface); overflow: hidden; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), 0 18px 34px -28px rgba(0, 0, 0, 0.9); transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease; } .feed-card:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--src) 32%, var(--line)); box-shadow: 0 22px 44px -24px color-mix(in srgb, var(--src) 45%, transparent), 0 18px 34px -28px rgba(0, 0, 0, 0.9); } .feed-thumb-link { position: relative; display: block; overflow: hidden; background: color-mix(in srgb, var(--src) 16%, var(--surface)); } .feed-thumb-link::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(to top, rgba(9, 11, 15, 0.55), transparent 52%); } .feed-thumb { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; transition: transform 0.4s ease; } .feed-card:hover .feed-thumb { transform: scale(1.06); } .thumb-tag, .source-chip { font-family: var(--mono); font-size: 0.64rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-deep); background: var(--src); } .thumb-tag { position: absolute; left: 0.7rem; bottom: 0.7rem; z-index: 1; padding: 0.24rem 0.6rem; border-radius: 999px; box-shadow: 0 6px 16px -6px rgba(0, 0, 0, 0.7); } .source-chip { display: inline-flex; align-items: center; padding: 0.2rem 0.55rem; border-radius: 999px; } .feed-card .card-body { padding: 1rem 1.1rem 1.1rem; } .feed-name { font-size: 0.68rem; letter-spacing: 0.02em; color: var(--ink-faint); } .feed-card .card-title { font-family: var(--display); font-size: 1.02rem; font-weight: 600; line-height: 1.32; } .feed-card .card-title a { color: var(--ink); text-decoration: none; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; transition: color 0.15s ease; } .feed-card .card-title a:hover { color: var(--src); } .feed-card .card-text { font-size: 0.86rem; line-height: 1.55; color: var(--ink-soft); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } .card-footer-meta { border-top: 1px solid var(--line); } .author { font-size: 0.78rem; color: var(--ink-soft); } .timestamp { font-size: 0.72rem; font-weight: 500; color: color-mix(in srgb, var(--src) 78%, var(--ink)); } .mono { font-family: var(--mono); } /* ---------- Empty state ---------- */ .empty-state { padding: 4.5rem 1rem; color: var(--ink-faint); } /* Same signal-bars mark as the header, unlit — a quiet, static glyph. */ .empty-mark { width: 44px; height: 30px; margin: 0 auto 1rem; background: linear-gradient(var(--youtube), var(--youtube)) 12px bottom / 4px 10px no-repeat, linear-gradient(var(--reddit), var(--reddit)) 19px bottom / 4px 16px no-repeat, linear-gradient(var(--rt), var(--rt)) 26px bottom / 4px 22px no-repeat; opacity: 0.5; } .empty-title { font-family: var(--display); font-size: 1.15rem; color: var(--ink); } /* ---------- Primary action ---------- */ /* The tally light: the brightest thing on the page, so there is never a question about what the primary action is. */ .btn-tally { border: 0; border-radius: 999px; padding: 0.7rem 1.7rem; font-family: var(--display); font-weight: 600; color: var(--ink-deep); background: var(--ink); box-shadow: 0 12px 28px -14px rgba(241, 243, 247, 0.4); transition: transform 0.15s ease, background 0.15s ease, box-shadow 0.15s ease; } .btn-tally:hover, .btn-tally:focus { color: var(--ink-deep); transform: translateY(-2px); background: #ffffff; box-shadow: 0 18px 34px -14px rgba(241, 243, 247, 0.5); } .btn-tally:disabled { opacity: 0.55; transform: none; color: var(--ink-deep); } .alert-soft { border: 1px solid color-mix(in srgb, var(--youtube) 40%, transparent); border-radius: 14px; background: color-mix(in srgb, var(--youtube) 12%, var(--surface)); color: #ffc2ce; } .alert-ok-soft { border: 1px solid color-mix(in srgb, var(--rt) 40%, transparent); border-radius: 14px; background: color-mix(in srgb, var(--rt) 12%, var(--surface)); color: #9beed2; } /* ---------- Manage page ---------- */ .manage-link { display: inline-flex; align-items: center; padding: 0.38rem 0.85rem; border-radius: 999px; border: 1px solid var(--line); background: rgba(255, 255, 255, 0.04); color: var(--ink-soft); font-size: 0.78rem; font-weight: 600; text-decoration: none; white-space: nowrap; transition: color 0.15s ease, border-color 0.15s ease, transform 0.15s ease, background 0.15s ease; } .manage-link:hover { color: var(--ink); border-color: var(--line-2); background: rgba(255, 255, 255, 0.07); transform: translateY(-1px); } .manage-title { font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); } .manage-main { max-width: 920px; } .manage-panel { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; padding: 1.25rem 1.4rem; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), 0 18px 34px -28px rgba(0, 0, 0, 0.9); } .manage-notice { max-width: 560px; margin: 3rem auto; } .manage-login { max-width: 460px; margin: 3rem auto; } .manage-heading { font-family: var(--display); font-size: 1.25rem; font-weight: 700; margin-bottom: 0.5rem; } .manage-subheading { font-family: var(--display); font-size: 1rem; font-weight: 600; margin-bottom: 0.85rem; } .btn-compact { padding: 0.5rem 1.35rem; white-space: nowrap; } .manage-group { margin-bottom: 1.9rem; } .manage-group-title { display: flex; align-items: center; gap: 0.5rem; font-family: var(--display); font-size: 1.02rem; font-weight: 700; margin-bottom: 0.7rem; } .manage-group-title .pill-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--src); } .manage-group-title .count { font-size: 0.68rem; font-weight: 600; color: var(--ink-soft); background: rgba(255, 255, 255, 0.07); padding: 0.12rem 0.5rem; border-radius: 999px; } .feed-rows { display: flex; flex-direction: column; gap: 0.55rem; } .feed-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.6rem 0.9rem; background: var(--surface); border: 1px solid var(--line); border-left: 4px solid var(--src); border-radius: 14px; padding: 0.7rem 1rem; transition: box-shadow 0.15s ease, opacity 0.15s ease; } .feed-row:hover { box-shadow: 0 12px 26px -18px rgba(0, 0, 0, 0.85); } .feed-row.is-off { opacity: 0.55; } .feed-row-main { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem 0.6rem; min-width: 0; flex: 1 1 320px; } .feed-row-label { font-weight: 600; font-size: 0.9rem; } .origin-badge { font-size: 0.6rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-soft); background: rgba(255, 255, 255, 0.07); padding: 0.16rem 0.5rem; border-radius: 999px; } .feed-row-url { font-size: 0.66rem; color: var(--ink-faint); text-decoration: none; max-width: 36ch; } .feed-row-url:hover { color: var(--ink); text-decoration: underline; } .health { display: inline-flex; align-items: center; gap: 0.32rem; font-size: 0.64rem; letter-spacing: 0.03em; white-space: nowrap; } .health-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; } .health-ok { color: var(--rt); } .health-err { color: var(--youtube); } .health-idle { color: var(--ink-faint); } .feed-row-actions { display: flex; align-items: center; gap: 0.45rem; flex-shrink: 0; } .btn-mini { border: 1px solid var(--line-2); border-radius: 999px; background: rgba(255, 255, 255, 0.04); color: var(--ink-soft); font-size: 0.72rem; font-weight: 600; padding: 0.3rem 0.85rem; transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease; } .btn-mini:hover, .btn-mini:focus { color: var(--ink); border-color: var(--ink-faint); background: rgba(255, 255, 255, 0.08); } .btn-mini-on { color: var(--ink); border-color: var(--ink-faint); background: rgba(255, 255, 255, 0.1); } .btn-mini-on:hover, .btn-mini-on:focus { color: var(--ink); border-color: var(--ink-soft); background: rgba(255, 255, 255, 0.14); } .btn-mini-danger:hover, .btn-mini-danger:focus { color: var(--youtube); border-color: color-mix(in srgb, var(--youtube) 55%, transparent); background: color-mix(in srgb, var(--youtube) 12%, transparent); } /* ---------- Form controls ---------- */ .form-control { background: var(--surface-2); border: 1px solid var(--line-2); color: var(--ink); } .form-control::placeholder { color: var(--ink-faint); } .form-control:focus { background: var(--surface-2); border-color: var(--ink-soft); color: var(--ink); box-shadow: 0 0 0 3px rgba(241, 243, 247, 0.12); } code { color: var(--ink); background: rgba(255, 255, 255, 0.06); padding: 0.1rem 0.35rem; border-radius: 6px; } /* ---------- Focus & motion ---------- */ a:focus-visible, button:focus-visible, input:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } }