veza/apps/web/src/index.css
senke 39b2b642d2 feat(web): UI premium Discord/Spotify-like — tokens, shadows, focus, layout
Plan UI premium 6–8 semaines (design system, shell, Storybook, a11y):

- Design system: DESIGN_TOKENS.md, APP_SHELL.md, FULL_LAYOUT_PAGE.md. Single source
  for layout/shell (index.css), shadows (design-system.css), durations/easing.
- Tokens: shadow-cover-depth, shadow-gold-glow, shadow-fab-glow; layout max-height
  (max-h-layout-drawer, max-h-layout-panel, max-h-layout-list). All duration-200/300/500
  replaced by --duration-fast/normal/slow. Arbitrary shadows replaced by token classes.
- Shell & player: Sidebar, Header, GlobalPlayer, MiniPlayer, PlayerQueue, PlayerControls,
  AudioPlayer use tokens; focus-visible on Sidebar, PlayerQueue, DropdownMenuTrigger/Item,
  TabsTrigger. Typography: text-[10px]/[9px] → text-xs where applicable.
- ESLint: no-restricted-syntax (warn) for w-/h-/rounded-/shadow-/text-/spacing arbitrary.
- Scripts: report-arbitrary-values.mjs, capture/compare/generate visual; visual-complete.spec.ts.
- Stories full layout: Dashboard, Playlists, Library, Settings, Profile in DashboardLayout.stories.
- .cursorrules + README: DESIGN_TOKENS, APP_SHELL, visual commands, no arbitrary without justification.
- apps/web/.gitignore: e2e test artifacts (test-results-visual, playwright-report-visual).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 17:15:58 +01:00

