Build the SvelteKit frontend: calm home with mood modes
- New frontend/ SvelteKit static SPA (Svelte 5), served by FastAPI from frontend/build (falls back to the legacy page if unbuilt). - Calm design system: cream/sage palette, serif headlines, generous space, no urgency colors, gentle motion (respects prefers-reduced-motion). - Home screen: mood-mode nav (Today/Wonder/People Helping/Solutions/Light Only/Grounded), the daily brief as a hero + remaining four, browsable mood lanes, an explicit calm end-state, inline Not today / Less like this / Hide affordances, and device-local Calm Filters mirroring goodnews/filters.py. - Backend: moods.py + GET /api/moods (single source of truth for the modes); FilterPrefs gains max_cortisol/max_ragebait ceilings (for Light Only). - Push categorical filters (include/mute topics+flavors, ceilings) into SQL in queries.feed so low-ranked-but-matching items (e.g. discovery for Wonder) are not truncated by ranking; only avoid-terms stay a Python pass. - PWA manifest + icon (installable; offline deferred per plan). - Multi-stage Dockerfile builds the site then serves it from the API. - Tests: queries.feed categorical filters (63 total). README updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/* goodNews calm design system.
|
||||
Warm but crisp: cream surfaces, sage accent, a serif voice for headlines,
|
||||
strong readable contrast, generous space. No urgency colors (no red). */
|
||||
:root {
|
||||
--bg: #faf6ee;
|
||||
--surface: #fffdf8;
|
||||
--ink: #21281f;
|
||||
--muted: #616c60;
|
||||
--sage: #2f7d5b;
|
||||
--sage-deep: #235e44;
|
||||
--sage-soft: #e6efe6;
|
||||
--line: #e7e1d4;
|
||||
--gold: #a9802f;
|
||||
|
||||
--serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
|
||||
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
|
||||
--maxw: 880px;
|
||||
--radius: 16px;
|
||||
--shadow: 0 1px 2px rgba(40, 38, 28, 0.04), 0 10px 30px rgba(40, 38, 28, 0.055);
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--bg);
|
||||
color: var(--ink);
|
||||
font-family: var(--sans);
|
||||
font-size: 17px;
|
||||
line-height: 1.62;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
font-family: var(--serif);
|
||||
font-weight: 600;
|
||||
line-height: 1.18;
|
||||
letter-spacing: -0.012em;
|
||||
margin: 0;
|
||||
}
|
||||
a { color: inherit; text-decoration: none; }
|
||||
img { max-width: 100%; display: block; }
|
||||
button { font-family: inherit; cursor: pointer; }
|
||||
::selection { background: var(--sage-soft); }
|
||||
|
||||
.container { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
|
||||
.muted { color: var(--muted); }
|
||||
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(238px, 1fr)); gap: 18px; }
|
||||
|
||||
/* a soft, slow fade for content as it arrives — calm, not flashy */
|
||||
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
|
||||
.rise { animation: rise 0.5s ease both; }
|
||||
@media (prefers-reduced-motion: reduce) { .rise { animation: none; } html { scroll-behavior: auto; } }
|
||||
Reference in New Issue
Block a user