Handoff: correct CSS-token convention; refresh Current state for 0.2.161

- Conventions: inline styles are now var()-ified (Phase 2), and the
  SHARE_PAGE_* export is pure literal hex with no :root (corrects the
  prior "three surfaces each carry a :root copy" claim). Records the
  CSS-value-position scoping rule for future sweeps.
- Current state: tighten the design-system entry to a snapshot now that
  detail lives in Conventions + ROADMAP.
This commit is contained in:
Keysat
2026-06-17 10:57:26 -05:00
parent 64f3e6628e
commit f2188fa797
+2 -2
View File
@@ -94,7 +94,7 @@ vendor/keysat-licensing-client/ local-link Keysat SDK
- **`recaps.cc` IS the operator's StartOS box**, served via Start9 Pages + StartTunnel. So `make install` (after a version bump) updates the public cloud site automatically — there is no separate cloud deploy step. A frontend-only change reaches recaps.cc as soon as the box serves the new `public/` files.
- **`render()` rebuilds the whole view via `innerHTML` — preserve live media + scroll across it.** It re-attaches the live podcast `<audio>` node (`replaceWith`, src-matched) and restores `.chunks-scroll` scrollTop, so a background re-render (e.g. the ~60s relay-credit poll) doesn't stop playback or bounce the reader to the top. YouTube minimize toggles the `.results-left.minimized` CSS class **in place** — never `render()`, because creating the YT iframe inside a `display:none` container wedges the IFrame API (black frame, needs reload); `ensureYtMounted()` + a `!state.videoMinimized` guard on `needsMount` keep the player from ever being built hidden, and `initPodcastPlayer()` is idempotent (`dataset.inited`). Don't reintroduce a full `render()` on minimize or drop these preservation steps.
- **URL parsing is duplicated server + client — edit both in lockstep.** `extractVideoId` (and the sibling classifiers `isChannelUrl` / `isPodcastUrl`) live in BOTH `server/util.js` and `public/index.html` with the same logic; the server copy is the one that actually rejects a submit (`server/index.js` → "Invalid YouTube URL"). When you teach one a new URL form, teach the other or the frontend preview and server will disagree. `extractVideoId` accepts `/watch?v=`, `youtu.be/`, `/embed/`, `/v/`, `/live/`, `/shorts/`, and a bare 11-char id; trailing `?si=…` tracking params are fine (the regex stops after the id). Tests: `server/test/util.test.js`.
- **Colors flow from CSS custom properties — edit the token, not the value.** `public/index.html`'s `<style>` opens with a `:root` token block (the single source of truth, mirroring `design/tokens.tokens.json`); the stylesheet references `var(--accent)` / `var(--surface)` / etc. Change a brand color there, once. **Three surfaces each carry their own `:root` copy and must stay in sync:** the main stylesheet, the `SHARE_PAGE_CSS` export string, and `public/auth.html` (standalone documents can't see each other's `:root`). Caveat: the long tail of inline `style=` attributes still hardcodes hex (Phase 2 in `ROADMAP.md`), and a few spots **cannot** take `var()` — the `<meta theme-color>`, SVG `fill`/`stroke` set via JS, and hex used in JS *logic* — so don't blind-sweep them.
- **Colors flow from CSS custom properties — edit the token, not the value.** `public/index.html`'s `<style>` opens with a `:root` token block (the single source of truth, mirroring `design/tokens.tokens.json`); the stylesheet **and the inline `style=` attributes** (var-ified in Phase 2) reference `var(--accent)` / `var(--surface)` / etc. Change a brand color there, once. **Two surfaces use `:root`+`var()` and must stay in sync:** the main stylesheet and `public/auth.html` (a standalone doc with its own `:root` copy). **The `SHARE_PAGE_*` share export is the exception** — a standalone document with **no `:root`**, so it's **pure literal hex**; a token change must be hand-mirrored into its literal values, and you must NOT introduce `var()` there (it won't resolve). **Left literal on purpose even in the main doc (don't blind-sweep):** `#fff`, hexes with no token, hex in JS *logic* (quoted ternary branches, `const c=…`), SVG `fill`/`stroke`, and `<meta theme-color>`. Phase 2 var-ified everything else by scoping to **CSS-value position** (hex preceded by `:`/space/`,`, never a quote) — reuse that rule for any future sweep.
### Client-side contract with the relay
@@ -140,7 +140,7 @@ unsure whether a change is contract-affecting, assume it is and check.
**Done & live:** self-serve Pro/Max purchase (Bitcoin inline-Lightning + Zaprite card, prepaid, relay owns tier/expiry), core-decoupling, per-tenant subscriptions, expiry-reminder emails (`POST /api/admin/reminders/run {test_email}`), **opt-in Daily Digest** (0.2.158, `b4fa5d7`): off-by-default daily email of a user's last ~24h of library recaps, each synthesized via `/relay/analyze` (operator-absorbed); `daily-digest.js` scan at `SEND_HOUR=8`, per-user watermark dedup, public tokenized unsubscribe, admin trigger `POST /api/admin/digest/run`; **YouTube `/live/` + `/shorts/` URL support** (0.2.159, `cb961cd`): `extractVideoId` now accepts those forms (was rejecting them as "Invalid YouTube URL"); and **self-contained shareable HTML export** (0.2.160, `621af7c`; first installed in 0.2.161): the Export menu offers a standalone `.html` with the embedded video + expandable timestamped summaries baked in, no account needed (native share sheet on mobile, download on desktop). Plans in `docs/*-plan.md`.
**Design system — DONE & live (0.2.161).** The `design/` contract (`design/DESIGN.md` + `design/tokens.tokens.json`; see the **Design** line up top) plus both cleanup phases are now installed. Phase 1: a canonical `:root` token block is the single source of truth in `public/index.html`'s `<style>`; the stylesheet + `public/auth.html` use `var(--token)`; all color/weight drift fixed. Phase 2: var-ified the long-tail inline `style=` hexes (346 + 7 `#475569` → `var()`, scoped to CSS-value position so JS-logic/quoted hex, the `<meta theme-color>`, SVG attrs, and the no-`:root` `SHARE_PAGE_*` region were dodged; `#fff` and no-token hexes left literal on purpose), and snapped off-scale font sizes (21) + radii (18) to the scale. Verified: 144 tests, both pages serve 200, every `var()` resolves, no off-scale residue. Phase 2 details + the remaining Style-Dictionary stretch goal are in `ROADMAP.md`.
**Design system — DONE & live (0.2.161).** The `design/` contract + both conformance-cleanup phases are installed: Phase 1 (canonical `:root` token block; stylesheet + `auth.html` on `var()`; drift fixed) and Phase 2 (var-ified the inline `style=` hexes 346 + 7 `#475569` and snapped off-scale fonts/radii to the scale). Verified: 144 tests, both pages serve 200, every `var()` resolves, no off-scale residue. The var-ify scoping rule + the `SHARE_PAGE_*` literal-hex exception now live in **Conventions**; only the Style-Dictionary `palette.css` stretch goal remains (`ROADMAP.md`).
**Only loose end:** the Daily Digest's relay-synthesis + SMTP path can't be exercised off-box, so it's installed but **not yet smoke-tested** — that's operator action #5 below. Everything else (schema/upgrade, scheduler boot, unsubscribe flow) is verified.