378 Commits

Author SHA1 Message Date
thejayman77 b174d8d2a7 home3/hub: shared HubBar with mobile hamburger + Art-card mobile crop fix
#2 Mobile top bar → hamburger: extracted the editorial bar (brand + nav + new
collapsible hamburger drop-panel) into a shared lib/components/HubBar.svelte,
used by both /home3 and HubShell (the /word /quote /onthisday detail pages), so
there's one nav to maintain/audit. Full horizontal nav ≥721px; hamburger + drop
panel ≤720px. Escape + link-click close it; panel is hidden on desktop as a
safety. Removed the duplicated bar markup/CSS from home3 + HubShell.

#1 Mobile layout / Art card: on phones the Art card now stacks image-first with
the painting in a proper 3:2 frame (aspect-ratio) instead of a stubby fixed
130px band that cropped the work to a sliver. Also drop the News gist's bottom
fade once the bento is single-column (natural height = no truncation, so the
fade was just dimming the final line), and let the joys header wrap on phones.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:55:36 -04:00
thejayman77 2e9d81bd86 WOTD: commit cached pronunciation clip for 'repose' (matches tracked audio)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:00:01 -04:00
thejayman77 84b1fb514f Small joys: Codex audit #2 fixes (route resolution, noindex, sense/tone, exclude-current re-pick)
- Admin joy item route moved to /api/admin/joys/{kind}/items/{item_id} so the
  /add and /repick verbs resolve to their own routes instead of 422-ing as a
  non-int item id (the launch blocker). Frontend mutate URL updated to match.
- Re-pick now excludes the currently-shown item: the endpoint reads today's
  daily pool_id and passes it as `avoid`, so "Re-pick today" yields a different
  item. Added `avoid` to pick_daily/_candidates across wotd/quote/onthisday.
- WOTD sense selection: the LLM now proposes word + intended part of speech, and
  _lookup prefers that sense (fixes "serene" returning the archaic noun).
- On This Day tone prompt tightened to favor genuinely uplifting events and
  exclude merely procedural/political-administrative ones.
- Caddy @hidden now also noindexes /word /quote /onthisday /admin (+ .html).
- Regression tests: add/repick resolve (401 not 422), add/feature/block/delete,
  re-pick excludes current; WOTD pos-preference + proposal parsing units.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 20:19:02 -04:00
thejayman77 3bde6534e9 Small joys: wire homepage rail to live data + rich pages (/word /quote /onthisday) + admin
- /home3: small-joys rail now reads live /api/word|quote|onthisday/today (placeholders only
  as fallback); each cell links to its detail page.
- HubShell component (shared bar/footer/fonts/tokens) for the hub + detail pages.
- /word: big word, IPA, Listen (cached clip + browser-TTS fallback), definition, sentences.
- /quote: the quote, attribution, and the AI "what it means".
- /onthisday: the date, year + fact, image, summary, source.
- Admin "Small Joys" tab: per-pool list with feature/block/delete/add + re-pick, for all
  three kinds. New admin API: GET/POST /api/admin/joys/{kind}[/{id}|/add|/repick].

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 18:52:38 -04:00
thejayman77 67d4bc32cb Small joys: Quote of the Day + Word of the Day engines
- quote.py: curated public-domain quote pool (16 seeded, admin-grows), deterministic daily
  pick, lazy AI "what it means" explainer of the real quote (cached). No LLM-invented quotes.
- wotd.py: LLM proposes positive words → validated/enriched against dictionaryapi.dev (real
  definition, IPA, examples, audio) → audio clip cached to our origin (TTS fallback) →
  deterministic daily pick. Tops the pool up toward 30/day.
- db.py: quote_pool/daily_quote + wotd_pool/daily_wotd tables.
- api.py: /api/quote/today, /api/word/today, /api/word/audio/{word} (GET+HEAD).
- cli.py: cycle steps for both (under --no-joys), shared LLM client.
- tests: test_quote.py (6) + test_wotd.py (5). 393 backend tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 17:28:55 -04:00
thejayman77 a7da8362ab Small joys backend: shared daily framework + On This Day engine
- goodnews/daily.py: shared helpers for the daily "small joys" (http_json, date-seeded
  deterministic pick, dedup key) so each joy is a small self-contained module.
- goodnews/onthisday.py: harvest today's MM-DD from Wikimedia's On-this-day feed →
  tone-filter to good/neutral (keyword floor + optional LLM refine) → pool → deterministic
  daily pick (idempotent, respects blocked/featured) → cached row. Network/LLM before any
  DB write. Multi-source ready (source column).
- db.py: onthisday_pool + daily_onthisday tables.
- api.py: GET /api/onthisday/today (edge-cacheable).
- cli.py: cycle step (run after Daily Art; --no-joys to skip), LLM client for tone refine.
- tests/test_onthisday.py: 7 tests (filter+dedup, pick idempotent, blocked/featured,
  never-empty, empty-pool, LLM-narrow). 382 backend tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 16:51:29 -04:00
thejayman77 4739d87f4b caddy: X-Robots-Tag noindex,nofollow on /home2 + /home3 (HTTP-level, for non-JS crawlers)
Per Codex audit — the JS <meta robots> isn't seen by bots that don't run JS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 15:59:30 -04:00
thejayman77 ea85e9cdfb home3 news footer: 3-min-read back to the right; 'Read more good news' is blue now
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 15:50:41 -04:00
thejayman77 48a0cc1111 home3 news: remove redundant 'Read article' (block is clickable), keep read-time; darken footer divider
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 15:36:48 -04:00
thejayman77 147701e7dc home3 news: summary clickable (->article); drop Read-article underline, add divider before Read-more-good-news
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:48:04 -04:00
thejayman77 de53873b4f home3: Entertainment nav is a non-clickable soon item (drop dead href=#)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:39:46 -04:00
thejayman77 440e8391d6 home3: clickable news photo + headline (-> article); top bar = Home(active)/News/Games/Art/Entertainment
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:37:47 -04:00
thejayman77 d3017598a2 home3 Entertainment: icon tiles (palette/smiley/sparkle) instead of teaser boxes, centered motif
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:11:24 -04:00
thejayman77 18e950bbf7 home3 news headline: drop JS char-slice, use CSS line-clamp:2 (word-boundary, fills 2 lines)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 13:20:32 -04:00
thejayman77 319c5f6b7e home3 news figure matte: fade silvery->white downward so it melts into the card
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:37:56 -04:00
thejayman77 6925a6951b home3 news image: photos display full-bleed (cover); only wide/tall figures get the framed plate (aspect-detected on load)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:30:12 -04:00
thejayman77 390bf5f43d home3: news image as tinted-matte framed plate (CD); Entertainment uses blurred teaser boxes (no play button) + non-video copy
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:22:14 -04:00
thejayman77 1ffc9c6e92 home3: news image contain-on-matte (figures sit whole); Entertainment centered play-glyph empty-state
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:10:41 -04:00
thejayman77 8037e72f17 home3 joys: clamp all cards to WORD card's height (min-height 170, no squish); darken WOTD definition
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 11:57:26 -04:00
thejayman77 772cb47d69 home3 joys: tighten WORD card (word line-height:1, phonetics up+darker), lower shared min-height so all rotations match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 11:43:15 -04:00
thejayman77 e38081733d home3: small-joys equal height + trimmed spacing + fresh palette (sky/rose/clay); news summary fills the room
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 11:11:09 -04:00
thejayman77 89352e7123 home3: small-joys rail -> rotating two-up shelf (option A: label + dots + arrows)
Two jewel cards at a time, reader-advanced (no auto-motion); 3 cells total, wraps. Keeps
each card at generous size instead of cramming three.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 10:58:55 -04:00
thejayman77 8cf061d214 home3: small-joys rail polished to 'little jewels' (CD spec — focal points, watermarks, accent tags, gradients)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 10:36:12 -04:00
thejayman77 3c519a5f50 home3: small-joys rail (WOTD/QOTD crafted + 'good thing today' SOON), whole-word headline clamp, 16px gaps
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 10:18:00 -04:00
thejayman77 2173802c70 home3: rename Daily Moment -> Entertainment; add skinny Word/Quote-of-the-day strip (placeholder)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 09:39:02 -04:00
thejayman77 de94d179bd home3: Art pinned top, Play/Moment pair vertically centered in the space below (FIX1)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 09:14:37 -04:00
thejayman77 65cb770514 home3: Art pinned top, pair pinned bottom, space distributed between (FIX1)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 09:11:02 -04:00
thejayman77 f4b20bdf79 home3: center the right column in the space (match FIX1), not top-aligned
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 09:08:08 -04:00
thejayman77 2e3cc5f382 home3: stop card stretch (independent right column, float not stretch); News gets two links (Read article + Read more good news)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 08:59:10 -04:00
thejayman77 5306c65c7b home3: consistent half-column bleed + equal-size side games on Play; FIX1 layout (fade-out gist, read-time meta, trimmed Art headline)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 06:33:57 -04:00
thejayman77 703ea22e0b home3 Play card: center word search, balance gaps, full wordle visible
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 06:06:44 -04:00
thejayman77 c95ca8775a home3 Play card: fit word-search panel + bolder BYTES, EAT/YTE tiles, richer amber
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 05:47:10 -04:00
thejayman77 a8762a1dd8 home3 Play card: fix Wordle tile colours (TYPE→BYTE, accurate green/amber)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 05:27:35 -04:00
thejayman77 79fb9b44fc home3 Play card: 'bleeding boards' graphic (Wordle + BYTES word-search + Memory Match)
Decorative tiles (no live answer = no spoilers); placeholder copy. Built from CD's
Play Card Graphic handoff.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 22:18:12 -04:00
thejayman77 d85e174a35 home3 refinements: clamp summary, bigger titles/logo/nav, crop art edge, clearer CTA
- News summary + headline clamped to 3 lines so the long brief gist no longer stretches
  the bento (option 1; placeholder-bubble option still available if preferred).
- News CTA "Read the brief" → "Read the good news" (clearer for first-time visitors).
- Art swatch crops a few px off every edge (::after inset) to remove the black scan edge
  at the top of paintings.
- Logo 42→48px, nav 15→16.5px, card titles bumped + weight 500→600 so they pop on scan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:35:55 -04:00
thejayman77 b83a3797e4 home3: Claude Design "Frame A" homepage (editorial, with colour) — real logo + live data
- Rebuilds the design handoff's preferred Frame A: Newsreader serif headlines + Hanken
  Grotesk body (both self-hosted, OFL, no Google hotlink), warm cream canvas, per-card
  accent tints (News teal, Art plum, Play amber, Moment green), bento grid.
- Uses our real /logo.svg instead of the mock's Bricolage wordmark + sunrise.
- Wired live: Good News pulls the top headline/summary/photo (respects the saved
  Closer-to-Home filter); Daily Art pulls today's Met piece (title/artist/year + thumbnail).
- Hidden prototype (noindex), spacing tuned per the /home2 pass (hero pulled up, more air
  before the bento). Sits beside /home2 for comparison.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 20:32:32 -04:00
thejayman77 84e251e8ec home2: drop the darker top strip on cards (keep tints + inset photos)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 20:19:59 -04:00
thejayman77 e298d25c92 home2 cards round 4: all cards tinted + top strip, inset photos, centered static headers
- All four cards now tinted with a taller (18px), darker (~24%) top color strip.
- Photos (news top, art right) sit inset + rounded so the card colour frames them.
- Static cards: header centered; CTA pinned to the bottom so Play/Daily Moment links line
  up. News tint = soft amber, Art = soft lilac, Play = sky, Moment = sage.
- Hub spacing: intro pulled up a touch, more gap between the intro and the cards.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 20:13:14 -04:00
thejayman77 4684a216b8 home2 cards round 3: photo-right art, unified side-by-side header, Manrope titles, top strip
- Art photo moved to the RIGHT (text/icon left) so it no longer clusters with the news
  photo in the center.
- Unified header: every card now has icon + title side-by-side; card titles switched from
  serif (too 'document') to Manrope bold. Art icon/title now match Play/Daily Moment sizes.
- Static cards (Play/Daily Moment) gain a darker top color strip (Monopoly-card feel) over
  the tinted body, derived from each tint via color-mix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:57:18 -04:00
thejayman77 b172c5eefd home2 round 2: Manrope nav, bigger logo, photo-top news / photo-left art, tinted static cards
- Self-hosted Manrope (OFL) as the hub sans; nav lighter (weight 500, soft slate, not all
  "on"). Logo up to 58px.
- News card: photo on top + headline below, and it now respects the reader's saved
  Closer-to-Home filter (goodnews:home/homeScope) so the headline matches their Brief.
- Art card: rectangular cover-cropped thumbnail on the LEFT (crops ragged scan edges),
  text on the right — variety against the photo-top news card.
- Play/Daily Moment: tinted backgrounds, bigger centered icon+title, blurb left-aligned.
- /fonts/* + /textures/* served immutable (Caddy live + snapshot).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:46:51 -04:00
thejayman77 5a8e178f51 Homepage hub: /home2 prototype — sections-as-data + bigger shell + hybrid room cards
- New sections registry (lib/rooms.js): each room is one data entry (title/blurb/href/cta/
  size/preview/icon) — add or resize by editing the list.
- Reusable RoomCard (lib/components/RoomCard.svelte) with size variants and hybrid previews:
  Art shows today's live thumbnail, News shows today's top headline, others are blurb+CTA.
- /home2 hidden prototype (noindex, unlinked) with a bigger top bar (logo 50px, larger nav
  labels) and a reflowing grid hub of the four rooms (News/Art/Play/Daily Moment). Iterate
  the look here, then promote to / and remove the clone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:26:31 -04:00
thejayman77 dd8706e2fc Art post-audit polish (Codex): image HEAD, texture immutable cache, lightbox a11y, spacing
- /api/art/image/{id} now answers HEAD as well as GET (was 404 on HEAD) — mirrors the
  /a/{id} fix. Added tests/test_art_api.py (GET+HEAD+size=full fallback + today payload).
- /textures/* served immutable (long cache) instead of no-cache; excluded from the
  revalidate matcher. Live Caddyfile + repo snapshot both updated.
- Lightbox: Escape closes it, and focus moves to it on open (keyboard-friendly).
- Trimmed the gallery's top padding so "Daily Art" sits closer to the bar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:17:30 -04:00
thejayman77 39c666b4ee Art frame final polish: four mitered wood rails (grain turns at corners) + brushed metals
- Woods are now built from four real mitered rails clipped to 45° joints, each showing the
  grain along its length — horizontal on top/bottom (rotated texture wood-grain-h.jpg),
  vertical on the sides — so the grain TURNS at every corner like real cut moulding. Each
  rail carries a directional bevel (lit top-left) for a rounded profile; per-species recolor
  moved onto the rails. Rendered via a Svelte snippet in both page + full-screen frames.
- Gold/Silver gain fine brushed-metal striations over the existing sheen.
- New asset: wood-grain-h.jpg (the CC0 texture rotated 90°), credited in textures/CREDITS.txt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:56:23 -04:00
thejayman77 006c1b2792 Art full-screen: light gallery wall, No-frame goes big, recessed-mat depth
- No frame in full-screen now fills the screen (img max 96vw / 88vh instead of the
  framed cap).
- Full-screen backdrop is a soft top-lit gallery wall (light, not dark) so the Black
  frame — and every frame — reads like a piece hung on a real wall; caption text darkened
  to match.
- Mat now sits recessed below the moulding: a rabbet groove line at the lip, frame shadow
  on the mat's top/left, catch-light on bottom/right — a small chiseled step in place of
  the flat frame→mat transition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:44:14 -04:00
thejayman77 c2c5b25ab1 Art frames: add Black frame; thicker full-screen rail; rail-only top of thickness slider
- Black frame (no grain) added after Silver — a satin charcoal moulding in the metals family.
- Full-screen rail bumped (clamp 18–36px) so the moulding reads as thick as the page view
  against the much larger image; mat held.
- Thickness slider extended to 1.9× and the mat now caps at 1.5× (min()), so the top of
  the slider thickens only the wood while the white border stays put. Applies to the
  full-screen frame too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:33:59 -04:00
thejayman77 90d3e8cbe6 Art frames: real photographic wood (CC0), Mahogany, full-screen fit + proportion fix
- Replace procedural grain with a real fine-grain wood texture (CC0, Poly Haven —
  static/textures/wood-grain.jpg). The three woods share it, recolored per species via
  CSS filter on ::before: Walnut (as-is dark), Oak (lightened/warmed), Mahogany (new —
  deepened/reddened). Miters now apply to all three woods; mat sits between texture and
  miters via z-index.
- Full-screen sizing fixed: image capped (max-height 66vh) so the bottom rail always
  fits — no more cutoff. Rail/mat dialed back to ~1:1 wood:white (was mat-heavy), only
  slightly larger than the page so the proportion matches the small view.

Texture credit (CC0, no attribution required) recorded in static/textures/CREDITS.txt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:20:27 -04:00
thejayman77 71fb16761b Art frames round 3: natural wood grain, thickness slider, no-jump layout, polish
- Oak grain is now a real feTurbulence noise field (organic wood, no drawn-on lines),
  with a soft light/shade for moulding roundness; miters kept.
- Thickness slider (0.7–1.5×) scales rail + mat via --frame-scale, remembered locally;
  applies to both the page and the full-screen view.
- No-jump layout: every frame — including "No frame" — reserves the same footprint
  (rail + mat as CSS vars), so switching never reflows the page. "No frame" is the bare
  art floating with a soft shadow.
- Full-screen wears a thicker rail + mat so the white border keeps its proportion at
  large size; "No frame" still maximizes there.
- Frame chips redesigned as beveled beads with a clean offset selection ring.
- Subtle fading hairline divider between the title and the artwork.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:02:26 -04:00
thejayman77 cd8175be81 Art frames: add wood-grain Oak with mitered corners + frame the full-screen view
- New "Oak" frame: real wood-grain along the rails plus 45° mitered corner joints
  (CSS conic-free miter via per-corner diagonal seam gradients sized to the rail width),
  so it reads as four lengths of moulding meeting at the corners.
- The lightbox now wears the selected frame too — the same moulding + cream mat around
  the full-resolution image, which makes the piece pop on a dark full screen. Image is
  capped to leave room for the frame; "No frame" still maximizes size.
- Frame picker wraps gracefully now that there are five options.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:42:31 -04:00
thejayman77 27788ba2a8 Art page round 2: virtual frames, real logo, hi-res zoom, spacing/affordance polish
- Virtual frames (Walnut/Gold/Silver/None), selectable + remembered in localStorage,
  built as a beveled moulding around a cream museum mat.
- Header uses the real /logo.svg wordmark; the "No ads" pill is replaced by an
  account icon (the pill doesn't need to follow every page).
- Lightbox now opens a full-resolution copy that fills the screen: art._download_image
  caches a hi-res {id}-full copy alongside the web-large display copy, served via
  /api/art/image/{id}?size=full (image_url_large in /api/art/today).
- Centered the placard bullet separators (explicit .sep spans, equal margins).
- Image no longer shifts on hover; a quiet "Click to expand" affordance sits on the art.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:25:31 -04:00
thejayman77 9bfec573e2 /art v1: single featured piece, framed (look-overhaul testbed)
A calm "walk up to one piece on a quiet wall" page for the Daily Art engine. Bright,
modern, cream canvas (not a dim brown gallery) so the artwork's own colors are the pop
— the new look prototyped, scoped to /art so it doesn't touch the rest of the site yet.

- Fetches /api/art/today; large soft-shadowed frame (click -> lightbox), a museum
  "placard" (serif title, artist · date, medium, "from The Met · Public Domain (CC0)",
  View-at-museum link). Calm loading/empty states. Unlinked from the homepage (safe to
  iterate). Ships the (Codex-cleared) art backend too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:48:58 -04:00