Move UI to BoardUI with slate + salmon theme; add PDF plan export
- Adopt BoardUI (Pro init): theme tokens, Inter, .dark mode, Button, SegmentedControl, Meter, Skeleton and ThemeToggle; remap the app's color aliases onto BoardUI tokens and swap lucide for Remix icons - Retint BoardUI's neutral ramp to cool slate with a salmon accent; drop the dotted background; raise muted text contrast - Simplify the landing page and remove the overlap explorer - Planner: explicit "I have this" toggle on grocery lines, pantry panel above the menu with the staples list spelled out, sticky aisle header fix, and a "Download PDF" plan export (jsPDF, lazy-loaded) - Recipes: replace the family cabbage soup with Cade's Cabbage Soup (adds Bone-In Ham Steak to the catalog); remove Ham, Bean & Cabbage Soup - Remove unused BoardUI components, dependencies and exports Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b02c7a024b
commit
df5dd3a70e
56 changed files with 4749 additions and 788 deletions
136
app/globals.css
136
app/globals.css
|
|
@ -1,57 +1,95 @@
|
|||
@import "tailwindcss";
|
||||
@import "../styles/globals.css";
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Warm Culinary Editorial Theme ("Parchment & Terracotta" / "Cast-Iron & Peach")
|
||||
---------------------------------------------------------------------------
|
||||
Perceptually uniform OKLCH tokens paired with CSS `light-dark()`.
|
||||
Every foreground/background pair is verified against WCAG 2.2 AA:
|
||||
- Body & 12px metadata (`ink`, `ink-muted`, `ink-faint`) >= 4.5:1
|
||||
- Interactive borders (`line-strong`, `selected-line`) >= 3.0:1 (SC 1.4.11)
|
||||
Plan my Meals BoardUI theme: cool slate neutrals with a salmon accent.
|
||||
BoardUI's surfaces, text and borders all read the neutral ramp, and every
|
||||
CTA / selection / focus state reads the accent ramp, so retinting these two
|
||||
ramps restyles the whole system (BoardUI's documented re-tint point).
|
||||
Accent 500/600 stay dark enough for white button labels (>= 4.5:1 blended).
|
||||
--------------------------------------------------------------------------- */
|
||||
@theme {
|
||||
/* Surfaces: warm unbleached linen in light mode, cast-iron slate in dark */
|
||||
--color-canvas: light-dark(oklch(97.4% 0.010 81.8), oklch(20.0% 0.021 245.9));
|
||||
--color-surface: light-dark(oklch(99.4% 0.006 84.6), oklch(24.5% 0.028 244.8));
|
||||
--color-raised: light-dark(oklch(94.3% 0.017 79.4), oklch(30.0% 0.035 242.7));
|
||||
--color-line: light-dark(oklch(84.6% 0.029 81.5), oklch(37.6% 0.042 242.8));
|
||||
--color-line-strong: light-dark(oklch(56.7% 0.032 74.0), oklch(62.5% 0.046 239.9));
|
||||
--color-neutral-50: oklch(98.4% 0.003 247.9);
|
||||
--color-neutral-100: oklch(97.4% 0.005 247.9);
|
||||
--color-neutral-200: oklch(93.8% 0.010 252.0);
|
||||
--color-neutral-300: oklch(86.9% 0.020 252.9);
|
||||
--color-neutral-400: oklch(70.4% 0.034 256.8);
|
||||
--color-neutral-500: oklch(55.4% 0.040 257.4);
|
||||
--color-neutral-600: oklch(44.6% 0.038 257.3);
|
||||
--color-neutral-700: oklch(37.2% 0.036 257.3);
|
||||
--color-neutral-800: oklch(26.5% 0.032 260.0);
|
||||
--color-neutral-900: oklch(20.5% 0.030 262.0);
|
||||
--color-neutral-925: oklch(16.5% 0.028 263.0);
|
||||
--color-neutral-950: oklch(13.0% 0.026 264.7);
|
||||
|
||||
/* Typography ink hierarchy */
|
||||
--color-ink: light-dark(oklch(22.8% 0.016 62.5), oklch(96.4% 0.021 79.1));
|
||||
--color-ink-muted: light-dark(oklch(40.7% 0.024 64.6), oklch(84.1% 0.017 250.9));
|
||||
--color-ink-faint: light-dark(oklch(48.0% 0.026 67.1), oklch(72.6% 0.028 251.7));
|
||||
--color-accent-50: oklch(97.3% 0.013 27);
|
||||
--color-accent-100: oklch(94.0% 0.030 27);
|
||||
--color-accent-200: oklch(88.5% 0.060 28);
|
||||
--color-accent-300: oklch(81.5% 0.100 29);
|
||||
--color-accent-400: oklch(72.5% 0.140 30);
|
||||
--color-accent-500: oklch(60.5% 0.155 31);
|
||||
--color-accent-600: oklch(53.5% 0.150 32);
|
||||
--color-accent-700: oklch(46.5% 0.130 32);
|
||||
--color-accent-800: oklch(39.5% 0.105 32);
|
||||
--color-accent-900: oklch(32.0% 0.080 31);
|
||||
--color-accent-950: oklch(23.0% 0.055 30);
|
||||
}
|
||||
|
||||
/* Primary culinary accent: Terracotta Paprika (light) / Warm Peach (dark) */
|
||||
--color-brand-300: light-dark(oklch(49.7% 0.151 37.0), oklch(82.9% 0.092 53.1));
|
||||
--color-brand-400: light-dark(oklch(51.8% 0.155 37.0), oklch(81.8% 0.098 52.8));
|
||||
--color-brand-500: light-dark(oklch(48.1% 0.146 36.8), oklch(85.8% 0.088 52.7));
|
||||
--color-brand-600: light-dark(oklch(54.0% 0.159 37.1), oklch(80.8% 0.102 52.6));
|
||||
--color-brand-950: light-dark(oklch(95.4% 0.025 65.6), oklch(26.8% 0.011 36.5));
|
||||
--color-brand-border: light-dark(oklch(71.0% 0.105 44.7), oklch(52.8% 0.088 49.3));
|
||||
--color-on-accent: light-dark(oklch(98.8% 0.009 67.7), oklch(18.8% 0.013 55.5));
|
||||
/* ---------------------------------------------------------------------------
|
||||
App token aliases → BoardUI semantic tokens.
|
||||
The app's components were written against these names; pointing them at
|
||||
BoardUI's tokens gives every screen the BoardUI look and its `.dark` flip.
|
||||
`inline` makes each utility read the BoardUI variable where it is used.
|
||||
--------------------------------------------------------------------------- */
|
||||
@theme inline {
|
||||
--color-canvas: var(--color-background-full);
|
||||
--color-surface: var(--color-background-primary-default);
|
||||
--color-raised: var(--color-background-secondary-default);
|
||||
--color-line: var(--color-separator-border);
|
||||
--color-line-strong: var(--color-border-button-hover);
|
||||
|
||||
/* Selected control fill & border (>= 4.4:1 boundary contrast) */
|
||||
--color-selected: light-dark(oklch(90.8% 0.023 78.2), oklch(35.3% 0.043 243.0));
|
||||
--color-selected-line: light-dark(oklch(49.8% 0.034 72.0), oklch(71.7% 0.046 240.1));
|
||||
--color-ink: var(--color-text-primary);
|
||||
/* BoardUI's text-tertiary (neutral-400 light / 600 dark) is ~2.5:1, too faint for body copy,
|
||||
so the app's two quiet text levels use their own steps that stay >= 4.5:1 (set below). */
|
||||
--color-ink-muted: var(--pm-ink-muted);
|
||||
--color-ink-faint: var(--pm-ink-faint);
|
||||
|
||||
/* Semantic status tokens (Herb Sage / Saffron Ochre / Chili) */
|
||||
--color-status-ok: light-dark(oklch(44.7% 0.092 154.8), oklch(84.0% 0.149 155.5));
|
||||
--color-status-ok-bg: light-dark(oklch(95.5% 0.018 161.1), oklch(27.6% 0.040 162.9));
|
||||
--color-status-ok-line: light-dark(oklch(69.9% 0.094 157.2), oklch(52.0% 0.101 156.2));
|
||||
/* Accent: BoardUI's accent ramp; text-on-surface uses the ghost foreground, which flips in dark. */
|
||||
--color-brand-300: var(--color-button-ghost-foreground);
|
||||
--color-brand-600: var(--color-accent-500);
|
||||
--color-brand-950: var(--color-button-ghost-background);
|
||||
--color-brand-border: color-mix(in oklab, var(--color-accent-500) 45%, transparent);
|
||||
--color-on-accent: var(--color-text-white);
|
||||
|
||||
--color-status-warn: light-dark(oklch(47.6% 0.106 63.3), oklch(88.3% 0.120 85.9));
|
||||
--color-status-warn-bg: light-dark(oklch(96.7% 0.029 82.6), oklch(26.8% 0.034 78.8));
|
||||
--color-status-warn-line: light-dark(oklch(72.6% 0.128 75.7), oklch(55.4% 0.107 76.3));
|
||||
--color-selected: var(--color-background-tertiary-default);
|
||||
--color-selected-line: var(--color-accent-500);
|
||||
|
||||
--color-status-danger: light-dark(oklch(48.1% 0.167 26.2), oklch(80.8% 0.103 19.6));
|
||||
--color-status-danger-bg: light-dark(oklch(95.2% 0.021 17.5), oklch(24.8% 0.043 13.6));
|
||||
--color-status-danger-line: light-dark(oklch(68.1% 0.127 21.0), oklch(49.1% 0.133 18.8));
|
||||
--color-status-ok: var(--color-notification-success-foreground);
|
||||
--color-status-ok-bg: var(--color-notification-success-background);
|
||||
--color-status-ok-line: color-mix(in oklab, var(--color-notification-success-foreground) 45%, transparent);
|
||||
|
||||
/* Three-voice editorial typography */
|
||||
--font-sans: var(--font-jakarta), system-ui, sans-serif;
|
||||
--font-serif: var(--font-fraunces), Georgia, Cambria, serif;
|
||||
--font-mono: var(--font-jb-mono), ui-monospace, SFMono-Regular, monospace;
|
||||
--color-status-warn: var(--color-status-yellow-text);
|
||||
--color-status-warn-bg: var(--color-status-yellow-background);
|
||||
--color-status-warn-line: color-mix(in oklab, var(--color-status-yellow-text) 45%, transparent);
|
||||
|
||||
--color-status-danger: var(--color-notification-error-foreground);
|
||||
--color-status-danger-bg: var(--color-notification-error-background);
|
||||
--color-status-danger-line: color-mix(in oklab, var(--color-notification-error-foreground) 45%, transparent);
|
||||
|
||||
/* BoardUI is single-family (Inter); the old serif display voice folds into it. */
|
||||
--font-serif: var(--font-sans);
|
||||
}
|
||||
|
||||
:root {
|
||||
--pm-ink-muted: var(--color-neutral-600);
|
||||
--pm-ink-faint: var(--color-neutral-500);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--pm-ink-muted: var(--color-neutral-300);
|
||||
--pm-ink-faint: var(--color-neutral-400);
|
||||
}
|
||||
|
||||
@theme {
|
||||
/* Animations */
|
||||
--animate-fade-in: fade-in 0.35s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
--animate-preview-timer: preview-timer 1s linear forwards;
|
||||
|
|
@ -83,14 +121,10 @@
|
|||
|
||||
@layer base {
|
||||
html {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
|
||||
html[data-theme="light"] {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] {
|
||||
html.dark {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +134,7 @@
|
|||
|
||||
/* Visible focus for keyboard users on every interactive element. */
|
||||
:where(button, a, input, select, summary, [tabindex]):focus-visible {
|
||||
@apply outline-2 outline-offset-2 outline-brand-600;
|
||||
@apply outline-2 outline-offset-2 outline-border-focus-ring;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
|
|
@ -172,12 +206,6 @@
|
|||
text-box-edge: cap alphabetic;
|
||||
}
|
||||
|
||||
/* Subtle tactile paper noise texture without GPU-heavy blur blobs */
|
||||
.paper-grain {
|
||||
background-image: radial-gradient(color-mix(in oklab, var(--color-ink) 5%, transparent) 1px, transparent 0);
|
||||
background-size: 18px 18px;
|
||||
}
|
||||
|
||||
/* Market receipt serrated / perforated divider feel */
|
||||
.receipt-rule {
|
||||
border-top: 1px dashed var(--color-line-strong);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue