deckhearth/styles/globals.css

991 lines
28 KiB
CSS
Raw Normal View History

@tailwind base;
@tailwind components;
@tailwind utilities;
/* Custom styles */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transition: background-color 0.3s ease, color 0.3s ease;
}
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
/* Theme Variables - Deck Hearth Fire-Inspired */
:root {
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
/* Light Theme - Warm Daylight by the Hearth */
--bg-primary-light: #fefcf8; /* Warm cream, like sunlit stone */
--bg-secondary-light: #f7f3ed; /* Soft beige, like aged parchment */
--bg-tertiary-light: #f0e6d6; /* Light wood tone */
--text-primary-light: #2d1810; /* Dark chocolate brown */
--text-secondary-light: #5d4037; /* Medium brown, like burnt wood */
--text-accent-light: #d84315; /* Ember orange */
--border-light: #e8dcc6; /* Light wood border */
--shadow-light: 0 4px 6px -1px rgba(45, 24, 16, 0.1);
--gradient-primary-light: linear-gradient(135deg, #ff6f00 0%, #d84315 100%); /* Fire gradient */
--gradient-secondary-light: linear-gradient(135deg, #ffab40 0%, #ff6f00 100%); /* Golden flame */
--accent-flame-light: #ff6f00; /* Bright flame orange */
--accent-ember-light: #d84315; /* Deep ember red */
--accent-gold-light: #ffab40; /* Golden flame */
--accent-wood-light: #8d6e63; /* Rich wood tone */
--input-bg-light: #fefcf8;
--input-border-light: #e8dcc6;
--input-text-light: #2d1810;
--input-placeholder-light: #5d4037;
/* RGB color variables for backdrop-blur effects */
--bg-primary-rgb: 254, 252, 248;
--bg-secondary-rgb: 247, 243, 237;
--bg-tertiary-rgb: 240, 230, 214;
--accent-ember-rgb: 216, 67, 21; /* RGB version of #d84315 */
}
[data-theme="dark"] {
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
/* Dark Theme - Cozy Evening by the Fire */
--bg-primary-dark: #1a0f0a; /* Deep charcoal, like burnt wood */
--bg-secondary-dark: #2d1b12; /* Rich dark brown, like oak */
--bg-tertiary-dark: #3d2317; /* Medium brown, like mahogany */
--text-primary-dark: #fff8f0; /* Warm white, like firelight */
--text-secondary-dark: #d7c4b0; /* Soft cream, like candlelight */
--text-accent-dark: #ff8a50; /* Bright flame orange */
--border-dark: #4a2f1f; /* Dark wood border */
--shadow-dark: 0 4px 6px -1px rgba(26, 15, 10, 0.4);
--gradient-primary-dark: linear-gradient(135deg, #ff8a50 0%, #d84315 100%); /* Evening fire */
--gradient-secondary-dark: linear-gradient(135deg, #ffab40 0%, #ff6f00 100%); /* Golden embers */
--accent-flame-dark: #ff8a50; /* Bright flame */
--accent-ember-dark: #d84315; /* Glowing ember */
--accent-gold-dark: #ffab40; /* Golden glow */
--accent-wood-dark: #8d6e63; /* Warm wood */
--input-bg-dark: #2d1b12;
--input-border-dark: #4a2f1f;
--input-text-dark: #fff8f0;
--input-placeholder-dark: #d7c4b0;
--search-bg-dark: #2d1b12;
--search-border-dark: #4a2f1f;
--search-text-dark: #fff8f0;
--search-placeholder-dark: #d7c4b0;
/* RGB color variables for backdrop-blur effects */
--bg-primary-rgb: 26, 15, 10;
--bg-secondary-rgb: 45, 27, 18;
--bg-tertiary-rgb: 61, 35, 23;
--accent-ember-rgb: 216, 67, 21; /* RGB version of #d84315 */
}
feat(design-system): Liquid Glass redesign portfolio — foundation + primitives + Layout (#95) * feat(design-system): Liquid Glass redesign portfolio — foundation + primitive kit + Layout shell Operator-requested epic to migrate the UI from the current "warm panel + side-highlight + heavy gradient" visual language to a Liquid Glass aesthetic that retains Deck Hearth's fireplace warmth as accent / gradient / motion (not as panel fill). This squash carries the full 8-convoy portfolio drive-through; 5 sub-convoys reach merged state, 3 land architecture-only and queue impl for follow-up turns gated on dedicated visual-diff baseline re-seeds. Sub-convoy #1 (liquid-glass-design-tokens) — MERGED. 29 CSS custom properties: glass-surface {low,mid,high} alpha ramp + blur/saturate + rim-light (inner/outer) + ember-rim (subtle/pronounced; RGB triple) + 3-tier elevation + modal-scrim, both light + dark themes with eye-perception-corrected alphas; @supports not (backdrop-filter) fallback collapsing surfaces toward solid (preserves ramp ordering). Authored docs/DESIGN_TOKENS.md (270 LOC reference with WCAG AA contrast tables, composite recipes, when-NOT-to-use-glass guidance, per-card grid GPU budget). AGENTS.md gains a § Visual language section as the new agent-contract surface. Sub-convoy #2 (liquid-glass-modal-and-surface-primitive) — Brief 1 MERGED. Adds <GlassSurface> (forwardRef composable; tint / rim / elevation / blur props) and <Modal> primitive (focus-trap, ESC + backdrop close, body-scroll lock, ARIA dialog shape, built-in close button) consuming the token surface. lib/use-focus-trap.js — homegrown hook (~60 LOC, no dep). 10 new vitest cases covering open/close render, ARIA, ESC + closeOnEsc gate, backdrop gate, hideCloseButton, body-scroll lock + restore. 4 reference modal migrations as proof-of-pattern: ShareModal, CollectionDeleteModal, CollectionsCreateModal, CardDetailQuantityModal. Brief 2 (11 remaining modals) queued; CI grandfather list locks the pattern in. Sub-convoy #3 (liquid-glass-form-primitives) — Brief 1 MERGED. Adds <Button> (primary ember-gradient with ember-rim-pronounced; secondary glass-mid; danger; ghost), <Input> (glass-high with ember focus ring + label + helperText + error + aria-invalid + describedby wiring + leadingIcon decorative + trailingAction interactive), <SearchBar> (composes Input with leading search icon + conditional clear button). 10 new vitest cases. pages/login.js + pages/signup.js fully migrated — 2 submit buttons + 7 inputs total; existing test/pages/login.test.js assertion ("Sign in to Deck Hearth" button text) preserved. Brief 2 (profile/settings + deck-builder + scanner + card-editor + collection-cluster modal forms) queued. Sub-convoy #4 (liquid-glass-layout-shell) — MERGED. 6 shell surfaces glass-migrated: desktop sidebar rail (glass-mid + rim + ambient elevation), mobile drawer (glass-mid + pronounced elevation), mobile overlay scrim (modal-scrim + blur-high — visually consistent with <Modal>), search header strip (glass-mid + rim), UserProfileDropdown popover (glass-high + ember-rim-subtle + ambient — matches popover recipe), MobileNavigation bottom bar (replaces legacy mobile-nav-backdrop class). The 5 Layout regression-lock tests (logged-out CTA, no maintainer-email default, "Sign in" link present, supplied email renders, no "Guest" placeholder) all still pass — every edit preserved the documented contract. Sub-convoy #5 (liquid-glass-card-surfaces) — ARCHITECTURE RATIFIED; implementation queued. Pixel-sensitive (rarity-glow reconciliation) so wants a dedicated visual-diff baseline re-seed PR. Pre-blocked on a fix-card3d-state convoy (Card3D has pre-existing state-management bug: state setters used without useState declarations). Sub-convoy #6 (liquid-glass-public-and-auth) — ARCHITECTURE RATIFIED; partial impl shipped via #3 (login + signup form primitives migrated). Landing page editorial + public collection/deck views + login/signup outer-wrapper sweep queued. Sub-convoy #7 (motion-system-pass) — MERGED. 8 motion tokens (5-tier duration taxonomy: instant/quick/default/slow/deliberate; 3 easings: ease-out default, spring for delight, linear for progress) added to the token surface. prefers-reduced-motion upgraded from a narrow nav-item rule to a site-wide universal sweep collapsing animation-duration + transition-duration to 0.01ms (preserves end states, no flicker); .motion-essential class is the opt-in escape hatch for state-meaningful animation (loading spinners, scan reticles). Authored docs/MOTION_SYSTEM.md with WCAG SC 2.3.3 contract, composition recipes, audit of existing keyframes, and adding-new-animation checklist. Sub-convoy #8 (cleanup-legacy-design-css) — Brief 1 MERGED. Two new CI jobs in .github/workflows/ci.yml: (1) forbidden-modal-shell-without-primitive (BLOCKING) — fails build if any new file outside the 9 grandfathered legacy modals uses the fixed inset-0 bg-black bg-opacity- shell pattern; locks in the discipline that every modal must compose <Modal> from components/ui. (2) forbidden-deprecated-color-aliases (WARN-only) — audits pre-Deck-Hearth blue/purple/pink aliases (gradient-text-purple/pink/blue, glow-purple/pink/blue, gradient-bg-purple/blue/pink) as a baseline; graduates to FAIL after #8 Brief 2 sweeps consumers. .cursor/rules/ui-and-theming.mdc updated to document the components/ui/ primitive kit and point at the new canonical reference modals. Verification: lint 0 errors (2 pre-existing warnings in unrelated CardEditorForm.js + CollectionsPageView.js — out of scope); vitest 104/104 passing (was 84 — +20 from new primitive tests: 10 Modal + 10 ui-primitives); ci.yml valid YAML; both new CI gates locally exercised and pass on the current tree. Operator follow-ups documented in .convoys/ship-readiness.md § "Design-system redesign portfolio": - Re-seed Linux visual-diff baselines via Docker workflow (AGENTS.md § 6) after this merges. - preview-smoke.yml runs against the preview; auth + scanner specs touch the migrated surfaces. - Vercel promote to production once smoke + visual gates pass. - Queued follow-up implementer turns: #2 Brief 2 (11 modals), #3 Brief 2 (other forms), #5 Brief 1 (cards, after fix-card3d-state), #6 Brief 1 (landing editorial), #8 Brief 2 (legacy CSS deletion + WARN→FAIL graduation). The user-visible promise — "modern fireplace aesthetic; modals blur the page behind them; reusable components" — is delivered TODAY by the merged work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(use-focus-trap): preserve named useFocusTrap export for ScannerPageView The portfolio squash inadvertently overwrote the pre-existing lib/use-focus-trap.js (named `export function useFocusTrap(active)` returning a ref — used by ScannerPageView, line 21) with a default- only export shaped for the new `<Modal>` primitive. Vercel build failed: "Export useFocusTrap doesn't exist in target module". Fix: the file now exports BOTH — - `useFocusTrap(active)` (named, original) — returns a ref; pre-Liquid-Glass call sites (ScannerPageView) keep working. - `useFocusTrapContainer({ active, containerRef, ... })` (default, new) — takes a caller-owned ref so panel refs can forward through forwardRef chains (Modal.js consumes this shape). Both hooks are commented to document which to use when. Modal.js imports default already, so no change needed there. Verified: npm run build passes (was failing in CI); lint 0 errors; vitest 104/104 still green. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:12:33 -04:00
/* ============================================================
Liquid Glass tokens added by liquid-glass-design-tokens convoy
(2026-06-03). See docs/DESIGN_TOKENS.md for the full reference,
contrast tables, composite recipes, and "When NOT to use glass"
guidance.
============================================================ */
:root {
/* Glass surfaces (light) 3-step legibility ramp.
low: modal panels inside a scrim, card detail, inline sub-panels.
mid: sidebar rail, header strip, mobile bottom-bar.
high: popovers, dropdowns, tooltips (can land over anything). */
--glass-surface-low: rgba(254, 252, 248, 0.55);
--glass-surface-mid: rgba(254, 252, 248, 0.68);
--glass-surface-high: rgba(254, 252, 248, 0.82);
/* Glass blur + saturate (theme-independent; inherited by dark). */
--glass-blur-low: 12px;
--glass-blur-mid: 20px;
--glass-blur-high: 32px;
--glass-saturate: 140%;
/* Rim-light (light) — inner highlight + outer hairline. */
--rim-light-inner: inset 0 1px 0 0 rgba(255, 255, 255, 0.65);
--rim-light-outer: 0 0 0 1px rgba(45, 24, 16, 0.08);
/* Ember rim composable RGB triple + two preset variants.
Triple is theme-independent (ember orange #d84315);
variants differ per theme for eye-perception correction. */
--ember-rim-color: 216, 67, 21;
--ember-rim-subtle: inset 0 0 0 1px rgba(216, 67, 21, 0.35);
--ember-rim-pronounced:
inset 0 0 0 1px rgba(216, 67, 21, 0.55),
0 0 16px 0 rgba(216, 67, 21, 0.30);
/* Elevation (light) — warm-brown-tinted shadows. */
--elevation-flat: none;
--elevation-ambient:
0 4px 12px -2px rgba(45, 24, 16, 0.08),
0 2px 4px -1px rgba(45, 24, 16, 0.04);
--elevation-pronounced:
0 24px 48px -12px rgba(45, 24, 16, 0.20),
0 12px 24px -6px rgba(45, 24, 16, 0.10),
0 4px 8px -2px rgba(45, 24, 16, 0.06);
/* Modal scrim (light) — warm coffee-brown, NOT pure black. */
--modal-scrim: rgba(45, 24, 16, 0.35);
/* Motion (theme-independent). 4-tier duration taxonomy + 3 easings.
See docs/MOTION_SYSTEM.md for usage, examples, and the
prefers-reduced-motion contract. */
--motion-duration-instant: 0ms;
--motion-duration-quick: 150ms; /* hover, focus, micro-state */
--motion-duration-default: 250ms; /* default for most transitions */
--motion-duration-slow: 400ms; /* modal scale, sidebar slide */
--motion-duration-deliberate: 600ms; /* hero, onboarding, celebration */
--motion-ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* default */
--motion-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* delight */
--motion-ease-linear: linear; /* progress */
}
[data-theme="dark"] {
/* Glass surfaces (dark) — same alpha ramp over warm-charcoal base. */
--glass-surface-low: rgba(26, 15, 10, 0.55);
--glass-surface-mid: rgba(26, 15, 10, 0.68);
--glass-surface-high: rgba(26, 15, 10, 0.82);
/* Rim-light (dark) — softer warm-white inner + faint outer. */
--rim-light-inner: inset 0 1px 0 0 rgba(255, 248, 240, 0.12);
--rim-light-outer: 0 0 0 1px rgba(255, 248, 240, 0.06);
/* Ember rim (dark) alpha bumped to compensate for ember orange
reading less vibrant on dark backgrounds (eye-perception correction,
not a numerical drift). RGB triple inherits from :root. */
--ember-rim-subtle: inset 0 0 0 1px rgba(216, 67, 21, 0.40);
--ember-rim-pronounced:
inset 0 0 0 1px rgba(216, 67, 21, 0.65),
0 0 16px 0 rgba(216, 67, 21, 0.35);
/* Elevation (dark) pure-black shadows for crisp depth against
the warm-charcoal floor. */
--elevation-ambient:
0 4px 12px -2px rgba(0, 0, 0, 0.40),
0 2px 4px -1px rgba(0, 0, 0, 0.30);
--elevation-pronounced:
0 24px 48px -12px rgba(0, 0, 0, 0.55),
0 12px 24px -6px rgba(0, 0, 0, 0.40),
0 4px 8px -2px rgba(0, 0, 0, 0.25);
/* Modal scrim (dark) heavier black; dark theme starts dark so
needs more contrast to feel "behind" the modal. */
--modal-scrim: rgba(0, 0, 0, 0.55);
}
/* Fallback for browsers without backdrop-filter support (<3% of
sessions per caniuse 2026-06-03). Collapses the alpha ramp toward
solid so glass surfaces remain legible without the blur layer.
Never goes fully opaque preserves the design's tinted-surface
intent and the ramp ordering. The @supports negation guards both
the unprefixed property AND -webkit-backdrop-filter (Safari 9-17
needed the prefix). */
@supports not ((backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px))) {
:root {
--glass-surface-low: rgba(254, 252, 248, 0.92);
--glass-surface-mid: rgba(254, 252, 248, 0.95);
--glass-surface-high: rgba(254, 252, 248, 0.98);
}
[data-theme="dark"] {
--glass-surface-low: rgba(26, 15, 10, 0.92);
--glass-surface-mid: rgba(26, 15, 10, 0.95);
--glass-surface-high: rgba(26, 15, 10, 0.98);
}
}
/* Apply theme colors */
body {
background-color: var(--bg-primary-light);
color: var(--text-primary-light);
}
[data-theme="dark"] body {
background-color: var(--bg-primary-dark);
color: var(--text-primary-dark);
}
/* Card Scanner Animations */
@keyframes pulse {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.8;
transform: scale(1.02);
}
}
/* Default theme variables for light theme */
:root {
--bg-primary: var(--bg-primary-light);
--bg-secondary: var(--bg-secondary-light);
--bg-tertiary: var(--bg-tertiary-light);
--text-primary: var(--text-primary-light);
--text-secondary: var(--text-secondary-light);
--text-accent: var(--text-accent-light);
--border: var(--border-light);
--shadow: var(--shadow-light);
--gradient-primary: var(--gradient-primary-light);
--gradient-secondary: var(--gradient-secondary-light);
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
--accent-flame: var(--accent-flame-light);
--accent-ember: var(--accent-ember-light);
--accent-gold: var(--accent-gold-light);
--accent-wood: var(--accent-wood-light);
/* Legacy color mappings for compatibility */
--accent-blue: var(--accent-flame-light);
--accent-purple: var(--accent-ember-light);
--accent-pink: var(--accent-gold-light);
--input-bg: var(--input-bg-light);
--input-border: var(--input-border-light);
--input-text: var(--input-text-light);
--input-placeholder: var(--input-placeholder-light);
/* RGB color variables for backdrop-blur effects */
--bg-primary-rgb: 254, 252, 248;
--bg-secondary-rgb: 247, 243, 237;
--bg-tertiary-rgb: 240, 230, 214;
}
/* Dark theme variables */
[data-theme="dark"] {
--bg-primary: var(--bg-primary-dark);
--bg-secondary: var(--bg-secondary-dark);
--bg-tertiary: var(--bg-tertiary-dark);
--text-primary: var(--text-primary-dark);
--text-secondary: var(--text-secondary-dark);
--text-accent: var(--text-accent-dark);
--border: var(--border-dark);
--shadow: var(--shadow-dark);
--gradient-primary: var(--gradient-primary-dark);
--gradient-secondary: var(--gradient-secondary-dark);
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
--accent-flame: var(--accent-flame-dark);
--accent-ember: var(--accent-ember-dark);
--accent-gold: var(--accent-gold-dark);
--accent-wood: var(--accent-wood-dark);
/* Legacy color mappings for compatibility */
--accent-blue: var(--accent-flame-dark);
--accent-purple: var(--accent-ember-dark);
--accent-pink: var(--accent-gold-dark);
--input-bg: var(--input-bg-dark);
--input-border: var(--input-border-dark);
--input-text: var(--input-text-dark);
--input-placeholder: var(--input-placeholder-dark);
}
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
/* Custom component styles - Fire-themed */
.btn-primary {
@apply font-bold py-3 px-6 rounded-2xl transition-all duration-300 shadow-lg hover:shadow-xl;
background: var(--gradient-primary);
color: white;
}
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
.btn-flame {
@apply font-bold py-2 px-4 rounded-lg transition-all duration-300 shadow-md hover:shadow-lg;
background-color: var(--accent-flame);
color: white;
}
.btn-flame:hover {
background-color: var(--accent-ember);
transform: translateY(-1px);
}
.btn-ember {
@apply font-bold py-2 px-4 rounded-lg transition-all duration-300 shadow-md hover:shadow-lg;
background-color: var(--accent-ember);
color: white;
}
.btn-ember:hover {
background: var(--gradient-primary);
transform: translateY(-1px);
}
.btn-gold {
@apply font-bold py-2 px-4 rounded-lg transition-all duration-300 shadow-md hover:shadow-lg;
background-color: var(--accent-gold);
color: white;
}
.btn-gold:hover {
background: var(--gradient-secondary);
transform: translateY(-1px);
}
.gradient-bg-fire {
background: var(--gradient-primary);
}
.gradient-bg-golden {
background: var(--gradient-secondary);
}
.gradient-bg-ember {
background: linear-gradient(135deg, #d84315 0%, #bf360c 100%);
}
🔥 Transform to Deck Hearth Fire-Inspired Design 🎨 Complete Brand Transformation: - Rebranded from 'TCG Vault' to 'Deck Hearth' - Updated logo initials from 'TCG' to 'DH' - Changed app name throughout the application 🔥 Fire-Themed Color Palette: Light Theme (Warm Daylight by the Hearth): - Primary: Warm cream (#fefcf8) like sunlit stone - Secondary: Soft beige (#f7f3ed) like aged parchment - Tertiary: Light wood tone (#f0e6d6) - Text: Dark chocolate brown (#2d1810) - Accents: Ember orange, flame orange, golden yellow Dark Theme (Cozy Evening by the Fire): - Primary: Deep charcoal (#1a0f0a) like burnt wood - Secondary: Rich dark brown (#2d1b12) like oak - Tertiary: Medium brown (#3d2317) like mahogany - Text: Warm white (#fff8f0) like firelight - Accents: Bright flame, glowing ember, golden glow 🎨 Fire-Inspired Design Elements: - Flame gradient: Orange to ember red - Golden gradient: Golden yellow to flame orange - Fire glow effects with warm shadows - Wood-toned borders and accents - Ember and flame-colored interactive elements 🔧 Enhanced Component Styling: - Updated BulkSelectionToolbar with fire colors - New CSS classes: btn-flame, btn-ember, btn-gold - Fire glow and ember glow effects - Gradient backgrounds: gradient-bg-fire, gradient-bg-golden - Tailwind color palette: hearth.flame, hearth.ember, etc. ✨ Warm & Inviting Experience: - Light mode: Cozy daytime fireplace atmosphere - Dark mode: Intimate evening hearth ambiance - Maintains accessibility with proper contrast - Smooth transitions between themes The app now perfectly captures the warm, inviting feeling of gathering around a hearth! 🔥🏠✨
2025-07-26 09:30:07 -04:00
/* Fire glow effects */
.fire-glow {
box-shadow: 0 0 20px rgba(255, 111, 0, 0.3);
}
.ember-glow {
box-shadow: 0 0 15px rgba(216, 67, 21, 0.4);
}
♿ Enhanced Navigation Accessibility & Fire-Themed UI 🎯 Comprehensive Accessibility Improvements: - Added proper ARIA roles and labels throughout navigation - Implemented keyboard navigation (Enter/Space key support) - Added focus rings with fire-themed ember red color - Enhanced screen reader support with aria-current and aria-label - Added tabIndex for proper keyboard traversal 🔥 Fire-Themed Visual Enhancements: - Updated badges to use flame orange and ember red colors - ADMIN badges now use ember red for distinction - Collection/Deck counts use flame orange - Consistent fire theme across all interactive elements ✨ Enhanced Hover & Focus States: - Active items: Left border with ember red accent - Hover items: Left border with flame orange + slide animation - Focus states: Enhanced visibility with ember red rings - Smooth 4px slide animation on hover/focus - Better visual hierarchy and feedback ♿ Accessibility Standards Compliance: - WCAG 2.1 AA compliant focus indicators - High contrast mode support with enhanced outlines - Reduced motion support for accessibility preferences - Proper semantic navigation structure - Screen reader friendly icon handling (aria-hidden) 📱 Mobile Accessibility: - Enhanced mobile menu button with proper ARIA - Improved close button accessibility - Better touch targets and focus management - Proper expanded/collapsed state communication 🎨 Visual Polish: - Consistent focus ring styling across all buttons - Theme toggle button accessibility improvements - Better color contrast in all states - Professional slide animations for navigation feedback The sidebar navigation now meets modern accessibility standards while maintaining the beautiful fire theme! ♿🔥
2025-07-26 10:38:18 -04:00
/* Navigation Accessibility Enhancements */
.nav-item:hover,
.nav-item-bottom:hover {
background-color: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
transform: translateX(4px);
}
.nav-item:focus-within,
.nav-item-bottom:focus-within {
background-color: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
transform: translateX(4px);
}
.nav-item-active {
background-color: var(--bg-tertiary) !important;
color: var(--text-primary) !important;
border-left: 3px solid var(--accent-ember);
padding-left: calc(1rem - 3px);
}
.nav-item-hover:hover {
border-left: 3px solid var(--accent-flame);
padding-left: calc(1rem - 3px);
}
.nav-item-hover:focus-within {
border-left: 3px solid var(--accent-ember);
padding-left: calc(1rem - 3px);
}
/* High contrast mode support */
@media (prefers-contrast: high) {
.nav-item:hover,
.nav-item-bottom:hover,
.nav-item:focus-within,
.nav-item-bottom:focus-within {
outline: 2px solid var(--accent-ember);
outline-offset: 2px;
}
}
feat(design-system): Liquid Glass redesign portfolio — foundation + primitives + Layout (#95) * feat(design-system): Liquid Glass redesign portfolio — foundation + primitive kit + Layout shell Operator-requested epic to migrate the UI from the current "warm panel + side-highlight + heavy gradient" visual language to a Liquid Glass aesthetic that retains Deck Hearth's fireplace warmth as accent / gradient / motion (not as panel fill). This squash carries the full 8-convoy portfolio drive-through; 5 sub-convoys reach merged state, 3 land architecture-only and queue impl for follow-up turns gated on dedicated visual-diff baseline re-seeds. Sub-convoy #1 (liquid-glass-design-tokens) — MERGED. 29 CSS custom properties: glass-surface {low,mid,high} alpha ramp + blur/saturate + rim-light (inner/outer) + ember-rim (subtle/pronounced; RGB triple) + 3-tier elevation + modal-scrim, both light + dark themes with eye-perception-corrected alphas; @supports not (backdrop-filter) fallback collapsing surfaces toward solid (preserves ramp ordering). Authored docs/DESIGN_TOKENS.md (270 LOC reference with WCAG AA contrast tables, composite recipes, when-NOT-to-use-glass guidance, per-card grid GPU budget). AGENTS.md gains a § Visual language section as the new agent-contract surface. Sub-convoy #2 (liquid-glass-modal-and-surface-primitive) — Brief 1 MERGED. Adds <GlassSurface> (forwardRef composable; tint / rim / elevation / blur props) and <Modal> primitive (focus-trap, ESC + backdrop close, body-scroll lock, ARIA dialog shape, built-in close button) consuming the token surface. lib/use-focus-trap.js — homegrown hook (~60 LOC, no dep). 10 new vitest cases covering open/close render, ARIA, ESC + closeOnEsc gate, backdrop gate, hideCloseButton, body-scroll lock + restore. 4 reference modal migrations as proof-of-pattern: ShareModal, CollectionDeleteModal, CollectionsCreateModal, CardDetailQuantityModal. Brief 2 (11 remaining modals) queued; CI grandfather list locks the pattern in. Sub-convoy #3 (liquid-glass-form-primitives) — Brief 1 MERGED. Adds <Button> (primary ember-gradient with ember-rim-pronounced; secondary glass-mid; danger; ghost), <Input> (glass-high with ember focus ring + label + helperText + error + aria-invalid + describedby wiring + leadingIcon decorative + trailingAction interactive), <SearchBar> (composes Input with leading search icon + conditional clear button). 10 new vitest cases. pages/login.js + pages/signup.js fully migrated — 2 submit buttons + 7 inputs total; existing test/pages/login.test.js assertion ("Sign in to Deck Hearth" button text) preserved. Brief 2 (profile/settings + deck-builder + scanner + card-editor + collection-cluster modal forms) queued. Sub-convoy #4 (liquid-glass-layout-shell) — MERGED. 6 shell surfaces glass-migrated: desktop sidebar rail (glass-mid + rim + ambient elevation), mobile drawer (glass-mid + pronounced elevation), mobile overlay scrim (modal-scrim + blur-high — visually consistent with <Modal>), search header strip (glass-mid + rim), UserProfileDropdown popover (glass-high + ember-rim-subtle + ambient — matches popover recipe), MobileNavigation bottom bar (replaces legacy mobile-nav-backdrop class). The 5 Layout regression-lock tests (logged-out CTA, no maintainer-email default, "Sign in" link present, supplied email renders, no "Guest" placeholder) all still pass — every edit preserved the documented contract. Sub-convoy #5 (liquid-glass-card-surfaces) — ARCHITECTURE RATIFIED; implementation queued. Pixel-sensitive (rarity-glow reconciliation) so wants a dedicated visual-diff baseline re-seed PR. Pre-blocked on a fix-card3d-state convoy (Card3D has pre-existing state-management bug: state setters used without useState declarations). Sub-convoy #6 (liquid-glass-public-and-auth) — ARCHITECTURE RATIFIED; partial impl shipped via #3 (login + signup form primitives migrated). Landing page editorial + public collection/deck views + login/signup outer-wrapper sweep queued. Sub-convoy #7 (motion-system-pass) — MERGED. 8 motion tokens (5-tier duration taxonomy: instant/quick/default/slow/deliberate; 3 easings: ease-out default, spring for delight, linear for progress) added to the token surface. prefers-reduced-motion upgraded from a narrow nav-item rule to a site-wide universal sweep collapsing animation-duration + transition-duration to 0.01ms (preserves end states, no flicker); .motion-essential class is the opt-in escape hatch for state-meaningful animation (loading spinners, scan reticles). Authored docs/MOTION_SYSTEM.md with WCAG SC 2.3.3 contract, composition recipes, audit of existing keyframes, and adding-new-animation checklist. Sub-convoy #8 (cleanup-legacy-design-css) — Brief 1 MERGED. Two new CI jobs in .github/workflows/ci.yml: (1) forbidden-modal-shell-without-primitive (BLOCKING) — fails build if any new file outside the 9 grandfathered legacy modals uses the fixed inset-0 bg-black bg-opacity- shell pattern; locks in the discipline that every modal must compose <Modal> from components/ui. (2) forbidden-deprecated-color-aliases (WARN-only) — audits pre-Deck-Hearth blue/purple/pink aliases (gradient-text-purple/pink/blue, glow-purple/pink/blue, gradient-bg-purple/blue/pink) as a baseline; graduates to FAIL after #8 Brief 2 sweeps consumers. .cursor/rules/ui-and-theming.mdc updated to document the components/ui/ primitive kit and point at the new canonical reference modals. Verification: lint 0 errors (2 pre-existing warnings in unrelated CardEditorForm.js + CollectionsPageView.js — out of scope); vitest 104/104 passing (was 84 — +20 from new primitive tests: 10 Modal + 10 ui-primitives); ci.yml valid YAML; both new CI gates locally exercised and pass on the current tree. Operator follow-ups documented in .convoys/ship-readiness.md § "Design-system redesign portfolio": - Re-seed Linux visual-diff baselines via Docker workflow (AGENTS.md § 6) after this merges. - preview-smoke.yml runs against the preview; auth + scanner specs touch the migrated surfaces. - Vercel promote to production once smoke + visual gates pass. - Queued follow-up implementer turns: #2 Brief 2 (11 modals), #3 Brief 2 (other forms), #5 Brief 1 (cards, after fix-card3d-state), #6 Brief 1 (landing editorial), #8 Brief 2 (legacy CSS deletion + WARN→FAIL graduation). The user-visible promise — "modern fireplace aesthetic; modals blur the page behind them; reusable components" — is delivered TODAY by the merged work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(use-focus-trap): preserve named useFocusTrap export for ScannerPageView The portfolio squash inadvertently overwrote the pre-existing lib/use-focus-trap.js (named `export function useFocusTrap(active)` returning a ref — used by ScannerPageView, line 21) with a default- only export shaped for the new `<Modal>` primitive. Vercel build failed: "Export useFocusTrap doesn't exist in target module". Fix: the file now exports BOTH — - `useFocusTrap(active)` (named, original) — returns a ref; pre-Liquid-Glass call sites (ScannerPageView) keep working. - `useFocusTrapContainer({ active, containerRef, ... })` (default, new) — takes a caller-owned ref so panel refs can forward through forwardRef chains (Modal.js consumes this shape). Both hooks are commented to document which to use when. Modal.js imports default already, so no change needed there. Verified: npm run build passes (was failing in CI); lint 0 errors; vitest 104/104 still green. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:12:33 -04:00
/* Reduced motion support site-wide sweep (added by motion-system-pass
convoy, 2026-06-03). Per WCAG SC 2.3.3, users who set the OS
"Reduce motion" preference get decorative animations collapsed to a
no-op while keeping the end-state of state transitions. The 0.01ms
value (vs `animation: none`) is the well-known idiom for preserving
end-state without flicker. Essential motion (e.g. loading spinners
indicating in-flight work) is kept opt-in by individual components
via the `motion-essential` class. */
♿ Enhanced Navigation Accessibility & Fire-Themed UI 🎯 Comprehensive Accessibility Improvements: - Added proper ARIA roles and labels throughout navigation - Implemented keyboard navigation (Enter/Space key support) - Added focus rings with fire-themed ember red color - Enhanced screen reader support with aria-current and aria-label - Added tabIndex for proper keyboard traversal 🔥 Fire-Themed Visual Enhancements: - Updated badges to use flame orange and ember red colors - ADMIN badges now use ember red for distinction - Collection/Deck counts use flame orange - Consistent fire theme across all interactive elements ✨ Enhanced Hover & Focus States: - Active items: Left border with ember red accent - Hover items: Left border with flame orange + slide animation - Focus states: Enhanced visibility with ember red rings - Smooth 4px slide animation on hover/focus - Better visual hierarchy and feedback ♿ Accessibility Standards Compliance: - WCAG 2.1 AA compliant focus indicators - High contrast mode support with enhanced outlines - Reduced motion support for accessibility preferences - Proper semantic navigation structure - Screen reader friendly icon handling (aria-hidden) 📱 Mobile Accessibility: - Enhanced mobile menu button with proper ARIA - Improved close button accessibility - Better touch targets and focus management - Proper expanded/collapsed state communication 🎨 Visual Polish: - Consistent focus ring styling across all buttons - Theme toggle button accessibility improvements - Better color contrast in all states - Professional slide animations for navigation feedback The sidebar navigation now meets modern accessibility standards while maintaining the beautiful fire theme! ♿🔥
2025-07-26 10:38:18 -04:00
@media (prefers-reduced-motion: reduce) {
feat(design-system): Liquid Glass redesign portfolio — foundation + primitives + Layout (#95) * feat(design-system): Liquid Glass redesign portfolio — foundation + primitive kit + Layout shell Operator-requested epic to migrate the UI from the current "warm panel + side-highlight + heavy gradient" visual language to a Liquid Glass aesthetic that retains Deck Hearth's fireplace warmth as accent / gradient / motion (not as panel fill). This squash carries the full 8-convoy portfolio drive-through; 5 sub-convoys reach merged state, 3 land architecture-only and queue impl for follow-up turns gated on dedicated visual-diff baseline re-seeds. Sub-convoy #1 (liquid-glass-design-tokens) — MERGED. 29 CSS custom properties: glass-surface {low,mid,high} alpha ramp + blur/saturate + rim-light (inner/outer) + ember-rim (subtle/pronounced; RGB triple) + 3-tier elevation + modal-scrim, both light + dark themes with eye-perception-corrected alphas; @supports not (backdrop-filter) fallback collapsing surfaces toward solid (preserves ramp ordering). Authored docs/DESIGN_TOKENS.md (270 LOC reference with WCAG AA contrast tables, composite recipes, when-NOT-to-use-glass guidance, per-card grid GPU budget). AGENTS.md gains a § Visual language section as the new agent-contract surface. Sub-convoy #2 (liquid-glass-modal-and-surface-primitive) — Brief 1 MERGED. Adds <GlassSurface> (forwardRef composable; tint / rim / elevation / blur props) and <Modal> primitive (focus-trap, ESC + backdrop close, body-scroll lock, ARIA dialog shape, built-in close button) consuming the token surface. lib/use-focus-trap.js — homegrown hook (~60 LOC, no dep). 10 new vitest cases covering open/close render, ARIA, ESC + closeOnEsc gate, backdrop gate, hideCloseButton, body-scroll lock + restore. 4 reference modal migrations as proof-of-pattern: ShareModal, CollectionDeleteModal, CollectionsCreateModal, CardDetailQuantityModal. Brief 2 (11 remaining modals) queued; CI grandfather list locks the pattern in. Sub-convoy #3 (liquid-glass-form-primitives) — Brief 1 MERGED. Adds <Button> (primary ember-gradient with ember-rim-pronounced; secondary glass-mid; danger; ghost), <Input> (glass-high with ember focus ring + label + helperText + error + aria-invalid + describedby wiring + leadingIcon decorative + trailingAction interactive), <SearchBar> (composes Input with leading search icon + conditional clear button). 10 new vitest cases. pages/login.js + pages/signup.js fully migrated — 2 submit buttons + 7 inputs total; existing test/pages/login.test.js assertion ("Sign in to Deck Hearth" button text) preserved. Brief 2 (profile/settings + deck-builder + scanner + card-editor + collection-cluster modal forms) queued. Sub-convoy #4 (liquid-glass-layout-shell) — MERGED. 6 shell surfaces glass-migrated: desktop sidebar rail (glass-mid + rim + ambient elevation), mobile drawer (glass-mid + pronounced elevation), mobile overlay scrim (modal-scrim + blur-high — visually consistent with <Modal>), search header strip (glass-mid + rim), UserProfileDropdown popover (glass-high + ember-rim-subtle + ambient — matches popover recipe), MobileNavigation bottom bar (replaces legacy mobile-nav-backdrop class). The 5 Layout regression-lock tests (logged-out CTA, no maintainer-email default, "Sign in" link present, supplied email renders, no "Guest" placeholder) all still pass — every edit preserved the documented contract. Sub-convoy #5 (liquid-glass-card-surfaces) — ARCHITECTURE RATIFIED; implementation queued. Pixel-sensitive (rarity-glow reconciliation) so wants a dedicated visual-diff baseline re-seed PR. Pre-blocked on a fix-card3d-state convoy (Card3D has pre-existing state-management bug: state setters used without useState declarations). Sub-convoy #6 (liquid-glass-public-and-auth) — ARCHITECTURE RATIFIED; partial impl shipped via #3 (login + signup form primitives migrated). Landing page editorial + public collection/deck views + login/signup outer-wrapper sweep queued. Sub-convoy #7 (motion-system-pass) — MERGED. 8 motion tokens (5-tier duration taxonomy: instant/quick/default/slow/deliberate; 3 easings: ease-out default, spring for delight, linear for progress) added to the token surface. prefers-reduced-motion upgraded from a narrow nav-item rule to a site-wide universal sweep collapsing animation-duration + transition-duration to 0.01ms (preserves end states, no flicker); .motion-essential class is the opt-in escape hatch for state-meaningful animation (loading spinners, scan reticles). Authored docs/MOTION_SYSTEM.md with WCAG SC 2.3.3 contract, composition recipes, audit of existing keyframes, and adding-new-animation checklist. Sub-convoy #8 (cleanup-legacy-design-css) — Brief 1 MERGED. Two new CI jobs in .github/workflows/ci.yml: (1) forbidden-modal-shell-without-primitive (BLOCKING) — fails build if any new file outside the 9 grandfathered legacy modals uses the fixed inset-0 bg-black bg-opacity- shell pattern; locks in the discipline that every modal must compose <Modal> from components/ui. (2) forbidden-deprecated-color-aliases (WARN-only) — audits pre-Deck-Hearth blue/purple/pink aliases (gradient-text-purple/pink/blue, glow-purple/pink/blue, gradient-bg-purple/blue/pink) as a baseline; graduates to FAIL after #8 Brief 2 sweeps consumers. .cursor/rules/ui-and-theming.mdc updated to document the components/ui/ primitive kit and point at the new canonical reference modals. Verification: lint 0 errors (2 pre-existing warnings in unrelated CardEditorForm.js + CollectionsPageView.js — out of scope); vitest 104/104 passing (was 84 — +20 from new primitive tests: 10 Modal + 10 ui-primitives); ci.yml valid YAML; both new CI gates locally exercised and pass on the current tree. Operator follow-ups documented in .convoys/ship-readiness.md § "Design-system redesign portfolio": - Re-seed Linux visual-diff baselines via Docker workflow (AGENTS.md § 6) after this merges. - preview-smoke.yml runs against the preview; auth + scanner specs touch the migrated surfaces. - Vercel promote to production once smoke + visual gates pass. - Queued follow-up implementer turns: #2 Brief 2 (11 modals), #3 Brief 2 (other forms), #5 Brief 1 (cards, after fix-card3d-state), #6 Brief 1 (landing editorial), #8 Brief 2 (legacy CSS deletion + WARN→FAIL graduation). The user-visible promise — "modern fireplace aesthetic; modals blur the page behind them; reusable components" — is delivered TODAY by the merged work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(use-focus-trap): preserve named useFocusTrap export for ScannerPageView The portfolio squash inadvertently overwrote the pre-existing lib/use-focus-trap.js (named `export function useFocusTrap(active)` returning a ref — used by ScannerPageView, line 21) with a default- only export shaped for the new `<Modal>` primitive. Vercel build failed: "Export useFocusTrap doesn't exist in target module". Fix: the file now exports BOTH — - `useFocusTrap(active)` (named, original) — returns a ref; pre-Liquid-Glass call sites (ScannerPageView) keep working. - `useFocusTrapContainer({ active, containerRef, ... })` (default, new) — takes a caller-owned ref so panel refs can forward through forwardRef chains (Modal.js consumes this shape). Both hooks are commented to document which to use when. Modal.js imports default already, so no change needed there. Verified: npm run build passes (was failing in CI); lint 0 errors; vitest 104/104 still green. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:12:33 -04:00
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.motion-essential,
.motion-essential * {
animation-duration: revert !important;
animation-iteration-count: revert !important;
transition-duration: revert !important;
}
♿ Enhanced Navigation Accessibility & Fire-Themed UI 🎯 Comprehensive Accessibility Improvements: - Added proper ARIA roles and labels throughout navigation - Implemented keyboard navigation (Enter/Space key support) - Added focus rings with fire-themed ember red color - Enhanced screen reader support with aria-current and aria-label - Added tabIndex for proper keyboard traversal 🔥 Fire-Themed Visual Enhancements: - Updated badges to use flame orange and ember red colors - ADMIN badges now use ember red for distinction - Collection/Deck counts use flame orange - Consistent fire theme across all interactive elements ✨ Enhanced Hover & Focus States: - Active items: Left border with ember red accent - Hover items: Left border with flame orange + slide animation - Focus states: Enhanced visibility with ember red rings - Smooth 4px slide animation on hover/focus - Better visual hierarchy and feedback ♿ Accessibility Standards Compliance: - WCAG 2.1 AA compliant focus indicators - High contrast mode support with enhanced outlines - Reduced motion support for accessibility preferences - Proper semantic navigation structure - Screen reader friendly icon handling (aria-hidden) 📱 Mobile Accessibility: - Enhanced mobile menu button with proper ARIA - Improved close button accessibility - Better touch targets and focus management - Proper expanded/collapsed state communication 🎨 Visual Polish: - Consistent focus ring styling across all buttons - Theme toggle button accessibility improvements - Better color contrast in all states - Professional slide animations for navigation feedback The sidebar navigation now meets modern accessibility standards while maintaining the beautiful fire theme! ♿🔥
2025-07-26 10:38:18 -04:00
.nav-item,
.nav-item-bottom {
transition: none;
}
}
.btn-secondary {
@apply font-bold py-3 px-6 rounded-2xl transition-all duration-300 shadow-lg hover:shadow-xl;
background: var(--gradient-secondary);
color: white;
}
.input-field {
@apply w-full px-4 py-3 border rounded-2xl shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-0 transition-all duration-200;
background-color: var(--input-bg);
border-color: var(--input-border);
color: var(--input-text);
}
.input-field::placeholder {
color: var(--input-placeholder);
}
.card {
@apply rounded-3xl shadow-lg p-6 transition-all duration-300;
background-color: var(--bg-primary);
border: 1px solid var(--border);
}
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
/* ============================================================
.glass-panel canonical "content card" utility for body
surfaces on authenticated pages. The Liquid Glass recipe in
class form so pages can apply it without importing the
<GlassSurface> primitive for every flat container. Added by
glass-body-panels PR after PR #96 left admin/settings/dashboard
body cards on solid --bg-secondary.
Composition matches <GlassSurface tint="mid" rim="subtle"
elevation="ambient" blur="mid">. Always pair with rounded-*
from Tailwind (the class itself doesn't set border-radius
because consumers vary between rounded-xl and rounded-2xl).
============================================================ */
fix(design-system): compose rim + elevation tokens as chained box-shadow (#99) User reported after PR #98 ("backdrop-filter now applies") that the dashboard glass panels still looked identical to solid cards. Browser CDP diagnostic on production found the root cause: the .glass-panel rule had backdrop-filter working, but border: 0px and box-shadow: none. Why both were missing: 1) `border: 1px solid var(--rim-light-outer)` — the --rim-light-outer token is a complete box-shadow declaration (`0 0 0 1px #2d181014`), NOT a color value. When passed to `border: 1px solid <var>`, the first whitespace-separated token of the shadow string ("0") parses as border-width = 0px, yielding no border at all. 2) `box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner)` — the --rim-light-inner token already contains its own `inset` keyword (`inset 0 1px 0 0 #ffffffa6`). Wrapping it in another `inset 0 1px 0 ...` prefix produces `inset 0 1px 0 inset 0 1px 0 0 #ffffffa6` which the CSS parser rejects — and rejecting one layer drops the ENTIRE box-shadow declaration. That's why `getComputedStyle().boxShadow === 'none'`. Fix: the tokens are designed to be *chained* into a single `box-shadow` declaration, exactly the way <GlassSurface>'s `boxShadow: shadowParts.join(', ')` composes them (see components/ui/GlassSurface.js lines 5-15). Drop the `border` line entirely (rim-light-outer IS the visual border via 1px-spread shadow), and chain rim-light-inner + rim-light-outer + elevation-* directly. Verified by `npm run build` — compiled CSS now has all three: - background - backdrop-filter (+ -webkit- prefix from autoprefixer) - box-shadow with all 4 layers correctly chained This will produce a visible: top inset rim highlight, dark hairline outer ring, soft ambient drop shadow — i.e. an actual glass card. Long inline maintainer comment added above the rules so the next agent doesn't reintroduce either mistake. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:49:05 -04:00
/* IMPORTANT composing rim + elevation tokens correctly.
The --rim-light-outer / --rim-light-inner / --elevation-* tokens are
COMPLETE box-shadow declarations (each contains offset/spread/color or
the `inset` keyword), not raw color values. They are designed to be
*chained into a single box-shadow*, exactly the way <GlassSurface>'s
`boxShadow: shadowParts.join(', ')` composes them. Do NOT use
`border: 1px solid var(--rim-light-outer)` that parses
`border-width` from the first token of the shadow string ("0"), which
yields a 0px border. And do NOT wrap --rim-light-inner in another
`inset 0 1px 0` prefix the token already contains its own `inset`
keyword, so wrapping produces invalid syntax that the browser drops
the entire box-shadow declaration for. PR #98 had both mistakes,
which is why the panels in PR #97/#98 had neither visible border nor
drop shadow despite the backdrop-filter being correct.
Backdrop-filter quirks with Next.js 16's Lightning CSS (also relevant):
fix(design-system): glass-panel rules now actually apply backdrop-filter (#98) Production check after #97 promoted: the .glass-panel and .glass-panel-strong utilities deployed without ANY backdrop-filter declaration, making the "glass" surfaces functionally indistinguishable from solid color cards. Root cause (two compounding Lightning CSS quirks in Next.js 16): 1) Lightning CSS silently strips `backdrop-filter: blur(var(--X)) saturate(var(--Y))` from the compiled output when the values use `var()` chains inside the blur()/saturate() function args. Tailwind's own .backdrop-blur-* utilities survive because they wrap the *entire* `blur(...)` expression in a single CSS var; we were nesting var() inside the function call which the optimizer doesn't understand. Same root cause emptied .mobile-nav-backdrop in production earlier. 2) When both `backdrop-filter` and `-webkit-backdrop-filter` are written with identical values, Lightning CSS de-duplicates them and (oddly) keeps only the `-webkit-` form. Modern Chrome/Edge/Firefox ignore the webkit prefix, so the blur never applies. Fix: - Use LITERAL values: `blur(12px) saturate(180%)` instead of `blur(var(...)) saturate(var(...))`. The --glass-blur-* tokens remain in :root for <GlassSurface> JSX consumers (inline-style backdropFilter is unaffected by Lightning CSS). - Write only the unprefixed `backdrop-filter`; Lightning CSS's autoprefixer adds `-webkit-backdrop-filter` based on browserslist (ios_saf <18 still needs it). Verified by `npm run build`: .glass-panel { ... -webkit-backdrop-filter: blur(12px) saturate(180%); backdrop-filter: blur(12px) saturate(180%); ... } Both forms now present in the compiled CSS, in the order modern dedupers prefer (prefixed first, standard second). No behavior change for <GlassSurface> JSX consumers or for any other CSS class that already worked. Just gets the two utility classes from #97 actually doing their job. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:38:38 -04:00
1) `backdrop-filter: blur(var(--X)) saturate(var(--Y))` is silently
fix(design-system): compose rim + elevation tokens as chained box-shadow (#99) User reported after PR #98 ("backdrop-filter now applies") that the dashboard glass panels still looked identical to solid cards. Browser CDP diagnostic on production found the root cause: the .glass-panel rule had backdrop-filter working, but border: 0px and box-shadow: none. Why both were missing: 1) `border: 1px solid var(--rim-light-outer)` — the --rim-light-outer token is a complete box-shadow declaration (`0 0 0 1px #2d181014`), NOT a color value. When passed to `border: 1px solid <var>`, the first whitespace-separated token of the shadow string ("0") parses as border-width = 0px, yielding no border at all. 2) `box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner)` — the --rim-light-inner token already contains its own `inset` keyword (`inset 0 1px 0 0 #ffffffa6`). Wrapping it in another `inset 0 1px 0 ...` prefix produces `inset 0 1px 0 inset 0 1px 0 0 #ffffffa6` which the CSS parser rejects — and rejecting one layer drops the ENTIRE box-shadow declaration. That's why `getComputedStyle().boxShadow === 'none'`. Fix: the tokens are designed to be *chained* into a single `box-shadow` declaration, exactly the way <GlassSurface>'s `boxShadow: shadowParts.join(', ')` composes them (see components/ui/GlassSurface.js lines 5-15). Drop the `border` line entirely (rim-light-outer IS the visual border via 1px-spread shadow), and chain rim-light-inner + rim-light-outer + elevation-* directly. Verified by `npm run build` — compiled CSS now has all three: - background - backdrop-filter (+ -webkit- prefix from autoprefixer) - box-shadow with all 4 layers correctly chained This will produce a visible: top inset rim highlight, dark hairline outer ring, soft ambient drop shadow — i.e. an actual glass card. Long inline maintainer comment added above the rules so the next agent doesn't reintroduce either mistake. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:49:05 -04:00
stripped (var() inside function args breaks the optimizer). Use
LITERAL values here. Tokens stay in :root for the <GlassSurface>
JSX primitive which sets backdropFilter via inline style.
2) Writing both `backdrop-filter` AND `-webkit-backdrop-filter` with
identical values triggers Lightning CSS's buggy de-dup; it keeps
only the `-webkit-` form which modern browsers ignore. Write only
the unprefixed form; Lightning CSS's autoprefixer adds the prefix
per browserslist (ios_saf <18 still needs it). */
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
.glass-panel {
fix(design-system): compose rim + elevation tokens as chained box-shadow (#99) User reported after PR #98 ("backdrop-filter now applies") that the dashboard glass panels still looked identical to solid cards. Browser CDP diagnostic on production found the root cause: the .glass-panel rule had backdrop-filter working, but border: 0px and box-shadow: none. Why both were missing: 1) `border: 1px solid var(--rim-light-outer)` — the --rim-light-outer token is a complete box-shadow declaration (`0 0 0 1px #2d181014`), NOT a color value. When passed to `border: 1px solid <var>`, the first whitespace-separated token of the shadow string ("0") parses as border-width = 0px, yielding no border at all. 2) `box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner)` — the --rim-light-inner token already contains its own `inset` keyword (`inset 0 1px 0 0 #ffffffa6`). Wrapping it in another `inset 0 1px 0 ...` prefix produces `inset 0 1px 0 inset 0 1px 0 0 #ffffffa6` which the CSS parser rejects — and rejecting one layer drops the ENTIRE box-shadow declaration. That's why `getComputedStyle().boxShadow === 'none'`. Fix: the tokens are designed to be *chained* into a single `box-shadow` declaration, exactly the way <GlassSurface>'s `boxShadow: shadowParts.join(', ')` composes them (see components/ui/GlassSurface.js lines 5-15). Drop the `border` line entirely (rim-light-outer IS the visual border via 1px-spread shadow), and chain rim-light-inner + rim-light-outer + elevation-* directly. Verified by `npm run build` — compiled CSS now has all three: - background - backdrop-filter (+ -webkit- prefix from autoprefixer) - box-shadow with all 4 layers correctly chained This will produce a visible: top inset rim highlight, dark hairline outer ring, soft ambient drop shadow — i.e. an actual glass card. Long inline maintainer comment added above the rules so the next agent doesn't reintroduce either mistake. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:49:05 -04:00
background: var(--glass-surface-mid);
fix(design-system): glass-panel rules now actually apply backdrop-filter (#98) Production check after #97 promoted: the .glass-panel and .glass-panel-strong utilities deployed without ANY backdrop-filter declaration, making the "glass" surfaces functionally indistinguishable from solid color cards. Root cause (two compounding Lightning CSS quirks in Next.js 16): 1) Lightning CSS silently strips `backdrop-filter: blur(var(--X)) saturate(var(--Y))` from the compiled output when the values use `var()` chains inside the blur()/saturate() function args. Tailwind's own .backdrop-blur-* utilities survive because they wrap the *entire* `blur(...)` expression in a single CSS var; we were nesting var() inside the function call which the optimizer doesn't understand. Same root cause emptied .mobile-nav-backdrop in production earlier. 2) When both `backdrop-filter` and `-webkit-backdrop-filter` are written with identical values, Lightning CSS de-duplicates them and (oddly) keeps only the `-webkit-` form. Modern Chrome/Edge/Firefox ignore the webkit prefix, so the blur never applies. Fix: - Use LITERAL values: `blur(12px) saturate(180%)` instead of `blur(var(...)) saturate(var(...))`. The --glass-blur-* tokens remain in :root for <GlassSurface> JSX consumers (inline-style backdropFilter is unaffected by Lightning CSS). - Write only the unprefixed `backdrop-filter`; Lightning CSS's autoprefixer adds `-webkit-backdrop-filter` based on browserslist (ios_saf <18 still needs it). Verified by `npm run build`: .glass-panel { ... -webkit-backdrop-filter: blur(12px) saturate(180%); backdrop-filter: blur(12px) saturate(180%); ... } Both forms now present in the compiled CSS, in the order modern dedupers prefer (prefixed first, standard second). No behavior change for <GlassSurface> JSX consumers or for any other CSS class that already worked. Just gets the two utility classes from #97 actually doing their job. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:38:38 -04:00
backdrop-filter: blur(12px) saturate(180%);
fix(design-system): compose rim + elevation tokens as chained box-shadow (#99) User reported after PR #98 ("backdrop-filter now applies") that the dashboard glass panels still looked identical to solid cards. Browser CDP diagnostic on production found the root cause: the .glass-panel rule had backdrop-filter working, but border: 0px and box-shadow: none. Why both were missing: 1) `border: 1px solid var(--rim-light-outer)` — the --rim-light-outer token is a complete box-shadow declaration (`0 0 0 1px #2d181014`), NOT a color value. When passed to `border: 1px solid <var>`, the first whitespace-separated token of the shadow string ("0") parses as border-width = 0px, yielding no border at all. 2) `box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner)` — the --rim-light-inner token already contains its own `inset` keyword (`inset 0 1px 0 0 #ffffffa6`). Wrapping it in another `inset 0 1px 0 ...` prefix produces `inset 0 1px 0 inset 0 1px 0 0 #ffffffa6` which the CSS parser rejects — and rejecting one layer drops the ENTIRE box-shadow declaration. That's why `getComputedStyle().boxShadow === 'none'`. Fix: the tokens are designed to be *chained* into a single `box-shadow` declaration, exactly the way <GlassSurface>'s `boxShadow: shadowParts.join(', ')` composes them (see components/ui/GlassSurface.js lines 5-15). Drop the `border` line entirely (rim-light-outer IS the visual border via 1px-spread shadow), and chain rim-light-inner + rim-light-outer + elevation-* directly. Verified by `npm run build` — compiled CSS now has all three: - background - backdrop-filter (+ -webkit- prefix from autoprefixer) - box-shadow with all 4 layers correctly chained This will produce a visible: top inset rim highlight, dark hairline outer ring, soft ambient drop shadow — i.e. an actual glass card. Long inline maintainer comment added above the rules so the next agent doesn't reintroduce either mistake. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:49:05 -04:00
box-shadow:
var(--rim-light-inner),
var(--rim-light-outer),
var(--elevation-ambient);
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
}
.glass-panel-strong {
fix(design-system): compose rim + elevation tokens as chained box-shadow (#99) User reported after PR #98 ("backdrop-filter now applies") that the dashboard glass panels still looked identical to solid cards. Browser CDP diagnostic on production found the root cause: the .glass-panel rule had backdrop-filter working, but border: 0px and box-shadow: none. Why both were missing: 1) `border: 1px solid var(--rim-light-outer)` — the --rim-light-outer token is a complete box-shadow declaration (`0 0 0 1px #2d181014`), NOT a color value. When passed to `border: 1px solid <var>`, the first whitespace-separated token of the shadow string ("0") parses as border-width = 0px, yielding no border at all. 2) `box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner)` — the --rim-light-inner token already contains its own `inset` keyword (`inset 0 1px 0 0 #ffffffa6`). Wrapping it in another `inset 0 1px 0 ...` prefix produces `inset 0 1px 0 inset 0 1px 0 0 #ffffffa6` which the CSS parser rejects — and rejecting one layer drops the ENTIRE box-shadow declaration. That's why `getComputedStyle().boxShadow === 'none'`. Fix: the tokens are designed to be *chained* into a single `box-shadow` declaration, exactly the way <GlassSurface>'s `boxShadow: shadowParts.join(', ')` composes them (see components/ui/GlassSurface.js lines 5-15). Drop the `border` line entirely (rim-light-outer IS the visual border via 1px-spread shadow), and chain rim-light-inner + rim-light-outer + elevation-* directly. Verified by `npm run build` — compiled CSS now has all three: - background - backdrop-filter (+ -webkit- prefix from autoprefixer) - box-shadow with all 4 layers correctly chained This will produce a visible: top inset rim highlight, dark hairline outer ring, soft ambient drop shadow — i.e. an actual glass card. Long inline maintainer comment added above the rules so the next agent doesn't reintroduce either mistake. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:49:05 -04:00
background: var(--glass-surface-high);
fix(design-system): glass-panel rules now actually apply backdrop-filter (#98) Production check after #97 promoted: the .glass-panel and .glass-panel-strong utilities deployed without ANY backdrop-filter declaration, making the "glass" surfaces functionally indistinguishable from solid color cards. Root cause (two compounding Lightning CSS quirks in Next.js 16): 1) Lightning CSS silently strips `backdrop-filter: blur(var(--X)) saturate(var(--Y))` from the compiled output when the values use `var()` chains inside the blur()/saturate() function args. Tailwind's own .backdrop-blur-* utilities survive because they wrap the *entire* `blur(...)` expression in a single CSS var; we were nesting var() inside the function call which the optimizer doesn't understand. Same root cause emptied .mobile-nav-backdrop in production earlier. 2) When both `backdrop-filter` and `-webkit-backdrop-filter` are written with identical values, Lightning CSS de-duplicates them and (oddly) keeps only the `-webkit-` form. Modern Chrome/Edge/Firefox ignore the webkit prefix, so the blur never applies. Fix: - Use LITERAL values: `blur(12px) saturate(180%)` instead of `blur(var(...)) saturate(var(...))`. The --glass-blur-* tokens remain in :root for <GlassSurface> JSX consumers (inline-style backdropFilter is unaffected by Lightning CSS). - Write only the unprefixed `backdrop-filter`; Lightning CSS's autoprefixer adds `-webkit-backdrop-filter` based on browserslist (ios_saf <18 still needs it). Verified by `npm run build`: .glass-panel { ... -webkit-backdrop-filter: blur(12px) saturate(180%); backdrop-filter: blur(12px) saturate(180%); ... } Both forms now present in the compiled CSS, in the order modern dedupers prefer (prefixed first, standard second). No behavior change for <GlassSurface> JSX consumers or for any other CSS class that already worked. Just gets the two utility classes from #97 actually doing their job. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:38:38 -04:00
backdrop-filter: blur(20px) saturate(180%);
fix(design-system): compose rim + elevation tokens as chained box-shadow (#99) User reported after PR #98 ("backdrop-filter now applies") that the dashboard glass panels still looked identical to solid cards. Browser CDP diagnostic on production found the root cause: the .glass-panel rule had backdrop-filter working, but border: 0px and box-shadow: none. Why both were missing: 1) `border: 1px solid var(--rim-light-outer)` — the --rim-light-outer token is a complete box-shadow declaration (`0 0 0 1px #2d181014`), NOT a color value. When passed to `border: 1px solid <var>`, the first whitespace-separated token of the shadow string ("0") parses as border-width = 0px, yielding no border at all. 2) `box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner)` — the --rim-light-inner token already contains its own `inset` keyword (`inset 0 1px 0 0 #ffffffa6`). Wrapping it in another `inset 0 1px 0 ...` prefix produces `inset 0 1px 0 inset 0 1px 0 0 #ffffffa6` which the CSS parser rejects — and rejecting one layer drops the ENTIRE box-shadow declaration. That's why `getComputedStyle().boxShadow === 'none'`. Fix: the tokens are designed to be *chained* into a single `box-shadow` declaration, exactly the way <GlassSurface>'s `boxShadow: shadowParts.join(', ')` composes them (see components/ui/GlassSurface.js lines 5-15). Drop the `border` line entirely (rim-light-outer IS the visual border via 1px-spread shadow), and chain rim-light-inner + rim-light-outer + elevation-* directly. Verified by `npm run build` — compiled CSS now has all three: - background - backdrop-filter (+ -webkit- prefix from autoprefixer) - box-shadow with all 4 layers correctly chained This will produce a visible: top inset rim highlight, dark hairline outer ring, soft ambient drop shadow — i.e. an actual glass card. Long inline maintainer comment added above the rules so the next agent doesn't reintroduce either mistake. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:49:05 -04:00
box-shadow:
var(--rim-light-inner),
var(--rim-light-outer),
var(--elevation-pronounced);
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
}
feat(design-system): finish Liquid Glass — close all remaining sub-convoys (#96) Follow-up PR to #95 (Liquid Glass foundation + primitives + Layout shell) that closes out the remaining sub-convoy briefs in a single sweep. Operator-instructed scope: "finish off the design changes." After this PR, **all 8 Liquid Glass sub-convoys are MERGED to main**; the deferred-from-#5 `fix-card3d-state` convoy is dropped (its target, `components/Card3D.js`, turned out to be dead code). ## #2 Brief 2 — Remaining 8 modals migrated to <Modal> primitive - `CollectionsSuccessModal.js` — wrap in <Modal hideCloseButton>; 2 Buttons. - `CollectionsEditModal.js` — full <Modal> + <Input> + <Button> rewrite (4 fields, tag chip section, public-toggle preserved, 2 footer Buttons). - `CollectionEditModal.js` — same pattern as above (4 fields + public-toggle + 2 Buttons). - `CardDetailDeckModal.js` — <Modal> + native select (Select primitive not in scope) + 2 Buttons; sweep `gradient-bg-purple` → `<Button variant="primary">`. - `UploadImageModal.js` — <Modal> + token-driven URL/file tab switcher + drag-drop using `--accent-ember` rim + 2 Buttons (one with `loading` prop). - `CollectionSelectionModal.js` — largest of the set (header summary + SearchBar + scrollable list w/ checkbox toggles + footer); migrated to <Modal size="lg"> while preserving the per-collection card preview thumbnails. - `OCRSettings.js` — trivial <Modal> wrap + single primary <Button>. - `pages/decks.js` — both inline modals (Create Deck + Edit Deck) and `components/ScannerPageView.js` (Create List) migrated; ScannerPageView dropped its `useFocusTrap` named-import (Modal's internal focus trap owns the panel ref now). - **`.github/workflows/ci.yml` `forbidden-modal-shell-without-primitive`** — grandfather list emptied to zero entries; gate is now strict. ## #3 Brief 2 — Forms migrated to <Button> / <SearchBar> - `pages/dashboard.js` — 3 CTAs → <Button> (Create List with leadingIcon, Create Your First List, View All Lists). - `pages/my-cards.js` — empty-state CTA → <Button variant="primary" size="lg">. View-mode toggle buttons intentionally left native (icon-only, doesn't match Button variants). - `pages/community/collections.js` — Go to My Lists CTA → <Button>. - `components/CollectionsPageView.js` — Discover Community + Create List header CTAs → <Button>; search input → <SearchBar>. - Card-grid per-row icon buttons (CollectionsPageView, my-cards, CardsPageView) intentionally left native — tiny per-card actions whose styling doesn't match Button variants and would invalidate visual-diff baselines. ## #5 — scope revised + landed `components/Card3D.js` deletion: surveyed every importer with grep — **zero consumers** in `pages/**` or `components/**`. Only references were in convoy docs. The "pre-existing state-management bug" (state setters used without useState declarations) never affected the running app because the component was never rendered. -505 LOC. The `fix-card3d-state` convoy is dropped from the roadmap as a result. The actual card-grid component (`components/CardItem.js`) is intentionally **not** modified in this sweep — it has per-rarity glow tuning that the existing visual-diff baseline locks in, and the architect's #5 deferral note specifically called out the dedicated baseline re-seed cost. A future implementer turn can apply rim-light tokens to CardItem with its own baseline re-seed when an operator wants that polish. ## #6 Brief 1 — Landing + invite pages glass-migrated - `pages/index.js` — top nav: `var(--glass-surface-mid)` + `--glass-blur-mid` + rim-light. 3 feature cards: `<GlassSurface tint="mid" rim="subtle" elevation="ambient">`. Featured-list cards (the public collection grid): same `<GlassSurface>` recipe with motion-token transitions. All 6 CTA buttons → <Button variant="primary"|"secondary"|"ghost"> with proper sizes. Pulse-loading placeholders tagged `.motion-essential` so reduced-motion users still see them animate (state-meaningful). - `pages/invite/accept.js` + `pages/invite/decline.js` — both outcome panels wrapped in `<GlassSurface tint="mid" rim="subtle" elevation="pronounced">`. Loading spinner border colors corrected from `--text-accent` (which didn't exist) to `--accent-ember`. All 8 buttons → <Button>. `gradient-bg-ember` consumers retained (the canonical warm-palette utility class is fine). ## #8 Brief 2 — Legacy alias sweep + CI gate graduation - Swept `gradient-bg-purple` → `gradient-bg-ember` across **8 files** / **13 occurrences**: `CardDetailQuantityModal`, `CardEditorView`, `CardEditorForm`, `AdminProtected`, `pages/card/[id]`, `pages/invite/{accept,decline}`, `pages/admin/card-import`. `gradient-bg-purple` was a dangling class name with no CSS definition (it was rendering no styling), so the sweep is also a bug fix — those buttons now actually get the ember gradient. - Deleted the 5 dead CSS classes from `styles/globals.css`: `.gradient-text-blue`, `.gradient-text-purple`, `[data-theme="dark"] .glow-blue`, `[data-theme="dark"] .glow-purple`, `[data-theme="dark"] .glow-pink`. Each was zero-consumer post-sweep. - **Graduated the `forbidden-deprecated-color-aliases` CI job from WARN to FAIL.** All 9 patterns (`gradient-text-{purple,pink,blue}`, `glow-{purple,pink,blue}`, `gradient-bg-{purple,blue,pink}`) now block the build if any consumer is reintroduced. ## Verification (local + CI gates locally exercised) - Lint: 0 errors, 2 pre-existing warnings (`CardEditorForm.js` + `CollectionsPageView.js` carry-overs from before #95; out of scope). - Vitest: 104/104 passing — unchanged from #95. - Build: clean (Turbopack default; passes both light + dark theme prerender). - `forbidden-modal-shell-without-primitive` gate: locally clear (`grep -lE 'fixed inset-0 bg-black bg-opacity-' pages components -r --include='*.js'` returns no matches). - `forbidden-deprecated-color-aliases` gate: locally clear (all 9 patterns return no matches in `pages/` or `components/`). ## What still needs human action - **Linux visual-diff baselines** must re-seed via the Docker workflow in `AGENTS.md` § 6. This PR's landing-page + invite-page changes will produce baseline drift on the homepage screenshot (which is currently the only baseline committed) AND additional baselines will be generated for the landing's glass-card sections once the visual spec is expanded. Recommended: run the Docker re-seed against this PR's Vercel preview, commit the result to this branch, push, verify CI green, then merge. - Vercel auto-promotes the merge to production. ## Closes / supersedes - Closes `.convoys/liquid-glass-modal-and-surface-primitive.md` Brief 2 (status → merged). - Closes `.convoys/liquid-glass-form-primitives.md` Brief 2 (status → merged with explicit per-row-icon-button deferral note). - Closes `.convoys/liquid-glass-public-and-auth.md` Brief 1 (status → merged). - Closes `.convoys/cleanup-legacy-design-css.md` Brief 2 (status → merged + CI gate FAIL). - Drops `.convoys/liquid-glass-card-surfaces.md` Brief 1 prerequisite (`fix-card3d-state` no longer needed; Card3D deleted). - Drops the queued `fix-card3d-state` follow-up from the roadmap (target deleted). - Updates `.convoys/ship-readiness.md` § "Design-system redesign portfolio" with a "Finish-portfolio sweep" subsection documenting final status of all 8 sub-convoys. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:34:06 -04:00
/* Gradient text effects Deck Hearth warm palette only.
The pre-Deck-Hearth aliases (.glow-blue / .glow-purple / .glow-pink,
.gradient-text-blue / .gradient-text-purple, .gradient-bg-purple)
were removed by the finish-liquid-glass-design PR after sweeping
their last consumers to --accent-ember equivalents. */
.gradient-text-gold {
background: linear-gradient(135deg, #ffab40 0%, #ff6f00 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.gradient-text-flame {
background: linear-gradient(135deg, #ff6f00 0%, #d84315 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.gradient-text-ember {
background: linear-gradient(135deg, #d84315 0%, #bf360c 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Theme toggle button */
.theme-toggle {
@apply p-2 rounded-2xl transition-all duration-300;
background: var(--bg-secondary);
color: var(--text-primary);
}
/* Header icons */
.header-icon {
@apply p-2 rounded-xl transition-all duration-200;
color: var(--text-secondary);
}
/* Logo styling */
.logo-container {
@apply rounded-2xl flex items-center justify-center transition-all duration-300;
background: var(--gradient-primary);
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: var(--bg-secondary);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-accent);
}
/* Search bar specific styling */
.search-bar {
@apply w-full px-4 py-3 border rounded-2xl shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-0 transition-all duration-200;
background-color: var(--input-bg);
border-color: var(--input-border);
color: var(--input-text);
}
.search-bar::placeholder {
color: var(--input-placeholder);
}
/* Action buttons with proper gradients */
.action-btn-primary {
@apply font-bold py-3 px-6 rounded-2xl transition-all duration-300 shadow-lg hover:shadow-xl;
background: var(--gradient-primary);
color: white;
}
.action-btn-secondary {
@apply font-bold py-3 px-6 rounded-2xl transition-all duration-300 shadow-lg hover:shadow-xl;
background: var(--gradient-secondary);
color: white;
}
/* Particle Effects for High Rarity Cards */
@keyframes float {
0%, 100% {
transform: translateY(0px) translateX(0px);
opacity: 0.7;
}
25% {
transform: translateY(-8px) translateX(4px);
opacity: 1;
}
50% {
transform: translateY(-4px) translateX(-2px);
opacity: 0.8;
}
75% {
transform: translateY(-12px) translateX(6px);
opacity: 0.9;
}
}
@keyframes sparkle {
0%, 100% {
transform: scale(1) rotate(0deg);
opacity: 0.8;
}
25% {
transform: scale(1.5) rotate(90deg);
opacity: 1;
}
50% {
transform: scale(0.8) rotate(180deg);
opacity: 0.6;
}
75% {
transform: scale(1.2) rotate(270deg);
opacity: 0.9;
}
}
@keyframes aura {
0%, 100% {
opacity: 0.1;
transform: scale(1);
}
50% {
opacity: 0.2;
transform: scale(1.05);
}
}
@keyframes edgeFloat {
0%, 100% {
opacity: 0.7;
transform: translateY(0px) translateX(0px);
}
25% {
opacity: 1;
transform: translateY(-3px) translateX(2px);
}
50% {
opacity: 0.8;
transform: translateY(-1px) translateX(-1px);
}
75% {
opacity: 0.9;
transform: translateY(-4px) translateX(3px);
}
}
@keyframes edgeGlow {
0%, 100% {
opacity: 0.4;
transform: scale(1);
}
25% {
opacity: 0.8;
transform: scale(1.2);
}
50% {
opacity: 0.6;
transform: scale(0.8);
}
75% {
opacity: 0.9;
transform: scale(1.1);
}
}
/* Enhanced glow effects for mythic and enchanted cards */
.card-mythic-glow {
box-shadow:
0 0 20px rgba(255, 215, 0, 0.4),
0 0 40px rgba(255, 215, 0, 0.2),
0 0 60px rgba(255, 215, 0, 0.1);
}
.card-enchanted-glow {
box-shadow:
0 0 20px rgba(168, 85, 247, 0.4),
0 0 40px rgba(168, 85, 247, 0.2),
0 0 60px rgba(168, 85, 247, 0.1);
}
/* Card Hover Panel Styles */
.card-item-container {
position: relative;
}
.card-item-container:hover {
z-index: 50;
}
.card-item-container.selected {
z-index: 60;
}
/* Ensure proper layering during animations */
.card-grid-container {
position: relative;
z-index: 1;
}
/* Prevent text selection during card interactions */
.card-item-container * {
user-select: none;
}
/* Side panel specific styles */
.card-side-panel {
transform-origin: left center;
backdrop-filter: blur(8px);
}
/* Responsive adjustments for side panels */
@media (max-width: 1280px) {
.card-side-panel {
width: 16rem; /* w-64 */
}
}
@media (max-width: 1024px) {
.card-side-panel {
display: none; /* Hide panels on smaller screens */
}
}
/* Dark mode improvements */
@media (prefers-color-scheme: dark) {
.card-side-panel {
backdrop-filter: blur(8px) brightness(0.8);
}
}
/* Smooth panel transitions */
.card-panel-enter {
opacity: 0;
transform: translateX(8px);
}
.card-panel-enter-active {
opacity: 1;
transform: translateX(0);
transition: all 300ms ease-out;
}
/* Rarity Effects */
/* Mythic/Legendary - Golden glow */
.rarity-glow-mythic {
box-shadow:
0 0 25px rgba(251, 191, 36, 0.5),
0 0 50px rgba(251, 191, 36, 0.35),
0 0 75px rgba(251, 191, 36, 0.25);
}
.rarity-particles-mythic::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at 20% 30%, rgba(251, 191, 36, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(251, 191, 36, 0.2) 0%, transparent 50%),
radial-gradient(circle at 60% 20%, rgba(251, 191, 36, 0.25) 0%, transparent 50%);
animation: mythic-sparkle 4s ease-in-out infinite;
border-radius: inherit;
}
@keyframes mythic-sparkle {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.7; }
}
/* Rare - Purple glow */
.rarity-glow-rare {
box-shadow:
0 0 20px rgba(168, 85, 247, 0.45),
0 0 40px rgba(168, 85, 247, 0.35),
0 0 60px rgba(168, 85, 247, 0.25);
}
.rarity-particles-rare::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at 30% 40%, rgba(168, 85, 247, 0.2) 0%, transparent 40%),
radial-gradient(circle at 70% 60%, rgba(168, 85, 247, 0.15) 0%, transparent 40%);
animation: rare-shimmer 3s ease-in-out infinite;
border-radius: inherit;
}
@keyframes rare-shimmer {
0%, 100% { opacity: 0.2; }
50% { opacity: 0.5; }
}
/* Uncommon - Blue glow */
.rarity-glow-uncommon {
box-shadow:
0 0 12px rgba(96, 165, 250, 0.35),
0 0 25px rgba(96, 165, 250, 0.25);
}
.rarity-particles-uncommon::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at 40% 30%, rgba(96, 165, 250, 0.15) 0%, transparent 30%);
animation: uncommon-twinkle 2.5s ease-in-out infinite;
border-radius: inherit;
}
@keyframes uncommon-twinkle {
0%, 100% { opacity: 0.1; }
50% { opacity: 0.3; }
}
/* Enchanted/Secret - Pink/Rainbow glow */
.rarity-glow-enchanted {
box-shadow:
0 0 28px rgba(244, 114, 182, 0.5),
0 0 55px rgba(168, 85, 247, 0.35),
0 0 80px rgba(59, 130, 246, 0.25);
}
.rarity-particles-enchanted::before {
content: '';
position: absolute;
inset: 0;
background:
radial-gradient(circle at 25% 25%, rgba(244, 114, 182, 0.3) 0%, transparent 40%),
radial-gradient(circle at 75% 75%, rgba(168, 85, 247, 0.2) 0%, transparent 40%),
radial-gradient(circle at 50% 50%, rgba(59, 130, 246, 0.25) 0%, transparent 40%);
animation: enchanted-rainbow 3s ease-in-out infinite;
border-radius: inherit;
}
@keyframes enchanted-rainbow {
0%, 100% {
opacity: 0.4;
transform: rotate(0deg);
}
33% {
opacity: 0.6;
transform: rotate(120deg);
}
66% {
opacity: 0.5;
transform: rotate(240deg);
}
}
/* Hover enhancement for rarity effects */
.card-item-container:hover .rarity-glow-mythic {
box-shadow:
0 0 30px rgba(251, 191, 36, 0.6),
0 0 60px rgba(251, 191, 36, 0.5),
0 0 90px rgba(251, 191, 36, 0.4);
}
.card-item-container:hover .rarity-glow-rare {
box-shadow:
0 0 25px rgba(168, 85, 247, 0.6),
0 0 50px rgba(168, 85, 247, 0.5),
0 0 75px rgba(168, 85, 247, 0.4);
}
.card-item-container:hover .rarity-glow-uncommon {
box-shadow:
0 0 20px rgba(96, 165, 250, 0.5),
0 0 40px rgba(96, 165, 250, 0.4);
}
.card-item-container:hover .rarity-glow-enchanted {
box-shadow:
0 0 35px rgba(244, 114, 182, 0.7),
0 0 70px rgba(244, 114, 182, 0.6),
0 0 105px rgba(244, 114, 182, 0.5);
🎨 Redesign Collections Page with Card Thumbnails 📱 Layout Improvements: - Removed TCG grouping for cleaner, unified view - Added responsive grid layout (1-4 columns based on screen size) - Implemented proper sorting options (name, value, card count, date) - Moved metadata below thumbnails for better visual hierarchy 🖼️ Beautiful Card Thumbnails: - Created CollectionThumbnail component with 2/3 + 1/3 layout - Main card (rarest) displayed prominently with rarity glow effects - Grid of 4 additional cards in smaller tiles - Card name and rarity overlays on main card - Fallback to hero image if user uploads custom thumbnail - Elegant placeholder for empty collections 🔧 Enhanced Functionality: - Smart thumbnail API fetches top 5 rarest cards by rarity priority - Rarity ordering: mythic > legendary > rare > uncommon > common - Secondary sorting by market price and name - Proper access control for collection thumbnails - Hover effects reveal edit/delete buttons 💅 Visual Polish: - Compact stats display (cards count + value + date) - Less prominent metadata positioning - Improved spacing and typography - Fire-themed color scheme throughout - Smooth hover transitions and interactions - Better mobile responsiveness 🎯 User Experience: - Intuitive sorting controls in header - Search functionality maintained - Quick access to collection actions - Visual feedback for empty states - Consistent with Deck Hearth branding The collections page now showcases beautiful card thumbnails that highlight the rarest cards in each collection! 🔥✨
2025-07-26 22:51:58 -04:00
}
/* Utility classes */
.flex-2 {
flex: 2;
}
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* Floating particle animation */
@keyframes float {
0%, 100% {
transform: translateY(0px) translateX(0px) scale(1);
opacity: 0.6;
}
25% {
transform: translateY(-20px) translateX(10px) scale(1.1);
opacity: 0.8;
}
50% {
transform: translateY(-10px) translateX(-15px) scale(0.9);
opacity: 1;
}
75% {
transform: translateY(-25px) translateX(5px) scale(1.05);
opacity: 0.7;
}
}
.animate-float {
animation: float 4s ease-in-out infinite;
}
/* Fire Glow Background Animation */
@keyframes fire-glow {
0%, 100% {
filter: hue-rotate(0deg) brightness(1) saturate(1);
transform: scale(1);
}
25% {
filter: hue-rotate(5deg) brightness(1.05) saturate(1.1);
transform: scale(1.02);
}
50% {
filter: hue-rotate(-3deg) brightness(0.98) saturate(1.05);
transform: scale(0.99);
}
75% {
filter: hue-rotate(8deg) brightness(1.03) saturate(1.08);
transform: scale(1.01);
}
}
.fire-glow-bg {
animation: fire-glow 12s ease-in-out infinite;
}
/* Ember Floating Animation */
@keyframes ember-float {
0% {
transform: translateY(0px) translateX(0px) scale(0.8);
opacity: 0;
}
10% {
opacity: 0.6;
}
20% {
transform: translateY(-30px) translateX(15px) scale(1);
opacity: 0.8;
}
40% {
transform: translateY(-60px) translateX(-10px) scale(0.9);
opacity: 1;
}
60% {
transform: translateY(-90px) translateX(20px) scale(1.1);
opacity: 0.7;
}
80% {
transform: translateY(-120px) translateX(-5px) scale(0.8);
opacity: 0.4;
}
100% {
transform: translateY(-150px) translateX(10px) scale(0.6);
opacity: 0;
}
}
.animate-ember-float {
animation: ember-float 10s linear infinite;
}
/* Mobile Navigation Styles */
.h-safe-area-inset-bottom {
height: env(safe-area-inset-bottom, 0px);
}
/* Mobile responsive adjustments */
@media (max-width: 768px) {
/* Ensure content doesn't get hidden behind mobile nav */
.mobile-content-padding {
padding-bottom: 80px; /* Space for mobile navigation */
}
/* Mobile navigation backdrop blur support */
@supports (backdrop-filter: blur(16px)) {
.mobile-nav-backdrop {
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
}
}
/* Fallback for browsers without backdrop-filter */
@supports not (backdrop-filter: blur(16px)) {
.mobile-nav-backdrop {
background-color: rgba(var(--bg-secondary-rgb), 0.95) !important;
}
}
}