Measured every theme's palette against WCAG AA. The unread badge's count on its --accent2 fill fell as low as 2.6:1 (Flat Remix light), and the unread dot with it; each theme's --accent2 is taken down until white on it clears 4.5. Tags were --warn or --bad on --raise, short of AA in most light themes, so they are outlined on the row's own ground instead. Nordic dark had --line equal to --panel2, so bordered buttons on a panel2 ground drew no edge at all. Classic's selected row left the row's icon buttons grey on the blue. A zero badge on a selected row was --raise on --raise and vanished. login.html never had a doctype or viewport meta, so it rendered in quirks mode and at desktop width on a phone, and its light palette sat under data-theme="light", which nothing ever set. It follows prefers-color-scheme now, signed out having no account to ask. Dropped the unused log and users icons. The Classic theme's label is now just "Classic". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
860 lines
42 KiB
CSS
860 lines
42 KiB
CSS
/* Inter, served by ipx itself (/inter.woff2) rather than a font CDN, so the page asks nothing of
|
|
anyone else. One variable file covers every weight used here; italics are synthesized. Classic
|
|
keeps Lucida Grande, the 2004 app's face. */
|
|
@font-face{font-family:Inter;src:url(/inter.woff2) format("woff2");font-weight:100 900;font-display:swap}
|
|
/* Palette taken from the 2004 iPodderX icon: the silver device body, the blue
|
|
screen, and the amber EQ bars. Hex values in comments are sampled straight from it. */
|
|
:root {
|
|
--bg:#0e131b; /* the screen's navy (#314B74), taken right down */
|
|
--panel:#151c27;
|
|
--panel2:#1c2431;
|
|
--raise:#25303f;
|
|
--line:#2c3849;
|
|
--fg:#f5f5f5; /* #F5F5F5 device highlight */
|
|
--dim:#95a0b1; /* #95A0B1 straight from the icon's blue-grey */
|
|
--faint:#7a8799; /* lifted from the icon ramp until it clears AA at small sizes */
|
|
--accent:#92b2e6; /* #92B2E6 the screen blue */
|
|
--accent2:#f49e2c; /* #F49E2C the EQ bars */
|
|
--ink:#0e131b; /* text on an accent fill */
|
|
--good:#6fbf8b;
|
|
--warn:#f49e2c; /* the amber doubles as the pending colour */
|
|
--bad:#e2705f;
|
|
--shadow:0 8px 28px rgba(6,10,16,.55);
|
|
}
|
|
/* Every other theme overrides the same variables, under data-theme and data-mode. The page's
|
|
script sets data-mode to light or dark, working Auto out from the system, so each theme has
|
|
one block per variant here and none needs repeating under a media query. */
|
|
:root[data-theme="modern"][data-mode="light"] {
|
|
--bg:#f2f4f7;
|
|
--panel:#ffffff; /* #FFFFFF device body */
|
|
--panel2:#e9edf3;
|
|
--raise:#dde3ec;
|
|
--line:#d6d6d6; /* #D6D6D6 device edge */
|
|
--fg:#1a1a1a; /* #1A1A1A icon outline */
|
|
--dim:#606060; /* #606060 */
|
|
--faint:#6b6b6b; /* between the icon's #929292 and #606060, to clear AA on the page ground */
|
|
--accent:#2d5391; /* #2D5391 the deep screen blue reads better on white */
|
|
--accent2:#985e0a; /* the EQ amber, taken down until white on it clears AA */
|
|
--ink:#ffffff;
|
|
--good:#2f7d4f;
|
|
--warn:#985e0a; /* the same amber; the lighter one failed AA as text */
|
|
--bad:#b3402f;
|
|
--shadow:0 8px 28px rgba(45,83,145,.14);
|
|
}
|
|
/* Dracula, and Alucard, its light half, from draculatheme.com/spec. The spec's comment colour
|
|
(#6272A4, #6C664B) is too faint for small text on its own background, so --faint is lifted. */
|
|
:root[data-theme="dracula"] {
|
|
--bg:#282a36;
|
|
--panel:#21222c;
|
|
--panel2:#343746;
|
|
--raise:#44475a; /* selection */
|
|
--line:#414558;
|
|
--fg:#f8f8f2;
|
|
--dim:#c9cbd6;
|
|
--faint:#9ea8c7;
|
|
--accent:#bd93f9; /* purple */
|
|
--accent2:#ff79c6; /* pink */
|
|
--ink:#282a36;
|
|
--good:#50fa7b;
|
|
--warn:#ffb86c;
|
|
--bad:#ff8080;
|
|
--shadow:0 8px 28px rgba(0,0,0,.45);
|
|
}
|
|
:root[data-theme="dracula"][data-mode="light"] {
|
|
--bg:#fffbeb;
|
|
--panel:#f7f2df;
|
|
--panel2:#efe9d3;
|
|
--raise:#cfcfde; /* selection */
|
|
--line:#ddd6bd;
|
|
--fg:#1f1f1f;
|
|
--dim:#454137;
|
|
--faint:#635d44;
|
|
--accent:#644ac9;
|
|
--accent2:#a3144d;
|
|
--ink:#ffffff;
|
|
--good:#14710a;
|
|
--warn:#a34d14;
|
|
--bad:#b83322;
|
|
--shadow:0 8px 28px rgba(108,102,75,.18);
|
|
}
|
|
/* Material 3's baseline scheme: surface, the surface containers, outline and primary. */
|
|
:root[data-theme="material"] {
|
|
--bg:#141218; /* surface */
|
|
--panel:#1d1b20; /* surface-container-low */
|
|
--panel2:#211f26; /* surface-container */
|
|
--raise:#36343b; /* surface-container-highest */
|
|
--line:#49454f; /* outline-variant */
|
|
--fg:#e6e0e9; /* on-surface */
|
|
--dim:#cac4d0; /* on-surface-variant */
|
|
--faint:#9a95a0; /* outline, a shade up to clear AA on the containers */
|
|
--accent:#d0bcff; /* primary */
|
|
--accent2:#efb8c8; /* tertiary */
|
|
--ink:#381e72; /* on-primary */
|
|
--good:#8fd6a0;
|
|
--warn:#f2c46b;
|
|
--bad:#f2b8b5; /* error */
|
|
--shadow:0 8px 28px rgba(0,0,0,.5);
|
|
}
|
|
:root[data-theme="material"][data-mode="light"] {
|
|
--bg:#fef7ff;
|
|
--panel:#f7f2fa;
|
|
--panel2:#f3edf7;
|
|
--raise:#e6e0e9;
|
|
--line:#cac4d0;
|
|
--fg:#1d1b20;
|
|
--dim:#49454f;
|
|
--faint:#67626c; /* outline (#79747E), a shade down to clear AA on the containers */
|
|
--accent:#6750a4;
|
|
--accent2:#7d5260;
|
|
--ink:#ffffff;
|
|
--good:#2b6c3c;
|
|
--warn:#7c5800;
|
|
--bad:#b3261e;
|
|
--shadow:0 8px 28px rgba(103,80,164,.14);
|
|
}
|
|
/* Adwaita, from libadwaita's own CSS variables: view, window and sidebar backgrounds, the blue
|
|
accent, and its destructive, success and warning colours. */
|
|
:root[data-theme="adwaita"] {
|
|
--bg:#1d1d20; /* view */
|
|
--panel:#2e2e32; /* sidebar, headerbar */
|
|
--panel2:#222226; /* window */
|
|
--raise:#3a3a3f;
|
|
--line:#3f3f45;
|
|
--fg:#ffffff;
|
|
--dim:#c4c4c8;
|
|
--faint:#a0a0a7;
|
|
--accent:#81d0ff;
|
|
--accent2:#3685e4; /* a hair lighter so the badge's dark count clears AA */
|
|
--ink:#1d1d20;
|
|
--good:#78e9ab;
|
|
--warn:#ffc252;
|
|
--bad:#ff938c;
|
|
--shadow:0 8px 28px rgba(0,0,0,.5);
|
|
}
|
|
:root[data-theme="adwaita"][data-mode="light"] {
|
|
--bg:#ffffff;
|
|
--panel:#ebebed;
|
|
--panel2:#fafafb;
|
|
--raise:#dcdce0;
|
|
--line:#d9d9dd;
|
|
--fg:#333338; /* rgb(0 0 6 / 80%) on white */
|
|
--dim:#57575d;
|
|
--faint:#66666c;
|
|
--accent:#0461be;
|
|
--accent2:#1c71d8; /* blue 4, a step down from the accent blue, so white on it clears AA */
|
|
--ink:#ffffff;
|
|
--good:#00753a;
|
|
--warn:#905400;
|
|
--bad:#c30000;
|
|
--shadow:0 8px 28px rgba(0,0,6,.12);
|
|
}
|
|
/* Flat Remix, from its GTK theme's _colors.scss: base and bg, fg, the selection blue, and its
|
|
link colours, which are the selection blue taken down (light) or up (dark) until readable. */
|
|
:root[data-theme="flatremix"] {
|
|
--bg:#272a34; /* base */
|
|
--panel:#23262f; /* bg: base darkened 2% */
|
|
--panel2:#2e323d;
|
|
--raise:#363b48;
|
|
--line:#3a3f4c;
|
|
--fg:#eeeeec;
|
|
--dim:#babec8;
|
|
--faint:#959baa;
|
|
--accent:#8fb6ff; /* link */
|
|
--accent2:#fd7d00; /* warning orange */
|
|
--ink:#1a1c23;
|
|
--good:#4cc28c;
|
|
--warn:#ff9a3c;
|
|
--bad:#ff6b6b;
|
|
--shadow:0 8px 28px rgba(0,0,0,.3);
|
|
}
|
|
:root[data-theme="flatremix"][data-mode="light"] {
|
|
--bg:#fafafa; /* base */
|
|
--panel:#ffffff; /* bg */
|
|
--panel2:#f0f0f1;
|
|
--raise:#e4e5e7;
|
|
--line:#d9d9d9; /* borders: bg darkened 15% */
|
|
--fg:#22252b;
|
|
--dim:#5c616c; /* fg */
|
|
--faint:#686d78;
|
|
--accent:#0060f0; /* link */
|
|
--accent2:#bb5c00; /* the warning orange taken down until white on it clears AA */
|
|
--ink:#ffffff;
|
|
--good:#23794f;
|
|
--warn:#a85400;
|
|
--bad:#d41919;
|
|
--shadow:0 8px 28px rgba(0,0,0,.1);
|
|
}
|
|
/* Paper: a single light palette, black on the colour of paper, colour kept for what matters.
|
|
Its blue and red are taken down a shade to clear AA on that background. */
|
|
:root[data-theme="paper"] {
|
|
--bg:#f2eede;
|
|
--panel:#ebe7d7;
|
|
--panel2:#e4e0d0;
|
|
--raise:#d8d5c7; /* highlight */
|
|
--line:#cdc9b9;
|
|
--fg:#000000;
|
|
--dim:#3d3a33;
|
|
--faint:#5a564c;
|
|
--accent:#1a5fae;
|
|
--accent2:#957100; /* taken down until white on it clears AA */
|
|
--ink:#ffffff;
|
|
--good:#216609;
|
|
--warn:#795a00;
|
|
--bad:#b1331f;
|
|
--shadow:0 8px 28px rgba(0,0,0,.12);
|
|
}
|
|
/* Nordic: the Nord palette. Polar Night for the dark half, Snow Storm for the light, Frost for
|
|
the accent and Aurora for the rest. Aurora red and Frost blue are shifted until they read. */
|
|
:root[data-theme="nordic"] {
|
|
--bg:#2e3440; /* nord0 */
|
|
--panel:#3b4252; /* nord1 */
|
|
--panel2:#434c5e; /* nord2 */
|
|
--raise:#4c566a; /* nord3 */
|
|
--line:#4c566a; /* nord3: nord2 is --panel2, and borders on it vanished */
|
|
--fg:#eceff4; /* nord6 */
|
|
--dim:#d8dee9; /* nord4 */
|
|
--faint:#b4bccb;
|
|
--accent:#93c9d8; /* nord8, a shade up */
|
|
--accent2:#ebcb8b; /* nord13 */
|
|
--ink:#2e3440;
|
|
--good:#b0c99b; /* nord14, a shade up */
|
|
--warn:#ebcb8b;
|
|
--bad:#f2aeb4;
|
|
--shadow:0 8px 28px rgba(0,0,0,.35);
|
|
}
|
|
:root[data-theme="nordic"][data-mode="light"] {
|
|
--bg:#eceff4; /* nord6 */
|
|
--panel:#e5e9f0; /* nord5 */
|
|
--panel2:#d8dee9; /* nord4 */
|
|
--raise:#cdd4e0;
|
|
--line:#c5cedb;
|
|
--fg:#2e3440; /* nord0 */
|
|
--dim:#3b4252; /* nord1 */
|
|
--faint:#4c566a; /* nord3 */
|
|
--accent:#3a5e8a;
|
|
--accent2:#ab644c;
|
|
--ink:#ffffff;
|
|
--good:#446632;
|
|
--warn:#7e590e;
|
|
--bad:#9c3f49;
|
|
--shadow:0 8px 28px rgba(46,52,64,.15);
|
|
}
|
|
/* Classic: the 2004 Mac app. Colours here; the chrome it needs is at the end of the sheet. */
|
|
:root[data-theme="classic"] {
|
|
color-scheme:light;
|
|
--bg:#ffffff;
|
|
--panel:#e7ebf1; /* the source list's pale blue-grey */
|
|
--panel2:#f2f2f2;
|
|
--raise:#d5dce7;
|
|
--line:#a9a9a9;
|
|
--fg:#000000;
|
|
--dim:#444444;
|
|
--faint:#666666;
|
|
--accent:#3875d7; /* Aqua selection blue */
|
|
--accent2:#2a5db0;
|
|
--ink:#ffffff;
|
|
--good:#237a23;
|
|
--warn:#9b5b00;
|
|
--bad:#c42b1c;
|
|
--shadow:0 4px 16px rgba(0,0,0,.28);
|
|
}
|
|
*{box-sizing:border-box}
|
|
/* A rule that sets display beats the UA's [hidden], and several below do. */
|
|
[hidden]{display:none!important}
|
|
html,body{height:100%}
|
|
body{
|
|
margin:0;background:var(--bg);color:var(--fg);
|
|
font:14.5px/1.55 Inter,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
|
|
display:grid;grid-template-rows:auto 1fr auto auto;overflow:hidden;
|
|
/* iOS Safari's address bar collapses and expands without firing a resize, so 100vh is
|
|
measured against whichever state happened to be current -- sized too tall while the bar
|
|
is showing, which puts the topbar (the hamburger included) under Safari's own chrome,
|
|
where a tap never reaches the page. Only a hard refresh reset it, forcing 100vh to be
|
|
recomputed. 100dvh tracks the real visible viewport as the bar moves; the 100vh above is
|
|
the fallback for a browser that does not know dvh. */
|
|
height:100vh;height:100dvh;
|
|
}
|
|
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
|
|
a{color:var(--accent)}
|
|
/* Inset wherever a parent clips its overflow, or the toolbar and the feed list cut the ring off. */
|
|
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
|
.tgroup button:focus-visible,.tgroup a:focus-visible,.feed:focus-visible,.place:focus-visible,.chev:focus-visible{outline-offset:-2px}
|
|
@media (prefers-reduced-motion:reduce){
|
|
*,*::before,*::after{animation:none!important;transition:none!important}
|
|
}
|
|
::-webkit-scrollbar{width:10px;height:10px}
|
|
::-webkit-scrollbar-thumb{background:var(--raise);border-radius:6px}
|
|
::-webkit-scrollbar-track{background:transparent}
|
|
|
|
/* ---------- shell ---------- */
|
|
#shell{display:grid;grid-template-columns:290px 1fr;min-height:0;min-width:0;overflow:hidden}
|
|
/* [ hides the feed list. A phone slides it over the page instead, so this is for wider screens. */
|
|
@media (min-width:821px){
|
|
body.nosb #shell{grid-template-columns:minmax(0,1fr)}
|
|
body.nosb #sidebar{display:none}
|
|
}
|
|
#sidebar{
|
|
background:var(--panel);border-right:1px solid var(--line);
|
|
display:flex;flex-direction:column;min-height:0;
|
|
}
|
|
.brand{display:flex;align-items:center;gap:9px;padding:14px 14px 10px}
|
|
.brand .logo{
|
|
width:30px;height:30px;flex:none;object-fit:contain;
|
|
}
|
|
.brand h1{font-size:16px;margin:0;font-weight:650;letter-spacing:-.01em;color:var(--fg);flex:1}
|
|
.iconbtn{
|
|
width:30px;height:30px;border-radius:8px;display:grid;place-items:center;
|
|
color:var(--dim);flex:none;
|
|
}
|
|
.iconbtn:hover{background:var(--raise);color:var(--fg)}
|
|
/* One toolbar across the window, as the original had: grouped buttons, search on the right. */
|
|
#topbar{
|
|
display:flex;align-items:center;gap:10px;padding:7px 12px;min-width:0;overflow:hidden;
|
|
background:var(--panel);border-bottom:1px solid var(--line);
|
|
}
|
|
#topbar .grow{flex:1}
|
|
#topbar #epSearch{width:260px;flex:none}
|
|
.tgroup{display:flex;flex:none;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:var(--panel2)}
|
|
.tgroup button,.tgroup a{padding:5px 11px;min-width:34px;color:var(--dim);font-size:14px;line-height:1.3}
|
|
.tgroup a{display:inline-grid;place-items:center}
|
|
.tgroup button+button,.tgroup button+a{border-left:1px solid var(--line)}
|
|
.tgroup button:hover:not(:disabled),.tgroup a:hover{background:var(--raise);color:var(--fg)}
|
|
.tgroup button:disabled{opacity:.35;cursor:default}
|
|
.sidetools button,.sidefoot button{
|
|
flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:8px;
|
|
padding:6px 8px;font-size:12.5px;color:var(--dim);
|
|
}
|
|
.sidetools button:hover,.sidefoot button:hover{border-color:var(--accent);color:var(--fg)}
|
|
/* Settings and the log are housekeeping: they sit under the feeds, out of the way. */
|
|
.sidefoot{
|
|
display:flex;flex-direction:column;gap:7px;padding:8px 12px;
|
|
border-top:1px solid var(--line);flex:none;
|
|
}
|
|
.sidefoot .row{display:flex;gap:6px}
|
|
.who{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--faint)}
|
|
.who span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.who button{flex:none;background:none;border:0;padding:2px 4px;color:var(--faint);text-decoration:underline}
|
|
.who button:hover{color:var(--fg)}
|
|
.sidefoot button{display:inline-flex;align-items:center;justify-content:center;gap:6px}
|
|
.sidefoot i{font-style:normal;opacity:.75}
|
|
.searchwrap{padding:0 12px 8px}
|
|
input[type=search],input[type=text],input[type=password],input[type=number],select{
|
|
width:100%;background:var(--bg);border:1px solid var(--line);color:var(--fg);
|
|
border-radius:8px;padding:7px 10px;font:inherit;font-size:13.5px;
|
|
}
|
|
input:focus,select:focus{outline:0;border-color:var(--accent)}
|
|
/* The wider left gutter is the folder triangle's; everything in the list shifts with it, so the
|
|
feeds still line up with the places above. */
|
|
#feedlist{overflow-y:auto;padding:0 8px 12px 16px;flex:1;min-height:0}
|
|
.feed{
|
|
display:flex;gap:10px;align-items:center;padding:7px 8px;border-radius:9px;
|
|
cursor:pointer;margin-bottom:1px;position:relative;
|
|
}
|
|
.feed:hover{background:var(--panel2)}
|
|
.feed.sel{background:var(--raise)}
|
|
/* A show sits under its folder's title, a size down, so an open folder reads as one. */
|
|
.feed.child{margin-left:11px}
|
|
/* Pinned feeds, at the top of the list: a small pin before the name, and a rule under the last. */
|
|
.feed .fpin .i{width:10px;height:10px;margin-right:5px;vertical-align:-1px;color:var(--accent)}
|
|
.feed.lastpin{margin-bottom:9px}
|
|
.feed.lastpin::after{content:"";position:absolute;left:8px;right:8px;bottom:-5px;border-bottom:1px solid var(--line)}
|
|
.feed.child .art{width:28px;height:28px;font-size:11px}
|
|
/* Only a folder has a triangle, hung in the margin so every feed's art lines up with the places
|
|
above it. The button is the row's full height and 24 px wide: a near miss used to open the
|
|
folder's page, and 16 px left the triangle cramped against the art. */
|
|
.chev{
|
|
position:absolute;left:-16px;top:0;bottom:0;width:24px;display:grid;place-items:center;
|
|
border-radius:4px;color:var(--faint);
|
|
}
|
|
.chev:hover{color:var(--fg)}
|
|
.chev.bad,.chev.bad:hover{color:var(--bad)}
|
|
/* A feed being checked: a small spinner in place of its unread count (issue #37). */
|
|
.feed.scanning .badge{display:none}
|
|
.feed.scanning::after{
|
|
content:"";flex:none;width:12px;height:12px;margin:0 6px;border-radius:50%;
|
|
border:2px solid var(--line);border-top-color:var(--accent);animation:ipxspin .8s linear infinite;
|
|
}
|
|
@keyframes ipxspin{to{transform:rotate(360deg)}}
|
|
/* A feed's error mark, in the triangle's place: the same column as every folder's triangle,
|
|
a child's included, which is why it moves left by the child's indent. */
|
|
.ferr{position:absolute;left:-16px;top:0;bottom:0;width:24px;display:grid;place-items:center;color:var(--bad)}
|
|
.ferr .i{width:12px;height:12px}
|
|
.feed.child .ferr{left:-27px}
|
|
.chev .i{width:12px;height:12px;transition:transform .12s}
|
|
.chev[aria-expanded="true"] .i{transform:rotate(90deg)}
|
|
.childlist{display:grid;grid-template-columns:minmax(0,1fr);gap:4px;margin-top:10px}
|
|
.childrow{
|
|
display:flex;gap:10px;align-items:center;padding:7px 9px;border:1px solid var(--line);
|
|
border-radius:9px;cursor:pointer;background:var(--panel);
|
|
}
|
|
.childrow:hover{border-color:var(--accent)}
|
|
.childrow .art{width:32px;height:32px;font-size:12px}
|
|
.childrow .txt{flex:1;min-width:0}
|
|
.childrow .txt b{display:block;font-weight:500;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
/* Currently Listening: how far into each episode you are, as a rail along the foot of its row.
|
|
The one in the player is marked as it is everywhere else, by the amber EQ bars, and its rail
|
|
and time left move as it plays. The rest stay neutral, so that one is what stands out. */
|
|
#listening .childrow{position:relative;overflow:hidden;gap:12px;padding:10px 10px 13px}
|
|
#listening .childrow .art{width:44px;height:44px;font-size:13px}
|
|
#listening .txt b{display:flex;align-items:center;gap:7px}
|
|
#listening .txt b span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
#listening .txt small{display:flex;gap:12px;margin-top:3px;color:var(--faint);font-size:11.5px}
|
|
#listening .txt small .fd{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
#listening .txt small .left{flex:none;color:var(--dim)}
|
|
#listening .childrow:not(.now) .eq{display:none}
|
|
#listening .rail{position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--raise)}
|
|
#listening .rail i{display:block;height:100%;width:0;background:var(--faint);transition:width .25s linear}
|
|
#listening .now{border-color:color-mix(in srgb,var(--accent2) 60%,var(--line))}
|
|
#listening .now .eq,#listening .now .left{color:var(--accent2)}
|
|
#listening .now .rail i{background:var(--accent2)}
|
|
/* Quiet buttons: a filled one on every row outshouted the row that is playing. */
|
|
#listening [data-a=play]{color:var(--accent)}
|
|
#listening [data-a=remove]{color:var(--faint)}
|
|
/* Directory's filters: .tabs for what a feed is, as the item filters are, and chips for what it
|
|
is about. A picked chip is underlined in --accent2, as the download bar and the now-playing EQ
|
|
are; a .badge's fill already means unread in the sidebar. */
|
|
.dirbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-top:4px}
|
|
.dirbar .tabs{flex:none}
|
|
.chips{display:flex;flex-wrap:wrap;gap:2px 6px;flex:1 1 0;min-width:0}
|
|
.chips button{flex:none;padding:4px 6px;font-size:13px;color:var(--dim);white-space:nowrap;border-bottom:2px solid transparent}
|
|
.chips button:hover{color:var(--fg)}
|
|
.chips button[aria-pressed="true"]{color:var(--fg);border-bottom-color:var(--accent2)}
|
|
/* Square cover art, title underneath: podcast art is made to be known at a glance. The subscribe
|
|
button stays visible, since a button that only shows on hover cannot be reached on a phone. */
|
|
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:18px 14px;margin-top:14px}
|
|
.tiles>.hint{grid-column:1/-1}
|
|
.tile{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 2px;align-items:start;cursor:pointer}
|
|
.tile .art{grid-column:1/-1;width:100%;height:auto;aspect-ratio:1;font-size:34px}
|
|
.tile .txt b{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;overflow-wrap:anywhere;font-weight:500;font-size:13px;line-height:1.3}
|
|
.tile .txt small{display:block;color:var(--faint);font-size:11.5px}
|
|
.tile:hover .txt b{color:var(--accent)}
|
|
/* Outlined, not filled: on --raise the warning and error colours fell short of AA in most light
|
|
themes, where on the row's own ground they clear it. */
|
|
.tag{
|
|
font-size:11px;font-weight:600;
|
|
padding:0 4px;border-radius:4px;border:1px solid;color:var(--warn);flex:none;
|
|
}
|
|
.art{
|
|
border-radius:7px;object-fit:cover;background:var(--raise);flex:none;
|
|
display:grid;place-items:center;color:var(--faint);font-weight:600;overflow:hidden;
|
|
}
|
|
/* Initials, tinted by a hash of the name so two "TS" in a row can be told apart. Mixed into the
|
|
page ground, not --raise: that is also the selected row, and a selected tile vanished into it. */
|
|
.art.ini{background:color-mix(in srgb,var(--tint) 24%,var(--bg));color:var(--tint)}
|
|
/* A folder: its first four shows' art, as iTunes built a playlist's from its albums. */
|
|
.art.mosaic{grid-template:1fr 1fr/1fr 1fr;place-items:stretch}
|
|
.art.mosaic img{width:100%;height:100%;min-height:0;object-fit:cover;display:block}
|
|
.feed .art{width:34px;height:34px;font-size:13px}
|
|
.feed .txt{min-width:0;flex:1}
|
|
.feed .txt b{display:block;font-weight:500;font-size:13.5px;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.feed .txt small{display:block;color:var(--faint);font-size:11.5px;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.badge{
|
|
background:var(--accent2);color:var(--ink);border-radius:20px;padding:1px 7px;
|
|
font-size:11px;font-weight:600;flex:none;min-width:26px;text-align:center;
|
|
}
|
|
.badge.zero{background:var(--raise);color:var(--faint)}
|
|
/* A selected row is --raise too, and the zero count's pill vanished into it. */
|
|
.sel .badge.zero{background:var(--bg)}
|
|
/* Counts, sizes and times that change in place should not jiggle the text around them. */
|
|
.badge,.feed small,.childrow small,.tile small,.ep,.fhead .sub,.dmeta,#status,#seekrow{font-variant-numeric:tabular-nums}
|
|
|
|
/* ---------- main ---------- */
|
|
#main{overflow:hidden;min-height:0;min-width:0;display:flex;flex-direction:column}
|
|
.wrap{flex:1;min-height:0;min-width:0;display:flex;flex-direction:column}
|
|
.wrap.plain{overflow-y:auto;padding:18px 22px 40px;display:block}
|
|
#content{display:flex;flex-direction:column;min-height:0;min-width:0;flex:1}
|
|
#content>.fhead,#content>.toolbar{padding-left:20px;padding-right:20px;flex:none}
|
|
#content>.fhead{padding-top:16px}
|
|
|
|
/* Three panes, as the original had: feeds beside, items above, the item below. */
|
|
#split{
|
|
display:grid;flex:1;min-height:0;
|
|
grid-template-columns:minmax(0,1fr) 270px;
|
|
grid-template-rows:minmax(90px,var(--listh,60%)) 7px 1fr;
|
|
grid-template-areas:"list files" "grab grab" "detail detail";
|
|
}
|
|
#list{grid-area:list;overflow:auto;padding:0 14px 10px;overscroll-behavior-y:contain}
|
|
/* Pull-to-refresh's note (gestures.ts). overscroll-behavior keeps the browser's own pull, which
|
|
reloads the page, from starting on top of it. */
|
|
#pulltip{display:flex;align-items:flex-end;justify-content:center;padding-bottom:6px;overflow:hidden;
|
|
font-size:12px;color:var(--faint)}
|
|
/* The selected item's files, beside the list, as the original's Files pane was. */
|
|
#files{grid-area:files;overflow-y:auto;padding:8px 12px;border-left:1px solid var(--line);background:var(--panel)}
|
|
/* Nothing selected, or an item with no files: the list takes the width. */
|
|
#split:has(>#files[hidden]){grid-template-columns:minmax(0,1fr) 0}
|
|
#files .encbox{margin-top:8px}
|
|
#files .empty{padding:24px 0}
|
|
.fhd{font-size:12px;color:var(--faint)}
|
|
#grab{grid-area:grab;cursor:row-resize;background:var(--line)}
|
|
#grab:hover{background:var(--accent)}
|
|
#detail{grid-area:detail;overflow-y:auto;padding:16px 20px 28px;background:var(--panel);border-top:1px solid var(--line)}
|
|
.dt{font-size:18px;font-weight:650;margin:0 0 5px;line-height:1.3;overflow-wrap:anywhere}
|
|
.dmeta{color:var(--faint);font-size:12.5px;display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
|
|
.dmeta .btn{padding:3px 9px;font-size:12px}
|
|
#detail .encbox{margin:0 0 10px}
|
|
.dbody{font-size:14.5px;line-height:1.65;overflow-wrap:anywhere;color:var(--fg)}
|
|
.dbody img{max-width:100%;height:auto;border-radius:6px}
|
|
.dbody a{color:var(--accent)}
|
|
.dbody pre{overflow-x:auto;background:var(--panel2);padding:10px;border-radius:8px}
|
|
.encbox{
|
|
display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:14px;
|
|
padding:10px 12px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);
|
|
}
|
|
.fhead{display:flex;gap:18px;margin-bottom:18px}
|
|
.fhead .art{width:118px;height:118px;font-size:34px;box-shadow:var(--shadow)}
|
|
.fhead .meta{min-width:0;flex:1;display:flex;flex-direction:column}
|
|
.fhead h2{margin:0 0 3px;font-size:23px;line-height:1.2;overflow-wrap:anywhere}
|
|
.fhead .sub{color:var(--dim);font-size:13px;margin-bottom:8px}
|
|
.fhead .sub a{color:var(--dim);text-decoration:none}
|
|
.fhead .sub a:hover{color:var(--accent)}
|
|
.acts{display:flex;gap:7px;flex-wrap:wrap;align-items:center;margin-top:auto}
|
|
.acts .btn{display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border-radius:999px}
|
|
.acts .btn i{font-style:normal;font-size:13px;line-height:1;opacity:.7}
|
|
.acts .btn.primary i{opacity:.9}
|
|
.acts .btn:hover{background:var(--raise)}
|
|
.acts .btn.primary:hover{background:var(--accent)}
|
|
.btn{
|
|
background:var(--panel2);border:1px solid var(--line);border-radius:8px;
|
|
padding:6px 12px;font-size:13px;
|
|
}
|
|
.btn:hover{border-color:var(--accent)}
|
|
a.btn{text-decoration:none;color:inherit}
|
|
.btn.primary{background:var(--accent);border-color:var(--accent);color:var(--ink);font-weight:600}
|
|
.btn.primary:hover{filter:brightness(1.08)}
|
|
.btn.danger:hover{border-color:var(--bad);color:var(--bad)}
|
|
/* An icon in place of a word; the word is in its tooltip. */
|
|
.btn.ico{padding:4px 9px;min-width:32px;font-size:14px;line-height:1.25;text-align:center}
|
|
/* Inline in a sentence, next to a plain-word error explanation. */
|
|
.btn.tiny{padding:2px 7px;font-size:11.5px;border-radius:6px;margin-left:2px}
|
|
/* The keys ? lists. */
|
|
.keys{border-collapse:collapse;width:100%;font-size:13px}
|
|
.keys th{text-align:left;font-weight:600;padding:12px 0 4px;color:var(--fg)}
|
|
.keys td{padding:3px 0;color:var(--dim)}
|
|
.keys td:first-child{width:10em;white-space:nowrap}
|
|
kbd{font:inherit;font-size:12px;color:var(--fg);background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:0 5px}
|
|
/* An icon (Font Awesome, embedded as SVG) in the button's own colour. */
|
|
.i{display:inline-block;width:16px;height:16px;vertical-align:-3px;flex:none;fill:currentColor}
|
|
/* A file's type as an icon, in place of the old DOWNLOADED / PENDING / audio chips: green once
|
|
it is here, red when the download failed. */
|
|
.kind{display:inline-grid;place-items:center;color:var(--dim)}
|
|
.kind.here{color:var(--good)}
|
|
.subbed{display:inline-flex;padding:0 9px;color:var(--good)}
|
|
.subbed .i{width:18px;height:18px}
|
|
.kind.bad{color:var(--bad)}
|
|
.fhead .art .i{width:22px;height:22px}
|
|
.toolbar{
|
|
display:flex;gap:10px;align-items:center;margin-bottom:12px;flex-wrap:wrap;
|
|
position:sticky;top:0;background:var(--bg);padding:6px 0 8px;z-index:3;
|
|
}
|
|
.tabs{display:flex;gap:2px;background:var(--panel2);border-radius:9px;padding:3px}
|
|
.tabs button{padding:5px 12px;border-radius:7px;font-size:13px;color:var(--dim)}
|
|
.tabs button.on{background:var(--raise);color:var(--fg);font-weight:500}
|
|
.tabs a{padding:5px 12px;border-radius:7px;font-size:13px;color:var(--dim);text-decoration:none}
|
|
.tabs a.on{background:var(--raise);color:var(--fg);font-weight:500}
|
|
|
|
/* ---------- the admin page (admin.html) ---------- */
|
|
/* One column that scrolls under the same header, rather than the app's fixed panes. */
|
|
body.adminpage{display:block;overflow:auto}
|
|
body.adminpage #topbar{position:sticky;top:0;z-index:5}
|
|
body.adminpage #topbar h1{font-size:16px;margin:0;font-weight:650}
|
|
body.adminpage #topbar .logo{border-radius:5px}
|
|
body.adminpage #topbar > a.btn{text-decoration:none}
|
|
body.adminpage #admin{max-width:780px;margin:0 auto}
|
|
body.adminpage #admin h2{font-size:18px;margin:0 0 12px}
|
|
body.adminpage #log{max-width:none}
|
|
.urow{padding:9px 0;border-bottom:1px solid var(--line)}
|
|
.toolbar .grow{flex:1;min-width:150px;max-width:320px}
|
|
|
|
/* ---------- items ---------- */
|
|
/* A table, as the original's was: unread, kept, title, feed, file, size, published. */
|
|
.ephead,.ep{
|
|
display:grid;gap:8px;align-items:center;
|
|
grid-template-columns:22px 22px minmax(120px,1fr) minmax(0,160px) 56px minmax(0,72px) minmax(0,92px) 64px;
|
|
}
|
|
/* A pixel more side padding than a row's: a row has a 1px border the heading has not, and without
|
|
it every heading sat a pixel left of its column. */
|
|
.ephead{
|
|
position:sticky;top:0;z-index:2;background:var(--bg);padding:7px 11px 5px;
|
|
border-bottom:1px solid var(--line);margin-bottom:3px;
|
|
font-size:12px;color:var(--faint);
|
|
}
|
|
/* Each heading sorts by its column; the caret says which way. */
|
|
.ephead .hs{display:flex;align-items:center;gap:4px;min-width:0;padding:0;border:0;background:none;
|
|
font:inherit;color:inherit;text-transform:inherit;letter-spacing:inherit;text-align:left;cursor:pointer}
|
|
.ephead .hs:hover,.ephead .hs.on{color:var(--fg)}
|
|
.ephead .hs .arr{display:inline-flex}
|
|
.ephead .hs .arr .i{width:8px;height:8px}
|
|
.ephead .hs .arr.asc{transform:rotate(-90deg)}
|
|
.ephead .hs .arr.desc{transform:rotate(90deg)}
|
|
/* An icon heading is centred over its column, as the icons under it are, and its caret hangs
|
|
outside so sorting by it does not push the icon off line. */
|
|
.ephead .hs.h-ic{justify-content:center;position:relative;width:100%}
|
|
.ephead .hs.h-ic .arr{position:absolute;left:100%}
|
|
.ep{padding:4px 10px;border-radius:7px;border:1px solid transparent;cursor:pointer;margin-bottom:1px}
|
|
.ep>*{min-width:0}
|
|
.ep.sel{background:var(--raise);border-color:var(--line)}
|
|
.ep:hover{background:var(--panel)}
|
|
/* Amber means new: the unread dot, the badges and a download under way. Blue is for the one
|
|
primary action and links, so a count no longer looks like a button. */
|
|
/* No padding: a button keeps the browser's side padding, which left too little room for the 16px
|
|
icon, so it spilled 3px right of centre and off line with its heading. */
|
|
.ep .st,.ep .fl{width:22px;height:22px;padding:0;border-radius:5px;display:grid;place-items:center;font-size:11px;color:var(--accent2)}
|
|
.ep .fl{color:var(--faint);font-size:13px}
|
|
.ep .fl.on{color:var(--fg)}
|
|
/* The icon's EQ bars mark what is playing: standing still, and moving only while it plays. A
|
|
paused animation was tried first; the frames it held were a pixel apart and read as dots. */
|
|
.eq{display:inline-flex;align-items:flex-end;gap:2px;width:13px;height:12px;flex:none}
|
|
.eq i{flex:1;height:100%;background:currentColor;border-radius:1px;transform-origin:bottom}
|
|
.eq i:nth-child(1){height:60%}
|
|
.eq i:nth-child(3){height:40%}
|
|
body.playing .eq i{animation:eq .9s ease-in-out infinite alternate}
|
|
body.playing .eq i:nth-child(1){animation-delay:-.3s}
|
|
body.playing .eq i:nth-child(3){animation-delay:-.6s}
|
|
@keyframes eq{from{transform:scaleY(.35)}}
|
|
.ep .st:hover,.ep .fl:hover{background:var(--raise)}
|
|
.ep .t{font-weight:600;font-size:13.5px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.ep.read .t{color:var(--dim);font-weight:500}
|
|
.ep .line{display:flex;gap:9px;align-items:center;flex-wrap:wrap;color:var(--faint);font-size:11.5px}
|
|
.ep .line:empty{display:none}
|
|
.ep .fd,.ep .size,.ep .date{color:var(--dim);font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
.ep .file{display:flex;gap:6px;align-items:center;position:relative;color:var(--faint);font-size:11.5px}
|
|
/* Under the icon, not beside it or on a line of its own: taking a line, it lifted the icon of
|
|
every file not yet downloaded above the downloaded ones' (issue #31). */
|
|
.ep .file .dlbar{position:absolute;left:0;right:0;bottom:-5px;margin:0}
|
|
.ep .rowacts{justify-content:flex-end}
|
|
/* One feed's own table has no need of a Feed column; All Subscriptions does. */
|
|
#split.one .ephead,#split.one .ep{grid-template-columns:22px 22px minmax(120px,1fr) 56px minmax(0,72px) minmax(0,92px) 64px}
|
|
#split.one .h-fd,#split.one .ep .fd{display:none}
|
|
.dot{width:3px;height:3px;border-radius:50%;background:var(--faint);flex:none}
|
|
.ep .rowacts{display:flex;gap:2px;align-items:flex-start;opacity:0;transition:opacity .12s}
|
|
.ep:hover .rowacts{opacity:1}
|
|
.dlbar{height:3px;background:transparent;border-radius:2px;overflow:hidden;margin-top:7px}
|
|
.dlbar.live{background:var(--raise)}
|
|
.dlbar i{display:block;height:100%;width:0;background:var(--accent2);transition:width .25s}
|
|
.empty{color:var(--faint);text-align:center;padding:50px 0}
|
|
#more{display:block;width:100%;margin-top:10px}
|
|
|
|
/* ---------- player ---------- */
|
|
#player{
|
|
border-top:1px solid var(--line);background:var(--panel);
|
|
display:none;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;
|
|
padding:9px 16px;box-shadow:0 -6px 24px rgba(6,10,16,.4);
|
|
}
|
|
#player.on{display:grid}
|
|
/* #audio is a <video> playing double duty as the audio element (see its tag). Only a video
|
|
file needs to be seen, floated above the bar rather than laid into it, so an audio episode's
|
|
layout is unchanged. */
|
|
#audio{display:none}
|
|
body.has-video #audio{
|
|
display:block;position:fixed;z-index:45;right:16px;bottom:120px;
|
|
width:360px;max-width:calc(100vw - 32px);aspect-ratio:16/9;background:#000;
|
|
border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,.5);
|
|
}
|
|
#pnow{display:flex;gap:11px;align-items:center;min-width:0;width:250px}
|
|
#pnow .art{width:44px;height:44px;font-size:13px}
|
|
#pnow .txt{min-width:0}
|
|
#pnow b{display:block;font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
#pnow .eq{color:var(--accent2);margin-right:6px}
|
|
#pnow small{color:var(--faint);font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
|
|
#pmid{display:flex;flex-direction:column;gap:3px;min-width:0}
|
|
#pbtns{display:flex;gap:5px;align-items:center;justify-content:center}
|
|
#pbtns .iconbtn{width:34px;height:34px}
|
|
#pplay{
|
|
width:40px!important;height:40px!important;background:var(--fg);color:var(--bg);
|
|
border-radius:50%;
|
|
}
|
|
#pplay:hover{background:var(--accent);color:var(--ink)}
|
|
#seekrow{display:flex;gap:9px;align-items:center;font-variant-numeric:tabular-nums;font-size:11.5px;color:var(--faint)}
|
|
input[type=range]{
|
|
-webkit-appearance:none;appearance:none;height:4px;border-radius:3px;flex:1;
|
|
background:var(--raise);cursor:pointer;
|
|
}
|
|
input[type=range]::-webkit-slider-thumb{
|
|
-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--accent);
|
|
}
|
|
input[type=range]::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--accent)}
|
|
#pright{display:flex;gap:8px;align-items:center}
|
|
#pright select{width:auto;padding:4px 6px;font-size:12px}
|
|
#vol{width:78px;flex:none}
|
|
|
|
/* ---------- overlays ---------- */
|
|
#modal{
|
|
position:fixed;inset:0;background:rgba(0,0,0,.6);display:none;
|
|
place-items:center;z-index:50;padding:20px;
|
|
}
|
|
#modal.on{display:grid}
|
|
.card{
|
|
background:var(--panel);border:1px solid var(--line);border-radius:14px;
|
|
padding:20px;width:min(460px,100%);box-shadow:var(--shadow);max-height:88vh;overflow:auto;
|
|
}
|
|
.card.wide{width:min(1000px,100%)}
|
|
#logbox{
|
|
background:var(--bg);border:1px solid var(--line);border-radius:9px;padding:10px 12px;
|
|
height:min(60vh,520px);overflow:auto;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;
|
|
}
|
|
#logbox .l{display:flex;gap:9px;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
#logbox time{color:var(--faint);flex:none}
|
|
#logbox .lv{flex:none;width:42px;font-weight:700}
|
|
#logbox .lv.ERROR{color:var(--bad)} #logbox .lv.WARN{color:var(--warn)}
|
|
#logbox .lv.INFO{color:var(--accent)} #logbox .lv.DEBUG,#logbox .lv.TRACE{color:var(--faint)}
|
|
#logbox .tg{color:var(--faint);flex:none}
|
|
.logbar{display:flex;gap:8px;align-items:center;margin-bottom:9px;flex-wrap:wrap}
|
|
.logbar .grow{flex:1;min-width:120px}
|
|
.card h3{margin:0 0 14px;font-size:17px}
|
|
.field{display:grid;gap:4px;margin-bottom:12px}
|
|
.field label{font-size:12px;color:var(--dim)}
|
|
.field .hint{font-size:11.5px;color:var(--faint)}
|
|
.check{display:flex;gap:8px;align-items:center;font-size:13.5px;margin-bottom:9px}
|
|
.inline{display:flex;gap:6px;align-items:stretch}
|
|
.inline input{flex:1;min-width:0}
|
|
.inline .btn{white-space:nowrap;flex:none}
|
|
.inline select{flex:none;width:auto}
|
|
.inline input[type=number]{flex:none;width:90px}
|
|
.check input{width:16px;height:16px;accent-color:var(--accent)}
|
|
.cardacts{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}
|
|
#toasts{position:fixed;bottom:88px;right:18px;display:flex;flex-direction:column;gap:8px;z-index:60}
|
|
.toast{
|
|
background:var(--raise);border:1px solid var(--line);border-radius:9px;
|
|
padding:9px 13px;font-size:13px;box-shadow:var(--shadow);animation:in .18s;max-width:340px;
|
|
}
|
|
.toast.bad{border-color:var(--bad);color:var(--bad)}
|
|
@keyframes in{from{opacity:0;transform:translateY(6px)}}
|
|
#burger,#dback{display:none}
|
|
/* Totals for what is showing, along the bottom, as the original's status bar. */
|
|
#status{
|
|
padding:3px 14px;min-height:22px;font-size:12px;color:var(--faint);background:var(--panel);
|
|
border-top:1px solid var(--line);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
|
|
}
|
|
/* The feed's own header, kept to one line so the table starts high, as it did. */
|
|
.fhead.slim{align-items:center;gap:8px 12px;margin-bottom:10px;flex-wrap:wrap}
|
|
.fhead.slim .art{width:44px;height:44px;font-size:15px;box-shadow:none}
|
|
.fhead.slim .meta{flex:1 1 260px}
|
|
/* One line each, or a long title wraps to three and pushes the table down. */
|
|
.fhead.slim h2,.fhead.slim .sub.stat{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
.fhead.slim h2{font-size:17px}
|
|
.fhead.slim .sub{margin-bottom:0;font-size:12.5px}
|
|
.fhead.slim .acts{margin-top:0;flex:none}
|
|
.fhead.slim .acts .btn{padding:5px 11px;font-size:12.5px}
|
|
/* Places above the feeds: not subscriptions, but where to look. */
|
|
.places{border-bottom:1px solid var(--line);margin:0 0 6px;padding-bottom:6px}
|
|
.place{display:flex;gap:10px;align-items:center;padding:6px 8px;border-radius:9px;cursor:pointer}
|
|
.place:hover{background:var(--panel2)}
|
|
.place.sel{background:var(--raise)}
|
|
.place .ico{width:18px;text-align:center;color:var(--accent);flex:none}
|
|
.place b{flex:1;font-weight:500;font-size:13.5px}
|
|
|
|
@media (max-width:820px){
|
|
#shell{grid-template-columns:1fr}
|
|
#sidebar{position:fixed;inset:0 auto 0 0;width:min(300px,86vw);z-index:42;transform:translateX(-100%);transition:transform .2s;box-shadow:var(--shadow)}
|
|
#sidebar.open{transform:none}
|
|
#scrim{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:41}
|
|
#player{position:relative;z-index:39;padding:7px 10px;gap:8px}
|
|
|
|
/* The feed list is reachable whether or not anything is playing. */
|
|
#burger{display:grid}
|
|
#topbar{gap:6px;padding:6px 8px}
|
|
#topbar .grow,.tgroup.item{display:none}
|
|
#topbar #epSearch{width:auto;flex:1;min-width:0}
|
|
.tgroup button,.tgroup a{padding:4px 8px;min-width:32px}
|
|
.fhead.slim .acts{flex:1 1 100%}
|
|
.iconbtn{width:38px;height:38px}
|
|
|
|
/* One pane at a time: the list, then the item over it. */
|
|
#split{grid-template-columns:1fr;grid-template-rows:1fr;grid-template-areas:"list"}
|
|
/* Title and date only; the files sit above the item's text in the reader instead. */
|
|
#files,.ephead,.ep .fd,.ep .file,.ep .size,.ep .rowacts{display:none}
|
|
.ep,#split.one .ep{grid-template-columns:20px 20px minmax(0,1fr) auto}
|
|
#grab{display:none}
|
|
#detail{position:fixed;inset:0;z-index:38;display:none;border-top:0;padding:12px 16px 90px}
|
|
body.reading #detail{display:block}
|
|
#dback{display:inline-block;margin-bottom:10px}
|
|
|
|
#content>.fhead,#content>.toolbar{padding-left:14px;padding-right:14px}
|
|
#content>.fhead{padding-top:12px}
|
|
.fhead{gap:12px;margin-bottom:12px}
|
|
.fhead .art{width:64px;height:64px;font-size:20px}
|
|
.fhead h2{font-size:18px}
|
|
.fhead .sub{font-size:12px;margin-bottom:6px}
|
|
.acts{gap:6px}
|
|
.acts .btn{padding:7px 10px;font-size:12.5px}
|
|
.toolbar{gap:8px}
|
|
#list{padding:0 12px 10px}
|
|
#player{grid-template-columns:1fr auto;grid-template-areas:"now right" "mid mid";gap:2px 8px}
|
|
#pnow{grid-area:now;width:auto}
|
|
#pright{grid-area:right}
|
|
#pmid{grid-area:mid}
|
|
#pnow .art{width:38px;height:38px}
|
|
#pnow .txt small,#pright #vol{display:none}
|
|
.wrap.plain{padding:14px}
|
|
.card{padding:16px}
|
|
/* The chips get a line of their own and scroll sideways rather than wrap, so they never push
|
|
the grid down. */
|
|
.chips{flex:1 1 100%;flex-wrap:nowrap;overflow-x:auto}
|
|
.tiles{grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:14px 10px}
|
|
|
|
/* A log line has no room for four columns: keep time and message, wrap as prose. */
|
|
#logbox{font-size:11.5px;padding:8px}
|
|
#logbox .l{flex-wrap:wrap;gap:6px}
|
|
#logbox .lv{width:auto}
|
|
#logbox .tg{display:none}
|
|
}
|
|
|
|
/* ---------- Classic: the 2004 Mac app ---------- */
|
|
/* After the iPodderX screenshots: brushed-metal chrome, a pale blue-grey source list, Aqua blue
|
|
for whatever is selected, red unread badges, a striped table and Lucida Grande. */
|
|
:root[data-theme="classic"] body{
|
|
font-family:"Lucida Grande","Lucida Sans Unicode","Lucida Sans",Geneva,Verdana,sans-serif;font-size:13px;
|
|
}
|
|
:root[data-theme="classic"] #topbar,
|
|
:root[data-theme="classic"] #status,
|
|
:root[data-theme="classic"] #player{background:linear-gradient(#ececec,#c9c9c9);border-color:#8e8e8e;color:#1a1a1a}
|
|
:root[data-theme="classic"] #status{text-align:center}
|
|
:root[data-theme="classic"] #sidebar{background:#e7ebf1;border-right-color:#a3a3a3}
|
|
:root[data-theme="classic"] #files{background:#f4f4f4}
|
|
:root[data-theme="classic"] .tgroup{background:none;border-color:#8e8e8e;border-radius:6px}
|
|
:root[data-theme="classic"] .tgroup button+button,:root[data-theme="classic"] .tgroup button+a{border-left-color:#8e8e8e}
|
|
:root[data-theme="classic"] .tgroup button,
|
|
:root[data-theme="classic"] .tgroup a,
|
|
:root[data-theme="classic"] .btn,
|
|
:root[data-theme="classic"] .tabs{background:linear-gradient(#ffffff,#d9d9d9);border-color:#8e8e8e;color:#1a1a1a}
|
|
:root[data-theme="classic"] .tabs{border:1px solid #8e8e8e;border-radius:6px}
|
|
:root[data-theme="classic"] .tgroup button:hover:not(:disabled),
|
|
:root[data-theme="classic"] .tgroup a:hover,
|
|
:root[data-theme="classic"] .btn:hover{background:linear-gradient(#f5f9ff,#cbdbf4)}
|
|
:root[data-theme="classic"] .btn.primary,
|
|
:root[data-theme="classic"] .tabs button.on,
|
|
:root[data-theme="classic"] .feed.sel,
|
|
:root[data-theme="classic"] .place.sel{background:linear-gradient(#86b0ec,#3a73cf);border-color:#2d5eae;color:#fff}
|
|
:root[data-theme="classic"] .feed.sel .txt small,
|
|
:root[data-theme="classic"] .place.sel .ico{color:#e6eeff}
|
|
:root[data-theme="classic"] #epSearch{border-radius:14px}
|
|
:root[data-theme="classic"] .badge{background:#c9302c;color:#fff}
|
|
:root[data-theme="classic"] .badge.zero{background:#b4bdc9;color:#fff}
|
|
:root[data-theme="classic"] .ephead,
|
|
:root[data-theme="classic"] .fhd{
|
|
background:linear-gradient(#fbfbfb,#dcdcdc);color:#1a1a1a;font-size:11px;
|
|
}
|
|
:root[data-theme="classic"] .fhd{padding:3px 6px;border:1px solid #c2c2c2}
|
|
:root[data-theme="classic"] .ephead{border-bottom-color:#a3a3a3}
|
|
:root[data-theme="classic"] .ep{border-radius:0;margin:0}
|
|
:root[data-theme="classic"] #eps .ep:nth-child(even){background:#edf3fe}
|
|
:root[data-theme="classic"] .ep .t{color:#1c4fa8}
|
|
:root[data-theme="classic"] .ep.read .t{color:#333}
|
|
:root[data-theme="classic"] #eps .ep.sel{background:#3875d7;border-color:#3875d7}
|
|
:root[data-theme="classic"] .ep.sel .t,
|
|
:root[data-theme="classic"] .ep.sel .fd,
|
|
:root[data-theme="classic"] .ep.sel .size,
|
|
:root[data-theme="classic"] .ep.sel .date,
|
|
:root[data-theme="classic"] .ep.sel .line,
|
|
:root[data-theme="classic"] .ep.sel .st,
|
|
:root[data-theme="classic"] .ep.sel .fl,
|
|
:root[data-theme="classic"] .ep.sel .file,
|
|
:root[data-theme="classic"] .ep.sel .kind,
|
|
:root[data-theme="classic"] .ep.sel .iconbtn:not(:hover){color:#fff}
|
|
/* Green and red stay green and red on the blue, just lighter so they read. */
|
|
:root[data-theme="classic"] .ep.sel .kind.here{color:#a6f3a6}
|
|
:root[data-theme="classic"] .ep.sel .kind.bad{color:#ffb8ad}
|
|
/* Lists were white in the original; the pale blue-grey belongs to the source list alone. */
|
|
:root[data-theme="classic"] .childrow{background:#fff}
|
|
:root[data-theme="classic"] .dt{background:linear-gradient(#80aae6,#3f78cf);color:#fff;padding:6px 12px;border-radius:4px}
|