Migrate ink tones, washi tones, mizu/ai/vermillion aliases, semantic feedback aliases, full typography (font/text/leading/tracking/weight), spacing scale, radius, motion (durations + easings + transition shorthands), z-index, layout primitives, and circadian state vars from apps/web/src/index.css to packages/design-system/tokens/semantic/dark.json. apps/web/src/index.css : - Removed ~125 lines of duplicate --sumi-* declarations (theme-independent only). - Kept theme-tuned values (bg/surface/border/text/accent/error/sage/gold/kin/ shadow/glass/scrollbar/live) — different opacities and hex per theme. - Kept --sumi-patina-warmth (runtime state) + --sumi-grain-opacity (theme-dep). - Kept --duration-fast / --duration-normal (non-prefixed Tailwind aliases). - Kept shadcn/Radix mapping + layout primitives (--header-height: 4rem etc.). packages/design-system/tokens/ : - primitive/color.json : added vermillion-ink (#a04050), ai (#2a4e68 indigo), contextual accents (graffiti/gaming/terminal/sakura), alpha.ivory-08. - semantic/dark.json : exhaustive expansion (~150 tokens) covering all the --sumi-* vars deleted from index.css, plus glass/scrollbar/shadow/transition shorthands authored as full CSS values where references aren't sufficient. - semantic/light.json : minimal overrides (theme-specific only) + grain-opacity override (0.06 vs dark 0.04). Result : - index.css : 1523 → 1398 LOC (-125, ~8% smaller). - tokens.css : 245 → 379 LOC (+134, full coverage of theme-independent vars). - vite build OK (14s). No visual regression — theme-tuned values intact. Light theme block (lines ~259-329 in index.css) intentionally left for a future commit : every override there is theme-tuned with subtle hex/opacity diffs that don't yet have 1:1 mappings in tokens. Will be migrated when light.json expands to match tuned values exactly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1398 lines
54 KiB
CSS
1398 lines
54 KiB
CSS
@import 'tailwindcss';
|
||
@import 'tw-animate-css';
|
||
|
||
/* SUMI generated tokens — Single source of truth. See packages/design-system/tokens/.
|
||
This adds --color-* primitives and --sumi-* semantics (bg/text/accent/viz/feedback).
|
||
The legacy :root block below still defines additional --sumi-* vars (typography, motion,
|
||
z-index, glass…) pending migration to tokens.json (Sprint 2 follow-up). */
|
||
@import '@veza/design-system/tokens.css';
|
||
|
||
@custom-variant dark (&:is([data-theme="dark"] *));
|
||
|
||
/* ╔══════════════════════════════════════════════════════════════════════════╗
|
||
║ SUMI DESIGN SYSTEM v3.0 — "Lavis d'encre" (墨の濃淡) ║
|
||
║ VEZA × TALAS — Single Source of Truth ║
|
||
║ Ink wash aesthetic — contrast, wabi-sabi, ma (間) ║
|
||
║ Accent: Mizu cyan (#0098B5) — the only color in monochrome ink wash ║
|
||
╚══════════════════════════════════════════════════════════════════════════╝ */
|
||
|
||
/* ═══ @font-face — Self-hosted woff2 ═══ */
|
||
@font-face {
|
||
font-family: 'Space Grotesk';
|
||
src: url('/fonts/SpaceGrotesk-Bold.woff2') format('woff2');
|
||
font-weight: 700;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
@font-face {
|
||
font-family: 'Inter';
|
||
src: url('/fonts/Inter-Variable.woff2') format('woff2');
|
||
font-weight: 100 900;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
@font-face {
|
||
font-family: 'JetBrains Mono';
|
||
src: url('/fonts/JetBrainsMono-Regular.woff2') format('woff2');
|
||
font-weight: 400;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
DARK THEME (default) — Sumi ink on void (墨の闇)
|
||
═══════════════════════════════════════════════════════════════════════════ */
|
||
:root, [data-theme="dark"] {
|
||
/* ═══ BACKGROUNDS — Ink dilutions (墨の濃淡) ═══ */
|
||
--sumi-bg-void: #0A0A0C;
|
||
--sumi-bg-base: #0D0D0F;
|
||
--sumi-bg-raised: #141416;
|
||
--sumi-bg-overlay: #1A1A1E;
|
||
--sumi-bg-hover: #222226;
|
||
--sumi-bg-active: #2A2A2F;
|
||
--sumi-bg-wash: #111113;
|
||
|
||
/* ═══ SURFACES — Ink planes (墨面) ═══ */
|
||
--sumi-surface-inset: #0B0B0D;
|
||
--sumi-surface-subtle: #161618;
|
||
--sumi-surface-card: #141416;
|
||
--sumi-surface-elevated: #1A1A1E;
|
||
|
||
/* ═══ BORDERS — Ink lines (筆線) ═══ */
|
||
--sumi-border-faint: rgba(232,227,219, 0.03);
|
||
--sumi-border-default: rgba(232,227,219, 0.06);
|
||
--sumi-border-strong: rgba(232,227,219, 0.10);
|
||
--sumi-border-focus: rgba(0,152,181, 0.50);
|
||
--sumi-border-accent: rgba(0,152,181, 0.25);
|
||
|
||
/* ═══ TEXT — Ink on washi (墨と和紙) ═══ */
|
||
--sumi-text-primary: #E8E3DB;
|
||
--sumi-text-secondary: #9A958D;
|
||
--sumi-text-tertiary: #6B6660;
|
||
--sumi-text-disabled: #3D3A35;
|
||
--sumi-text-inverse: #F2EDE6;
|
||
--sumi-text-link: #0098B5;
|
||
|
||
/* ═══ PIGMENT — Mizu cyan (水) — the only color ═══ */
|
||
--sumi-accent: #0098B5;
|
||
--sumi-accent-hover: #00B4D8;
|
||
--sumi-accent-active: #007A94;
|
||
--sumi-accent-muted: rgba(0,152,181, 0.18);
|
||
--sumi-accent-subtle: rgba(0,152,181, 0.06);
|
||
--sumi-accent-emphasis: #006B7F;
|
||
|
||
/* ═══ FUNCTIONAL — Diluted pastels only (never solid fills) ═══ */
|
||
--sumi-error: rgba(180,80,70, 0.55);
|
||
--sumi-error-hover: rgba(180,80,70, 0.65);
|
||
--sumi-error-subtle: rgba(180,80,70, 0.10);
|
||
|
||
--sumi-sage: rgba(90,140,100, 0.60);
|
||
--sumi-sage-hover: rgba(90,140,100, 0.70);
|
||
--sumi-sage-subtle: rgba(90,140,100, 0.10);
|
||
|
||
--sumi-gold: rgba(190,150,60, 0.55);
|
||
--sumi-gold-hover: rgba(190,150,60, 0.65);
|
||
--sumi-gold-subtle: rgba(190,150,60, 0.10);
|
||
|
||
/* ═══ 金 — KIN (GOLD LEAF) ═══ */
|
||
--sumi-kin: #b8860b;
|
||
--sumi-kin-hover: #c8960b;
|
||
--sumi-kin-subtle: rgba(184,134,11, 0.08);
|
||
|
||
/* ═══ LEGACY ALIASES — backwards compat (components still reference these) ═══ */
|
||
--sumi-vermillion: #a04050;
|
||
--sumi-vermillion-hover: #b05060;
|
||
--sumi-vermillion-subtle: rgba(160,64,80, 0.10);
|
||
|
||
/* PATINA — runtime state, mutated by ThemeProvider per account age.
|
||
grain-opacity is theme-dependent (overridden in [data-theme="light"] below). */
|
||
--sumi-patina-warmth: 0deg;
|
||
--sumi-grain-opacity: 0.04;
|
||
|
||
/* Tokenized in @veza/design-system/tokens.css (theme-independent):
|
||
- 墨の六色 ink tones (--sumi-ink-{kuro,sumi,usuzumi,hai,gin,kasumi})
|
||
- 和紙 washi tones (--sumi-washi-*)
|
||
- mizu/ai/vermillion aliases
|
||
- circadian state (--sumi-circadian-warmth/brightness)
|
||
- semantic aliases (--sumi-{success,warning,info,live,online,error-semantic}*)
|
||
- typography (--sumi-font-*, --sumi-text-{xs..4xl}, --sumi-{leading,tracking,weight}-*)
|
||
- spacing + radius (--sumi-space-*, --sumi-radius-*) */
|
||
|
||
/* ═══ SHADOWS — Ink diffusion (滲み) — omnidirectional ═══ */
|
||
--sumi-shadow-xs: 0 0 4px rgba(26,26,30, 0.03);
|
||
--sumi-shadow-sm: 0 0 8px rgba(26,26,30, 0.05);
|
||
--sumi-shadow-md: 0 0 16px rgba(26,26,30, 0.08);
|
||
--sumi-shadow-lg: 0 0 24px rgba(26,26,30, 0.10);
|
||
--sumi-shadow-xl: 0 0 32px rgba(26,26,30, 0.15);
|
||
--sumi-shadow-2xl: 0 0 48px rgba(26,26,30, 0.20);
|
||
--sumi-shadow-glow: 0 0 0 3px rgba(0,152,181, 0.25);
|
||
--sumi-shadow-glow-lg: 0 0 20px rgba(0,152,181, 0.12);
|
||
--sumi-shadow-kin: 0 0 16px rgba(184,134,11, 0.15);
|
||
|
||
/* ═══ GLASS — Shoji screen (障子) ═══ */
|
||
--sumi-glass-bg: rgba(13,13,15, 0.80);
|
||
--sumi-glass-border: rgba(232,227,219, 0.04);
|
||
--sumi-glass-blur: 12px;
|
||
|
||
/* ═══ SCROLLBAR ═══ */
|
||
--sumi-scrollbar-track: transparent;
|
||
--sumi-scrollbar-thumb: rgba(232,227,219, 0.06);
|
||
--sumi-scrollbar-hover: rgba(232,227,219, 0.12);
|
||
|
||
/* Tokenized in @veza/design-system/tokens.css (theme-independent):
|
||
- motion (--sumi-motion-{goutte,trait,lavis,vague,maree})
|
||
- duration aliases (--sumi-duration-{instant,fast,normal,slow,slower})
|
||
- easings (--sumi-ease-{goutte,trait,lavis,vague,maree,rebond,default,out,in,in-out,bounce,spring})
|
||
- transition shorthands (--sumi-transition-{colors,opacity,transform,shadow})
|
||
- z-index scale (--sumi-z-*)
|
||
- layout primitives (--sumi-{max-width,max-width-content,max-width-narrow,max-width-prose,sidebar-width,sidebar-collapsed,header-height,player-height}) */
|
||
|
||
/* Non-prefixed legacy aliases (Tailwind utilities still reference these — KEEP) */
|
||
--duration-fast: var(--sumi-motion-trait);
|
||
--duration-normal: var(--sumi-motion-lavis);
|
||
|
||
/* ═══ CONTEXTUAL ACCENTS (feature-specific) ═══ */
|
||
--graffiti-magenta: #a04050;
|
||
--gaming-gold: #b8860b;
|
||
--terminal-green: #4f6840;
|
||
--sakura: #d4a0b0;
|
||
--sumi-mizu: #0098B5; /* 水 — mizu cyan accent */
|
||
--sumi-ai: #2a4e68; /* 藍 — indigo */
|
||
|
||
/* ═══ 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-error);
|
||
--destructive-foreground: #E8E3DB;
|
||
--success: var(--sumi-success);
|
||
--success-foreground: #E8E3DB;
|
||
--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-error);
|
||
--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;
|
||
--mobile-bottom-nav-height: 4rem;
|
||
--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 (和紙) — Ink on warm paper
|
||
═══════════════════════════════════════════════════════════════════════════ */
|
||
[data-theme="light"] {
|
||
--sumi-bg-void: #E8E3DB;
|
||
--sumi-bg-base: #F2EDE6;
|
||
--sumi-bg-raised: #F2EDE6;
|
||
--sumi-bg-overlay: #F2EDE6;
|
||
--sumi-bg-hover: #E8E3DB;
|
||
--sumi-bg-active: #DED9D1;
|
||
--sumi-bg-wash: #ECE7DF;
|
||
|
||
--sumi-surface-inset: #E0DBD3;
|
||
--sumi-surface-subtle: #E8E3DB;
|
||
--sumi-surface-card: #F2EDE6;
|
||
--sumi-surface-elevated: #F7F2EB;
|
||
|
||
--sumi-border-faint: rgba(26,26,30, 0.04);
|
||
--sumi-border-default: rgba(26,26,30, 0.06);
|
||
--sumi-border-strong: rgba(26,26,30, 0.12);
|
||
--sumi-border-focus: rgba(0,122,148, 0.45);
|
||
--sumi-border-accent: rgba(0,122,148, 0.20);
|
||
|
||
--sumi-text-primary: #1A1A1E;
|
||
--sumi-text-secondary: #4A4A50;
|
||
--sumi-text-tertiary: #6B6660;
|
||
--sumi-text-disabled: #B5B0A8;
|
||
--sumi-text-inverse: #E8E3DB;
|
||
--sumi-text-link: #006B7F;
|
||
|
||
--sumi-accent: #007A94;
|
||
--sumi-accent-hover: #006B7F;
|
||
--sumi-accent-active: #008DAD;
|
||
--sumi-accent-subtle: rgba(0,122,148, 0.08);
|
||
--sumi-accent-muted: rgba(0,122,148, 0.15);
|
||
--sumi-accent-emphasis: #005A6B;
|
||
|
||
--sumi-error: rgba(180,80,70, 0.70);
|
||
--sumi-error-hover: rgba(180,80,70, 0.80);
|
||
--sumi-error-subtle: rgba(180,80,70, 0.08);
|
||
|
||
--sumi-sage: rgba(60,100,70, 0.75);
|
||
--sumi-sage-hover: rgba(60,100,70, 0.85);
|
||
--sumi-sage-subtle: rgba(60,100,70, 0.08);
|
||
|
||
--sumi-gold: rgba(160,125,40, 0.70);
|
||
--sumi-gold-hover: rgba(160,125,40, 0.80);
|
||
--sumi-gold-subtle: rgba(160,125,40, 0.08);
|
||
|
||
--sumi-kin: #9a7208;
|
||
--sumi-kin-hover: #886008;
|
||
--sumi-kin-subtle: rgba(154,114,8, 0.06);
|
||
|
||
--sumi-live: rgba(180,80,70, 0.70);
|
||
|
||
--sumi-shadow-xs: 0 0 4px rgba(26,26,30, 0.03);
|
||
--sumi-shadow-sm: 0 0 8px rgba(26,26,30, 0.04);
|
||
--sumi-shadow-md: 0 0 16px rgba(26,26,30, 0.06);
|
||
--sumi-shadow-lg: 0 0 24px rgba(26,26,30, 0.08);
|
||
--sumi-shadow-xl: 0 0 32px rgba(26,26,30, 0.10);
|
||
--sumi-shadow-2xl: 0 0 48px rgba(26,26,30, 0.12);
|
||
--sumi-shadow-glow: 0 0 0 3px rgba(0,122,148, 0.18);
|
||
--sumi-shadow-kin: 0 0 16px rgba(154,114,8, 0.12);
|
||
|
||
--sumi-glass-bg: rgba(242,237,230, 0.85);
|
||
--sumi-glass-border: rgba(26,26,30, 0.04);
|
||
|
||
--sumi-scrollbar-thumb: rgba(26,26,30, 0.08);
|
||
--sumi-scrollbar-hover: rgba(26,26,30, 0.16);
|
||
|
||
/* --sumi-grain-opacity overridden via tokens-light.css (see semantic/light.json) */
|
||
|
||
--primary-foreground: #F2EDE6;
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
HIGH CONTRAST MODE — 極墨 (Extreme Ink) — WCAG AA 4.5:1+
|
||
═══════════════════════════════════════════════════════════════════════════ */
|
||
[data-theme="dark"][data-contrast="high"] {
|
||
--sumi-bg-void: #000000;
|
||
--sumi-bg-base: #050506;
|
||
--sumi-bg-raised: #0D0D0F;
|
||
--sumi-bg-overlay: #141416;
|
||
--sumi-bg-hover: #1E1E22;
|
||
--sumi-bg-active: #262628;
|
||
--sumi-text-primary: #ffffff;
|
||
--sumi-text-secondary: #D5D0C8;
|
||
--sumi-text-tertiary: #B0ABA3;
|
||
--sumi-border-default: rgba(232,227,219, 0.25);
|
||
--sumi-border-faint: rgba(232,227,219, 0.12);
|
||
--sumi-border-strong: rgba(232,227,219, 0.40);
|
||
--sumi-accent: #00C4E8;
|
||
--sumi-accent-hover: #00D8FF;
|
||
}
|
||
|
||
[data-theme="light"][data-contrast="high"] {
|
||
--sumi-bg-void: #ffffff;
|
||
--sumi-bg-base: #FDFCF8;
|
||
--sumi-bg-raised: #F8F5EE;
|
||
--sumi-bg-overlay: #F0ECE2;
|
||
--sumi-bg-hover: #E5E0D5;
|
||
--sumi-bg-active: #D8D2C5;
|
||
--sumi-text-primary: #000000;
|
||
--sumi-text-secondary: #1A1A1E;
|
||
--sumi-text-tertiary: #3D3A35;
|
||
--sumi-border-default: rgba(26,26,30, 0.25);
|
||
--sumi-border-faint: rgba(26,26,30, 0.12);
|
||
--sumi-border-strong: rgba(26,26,30, 0.40);
|
||
--sumi-accent: #005A6B;
|
||
--sumi-accent-hover: #004A58;
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
DENSITY MODES — compact reduces spacing ~25%
|
||
═══════════════════════════════════════════════════════════════════════════ */
|
||
[data-density="compact"] {
|
||
--sumi-space-0-5: 1.5px;
|
||
--sumi-space-1: 3px;
|
||
--sumi-space-1-5: 4.5px;
|
||
--sumi-space-2: 6px;
|
||
--sumi-space-2-5: 7.5px;
|
||
--sumi-space-3: 9px;
|
||
--sumi-space-4: 12px;
|
||
--sumi-space-5: 15px;
|
||
--sumi-space-6: 18px;
|
||
--sumi-space-8: 24px;
|
||
--sumi-space-10: 30px;
|
||
--sumi-space-12: 36px;
|
||
--sumi-space-16: 48px;
|
||
--sumi-space-20: 60px;
|
||
--sumi-text-base: 0.8125rem;
|
||
}
|
||
|
||
[data-density="comfortable"] {
|
||
font-size: 1rem;
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
FOCUS VISIBLE — distinct ring for keyboard navigation
|
||
═══════════════════════════════════════════════════════════════════════════ */
|
||
:focus-visible {
|
||
outline: 2px solid var(--sumi-accent);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
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: #d090a8;
|
||
--color-sumi-mizu: var(--sumi-mizu);
|
||
--color-sumi-kin: var(--sumi-kin);
|
||
--color-sumi-ai: var(--sumi-ai);
|
||
|
||
/* 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-size: var(--sumi-font-size-base);
|
||
font-feature-settings: "cv02", "cv03", "cv04", "cv11";
|
||
}
|
||
|
||
/* ═══ SUMI v3 — Washi fiber grain (和紙繊維) ═══
|
||
Anisotropic noise simulating washi paper fiber direction.
|
||
baseFrequency 0.4x0.9 = horizontal fibers. 5 octaves = fine detail.
|
||
GPU-composited via position:fixed. */
|
||
body::after {
|
||
content: '';
|
||
position: fixed;
|
||
inset: 0;
|
||
background:
|
||
url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='w'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.4 0.9' numOctaves='5' stitchTiles='stitch' seed='2'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23w)'/%3E%3C/svg%3E");
|
||
opacity: var(--sumi-grain-opacity, 0.04);
|
||
pointer-events: none;
|
||
z-index: 9998;
|
||
mix-blend-mode: soft-light;
|
||
}
|
||
|
||
/* ═══ SUMI v3 — Subtle ink wash vignette (墨暈し) ═══
|
||
Very faint radial light at top-center, like a distant lamp on canvas. */
|
||
body::before {
|
||
content: '';
|
||
position: fixed;
|
||
inset: 0;
|
||
background: radial-gradient(ellipse at 30% 20%, rgba(210,195,168, 0.04) 0%, transparent 60%),
|
||
radial-gradient(ellipse at 70% 80%, rgba(180,165,135, 0.03) 0%, transparent 50%);
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
|
||
/* ═══ SUMI v3 — Circadian + Patina filter ═══
|
||
Applied on #root to avoid affecting the grain layer.
|
||
hue-rotate shifts warmth. brightness adjusts for time of day.
|
||
Transition is 5 min (300s) so changes are imperceptible. */
|
||
#root {
|
||
filter:
|
||
hue-rotate(calc(var(--sumi-circadian-warmth) + var(--sumi-patina-warmth, 0deg)))
|
||
brightness(var(--sumi-circadian-brightness));
|
||
transition: filter 300s linear;
|
||
}
|
||
|
||
/* Eco mode — disable all cosmetic layers */
|
||
[data-eco="true"] body::after { display: none; }
|
||
[data-eco="true"] body::before { display: none; }
|
||
[data-eco="true"] #root { filter: none; transition: none; }
|
||
|
||
/* Respect reduced motion */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
body::after { display: none; }
|
||
body::before { display: none; }
|
||
#root { filter: none; transition: none; }
|
||
}
|
||
|
||
/* ═══ SUMI v3 — Patina levels (墨の歳月) ═══ */
|
||
[data-patina="1"] { --sumi-grain-opacity: 0.05; }
|
||
[data-patina="2"] { --sumi-grain-opacity: 0.06; }
|
||
[data-patina="3"] {
|
||
--sumi-grain-opacity: 0.07;
|
||
--sumi-border-default: rgba(0,152,181, 0.05);
|
||
}
|
||
[data-patina="4"] {
|
||
--sumi-grain-opacity: 0.08;
|
||
--sumi-border-default: rgba(0,152,181, 0.08);
|
||
--sumi-shadow-sm: 0 0 8px rgba(0,152,181, 0.08);
|
||
}
|
||
|
||
::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 — Space Grotesk Bold UPPERCASE (engraved stone) */
|
||
h1, h2, h3, h4, h5, h6 {
|
||
@apply font-heading text-foreground;
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
text-wrap: balance;
|
||
}
|
||
|
||
h1 { font-size: 2rem; letter-spacing: 0.15em; line-height: 1.2; }
|
||
h2 { font-size: 1.5rem; letter-spacing: 0.12em; line-height: 1.3; }
|
||
h3 { font-size: 1.25rem; letter-spacing: 0.10em; line-height: 1.4; }
|
||
h4 { font-size: 1.125rem; letter-spacing: 0.08em; line-height: 1.4; }
|
||
h5 { font-size: 1rem; letter-spacing: 0.08em; line-height: 1.4; }
|
||
h6 { font-size: 0.875rem; letter-spacing: 0.08em; line-height: 1.5; }
|
||
|
||
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); }
|
||
.h-mobile-nav { height: var(--mobile-bottom-nav-height); }
|
||
|
||
/* 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);
|
||
}
|
||
|
||
/* ═══ Ink Edge utilities — diffused shadows instead of borders ═══ */
|
||
.ink-edge {
|
||
border: none;
|
||
box-shadow: 0 0 8px rgba(26,26,30, 0.05);
|
||
}
|
||
.ink-edge-faint {
|
||
border: none;
|
||
box-shadow: 0 0 4px rgba(26,26,30, 0.03);
|
||
}
|
||
.ink-edge-strong {
|
||
border: none;
|
||
box-shadow: 0 0 12px rgba(26,26,30, 0.08);
|
||
}
|
||
.ink-edge-bottom {
|
||
border: none;
|
||
box-shadow: 0 4px 8px -4px rgba(26,26,30, 0.08);
|
||
}
|
||
.ink-edge-right {
|
||
border: none;
|
||
box-shadow: 4px 0 8px -4px rgba(26,26,30, 0.06);
|
||
}
|
||
|
||
/* Glass Effect — Shoji screen (障子) */
|
||
.glass, .sumi-glass {
|
||
background: var(--sumi-glass-bg);
|
||
backdrop-filter: blur(var(--sumi-glass-blur)) saturate(0.85);
|
||
-webkit-backdrop-filter: blur(var(--sumi-glass-blur)) saturate(0.85);
|
||
box-shadow: 0 0 8px rgba(26,26,30, 0.05);
|
||
}
|
||
|
||
/* Typography utilities — SUMI hierarchy */
|
||
.font-heading { font-family: var(--sumi-font-heading); }
|
||
.font-serif { font-family: var(--sumi-font-serif); }
|
||
|
||
.text-display { font-size: 2.25rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.15em; line-height: 1.2; }
|
||
.text-heading-1 { font-size: 1.875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; line-height: 1.3; }
|
||
.text-heading-2 { font-size: 1.5rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.10em; line-height: 1.4; }
|
||
.text-heading-3 { font-size: 1.25rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; line-height: 1.4; }
|
||
.text-heading-4 { font-size: 1.125rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; line-height: 1.4; }
|
||
.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: 2.25rem; font-weight: 700; line-height: 1.2; letter-spacing: 0.15em; text-transform: uppercase; }
|
||
.sumi-h1 { font-family: var(--sumi-font-heading); font-size: 1.875rem; font-weight: 700; line-height: 1.3; letter-spacing: 0.12em; text-transform: uppercase; }
|
||
.sumi-h2 { font-family: var(--sumi-font-heading); font-size: 1.5rem; font-weight: 700; line-height: 1.4; letter-spacing: 0.10em; text-transform: uppercase; }
|
||
.sumi-h3 { font-family: var(--sumi-font-heading); font-size: 1.25rem; font-weight: 700; line-height: 1.4; letter-spacing: 0.08em; text-transform: uppercase; }
|
||
.sumi-h4 { font-family: var(--sumi-font-heading); font-size: 1.125rem; font-weight: 700; line-height: 1.4; letter-spacing: 0.08em; text-transform: uppercase; }
|
||
.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; }
|
||
.animate-content-reveal { animation: content-reveal var(--sumi-duration-slow) var(--sumi-ease-out) both; }
|
||
.animate-glow-breathe { animation: glow-breathe 3s ease-in-out infinite; }
|
||
.animate-vinyl-spin { animation: vinyl-spin 3s linear infinite; }
|
||
.animate-vinyl-spin.paused { animation-play-state: paused; }
|
||
.animate-slide-in-right { animation: slide-in-right var(--sumi-duration-normal) var(--sumi-ease-spring); }
|
||
.animate-subtle-float { animation: subtle-float 6s ease-in-out infinite; }
|
||
.animate-card-enter { animation: card-enter var(--sumi-duration-slow) var(--sumi-ease-out) both; }
|
||
|
||
/* Now-playing EQ bars container */
|
||
.eq-bars {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
gap: 2px;
|
||
height: 14px;
|
||
width: 14px;
|
||
}
|
||
.eq-bars > span {
|
||
display: block;
|
||
width: 3px;
|
||
border-radius: 1px;
|
||
background: currentColor;
|
||
}
|
||
.eq-bars > span:nth-child(1) { animation: eq-bar-1 0.8s ease-in-out infinite; }
|
||
.eq-bars > span:nth-child(2) { animation: eq-bar-2 0.7s ease-in-out infinite; }
|
||
.eq-bars > span:nth-child(3) { animation: eq-bar-3 0.9s ease-in-out infinite; }
|
||
.eq-bars.paused > span { animation-play-state: paused; height: 30%; }
|
||
|
||
/* Gradient text animation */
|
||
.animate-gradient-text {
|
||
background-size: 200% auto;
|
||
animation: gradient-shift 3s ease-in-out infinite;
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
}
|
||
|
||
/* Section divider — brush stroke (筆致) */
|
||
.section-divider {
|
||
height: 2px;
|
||
background: linear-gradient(90deg,
|
||
transparent 0%,
|
||
var(--sumi-border-faint) 8%,
|
||
var(--sumi-border-strong) 25%,
|
||
var(--sumi-border-strong) 75%,
|
||
var(--sumi-border-faint) 92%,
|
||
transparent 100%
|
||
);
|
||
opacity: 0.8;
|
||
}
|
||
|
||
/* Gold leaf line — 金箔 accent divider */
|
||
.gold-line {
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent 0%, rgba(184,134,11,0.4) 30%, rgba(184,134,11,0.15) 70%, transparent 100%);
|
||
}
|
||
|
||
/* Player bar entrance */
|
||
.player-bar-entrance {
|
||
animation: player-bar-entrance var(--sumi-duration-slower) var(--sumi-ease-spring) both;
|
||
}
|
||
|
||
/* Progress bar — ink flow */
|
||
.progress-bar-animated {
|
||
background: linear-gradient(90deg, var(--sumi-accent) 0%, var(--sumi-accent-hover) 50%, var(--sumi-accent) 100%);
|
||
background-size: 200% 100%;
|
||
animation: progress-shimmer 2s ease-in-out infinite;
|
||
}
|
||
|
||
/* Sumi-e animation utilities */
|
||
.animate-ink-drop { animation: sumi-ink-drop var(--sumi-duration-slow) var(--sumi-ease-spring); }
|
||
.animate-ink-spread { animation: sumi-ink-spread var(--sumi-duration-slower) var(--sumi-ease-out); }
|
||
.animate-brush-stroke { animation: sumi-brush-stroke var(--sumi-duration-slow) var(--sumi-ease-out); }
|
||
.animate-ink-reveal { animation: sumi-ink-reveal var(--sumi-duration-slower) var(--sumi-ease-out) both; }
|
||
|
||
/* Discord-style hover card lift */
|
||
.hover-lift {
|
||
transition: transform var(--sumi-duration-normal) var(--sumi-ease-out),
|
||
box-shadow var(--sumi-duration-normal) var(--sumi-ease-out);
|
||
}
|
||
.hover-lift:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--sumi-shadow-lg);
|
||
}
|
||
.hover-lift:active {
|
||
transform: translateY(0);
|
||
box-shadow: var(--sumi-shadow-sm);
|
||
}
|
||
|
||
/* Scrollbar hide utility */
|
||
.scrollbar-hide {
|
||
-ms-overflow-style: none;
|
||
scrollbar-width: none;
|
||
}
|
||
.scrollbar-hide::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
/* Line clamp utilities */
|
||
.line-clamp-2 {
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
.line-clamp-3 {
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 3;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* Ink Wash Texture — sumi-nagashi (墨流し) */
|
||
.sumi-wash-texture { position: relative; }
|
||
.sumi-wash-texture::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background:
|
||
radial-gradient(ellipse at 15% 60%, var(--sumi-accent-subtle) 0%, transparent 55%),
|
||
radial-gradient(ellipse at 85% 25%, rgba(255,255,255,0.015) 0%, transparent 45%),
|
||
radial-gradient(ellipse at 50% 90%, rgba(0,152,181,0.03) 0%, transparent 50%);
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* Ink bleed hover — bokashi (暈し) */
|
||
.sumi-ink-bleed { position: relative; overflow: hidden; }
|
||
.sumi-ink-bleed::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background: radial-gradient(circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
|
||
rgba(0,152,181, 0.06) 0%,
|
||
transparent 55%);
|
||
opacity: 0;
|
||
transition: opacity var(--sumi-duration-normal) var(--sumi-ease-default);
|
||
pointer-events: none;
|
||
}
|
||
.sumi-ink-bleed:hover::after { opacity: 1; }
|
||
|
||
/* Hanko stamp — subtle seal impression (判子) */
|
||
.sumi-hanko {
|
||
transform: rotate(-1.5deg);
|
||
box-shadow:
|
||
1px 1px 0 rgba(0,152,181, 0.2),
|
||
-0.5px -0.5px 0 rgba(0,0,0, 0.08);
|
||
}
|
||
|
||
/* Notan — dramatic light/dark contrast container (濃淡) */
|
||
.sumi-notan {
|
||
background: linear-gradient(
|
||
180deg,
|
||
var(--sumi-bg-void) 0%,
|
||
var(--sumi-bg-base) 30%,
|
||
var(--sumi-bg-raised) 100%
|
||
);
|
||
}
|
||
|
||
/* Bokashi gradient wash — for hero backgrounds (暈し) */
|
||
.sumi-bokashi {
|
||
background: linear-gradient(
|
||
135deg,
|
||
var(--sumi-bg-void) 0%,
|
||
var(--sumi-bg-base) 40%,
|
||
var(--sumi-bg-wash) 60%,
|
||
var(--sumi-bg-void) 100%
|
||
);
|
||
}
|
||
|
||
/* Sumi-nagashi marble background — floating ink (墨流し) */
|
||
.sumi-nagashi {
|
||
background:
|
||
radial-gradient(ellipse at 20% 50%, var(--sumi-bg-wash) 0%, transparent 50%),
|
||
radial-gradient(ellipse at 80% 50%, var(--sumi-bg-raised) 0%, transparent 40%),
|
||
radial-gradient(ellipse at 50% 80%, rgba(0,152,181,0.02) 0%, transparent 45%),
|
||
var(--sumi-bg-void);
|
||
background-size: 200% 200%;
|
||
}
|
||
.sumi-nagashi.animate { animation: sumi-nagashi 25s ease-in-out infinite; }
|
||
|
||
/* Ink card — atmospheric container with wash background */
|
||
.ink-card {
|
||
position: relative;
|
||
border-radius: var(--sumi-radius-sm);
|
||
overflow: hidden;
|
||
}
|
||
.ink-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: -20px;
|
||
background:
|
||
radial-gradient(ellipse at 25% 25%, rgba(232,224,208, 0.035) 0%, transparent 55%),
|
||
radial-gradient(ellipse at 75% 75%, rgba(232,224,208, 0.025) 0%, transparent 50%);
|
||
filter: blur(8px);
|
||
pointer-events: none;
|
||
}
|
||
.ink-card::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0; left: 5%; right: 10%;
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent 0%, var(--sumi-border-default) 20%, var(--sumi-border-faint) 60%, transparent 100%);
|
||
pointer-events: none;
|
||
}
|
||
.ink-card > * { position: relative; z-index: 1; }
|
||
|
||
/* Ghost kanji — large decorative character */
|
||
.ghost-kanji {
|
||
position: absolute;
|
||
font-family: var(--sumi-font-heading);
|
||
font-weight: 200;
|
||
opacity: 0.06;
|
||
pointer-events: none;
|
||
user-select: none;
|
||
line-height: 1;
|
||
z-index: 0;
|
||
color: currentColor;
|
||
}
|
||
[data-theme="light"] .ghost-kanji { opacity: 0.08; }
|
||
|
||
/* Brush underline — vermillion stroke accent */
|
||
.brush-underline::after {
|
||
content: '';
|
||
display: block;
|
||
margin-top: 8px;
|
||
height: 2px;
|
||
width: min(120px, 40%);
|
||
background: linear-gradient(90deg, var(--sumi-accent) 0%, transparent 100%);
|
||
border-radius: 1px;
|
||
}
|
||
|
||
/* Hanko seal — logo mark */
|
||
.hanko-seal {
|
||
position: relative;
|
||
transform: rotate(-2deg);
|
||
box-shadow:
|
||
0 0 0 1px rgba(0,152,181, 0.25),
|
||
0 2px 8px rgba(0,152,181, 0.12);
|
||
overflow: hidden;
|
||
}
|
||
.hanko-seal::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='50' height='50'%3E%3Cfilter id='n'%3E%3CfeTurbulence baseFrequency='0.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.15'/%3E%3C/svg%3E");
|
||
mix-blend-mode: overlay;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* Brush stroke divider — tapered ink line */
|
||
.brush-divider {
|
||
height: 2px;
|
||
background: linear-gradient(90deg,
|
||
var(--sumi-border-strong) 0%,
|
||
var(--sumi-border-default) 40%,
|
||
var(--sumi-border-faint) 70%,
|
||
transparent 100%);
|
||
border-radius: 1px;
|
||
}
|
||
|
||
/* Vertical brush stroke border — for sidebar/panel edges */
|
||
.sumi-stroke-border-left {
|
||
border-left: 2px solid var(--sumi-border-strong);
|
||
border-image: linear-gradient(
|
||
to bottom,
|
||
transparent 0%,
|
||
var(--sumi-border-default) 10%,
|
||
var(--sumi-border-strong) 30%,
|
||
var(--sumi-border-strong) 70%,
|
||
var(--sumi-border-default) 90%,
|
||
transparent 100%
|
||
) 1;
|
||
}
|
||
|
||
/* Noise texture utility — washi fiber (和紙) */
|
||
.noise { position: relative; }
|
||
.noise::before {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 0;
|
||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.35 0.85' numOctaves='5' stitchTiles='stitch' seed='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%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; }
|
||
.animate-content-reveal { animation: none; }
|
||
.animate-glow-breathe { animation: none; }
|
||
.animate-vinyl-spin { animation: none; }
|
||
.animate-slide-in-right { animation: none; }
|
||
.animate-subtle-float { animation: none; }
|
||
.progress-bar-animated { animation: none; }
|
||
.hover-lift { transition: none; }
|
||
.hover-lift:hover { transform: none; }
|
||
.animate-ink-drop { animation: none; }
|
||
.animate-ink-spread { animation: none; }
|
||
.animate-brush-stroke { animation: none; }
|
||
.animate-ink-reveal { animation: none; }
|
||
.sumi-nagashi.animate { animation: none; }
|
||
.sumi-ink-bleed::after { display: 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); }
|
||
}
|
||
|
||
/* Pop animation for modals/toasts */
|
||
@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); }
|
||
}
|
||
|
||
/* Player bar entrance — Spotify-style float up */
|
||
@keyframes player-bar-entrance {
|
||
from { opacity: 0; transform: translateY(20px) scale(0.98); }
|
||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||
}
|
||
|
||
/* Ink content reveal — emerges from darkness */
|
||
@keyframes content-reveal {
|
||
from { opacity: 0; transform: translateY(16px) scale(0.99); filter: blur(6px); }
|
||
to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
|
||
}
|
||
|
||
/* Sumi ink glow — subtle vermillion breathe */
|
||
@keyframes glow-breathe {
|
||
0%, 100% { box-shadow: 0 0 0 0 rgba(0,152,181, 0); }
|
||
50% { box-shadow: 0 0 20px 2px rgba(0,152,181, 0.10); }
|
||
}
|
||
|
||
/* Vinyl spin for now-playing */
|
||
@keyframes vinyl-spin {
|
||
from { transform: rotate(0deg); }
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
/* Progress bar shimmer (Spotify-style) */
|
||
@keyframes progress-shimmer {
|
||
0% { background-position: -200% 0; }
|
||
100% { background-position: 200% 0; }
|
||
}
|
||
|
||
/* Notification slide in from right */
|
||
@keyframes slide-in-right {
|
||
from { opacity: 0; transform: translateX(100%); }
|
||
to { opacity: 1; transform: translateX(0); }
|
||
}
|
||
|
||
/* Subtle float for cards */
|
||
@keyframes subtle-float {
|
||
0%, 100% { transform: translateY(0); }
|
||
50% { transform: translateY(-4px); }
|
||
}
|
||
|
||
@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); }
|
||
}
|
||
|
||
/* Now-playing EQ bars — 3-bar audio visualizer */
|
||
@keyframes eq-bar-1 {
|
||
0%, 100% { height: 30%; }
|
||
25% { height: 80%; }
|
||
50% { height: 50%; }
|
||
75% { height: 100%; }
|
||
}
|
||
@keyframes eq-bar-2 {
|
||
0%, 100% { height: 50%; }
|
||
20% { height: 100%; }
|
||
45% { height: 30%; }
|
||
70% { height: 80%; }
|
||
}
|
||
@keyframes eq-bar-3 {
|
||
0%, 100% { height: 60%; }
|
||
30% { height: 40%; }
|
||
55% { height: 100%; }
|
||
80% { height: 45%; }
|
||
}
|
||
|
||
/* Gradient text shimmer (for headings) */
|
||
@keyframes gradient-shift {
|
||
0% { background-position: 0% 50%; }
|
||
50% { background-position: 100% 50%; }
|
||
100% { background-position: 0% 50%; }
|
||
}
|
||
|
||
/* Gentle card entrance — stagger-friendly */
|
||
@keyframes card-enter {
|
||
from { opacity: 0; transform: translateY(12px) scale(0.97); }
|
||
to { opacity: 1; transform: translateY(0) scale(1); }
|
||
}
|
||
|
||
/* Ripple expand for empty states */
|
||
@keyframes ripple-expand {
|
||
0% { transform: scale(0.8); opacity: 0.4; }
|
||
50% { transform: scale(1.15); opacity: 0.15; }
|
||
100% { transform: scale(0.8); opacity: 0.4; }
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
SUMI-E ANIMATIONS — 墨絵 Ink Wash Effects
|
||
═══════════════════════════════════════════════════════════════════════════ */
|
||
|
||
/* Ink drop — element appears like ink hitting wet paper */
|
||
@keyframes sumi-ink-drop {
|
||
0% { transform: scale(0); opacity: 0; border-radius: 50%; }
|
||
35% { transform: scale(1.08); opacity: 0.85; border-radius: 48% 52% 50% 50%; }
|
||
55% { transform: scale(0.96); opacity: 1; }
|
||
75% { transform: scale(1.02); }
|
||
100% { transform: scale(1); opacity: 1; border-radius: inherit; }
|
||
}
|
||
|
||
/* Ink spread — circular reveal like ink spreading on washi */
|
||
@keyframes sumi-ink-spread {
|
||
0% { clip-path: circle(0% at 50% 50%); filter: blur(6px); opacity: 0; }
|
||
40% { filter: blur(2px); opacity: 0.8; }
|
||
100% { clip-path: circle(100% at 50% 50%); filter: blur(0); opacity: 1; }
|
||
}
|
||
|
||
/* Brush stroke reveal — horizontal wipe like a calligraphy stroke */
|
||
@keyframes sumi-brush-stroke {
|
||
0% { clip-path: inset(0 100% 0 0); opacity: 0.4; }
|
||
60% { clip-path: inset(0 8% 0 0); opacity: 0.9; }
|
||
100% { clip-path: inset(0 0 0 0); opacity: 1; }
|
||
}
|
||
|
||
/* Ink reveal — content emerges from darkness like ink on wet paper */
|
||
@keyframes sumi-ink-reveal {
|
||
0% { opacity: 0; transform: translateY(12px); filter: blur(8px) brightness(0.7); }
|
||
40% { filter: blur(3px) brightness(0.9); }
|
||
100% { opacity: 1; transform: translateY(0); filter: blur(0) brightness(1); }
|
||
}
|
||
|
||
/* Sumi-nagashi — floating ink marble drift */
|
||
@keyframes sumi-nagashi {
|
||
0% { background-position: 0% 50%; }
|
||
25% { background-position: 100% 25%; }
|
||
50% { background-position: 100% 75%; }
|
||
75% { background-position: 0% 60%; }
|
||
100% { background-position: 0% 50%; }
|
||
}
|
||
|
||
/* Ink pulse — like a droplet ripple in an ink stone (硯) */
|
||
@keyframes sumi-ink-pulse {
|
||
0% { box-shadow: 0 0 0 0 rgba(0,152,181, 0.25); }
|
||
50% { box-shadow: 0 0 0 8px rgba(0,152,181, 0); }
|
||
100% { box-shadow: 0 0 0 0 rgba(0,152,181, 0); }
|
||
}
|
||
|
||
/* ═══════════════════════════════════════════════════════════════════════════
|
||
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; }
|
||
}
|