1142 lines
No EOL
29 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@import 'tailwindcss';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
/* ╔══════════════════════════════════════════════════════════════════════════╗
║ KŌDŌ DESIGN SYSTEM v3.0 — "The Path of Sound" ║
║ VEZA × TALAS — Manga × Graffiti × Nature × Gaming × Linux ║
╚══════════════════════════════════════════════════════════════════════════╝ */
:root {
/* ═══════════════════════════════════════════════════════════════════════════
CORE PALETTE — Light Mode
═══════════════════════════════════════════════════════════════════════════ */
--background: oklch(0.985 0 0);
--foreground: oklch(0.145 0.005 265);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0.005 265);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0.005 265);
/* Primary: Neon Cyan — Tech, Flow, Future */
--primary: oklch(0.75 0.18 195);
--primary-foreground: oklch(0.13 0.02 265);
/* Secondary: Hot Magenta — Street, Passion, Edge */
--secondary: oklch(0.65 0.25 330);
--secondary-foreground: oklch(0.98 0 0);
--muted: oklch(0.96 0.005 265);
--muted-foreground: oklch(0.45 0.015 265);
--accent: oklch(0.95 0.01 265);
--accent-foreground: oklch(0.20 0.01 265);
/* Semantic Colors */
--destructive: oklch(0.60 0.22 25);
--destructive-foreground: oklch(0.98 0 0);
--success: oklch(0.72 0.19 145);
--success-foreground: oklch(0.13 0.02 145);
--warning: oklch(0.80 0.16 75);
--warning-foreground: oklch(0.20 0.05 75);
--info: oklch(0.70 0.15 230);
--info-foreground: oklch(0.13 0.02 230);
--border: oklch(0.90 0.005 265);
--input: oklch(0.90 0.005 265);
--ring: oklch(0.75 0.18 195);
/* Charts */
--chart-1: oklch(0.75 0.18 195);
--chart-2: oklch(0.65 0.25 330);
--chart-3: oklch(0.72 0.19 145);
--chart-4: oklch(0.70 0.20 290);
--chart-5: oklch(0.80 0.16 75);
--radius: 0.5rem;
/* Sidebar */
--sidebar: oklch(0.98 0.003 265);
--sidebar-foreground: oklch(0.145 0.005 265);
--sidebar-primary: oklch(0.75 0.18 195);
--sidebar-primary-foreground: oklch(0.13 0.02 265);
--sidebar-accent: oklch(0.94 0.01 265);
--sidebar-accent-foreground: oklch(0.20 0.01 265);
--sidebar-border: oklch(0.90 0.005 265);
--sidebar-ring: oklch(0.75 0.18 195);
/* Sidebar active item indicator (left border) — use instead of arbitrary shadow */
--sidebar-active-indicator: inset 2px 0 0 0 var(--sidebar-primary);
/* Sidebar layout — Phase 3: tokens (Discord 240px expanded, 72px collapsed) */
--sidebar-width-expanded: 15rem;
/* 240px — aligné Discord channel list */
--sidebar-width-collapsed: 5rem;
/* 80px — collapsed icons-only */
--sidebar-offset-left: 1.5rem;
--sidebar-offset-top: 5rem;
--sidebar-offset-bottom: 1.5rem;
--sidebar-z-index: 95;
--sidebar-overlay-z-index: 90;
/* Dashboard stat cards — Phase 3: ombre réduite pour hiérarchie */
--stat-icon-shadow: 0 0 6px rgb(255 255 255 / 0.08);
/* Sparkline / path glow (currentColor) */
--stat-sparkline-glow: 0 0 8px currentColor;
/* Layout primitives — standard widths/heights for app shell and pages */
--layout-content-max-width: 100rem;
/* 1600px — main content max width */
--layout-main-min-height: calc(100vh - 4rem);
/* below 64px header */
--layout-page-min-height: 37.5rem;
/* 600px — full-page min height */
--layout-page-min-height-sm: 25rem;
/* 400px — compact page / empty state */
--layout-story-decorator-min-height: 12rem;
/* 192px — story wrapper (min-h-48) */
--layout-gap: 1rem;
/* 16px — default gap between sections (align Tailwind gap-4) */
--layout-gap-sm: 0.75rem;
/* 12px — tight gap (gap-3) */
--layout-gap-lg: 1.5rem;
/* 24px — loose gap (gap-6) */
--layout-drawer-max-height: 60vh;
/* queue, side panels */
--layout-panel-max-height: 70vh;
/* floating panels (e.g. audio player popover) */
--layout-list-max-height: 25rem;
/* 400px — scroll lists (align min-h-layout-page-sm) */
/* App shell — header, main offsets and margins (sidebar-driven) */
--header-height: 4rem;
/* fixed header bar height (was h-16) */
--main-offset-top: 5rem;
/* main padding-top to clear fixed header (was pt-20) */
--main-offset-bottom: 8rem;
/* main padding-bottom reserve for floating player (was pb-32) */
--main-margin-left-expanded: 18rem;
/* main margin when sidebar open: sidebar 15rem + 3rem gap */
--main-margin-left-collapsed: 7rem;
/* main margin when sidebar collapsed: 5rem + 2rem gap */
--header-left-expanded: 18rem;
/* header bar left edge when sidebar open */
--header-left-collapsed: 5rem;
/* header bar left edge when sidebar collapsed */
/* ═══════════════════════════════════════════════════════════════════════════
KŌDŌ EXTENDED PALETTE — "Spectre Urbain"
═══════════════════════════════════════════════════════════════════════════ */
/* Void Scale */
--void-0: oklch(0.985 0 0);
--void-50: oklch(0.97 0.003 265);
--void-100: oklch(0.94 0.005 265);
--void-200: oklch(0.88 0.008 265);
--void-300: oklch(0.78 0.01 265);
--void-400: oklch(0.62 0.015 265);
--void-500: oklch(0.50 0.02 265);
--void-600: oklch(0.40 0.025 265);
--void-700: oklch(0.30 0.02 265);
--void-800: oklch(0.22 0.015 265);
--void-900: oklch(0.15 0.01 265);
--void-950: oklch(0.10 0.005 265);
/* Neon Cyan Scale */
--cyan-50: oklch(0.97 0.04 195);
--cyan-100: oklch(0.93 0.08 195);
--cyan-200: oklch(0.88 0.12 195);
--cyan-300: oklch(0.82 0.15 195);
--cyan-400: oklch(0.78 0.17 195);
--cyan-500: oklch(0.75 0.18 195);
--cyan-600: oklch(0.65 0.16 195);
--cyan-700: oklch(0.55 0.14 195);
--cyan-800: oklch(0.45 0.12 195);
--cyan-900: oklch(0.35 0.10 195);
/* Hot Magenta Scale */
--magenta-50: oklch(0.97 0.05 330);
--magenta-100: oklch(0.93 0.10 330);
--magenta-200: oklch(0.85 0.16 330);
--magenta-300: oklch(0.78 0.20 330);
--magenta-400: oklch(0.70 0.23 330);
--magenta-500: oklch(0.65 0.25 330);
--magenta-600: oklch(0.55 0.22 330);
--magenta-700: oklch(0.45 0.18 330);
--magenta-800: oklch(0.35 0.14 330);
--magenta-900: oklch(0.28 0.10 330);
/* Acid Lime Scale */
--lime-50: oklch(0.97 0.05 145);
--lime-100: oklch(0.94 0.10 145);
--lime-200: oklch(0.88 0.14 145);
--lime-300: oklch(0.82 0.17 145);
--lime-400: oklch(0.77 0.18 145);
--lime-500: oklch(0.72 0.19 145);
--lime-600: oklch(0.62 0.17 145);
--lime-700: oklch(0.52 0.14 145);
--lime-800: oklch(0.42 0.11 145);
--lime-900: oklch(0.32 0.08 145);
/* Gaming Colors */
--xp-gold: oklch(0.85 0.16 85);
--hp-red: oklch(0.60 0.22 25);
--mp-blue: oklch(0.60 0.18 250);
--shield-purple: oklch(0.55 0.22 300);
/* Nature Tones */
--moss: oklch(0.45 0.10 145);
--moss-light: oklch(0.55 0.12 145);
--bark: oklch(0.35 0.05 55);
--leaf: oklch(0.62 0.15 140);
/* Manga Spectrum */
--sakura: oklch(0.85 0.10 350);
--yurei: oklch(0.60 0.15 290);
--shonen: oklch(0.60 0.20 30);
/* Terminal */
--terminal-green: oklch(0.75 0.20 145);
--terminal-amber: oklch(0.80 0.15 80);
--matrix: oklch(0.15 0.05 145);
/* Gradients */
--gradient-neon: linear-gradient(135deg, var(--cyan-500), var(--magenta-500), var(--lime-500));
--gradient-cyber: linear-gradient(135deg, var(--cyan-400), var(--magenta-500));
--gradient-sunset: linear-gradient(135deg, oklch(0.65 0.20 35), var(--magenta-500));
--gradient-forest: linear-gradient(135deg, var(--moss), var(--leaf), var(--lime-500));
--gradient-manga: linear-gradient(135deg, var(--sakura), var(--yurei));
--gradient-terminal: linear-gradient(180deg, var(--matrix), var(--void-950));
--gradient-gaming: linear-gradient(135deg, var(--shonen), var(--xp-gold));
/* Glows */
--glow-cyan: 0 0 20px oklch(0.75 0.18 195 / 0.4);
--glow-magenta: 0 0 20px oklch(0.65 0.25 330 / 0.4);
--glow-lime: 0 0 20px oklch(0.72 0.19 145 / 0.4);
--glow-gold: 0 0 20px oklch(0.85 0.16 85 / 0.4);
--glow-terminal: 0 0 10px oklch(0.75 0.20 145 / 0.3);
/* Glass */
--glass-bg: oklch(1 0 0 / 0.8);
--glass-border: oklch(0 0 0 / 0.05);
--glass-blur: 16px;
/* Animation Easings */
--ease-out: cubic-bezier(0.33, 1, 0.68, 1);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
--duration-instant: 100ms;
--duration-fast: 150ms;
--duration-normal: 250ms;
/* Immersive UI: micro-interactions (hover, focus) */
--duration-immersive: 200ms;
--duration-slow: 400ms;
--duration-slower: 600ms;
/* Clip Paths — Manga Style */
--clip-manga: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
--clip-manga-lg: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 20px 100%, 0 calc(100% - 20px));
--clip-hex: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
--clip-badge: polygon(0 10%, 10% 0, 90% 0, 100% 10%, 100% 90%, 90% 100%, 10% 100%, 0 90%);
--clip-slant: polygon(0 0, 100% 0, 100% calc(100% - 8px), 0 100%);
}
/* ═══════════════════════════════════════════════════════════════════════════
DARK MODE — The Void
═══════════════════════════════════════════════════════════════════════════ */
.dark {
/* Spotify/Discord Premium: Deep, rich dark tones */
/* Main Background: Very deep void (approx #0d0d12) */
--background: oklch(0.10 0.005 265);
--foreground: oklch(0.98 0 0);
/* Cards/Surfaces: Slight elevation (approx #16161e) */
--card: oklch(0.13 0.01 265);
--card-foreground: oklch(0.98 0 0);
--popover: oklch(0.13 0.01 265);
--popover-foreground: oklch(0.98 0 0);
/* Primary: Electric Cyan (preserved but refined) */
--primary: oklch(0.72 0.19 195);
--primary-foreground: oklch(0.08 0.02 265);
--secondary: oklch(0.25 0.04 265);
/* Darker secondary surface */
--secondary-foreground: oklch(0.90 0.01 265);
--muted: oklch(0.18 0.01 265);
--muted-foreground: oklch(0.65 0.02 265);
/* Accent: Hover states (approx #23232f) */
--accent: oklch(0.20 0.02 265);
--accent-foreground: oklch(0.98 0 0);
--destructive: oklch(0.62 0.22 25);
--destructive-foreground: oklch(0.98 0 0);
/* Borders: Very subtle, refined transparency */
--border: oklch(1 0 0 / 0.08);
--input: oklch(1 0 0 / 0.08);
--ring: oklch(0.72 0.19 195 / 0.5);
/* Sidebar: Darkest surface (approx #08080c) */
--sidebar: oklch(0.08 0.005 265);
--sidebar-foreground: oklch(0.65 0.02 265);
/* Muted by default */
--sidebar-primary: oklch(0.72 0.19 195);
--sidebar-primary-foreground: oklch(0.98 0 0);
--sidebar-accent: oklch(1 0 0 / 0.04);
--sidebar-accent-foreground: oklch(0.98 0 0);
--sidebar-border: oklch(1 0 0 / 0.04);
--sidebar-ring: oklch(0.72 0.19 195);
/* Charts */
--chart-1: oklch(0.75 0.18 195);
--chart-2: oklch(0.65 0.25 330);
--chart-3: oklch(0.72 0.19 145);
--chart-4: oklch(0.70 0.20 290);
--chart-5: oklch(0.80 0.16 75);
/* Update Void Scale for lighter theme (shifted up) */
--void-0: oklch(0.15 0.02 265);
--void-50: oklch(0.18 0.02 265);
--void-100: oklch(0.22 0.02 265);
/* ...rest can stay relative or be unused */
--void-950: oklch(0.98 0 0);
/* Glows - Adjusted for lighter contrast */
--glow-cyan: 0 0 25px oklch(0.75 0.18 195 / 0.25);
--glow-magenta: 0 0 25px oklch(0.65 0.25 330 / 0.25);
--glow-lime: 0 0 25px oklch(0.72 0.19 145 / 0.25);
--glow-gold: 0 0 25px oklch(0.85 0.16 85 / 0.25);
--glow-terminal: 0 0 15px oklch(0.78 0.20 145 / 0.2);
/* Glass - Lighter background opacity */
--glass-bg: oklch(0.18 0.02 265 / 0.6);
--glass-border: oklch(1 0 0 / 0.1);
--glass-blur: 24px;
}
@theme inline {
/* Typography — KŌDŌ Font Stack (audit P3: explicit fallback if Rajdhani glyphs fail) */
--font-sans: 'Rajdhani', 'Inter', 'Noto Sans JP', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'Consolas', monospace;
--font-display: 'Orbitron', 'Bebas Neue', sans-serif;
--font-jp: 'Noto Sans JP', sans-serif;
/* Core Design Tokens */
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
/* Extended Semantic Colors */
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
/* Neon Colors */
--color-cyan: var(--cyan-500);
--color-magenta: var(--magenta-500);
--color-lime: var(--lime-500);
--color-gold: var(--xp-gold);
/* Chart Colors */
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
/* Radius — Squircle: xl for surfaces, full for interactive */
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--radius-2xl: calc(var(--radius) + 8px);
--radius-full: 9999px;
/* Sidebar */
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
/* ═══════════════════════════════════════════════════════════════════════════
BASE STYLES
═══════════════════════════════════════════════════════════════════════════ */
@layer base {
* {
@apply border-border outline-ring/50;
}
html {
scroll-behavior: smooth;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "cv02", "cv03", "cv04", "cv11";
}
/* Noise texture overlay */
body::before {
content: '';
position: fixed;
inset: 0;
background:
url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
opacity: 0.015;
pointer-events: none;
z-index: 9998;
}
::selection {
background: var(--primary);
color: var(--primary-foreground);
}
/* Custom Scrollbar — Spotify/Discord-like: thin, subtle, low visual weight */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.12);
border-radius: 9999px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.22);
}
@supports (scrollbar-width: thin) {
* {
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
}
}
/* Typography */
h1,
h2,
h3,
h4,
h5,
h6 {
@apply font-sans font-semibold tracking-tight text-foreground;
text-wrap: balance;
}
h1 {
@apply text-4xl md:text-5xl;
}
h2 {
@apply text-3xl md:text-4xl;
}
h3 {
@apply text-2xl md:text-3xl;
}
h4 {
@apply text-xl md:text-2xl;
}
h5 {
@apply text-lg md:text-xl;
}
h6 {
@apply text-base md:text-lg;
}
p {
@apply text-muted-foreground leading-relaxed;
text-wrap: pretty;
}
a:not([class]) {
@apply text-primary transition-colors;
}
a:not([class]):hover {
@apply text-primary/80;
}
code {
@apply font-mono text-sm bg-muted px-1.5 py-0.5 rounded;
}
pre {
@apply font-mono text-sm bg-muted p-4 rounded-lg overflow-x-auto;
}
}
/* ═══════════════════════════════════════════════════════════════════════════
KŌDŌ UTILITY CLASSES
═══════════════════════════════════════════════════════════════════════════ */
@layer utilities {
/* Layout primitives — use instead of arbitrary values for app shell and pages */
.max-w-layout-content {
max-width: var(--layout-content-max-width);
}
.min-h-layout-main {
min-height: var(--layout-main-min-height);
}
.min-h-layout-page {
min-height: var(--layout-page-min-height);
}
.min-h-layout-page-sm {
min-height: var(--layout-page-min-height-sm);
}
.min-h-layout-story {
min-height: var(--layout-story-decorator-min-height);
}
.max-h-layout-drawer {
max-height: var(--layout-drawer-max-height);
}
.max-h-layout-panel {
max-height: var(--layout-panel-max-height);
}
.max-h-layout-list {
max-height: var(--layout-list-max-height);
}
/* Sidebar layout — use tokens instead of arbitrary values */
.w-sidebar-expanded {
width: var(--sidebar-width-expanded);
}
.w-sidebar-collapsed {
width: var(--sidebar-width-collapsed);
}
.left-sidebar {
left: var(--sidebar-offset-left);
}
.top-sidebar {
top: var(--sidebar-offset-top);
}
.bottom-sidebar {
bottom: var(--sidebar-offset-bottom);
}
.z-sidebar {
z-index: var(--sidebar-z-index);
}
.z-sidebar-overlay {
z-index: var(--sidebar-overlay-z-index);
}
/* App shell — utility classes for layout (use with lg: for desktop) */
.h-header {
height: var(--header-height);
}
.pt-main {
padding-top: var(--main-offset-top);
}
.pb-main {
padding-bottom: var(--main-offset-bottom);
}
.ml-main-expanded {
margin-left: var(--main-margin-left-expanded);
}
.ml-main-collapsed {
margin-left: var(--main-margin-left-collapsed);
}
.left-header-expanded {
left: var(--header-left-expanded);
}
.left-header-collapsed {
left: var(--header-left-collapsed);
}
.drop-shadow-stat-icon {
filter: drop-shadow(var(--stat-icon-shadow));
}
.drop-shadow-stat-sparkline {
filter: drop-shadow(var(--stat-sparkline-glow));
}
/* Shell transition — sidebar width/opacity (use on aside and inner content) */
.transition-shell {
transition: width var(--duration-normal) var(--ease-out),
opacity var(--duration-normal) var(--ease-out),
transform var(--duration-normal) var(--ease-out);
}
/* Modal/page animations (camelCase class names used in codebase) — tokenized */
.animate-fadeIn {
animation: fade-in var(--duration-normal) var(--ease-out);
}
.animate-scaleIn {
animation: scale-in var(--duration-normal) var(--ease-out);
}
/* Semantic shadows — card, modal, tooltip (tokens from design-system.css) */
.shadow-card {
box-shadow: var(--shadow-card);
}
.shadow-card-hover {
box-shadow: var(--shadow-card-hover);
}
.shadow-card-glow-cyan {
box-shadow: var(--shadow-card-glow-cyan);
}
.shadow-card-glow-magenta {
box-shadow: var(--shadow-card-glow-magenta);
}
.shadow-modal {
box-shadow: var(--shadow-modal);
}
.shadow-tooltip {
box-shadow: var(--shadow-tooltip);
}
/* Sidebar active nav item — left border indicator */
.sidebar-active-indicator {
box-shadow: var(--sidebar-active-indicator);
}
/* Button primary hover glow */
.shadow-button-primary-glow {
box-shadow: var(--button-primary-glow);
}
.shadow-button-primary-glow-hover {
box-shadow: var(--button-primary-glow-hover);
}
/* Player thumb and bar hover (tokens from design-system.css) */
.shadow-player-thumb {
box-shadow: var(--player-thumb-glow);
}
.shadow-player-hover {
box-shadow: var(--player-hover-glow);
}
.shadow-queue-item-current {
box-shadow: var(--queue-item-current-glow);
}
.shadow-slider-thumb {
box-shadow: var(--slider-thumb-glow);
}
/* Status / activity dots (dashboard) */
.shadow-status-dot-cyan {
box-shadow: var(--status-dot-glow-cyan);
}
.shadow-status-dot-lime {
box-shadow: var(--status-dot-glow-lime);
}
.shadow-status-dot-magenta {
box-shadow: var(--status-dot-glow-magenta);
}
.shadow-cover-depth {
box-shadow: var(--shadow-cover-depth);
}
.shadow-gold-glow {
box-shadow: var(--shadow-gold-glow);
}
.shadow-fab-glow {
box-shadow: var(--shadow-fab-glow);
}
.shadow-fab-glow-hover:hover {
box-shadow: var(--shadow-fab-glow-hover);
}
/* Neon Glows */
.glow-cyan {
box-shadow: var(--glow-cyan);
}
.glow-magenta {
box-shadow: var(--glow-magenta);
}
.glow-lime {
box-shadow: var(--glow-lime);
}
.glow-gold {
box-shadow: var(--glow-gold);
}
.glow-terminal {
box-shadow: var(--glow-terminal);
}
/* Text Gradients */
.text-gradient-neon {
@apply bg-clip-text text-transparent;
background-image: var(--gradient-neon);
}
.text-gradient-cyber {
@apply bg-clip-text text-transparent;
background-image: var(--gradient-cyber);
}
.text-gradient-sunset {
@apply bg-clip-text text-transparent;
background-image: var(--gradient-sunset);
}
.text-gradient-forest {
@apply bg-clip-text text-transparent;
background-image: var(--gradient-forest);
}
.text-gradient-manga {
@apply bg-clip-text text-transparent;
background-image: var(--gradient-manga);
}
/* Glass Effect */
.glass {
background: var(--glass-bg);
backdrop-filter: blur(var(--glass-blur));
border: 1px solid var(--glass-border);
}
/* Noise Texture */
.noise {
position: relative;
}
.noise::before {
content: "";
position: absolute;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
pointer-events: none;
opacity: 0.5;
mix-blend-mode: overlay;
border-radius: inherit;
}
/* Scanlines */
.scanlines::after {
content: '';
position: absolute;
inset: 0;
background: repeating-linear-gradient(0deg,
transparent,
transparent 2px,
oklch(0 0 0 / 0.03) 2px,
oklch(0 0 0 / 0.03) 4px);
pointer-events: none;
border-radius: inherit;
}
/* Manga Clip Paths */
.clip-manga {
clip-path: var(--clip-manga);
}
.clip-manga-lg {
clip-path: var(--clip-manga-lg);
}
.clip-hex {
clip-path: var(--clip-hex);
}
.clip-badge {
clip-path: var(--clip-badge);
}
.clip-slant {
clip-path: var(--clip-slant);
}
/* Font Utilities */
.font-display {
font-family: var(--font-display);
}
.font-jp {
font-family: var(--font-jp);
}
/* Animation Utilities */
.animate-glow-pulse {
animation: glow-pulse 2s ease-in-out infinite;
}
.animate-float {
animation: float 6s ease-in-out infinite;
}
.animate-slide-up {
animation: slide-up var(--duration-normal) var(--ease-out);
}
.animate-fade-in {
animation: fade-in var(--duration-normal) var(--ease-out);
}
.animate-spin-slow {
animation: spin-slow 10s linear infinite;
}
.animate-achievement {
animation: achievement-slide 0.5s var(--ease-spring);
}
.animate-eq {
animation: eq-bounce 0.5s ease-in-out infinite;
}
/* Hover Effects */
.hover-lift {
@apply transition-transform duration-[var(--duration-fast)];
}
.hover-lift:hover {
@apply -translate-y-1;
}
.hover-glow-cyan {
@apply transition-shadow duration-[var(--duration-fast)];
}
.hover-glow-cyan:hover {
box-shadow: var(--glow-cyan);
}
.hover-glow-magenta {
@apply transition-shadow duration-[var(--duration-fast)];
}
.hover-glow-magenta:hover {
box-shadow: var(--glow-magenta);
}
.hover-glow-lime {
@apply transition-shadow duration-[var(--duration-fast)];
}
.hover-glow-lime:hover {
box-shadow: var(--glow-lime);
}
.hover-glow-gold {
@apply transition-shadow duration-[var(--duration-fast)];
}
.hover-glow-gold:hover {
box-shadow: var(--glow-gold);
}
/* Gaming specific */
.text-xp {
color: var(--xp-gold);
}
.text-hp {
color: var(--hp-red);
}
.text-mp {
color: var(--mp-blue);
}
.text-terminal {
color: var(--terminal-green);
text-shadow: var(--glow-terminal);
}
.bg-terminal {
background: var(--gradient-terminal);
}
.bg-gaming {
background: var(--gradient-gaming);
}
.bg-manga {
background: var(--gradient-manga);
}
.bg-forest {
background: var(--gradient-forest);
}
/* Border neon */
.border-neon-cyan {
border-color: var(--cyan-500);
}
.border-neon-magenta {
border-color: var(--magenta-500);
}
.border-neon-lime {
border-color: var(--lime-500);
}
.border-neon-gold {
border-color: var(--xp-gold);
}
}
/* ═══════════════════════════════════════════════════════════════════════════
KEYFRAME ANIMATIONS
═══════════════════════════════════════════════════════════════════════════ */
@keyframes glow-pulse {
0%,
100% {
opacity: 1;
filter: brightness(1);
}
50% {
opacity: 0.85;
filter: brightness(1.15);
}
}
@keyframes float {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes shimmer {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
@keyframes spin-slow {
to {
transform: rotate(360deg);
}
}
@keyframes pulse-ring {
0% {
transform: scale(0.8);
opacity: 1;
}
100% {
transform: scale(1.5);
opacity: 0;
}
}
@keyframes eq-bounce {
0%,
100% {
transform: scaleY(1);
}
50% {
transform: scaleY(0.3);
}
}
@keyframes typing {
0%,
60%,
100% {
transform: translateY(0);
}
30% {
transform: translateY(-4px);
}
}
@keyframes achievement-slide {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes graffiti-shake {
0%,
100% {
transform: rotate(0deg);
}
25% {
transform: rotate(-2deg);
}
75% {
transform: rotate(2deg);
}
}
@keyframes terminal-blink {
0%,
50% {
opacity: 1;
}
51%,
100% {
opacity: 0;
}
}
@keyframes neon-flicker {
0%,
19%,
21%,
23%,
25%,
54%,
56%,
100% {
opacity: 1;
text-shadow: var(--glow-cyan);
}
20%,
24%,
55% {
opacity: 0.8;
text-shadow: none;
}
}
@keyframes bar-fill {
from {
width: 0;
}
}
@keyframes level-up {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2);
filter: brightness(1.5);
}
100% {
transform: scale(1);
}
}