Commit Graph

8 Commits

Author SHA1 Message Date
Ray Slakinski
f9225f0d21 Keep the bottom bar clear of the home indicator (#46)
body is a grid of topbar / main / status / player, and nothing in the page
accounted for a display's own intrusions. Mobile Safari hides that by
insetting the layout viewport to the safe area, so the site was fine in a
browser -- but a full-screen shell, the native app or the site added to an
iOS home screen, hands the page the whole display, and the last row landed
under the home indicator with its seek bar and times half cut off.

viewport-fit=cover asks for the whole screen deliberately, and the bars
along the edges now pay for the insets in padding: the bottom for the
indicator, left and right for the notch in landscape. A browser with its
own chrome reports nought and nothing moves.

The padding has to be longhand, and there is a comment saying so, because
the minifier drops the space between a calc() and the value after it in a
shorthand -- padding:7px calc(12px + var(--safe-r))7px ... -- and a browser
then throws the whole declaration away. The bars lost all their padding,
which moved the item list far enough that the pull-to-refresh browser test
stopped finding it; nothing reported an error, and the page still loaded.
buildStyle now fails the build on a calc() run into its neighbour rather
than trusting it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 19:10:39 -04:00
ad15ae3dfe Glass theme, after Apple's Liquid Glass (#43)
Translucent panels with backdrop-filter blur and saturation over a soft
coloured wash, light and dark, going solid under prefers-reduced-transparency
and prefers-contrast: more. The sticky filter bar and column headings are
frosted, since the list scrolls under them.

Text on a see-through panel lands on whatever the wash is behind it, so the
palette's hex values alone no longer say whether it clears AA. contrast.js
now samples the wash as the browser composites it on three viewport shapes.
It caught the first light palette at 3.7:1 for faint text, and a tinted
selection that failed everywhere; both were changed.

Left out: SVG displacement-map refraction, which Chromium alone applies to a
backdrop and only on fixed-size shapes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 20:45:01 +00:00
768d02c840 Catppuccin, Gruvbox, Solarized and High contrast themes
Each in light and dark. The published palettes missed AA in 19 places,
mostly Solarized and Catppuccin Latte, so each failing colour is moved
the least distance, toward black or white, that clears every pair it is
drawn in. Solarized dark's base0 had to rise to base1 to read on base02,
so its dim sits between base2 and base1 to keep three steps of type.

tests/contrast.js checks every palette against the pairs the page draws,
and a border that matches the ground it sits on. Its first run caught
Classic's links at 3.7:1 on the source list and Modern's faint at 4.3:1
on inputs; both are tuned. A failed toast moves to --panel, since the
error colours are tuned for the page's grounds, not --raise.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:24:56 +00:00
35b57fa997 Settings and the shortcuts list close from the corner
Both have nothing to confirm, so their only button was a lone X at the
foot of the card, below the fold of a long Settings card. A dialog with a
confirm keeps Cancel beside it at the bottom, where the pair belongs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 01:45:02 +00:00
43ffafe7ac A UI pass: contrast in every theme, and a sign-in page that fits
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>
2026-09-19 01:37:21 +00:00
45cbd3a239 The scan spinner takes the unread count's place
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 01:21:49 +00:00
905dfa0b02 A spinner on the feed being checked, not toasts; check only your own feeds
The scan's events reach everyone, so every browser showed "<feed>: N new" and
"Scanning…" toasts, and refreshed, for everyone's feeds. Now a feed's row, and
its folder's, carries a spinner between feed_start and its done, skip or error;
the list refreshes only for the reader's own feeds; the scan toasts are gone, and
"Downloaded" is said only for a file on screen.

"Check every feed" from the web UI sent a scan of every feed on the server.
Command::Fetch takes an optional `feeds` list -- those feeds and the feeds
inside any OPML among them -- and the web fills it with the asker's
subscriptions. The schedule and the CLI send none, meaning every feed.

Closes #37.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 01:17:40 +00:00
aeb686163b A separate admin page: server settings, accounts and the log
/admin, with Server, Accounts and Log sections chosen by the URL's hash. The
server sends the page and /admin.js to admins only (anyone else asking for the
page goes back to the app, and the script is 403), and removes the header's link
to it from everyone else's page rather than hiding it. The API keeps refusing
all of it to non-admins as before.

Settings becomes personal: theme, OPML import and export, and the schedule and
download folder to read. The server fields, the Users dialog and the Log dialog
move out of dialogs.ts into admin.ts.

The CSS moves out of index.html into web/app.css, which both pages load as
/app.css?v=<hash>, served immutable like the scripts. The smoke test checks both
pages.

Closes #19.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 15:28:28 +00:00