/* === 4. Layout shell: body & #app ==================================== */ body { font-family: var(--font-sans); background-color: var(--surface-page); color: var(--content); line-height: 1.5; overflow: hidden; } #app { display: flex; flex-direction: column; height: 100vh; } /* === 4. Layout shell: main =========================================== */ .main { display: flex; flex: 1; overflow: hidden; } /* === 5. Header ========================================================== */ .header { display: flex; justify-content: space-between; align-items: center; padding: var(--gap-peer) var(--gap-section); background-color: var(--surface-overlay); border-bottom: var(--border-width) solid var(--border); -webkit-user-select: none; user-select: none; position: relative; } .header-actions { display: flex; gap: var(--gap-peer); align-items: center; } /* Carries `.field` in the markup: shape is below, fill and inset edge come from the generated layout.css. Width is the only thing that made this a different rule from a form field, and it is all that is left here. */ .search-input { width: 180px; } /* `.search-spinner` and `@keyframes spin` are gone (2026-08-26). They were the only rotation left in this file, and a spinner turns at a rate it invented: it reads as progress on a wait that has none to report. Search here is a local query behind a 300ms debounce, so under rule 4 of wiki `loading-and-progress-standard` there was nothing for it to say. */ .search-input::placeholder { color: var(--content-muted); } /* `.sort-select` is gone: every property it set is `.field` plus the `select.field` cursor, and its `:focus { outline: none }` was killing the generated `.field:focus-visible` ring on the one control that had no ring of its own to replace it with. The call sites carry `.field`. */ /* === 6. Sidebar ======================================================== */ .sidebar { width: 220px; min-width: 220px; background-color: var(--surface-overlay); border-right: var(--border-width) solid var(--border); display: flex; flex-direction: column; overflow-y: auto; scrollbar-gutter: stable; } .sidebar h2 { padding: var(--gap-peer) var(--gap-group); font-size: var(--font-size-sm); font-weight: 700; color: var(--content-muted); text-transform: uppercase; letter-spacing: 0.5px; border-bottom: var(--border-width) solid var(--border); } /* === 7. Items panel ==================================================== */ .items-panel { flex: 1; display: flex; flex-direction: column; overflow-y: auto; background-color: var(--surface-page); } /* `.items-list`, `.plugin-list` and `.sources-list` each wrote `list-style: none` by hand. All three carry `.list` now, which is the generated reset; `.sources-list` keeps its padding and the other two had nothing else to keep. */ /* Article rows: feed items + reading-list bookmarks. Uses the renderRow .row layout (icon / content / actions, flex + gap) plus article appearance + read/unread/selected/pinned state. Replaces the legacy .item-* layout. */ .row--article { padding: var(--gap-peer) var(--gap-section); border-bottom: var(--border-width) solid var(--border); /* 3px, wider than a frame on purpose: this edge is the state marker. */ border-left: 3px solid transparent; cursor: pointer; } .row--article:hover { background-color: var(--surface-overlay); } .row--article.is-unread { border-left-color: var(--danger); background-color: color-mix(in srgb, var(--danger) 6%, var(--surface-page)); } .row--article.is-read { color: var(--content-secondary); } .row--article.is-selected { background-color: var(--surface-sunken); border-left-color: var(--category-four); } .row--article.is-unread.is-selected { border-left-color: var(--danger); background-color: color-mix(in srgb, var(--danger) 12%, var(--surface-page)); } .row--article.is-pinned { border-left-color: var(--action); } .empty-icon { display: flex; justify-content: center; margin-bottom: var(--gap-section); color: var(--content-muted); } .empty-icon svg { width: 2.5rem; height: 2.5rem; } /* Standalone empty-state block. The items/bookmarks empty rows use `
No items