deckhearth/styles/globals.css
Randall Stillwell 66553fa99a 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>
2026-06-03 19:52:46 -05:00

958 lines
No EOL
26 KiB
CSS

@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;
}
/* Theme Variables - Deck Hearth Fire-Inspired */
:root {
/* 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"] {
/* 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 */
}
/* ============================================================
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);
--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);
--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);
}
/* 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;
}
.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%);
}
/* 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);
}
/* 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;
}
}
/* 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. */
@media (prefers-reduced-motion: reduce) {
*,
*::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;
}
.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);
}
/* Glowing effects for dark theme */
[data-theme="dark"] .glow-blue {
box-shadow: 0 0 20px rgba(6, 182, 212, 0.3);
}
[data-theme="dark"] .glow-purple {
box-shadow: 0 0 20px rgba(139, 92, 246, 0.3);
}
[data-theme="dark"] .glow-pink {
box-shadow: 0 0 20px rgba(236, 72, 153, 0.3);
}
/* Gradient text effects */
.gradient-text-blue {
background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.gradient-text-purple {
background: linear-gradient(135deg, #8b5cf6 0%, #ec4899 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.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);
}
/* 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;
}
}
}