veza/apps/web/src/index.css

881 lines
35 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([data-theme="dark"] *));
/* ╔══════════════════════════════════════════════════════════════════════════╗
║ SUMI DESIGN SYSTEM v2.0 — "L'encre et la lumière" ║
║ VEZA × TALAS — Single Source of Truth ║
║ Ref: apps/web/docs/DESIGN_SYSTEM_REFERENCE.md ║
╚══════════════════════════════════════════════════════════════════════════╝ */
/* ═══════════════════════════════════════════════════════════════════════════
DARK THEME (default) — Ink on void
═══════════════════════════════════════════════════════════════════════════ */
:root, [data-theme="dark"] {
/* ═══ BACKGROUNDS ═══ */
--sumi-bg-void: #0c0c0f;
--sumi-bg-base: #121215;
--sumi-bg-raised: #1a1a1f;
--sumi-bg-overlay: #222228;
--sumi-bg-hover: #2a2a31;
--sumi-bg-active: #32323a;
--sumi-bg-wash: #18181d;
/* ═══ SURFACES ═══ */
--sumi-surface-inset: #101013;
--sumi-surface-subtle: #1e1e24;
--sumi-surface-card: #1a1a1f;
--sumi-surface-elevated: #242430;
/* ═══ BORDERS ═══ */
--sumi-border-faint: rgba(255,255,255, 0.06);
--sumi-border-default: rgba(255,255,255, 0.10);
--sumi-border-strong: rgba(255,255,255, 0.16);
--sumi-border-focus: rgba(139,170,220, 0.50);
--sumi-border-accent: rgba(139,170,220, 0.30);
/* ═══ TEXT ═══ */
--sumi-text-primary: #f0ede8;
--sumi-text-secondary: #a8a4a0;
--sumi-text-tertiary: #706c68;
--sumi-text-disabled: #4a4844;
--sumi-text-inverse: #121215;
--sumi-text-link: #8baade;
/* ═══ PIGMENTS — Les 4 Pigments d'accent ═══ */
--sumi-accent: #7c9dd6;
--sumi-accent-hover: #93afe0;
--sumi-accent-active: #6b8dc6;
--sumi-accent-muted: rgba(124,157,214, 0.20);
--sumi-accent-subtle: rgba(124,157,214, 0.12);
--sumi-accent-emphasis: #5a7fba;
--sumi-vermillion: #d4634a;
--sumi-vermillion-hover: #de7a64;
--sumi-vermillion-subtle: rgba(212,99,74, 0.12);
--sumi-sage: #7a9e6c;
--sumi-sage-hover: #8eb280;
--sumi-sage-subtle: rgba(122,158,108, 0.12);
--sumi-gold: #c9a84c;
--sumi-gold-hover: #d6b860;
--sumi-gold-subtle: rgba(201,168,76, 0.12);
/* ═══ SEMANTIC ═══ */
--sumi-success: var(--sumi-sage);
--sumi-success-subtle: var(--sumi-sage-subtle);
--sumi-warning: var(--sumi-gold);
--sumi-warning-subtle: var(--sumi-gold-subtle);
--sumi-error: var(--sumi-vermillion);
--sumi-error-subtle: var(--sumi-vermillion-subtle);
--sumi-info: var(--sumi-accent);
--sumi-live: #e05a5a;
--sumi-online: var(--sumi-sage);
/* ═══ TYPOGRAPHY ═══ */
--sumi-font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--sumi-font-heading: 'Space Grotesk', 'Inter', sans-serif;
--sumi-font-mono: 'JetBrains Mono', 'SF Mono', 'Consolas', monospace;
--sumi-font-serif: 'Noto Serif JP', Georgia, serif;
--sumi-text-4xl: 2.25rem;
--sumi-text-3xl: 1.875rem;
--sumi-text-2xl: 1.5rem;
--sumi-text-xl: 1.25rem;
--sumi-text-lg: 1.125rem;
--sumi-text-md: 1rem;
--sumi-text-base: 0.875rem;
--sumi-text-sm: 0.8125rem;
--sumi-text-xs: 0.75rem;
--sumi-leading-none: 1;
--sumi-leading-tight: 1.25;
--sumi-leading-snug: 1.375;
--sumi-leading-normal: 1.5;
--sumi-leading-relaxed: 1.625;
--sumi-leading-loose: 1.75;
--sumi-tracking-tighter: -0.03em;
--sumi-tracking-tight: -0.015em;
--sumi-tracking-normal: 0;
--sumi-tracking-wide: 0.025em;
--sumi-tracking-wider: 0.05em;
--sumi-tracking-widest: 0.1em;
--sumi-weight-light: 300;
--sumi-weight-regular: 400;
--sumi-weight-medium: 500;
--sumi-weight-semibold: 600;
--sumi-weight-bold: 700;
/* ═══ SPACING ═══ */
--sumi-space-0-5: 2px;
--sumi-space-1: 4px;
--sumi-space-1-5: 6px;
--sumi-space-2: 8px;
--sumi-space-2-5: 10px;
--sumi-space-3: 12px;
--sumi-space-4: 16px;
--sumi-space-5: 20px;
--sumi-space-6: 24px;
--sumi-space-8: 32px;
--sumi-space-10: 40px;
--sumi-space-12: 48px;
--sumi-space-16: 64px;
--sumi-space-20: 80px;
/* ═══ RADIUS ═══ */
--sumi-radius-xs: 2px;
--sumi-radius-sm: 4px;
--sumi-radius-md: 6px;
--sumi-radius-lg: 12px;
--sumi-radius-xl: 16px;
--sumi-radius-2xl: 20px;
--sumi-radius-full: 9999px;
/* ═══ SHADOWS ═══ */
--sumi-shadow-xs: 0 1px 2px rgba(0,0,0,0.30);
--sumi-shadow-sm: 0 2px 4px rgba(0,0,0,0.25), 0 1px 2px rgba(0,0,0,0.20);
--sumi-shadow-md: 0 4px 12px rgba(0,0,0,0.30), 0 2px 4px rgba(0,0,0,0.15);
--sumi-shadow-lg: 0 8px 24px rgba(0,0,0,0.35), 0 4px 8px rgba(0,0,0,0.20);
--sumi-shadow-xl: 0 16px 48px rgba(0,0,0,0.40), 0 8px 16px rgba(0,0,0,0.20);
--sumi-shadow-2xl: 0 24px 64px rgba(0,0,0,0.50);
--sumi-shadow-glow: 0 0 0 3px rgba(124,157,214,0.25);
--sumi-shadow-glow-lg: 0 0 20px rgba(124,157,214,0.15);
/* ═══ GLASS ═══ */
--sumi-glass-bg: rgba(18,18,21, 0.80);
--sumi-glass-border: rgba(255,255,255, 0.08);
--sumi-glass-blur: 12px;
/* ═══ SCROLLBAR ═══ */
--sumi-scrollbar-track: transparent;
--sumi-scrollbar-thumb: rgba(255,255,255, 0.10);
--sumi-scrollbar-hover: rgba(255,255,255, 0.18);
/* ═══ MOTION ═══ */
--sumi-duration-instant: 75ms;
--sumi-duration-fast: 150ms;
--sumi-duration-normal: 200ms;
--sumi-duration-slow: 300ms;
--sumi-duration-slower: 500ms;
/* Aliases for components using legacy var names */
--duration-fast: var(--sumi-duration-fast);
--duration-normal: var(--sumi-duration-normal);
--sumi-ease-default: cubic-bezier(0.25, 0.1, 0.25, 1);
--sumi-ease-out: cubic-bezier(0.33, 1, 0.68, 1);
--sumi-ease-in: cubic-bezier(0.32, 0, 0.67, 0);
--sumi-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--sumi-ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
--sumi-ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.1);
--sumi-transition-colors: color var(--sumi-duration-fast) var(--sumi-ease-default),
background-color var(--sumi-duration-fast) var(--sumi-ease-default),
border-color var(--sumi-duration-fast) var(--sumi-ease-default);
--sumi-transition-opacity: opacity var(--sumi-duration-fast) var(--sumi-ease-default);
--sumi-transition-transform: transform var(--sumi-duration-normal) var(--sumi-ease-out);
--sumi-transition-shadow: box-shadow var(--sumi-duration-fast) var(--sumi-ease-default);
/* ═══ Z-INDEX ═══ */
--sumi-z-base: 0;
--sumi-z-raised: 10;
--sumi-z-dropdown: 100;
--sumi-z-sticky: 200;
--sumi-z-overlay: 300;
--sumi-z-modal: 400;
--sumi-z-popover: 500;
--sumi-z-toast: 600;
--sumi-z-tooltip: 700;
--sumi-z-max: 999;
/* ═══ LAYOUT ═══ */
--sumi-max-width: 1400px;
--sumi-max-width-content: 1200px;
--sumi-max-width-narrow: 800px;
--sumi-max-width-prose: 65ch;
--sumi-sidebar-width: 240px;
--sumi-sidebar-collapsed: 64px;
--sumi-header-height: 56px;
--sumi-player-height: 80px;
/* ═══ CONTEXTUAL ACCENTS (feature-specific) ═══ */
--graffiti-magenta: #c840a0;
--gaming-gold: #d4b040;
--terminal-green: #3eaa5e;
--sakura: #e0a0b8;
/* ═══ SHADCN/RADIX SEMANTIC MAPPING ═══ */
--background: var(--sumi-bg-base);
--foreground: var(--sumi-text-primary);
--card: var(--sumi-surface-card);
--card-foreground: var(--sumi-text-primary);
--popover: var(--sumi-bg-overlay);
--popover-foreground: var(--sumi-text-primary);
--primary: var(--sumi-accent);
--primary-foreground: var(--sumi-text-inverse);
--secondary: var(--sumi-bg-hover);
--secondary-foreground: var(--sumi-text-primary);
--muted: var(--sumi-bg-hover);
--muted-foreground: var(--sumi-text-secondary);
--accent: var(--sumi-bg-hover);
--accent-foreground: var(--sumi-text-primary);
--destructive: var(--sumi-vermillion);
--destructive-foreground: #ffffff;
--success: var(--sumi-success);
--success-foreground: #ffffff;
--warning: var(--sumi-warning);
--warning-foreground: var(--sumi-text-inverse);
--info: var(--sumi-info);
--info-foreground: var(--sumi-text-inverse);
--border: var(--sumi-border-default);
--input: var(--sumi-border-default);
--ring: var(--sumi-border-focus);
--radius: var(--sumi-radius-md);
/* Charts */
--chart-1: var(--sumi-accent);
--chart-2: var(--sumi-vermillion);
--chart-3: var(--sumi-sage);
--chart-4: var(--sumi-gold);
--chart-5: #8b7ec8;
/* Sidebar mapping */
--sidebar: var(--sumi-bg-raised);
--sidebar-foreground: var(--sumi-text-secondary);
--sidebar-primary: var(--sumi-accent);
--sidebar-primary-foreground: var(--sumi-text-primary);
--sidebar-accent: var(--sumi-accent-subtle);
--sidebar-accent-foreground: var(--sumi-text-primary);
--sidebar-border: var(--sumi-border-faint);
--sidebar-ring: var(--sumi-accent);
/* Sidebar active item indicator */
--sidebar-active-indicator: inset 2px 0 0 0 var(--sidebar-primary);
/* ═══ LAYOUT PRIMITIVES (preserved from previous system) ═══ */
--layout-content-max-width: 100rem;
--layout-main-min-height: calc(100vh - 4rem);
--layout-page-min-height: 37.5rem;
--layout-page-min-height-sm: 25rem;
--layout-story-decorator-min-height: 12rem;
--layout-gap: 1rem;
--layout-gap-sm: 0.75rem;
--layout-gap-lg: 1.5rem;
--layout-drawer-max-height: 60vh;
--layout-panel-max-height: 70vh;
--layout-list-max-height: 25rem;
--layout-modal-max-height: 85vh;
--layout-modal-max-height-sm: 80vh;
--layout-modal-max-height-xs: 70vh;
--layout-modal-max-height-lg: 90vh;
--layout-lyrics-height: 60vh;
--layout-lyrics-height-sm: 50vh;
--layout-chat-height: calc(100vh - 6.25rem);
--layout-chat-main-height: calc(100vh - 6rem);
--layout-stream-height: calc(100vh - 6rem);
--layout-modal-full-height: calc(100vh - 2rem);
/* App shell — header, main offsets and margins (sidebar-driven) */
--header-height: 4rem;
--main-offset-top: 5rem;
--main-offset-bottom: 9rem;
--main-margin-left-expanded: 18rem;
--main-margin-left-collapsed: 7rem;
--header-left-expanded: 18rem;
--header-left-collapsed: 5rem;
/* Sidebar layout */
--sidebar-width-expanded: 15rem;
--sidebar-width-collapsed: 5rem;
--sidebar-offset-left: 1.5rem;
--sidebar-offset-top: 5rem;
--sidebar-offset-bottom: 1.5rem;
--sidebar-z-index: 95;
--sidebar-overlay-z-index: 90;
--player-z-index: var(--sumi-z-sticky);
}
/* ═══════════════════════════════════════════════════════════════════════════
LIGHT THEME — Washi Paper (和紙)
═══════════════════════════════════════════════════════════════════════════ */
[data-theme="light"] {
--sumi-bg-void: #f0ece4;
--sumi-bg-base: #f6f3ed;
--sumi-bg-raised: #ffffff;
--sumi-bg-overlay: #ffffff;
--sumi-bg-hover: #ede9e1;
--sumi-bg-active: #e4e0d8;
--sumi-bg-wash: #f8f6f1;
--sumi-surface-inset: #ebe7df;
--sumi-surface-subtle: #f2eee6;
--sumi-surface-card: #ffffff;
--sumi-surface-elevated: #ffffff;
--sumi-border-faint: rgba(0,0,0, 0.05);
--sumi-border-default: rgba(0,0,0, 0.10);
--sumi-border-strong: rgba(0,0,0, 0.18);
--sumi-border-focus: rgba(80,110,170, 0.45);
--sumi-border-accent: rgba(80,110,170, 0.25);
--sumi-text-primary: #1a1816;
--sumi-text-secondary: #5c5854;
--sumi-text-tertiary: #8a8580;
--sumi-text-disabled: #b5b0aa;
--sumi-text-inverse: #f0ede8;
--sumi-text-link: #4a6fa5;
--sumi-accent: #4a6fa5;
--sumi-accent-hover: #3a5f95;
--sumi-accent-active: #5a7fb5;
--sumi-accent-subtle: rgba(74,111,165, 0.12);
--sumi-accent-muted: rgba(74,111,165, 0.20);
--sumi-accent-emphasis: #3d5f90;
--sumi-vermillion: #b84a35;
--sumi-vermillion-hover: #a03e2e;
--sumi-vermillion-subtle: rgba(184,74,53, 0.12);
--sumi-sage: #5a7e4e;
--sumi-sage-hover: #4d6e42;
--sumi-sage-subtle: rgba(90,126,78, 0.12);
--sumi-gold: #9a7d2e;
--sumi-gold-hover: #8a6d20;
--sumi-gold-subtle: rgba(154,125,46, 0.12);
--sumi-live: #c84040;
--sumi-shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
--sumi-shadow-sm: 0 2px 4px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
--sumi-shadow-md: 0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04);
--sumi-shadow-lg: 0 8px 24px rgba(0,0,0,0.10), 0 4px 8px rgba(0,0,0,0.05);
--sumi-shadow-xl: 0 16px 48px rgba(0,0,0,0.12), 0 8px 16px rgba(0,0,0,0.06);
--sumi-shadow-2xl: 0 24px 64px rgba(0,0,0,0.15);
--sumi-shadow-glow: 0 0 0 3px rgba(74,111,165,0.25);
--sumi-glass-bg: rgba(255,255,255, 0.85);
--sumi-glass-border: rgba(0,0,0, 0.06);
--sumi-scrollbar-thumb: rgba(0,0,0, 0.12);
--sumi-scrollbar-hover: rgba(0,0,0, 0.22);
--primary-foreground: #ffffff;
}
/* ═══════════════════════════════════════════════════════════════════════════
TAILWIND THEME MAPPING
═══════════════════════════════════════════════════════════════════════════ */
@theme inline {
/* Typography */
--font-sans: var(--sumi-font-body);
--font-heading: var(--sumi-font-heading);
--font-mono: var(--sumi-font-mono);
--font-serif: var(--sumi-font-serif);
/* Semantic color mapping to Tailwind utilities */
--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 */
--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);
/* SUMI direct accent access */
--color-sumi-accent: var(--sumi-accent);
--color-sumi-vermillion: var(--sumi-vermillion);
--color-sumi-sage: var(--sumi-sage);
--color-sumi-gold: var(--sumi-gold);
--color-gaming-gold: var(--sumi-gold);
--color-terminal-green: #3eaa5e;
--color-graffiti-magenta: #c840a0;
--color-sakura: #e0a0b8;
/* 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);
/* Shadows — wired to SUMI tokens (auto dark/light) */
--shadow-xs: var(--sumi-shadow-xs);
--shadow-sm: var(--sumi-shadow-sm);
--shadow-md: var(--sumi-shadow-md);
--shadow-lg: var(--sumi-shadow-lg);
--shadow-xl: var(--sumi-shadow-xl);
--shadow-2xl: var(--sumi-shadow-2xl);
/* Card-specific shadows */
--shadow-card: var(--sumi-shadow-sm);
--shadow-card-hover: var(--sumi-shadow-md);
/* Radius */
--radius-sm: var(--sumi-radius-sm);
--radius-md: var(--sumi-radius-md);
--radius-lg: var(--sumi-radius-lg);
--radius-xl: var(--sumi-radius-xl);
--radius-2xl: var(--sumi-radius-2xl);
--radius-full: var(--sumi-radius-full);
/* 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";
}
/* Paper grain texture — barely perceptible washi feeling */
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.012;
pointer-events: none;
z-index: 9998;
mix-blend-mode: overlay;
}
::selection {
background: var(--primary);
color: var(--primary-foreground);
}
/* Custom Scrollbar — thin, subtle */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: var(--sumi-scrollbar-track);
}
::-webkit-scrollbar-thumb {
background: var(--sumi-scrollbar-thumb);
border-radius: var(--sumi-radius-full);
transition: background-color 0.2s ease;
}
::-webkit-scrollbar-thumb:hover {
background: var(--sumi-scrollbar-hover);
}
@supports (scrollbar-width: thin) {
* {
scrollbar-width: thin;
scrollbar-color: var(--sumi-scrollbar-thumb) transparent;
}
}
/* Typography — headings use Space Grotesk */
h1, h2, h3, h4, h5, h6 {
@apply font-heading 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;
}
}
/* ═══════════════════════════════════════════════════════════════════════════
SUMI UTILITY CLASSES
═══════════════════════════════════════════════════════════════════════════ */
@layer utilities {
/* Layout primitives — standard widths/heights 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); }
.max-h-layout-modal { max-height: var(--layout-modal-max-height); }
.max-h-layout-modal-sm { max-height: var(--layout-modal-max-height-sm); }
.max-h-layout-modal-xs { max-height: var(--layout-modal-max-height-xs); }
.max-h-layout-modal-lg { max-height: var(--layout-modal-max-height-lg); }
.h-layout-modal-sm { height: var(--layout-modal-max-height-sm); }
.h-layout-lyrics { height: var(--layout-lyrics-height); }
.h-layout-lyrics-sm { height: var(--layout-lyrics-height-sm); }
.h-layout-chat { height: var(--layout-chat-height); }
.h-layout-chat-main { height: var(--layout-chat-main-height); }
.h-layout-stream { height: var(--layout-stream-height); }
.h-layout-modal-full { height: var(--layout-modal-full-height); }
/* Sidebar layout utilities */
.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); }
.z-player { z-index: var(--player-z-index); }
/* App shell — header / main offsets */
.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); }
/* Responsive margin-left for main */
@media (min-width: 1024px) {
.lg\:ml-main-expanded { margin-left: var(--main-margin-left-expanded); }
.lg\:ml-main-collapsed { margin-left: var(--main-margin-left-collapsed); }
.lg\:left-main-expanded { left: var(--main-margin-left-expanded); }
.lg\:left-main-collapsed { left: var(--main-margin-left-collapsed); }
.lg\:w-player-bar-expanded { width: calc(100vw - var(--main-margin-left-expanded) - 1rem); }
.lg\:w-player-bar-collapsed { width: calc(100vw - var(--main-margin-left-collapsed) - 1rem); }
}
/* Player bar width: mobile (no sidebar) */
.w-player-bar { width: calc(100vw - 2rem); }
.left-header-expanded { left: var(--header-left-expanded); }
.left-header-collapsed { left: var(--header-left-collapsed); }
/* Shell transition — sidebar width/opacity */
.transition-shell {
transition: width var(--sumi-duration-normal) var(--sumi-ease-out),
opacity var(--sumi-duration-normal) var(--sumi-ease-out),
transform var(--sumi-duration-normal) var(--sumi-ease-out);
}
/* Respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.transition-shell {
transition: none;
}
.player-bar-entrance {
animation: none !important;
}
}
/* Sidebar active nav item — left border indicator */
.sidebar-active-indicator {
box-shadow: var(--sidebar-active-indicator);
}
/* Glass Effect */
.glass, .sumi-glass {
background: var(--sumi-glass-bg);
backdrop-filter: blur(var(--sumi-glass-blur));
-webkit-backdrop-filter: blur(var(--sumi-glass-blur));
border: 1px solid var(--sumi-glass-border);
}
/* Typography utilities — SUMI hierarchy */
.font-heading { font-family: var(--sumi-font-heading); }
.font-serif { font-family: var(--sumi-font-serif); }
.text-display { @apply text-4xl font-bold tracking-tight; }
.text-heading-1 { @apply text-3xl font-semibold tracking-tight; }
.text-heading-2 { @apply text-2xl font-semibold; }
.text-heading-3 { @apply text-xl font-medium; }
.text-heading-4 { @apply text-lg font-medium; }
.text-body-lg { @apply text-base leading-relaxed; }
.text-body { @apply text-sm leading-relaxed; }
.text-caption { @apply text-xs text-muted-foreground; }
.text-label { @apply text-xs font-medium uppercase tracking-wider text-muted-foreground; }
/* SUMI typography classes (from design system) */
.sumi-display { font-family: var(--sumi-font-heading); font-size: var(--sumi-text-4xl); font-weight: var(--sumi-weight-bold); line-height: var(--sumi-leading-tight); letter-spacing: var(--sumi-tracking-tighter); }
.sumi-h1 { font-family: var(--sumi-font-heading); font-size: var(--sumi-text-3xl); font-weight: var(--sumi-weight-semibold); line-height: var(--sumi-leading-tight); letter-spacing: var(--sumi-tracking-tight); }
.sumi-h2 { font-family: var(--sumi-font-heading); font-size: var(--sumi-text-2xl); font-weight: var(--sumi-weight-semibold); line-height: var(--sumi-leading-snug); letter-spacing: var(--sumi-tracking-tight); }
.sumi-h3 { font-family: var(--sumi-font-heading); font-size: var(--sumi-text-xl); font-weight: var(--sumi-weight-medium); line-height: var(--sumi-leading-snug); }
.sumi-h4 { font-family: var(--sumi-font-heading); font-size: var(--sumi-text-lg); font-weight: var(--sumi-weight-medium); line-height: var(--sumi-leading-snug); }
.sumi-body-lg { font-size: var(--sumi-text-md); font-weight: var(--sumi-weight-regular); line-height: var(--sumi-leading-relaxed); }
.sumi-body { font-size: var(--sumi-text-base); font-weight: var(--sumi-weight-regular); line-height: var(--sumi-leading-normal); }
.sumi-body-sm { font-size: var(--sumi-text-sm); font-weight: var(--sumi-weight-regular); line-height: var(--sumi-leading-normal); }
.sumi-caption { font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-regular); line-height: var(--sumi-leading-normal); }
.sumi-label { font-size: var(--sumi-text-xs); font-weight: var(--sumi-weight-medium); line-height: var(--sumi-leading-normal); letter-spacing: var(--sumi-tracking-wider); text-transform: uppercase; }
.sumi-mono { font-family: var(--sumi-font-mono); font-size: var(--sumi-text-sm); }
/* Animation Utilities */
.animate-fade-in { animation: sumi-fade-in var(--sumi-duration-normal) var(--sumi-ease-out); }
.animate-slide-up { animation: sumi-slide-up var(--sumi-duration-normal) var(--sumi-ease-out); }
.animate-scale-in { animation: sumi-scale-in var(--sumi-duration-normal) var(--sumi-ease-out); }
.animate-fadeIn { animation: sumi-fade-in var(--sumi-duration-normal) var(--sumi-ease-out); }
.animate-scaleIn { animation: sumi-scale-in var(--sumi-duration-normal) var(--sumi-ease-out); }
.animate-pop { animation: sumi-pop var(--sumi-duration-slower) var(--sumi-ease-bounce); }
.animate-like-bounce { animation: like-bounce var(--sumi-duration-slow) var(--sumi-ease-out); }
.animate-shake { animation: shake 0.4s ease-in-out; }
.animate-spin-slow { animation: spin-slow 10s linear infinite; }
.animate-achievement { animation: achievement-slide 0.5s var(--sumi-ease-spring); }
.animate-eq { animation: eq-bar 0.5s ease-in-out infinite; }
.animate-marquee { animation: marquee 10s linear infinite; }
.animate-auth-enter { animation: auth-enter var(--sumi-duration-slow) var(--sumi-ease-out) both; }
.animate-empty-state-in { animation: sumi-scale-in var(--sumi-duration-normal) var(--sumi-ease-out) both; }
.animate-stagger-in { animation: sumi-slide-up var(--sumi-duration-normal) var(--sumi-ease-out) both; }
.animate-glow-pulse { animation: sumi-pulse 2s ease-in-out infinite; }
/* Ink Wash Texture (hero/feature sections) */
.sumi-wash-texture { position: relative; }
.sumi-wash-texture::after {
content: '';
position: absolute;
inset: 0;
background:
radial-gradient(ellipse at 20% 50%, var(--sumi-accent-subtle) 0%, transparent 60%),
radial-gradient(ellipse at 80% 20%, rgba(201,168,76,0.04) 0%, transparent 50%);
pointer-events: none;
}
/* Noise texture utility */
.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;
}
@media (prefers-reduced-motion: reduce) {
.animate-stagger-in { animation: none; }
.animate-glow-pulse { animation: none; }
}
}
/* ═══════════════════════════════════════════════════════════════════════════
SKELETON SHIMMER — loading effect
═══════════════════════════════════════════════════════════════════════════ */
.skeleton-shimmer {
background: linear-gradient(
90deg,
transparent 0%,
rgba(255, 255, 255, 0.06) 40%,
rgba(255, 255, 255, 0.1) 50%,
rgba(255, 255, 255, 0.06) 60%,
transparent 100%
);
background-size: 200% 100%;
animation: shimmer 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.skeleton-shimmer {
animation: none;
background: none;
}
}
/* ═══════════════════════════════════════════════════════════════════════════
KEYFRAME ANIMATIONS — SUMI
═══════════════════════════════════════════════════════════════════════════ */
/* Core SUMI animations */
@keyframes sumi-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
/* S5.1: Branded loading progress bar */
@keyframes loading-progress {
0% { width: 0; transform: translateX(0); }
50% { width: 70%; transform: translateX(0); }
100% { width: 100%; transform: translateX(100%); }
}
@keyframes sumi-fade-out {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes sumi-slide-up {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes sumi-slide-down {
from { opacity: 0; transform: translateY(-8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes sumi-scale-in {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes sumi-scale-out {
from { opacity: 1; transform: scale(1); }
to { opacity: 0; transform: scale(0.95); }
}
/* Achievement pop — the ONE playful animation (gaming touch) */
@keyframes sumi-pop {
0% { opacity: 0; transform: scale(0.8); }
60% { opacity: 1; transform: scale(1.05); }
100% { transform: scale(1); }
}
/* Live/status pulse */
@keyframes sumi-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
/* Ink brush stroke reveal — page transitions */
@keyframes sumi-brush-reveal {
from { clip-path: inset(0 100% 0 0); }
to { clip-path: inset(0 0 0 0); }
}
/* Skeleton loading */
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* EQ bars — "now playing" indicator */
@keyframes eq-bar {
0%, 100% { transform: scaleY(0.3); }
50% { transform: scaleY(1); }
}
/* Legacy-compatible animations (used in existing codebase) */
@keyframes like-bounce {
0% { transform: scale(1); }
25% { transform: scale(1.3); }
50% { transform: scale(0.9); }
75% { transform: scale(1.1); }
100% { transform: scale(1); }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
20%, 40%, 60%, 80% { transform: translateX(4px); }
}
@keyframes spin-slow {
to { transform: rotate(360deg); }
}
@keyframes typing {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-4px); }
}
@keyframes marquee {
0%, 20% { transform: translateX(0); }
80%, 100% { transform: translateX(-100%); }
}
@keyframes achievement-slide {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes terminal-blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
@keyframes auth-enter {
from { opacity: 0; transform: translateY(12px) scale(0.98); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
@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); }
}
/* ═══════════════════════════════════════════════════════════════════════════
REDUCED MOTION
═══════════════════════════════════════════════════════════════════════════ */
@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;
}
/* Keep opacity transitions for functional feedback */
.interactive { transition: opacity 100ms ease-out; }
}