@import "tailwindcss"; @plugin "tailwindcss-animate"; @custom-variant dark (&:where(.dark, .dark *)); @theme { --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif; --font-mono: var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace; /* shadcn / legacy tokens, preserved for component compatibility */ --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); --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); /* * Design system tokens (DESIGN.md). Use these in new components. * Surfaces stack via luminance, accent is reserved for interactive cyan, * status colors are reserved for actual semantic status. */ --color-surface-0: var(--surface-0); --color-surface-1: var(--surface-1); --color-surface-2: var(--surface-2); --color-surface-3: var(--surface-3); --color-text-primary: var(--text-primary); --color-text-secondary: var(--text-secondary); --color-text-tertiary: var(--text-tertiary); --color-accent-primary: var(--accent-primary); --color-accent-primary-soft: var(--accent-primary-soft); --color-accent-primary-border: var(--accent-primary-border); --color-border-default: var(--border-default); --color-border-subtle: var(--border-subtle); --color-status-success: var(--status-success); --color-status-warning: var(--status-warning); --color-status-error: var(--status-error); --radius-lg: var(--radius); --radius-md: calc(var(--radius) - 2px); --radius-sm: calc(var(--radius) - 4px); --animate-accordion-down: accordion-down 0.2s ease-out; --animate-accordion-up: accordion-up 0.2s ease-out; --animate-fade-in-up: fade-in-up 600ms cubic-bezier(0.16, 1, 0.3, 1) both; @keyframes accordion-down { from { height: 0; } to { height: var(--radix-accordion-content-height); } } @keyframes accordion-up { from { height: var(--radix-accordion-content-height); } to { height: 0; } } @keyframes fade-in-up { from { opacity: 0; transform: translate3d(0, 16px, 0); } to { opacity: 1; transform: translate3d(0, 0, 0); } } } /* The default border color has changed to `currentColor` in Tailwind CSS v4, so we've added these compatibility styles to make sure everything still looks the same as it did with Tailwind CSS v3. */ @layer base { *, ::after, ::before, ::backdrop, ::file-selector-button { border-color: var(--color-gray-200, currentColor); } } @layer base { :root { /* Dark Theme Only - Terminal/Hacker Aesthetic */ /* shadcn / legacy tokens, preserved */ --background: #0a0a0a; --foreground: #ededed; --card: #111111; --card-foreground: #ededed; --popover: #111111; --popover-foreground: #ededed; --primary: #00d4ff; --primary-foreground: #000000; --secondary: #7c3aed; --secondary-foreground: #ffffff; --muted: #1a1a1a; --muted-foreground: #a1a1a1; --accent: #1a1a1a; --accent-foreground: #ededed; --destructive: #ef4444; --destructive-foreground: #ffffff; --border: #262626; --input: #262626; --ring: #00d4ff; /* Charts */ --chart-1: #00d4ff; --chart-2: #7c3aed; --chart-3: #10b981; --chart-4: #f59e0b; --chart-5: #ef4444; /* Code */ --code-bg: #1e1e2e; --code-text: #cdd6f4; /* * Design system tokens (DESIGN.md). * Surfaces stack by luminance, not by shadow. Borders are punctuation. * Cyan is the only chromatic brand color. */ --surface-0: #0a0a0a; --surface-1: rgba(255, 255, 255, 0.018); --surface-2: rgba(255, 255, 255, 0.035); --surface-3: rgba(255, 255, 255, 0.055); --text-primary: #ededed; --text-secondary: #a1a1a1; --text-tertiary: #71717a; --accent-primary: #00d4ff; --accent-primary-soft: rgba(0, 212, 255, 0.1); --accent-primary-border: rgba(0, 212, 255, 0.2); --border-default: #262626; --border-subtle: rgba(255, 255, 255, 0.06); --status-success: #10b981; --status-warning: #f59e0b; --status-error: #ef4444; /* Spacing */ --radius: 0.5rem; /* Typography */ --font-geist-sans: var(--font-geist-sans); --font-geist-mono: var(--font-geist-mono); --font-heading: var(--font-geist-sans); --font-body: var(--font-geist-sans); --font-code: var(--font-geist-mono); } } @layer base { * { @apply border-border; } body { @apply bg-background text-foreground; font-feature-settings: "rlig" 1, "calt" 1; } /* * Hero background image fades in after first paint so the headline text is * the LCP candidate. The image is decorative (opacity 30%) and is preloaded * with low priority so it doesn't compete with critical resources. */ .hero-bg { opacity: 0; animation: hero-bg-fade-in 600ms ease-out 200ms forwards; } @keyframes hero-bg-fade-in { to { opacity: 0.3; } } @media (prefers-reduced-motion: reduce) { .hero-bg { animation: none; opacity: 0.3; } } h1, h2, h3, h4, h5, h6 { font-family: var(--font-geist-sans); } [lang|="ko"] h1, [lang|="ko"] h2, [lang|="ko"] h3, [lang|="ko"] h4, [lang|="ko"] h5, [lang|="ko"] h6, [lang|="ja"] h1, [lang|="ja"] h2, [lang|="ja"] h3, [lang|="ja"] h4, [lang|="ja"] h5, [lang|="ja"] h6, [lang|="zh"] h1, [lang|="zh"] h2, [lang|="zh"] h3, [lang|="zh"] h4, [lang|="zh"] h5, [lang|="zh"] h6 { letter-spacing: normal !important; text-wrap: pretty; } :where([lang|="ko"], [lang|="ja"], [lang|="zh"]) :where(p, li, blockquote, figcaption, td, th, a, button, span) { overflow-wrap: break-word; } [lang|="ko"] :where(h1, h2, h3, h4, h5, h6, p, li, blockquote, figcaption, td, th, a, button, span) { word-break: keep-all; } :where([lang|="ja"], [lang|="zh"]) :where(h1, h2, h3, h4, h5, h6, p, li, blockquote, figcaption, td, th, a, button, span) { word-break: normal; line-break: strict; } html { scroll-behavior: auto; } ::selection { @apply bg-primary/20 text-primary; } ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { @apply bg-muted; } ::-webkit-scrollbar-thumb { @apply bg-border hover:bg-muted-foreground/50 rounded-full transition-colors; } } @layer utilities { .glow-cyan { box-shadow: 0 0 15px -5px rgba(0, 212, 255, 0.3); } .glow-purple { box-shadow: 0 0 15px -5px rgba(124, 58, 237, 0.3); } .text-glow-cyan { text-shadow: 0 0 8px rgba(0, 212, 255, 0.3); } /* * Section entrance — fade-in-up with stagger via CSS var. * Set `--reveal-index` on each child (0, 1, 2, ...) to cascade. * Respects prefers-reduced-motion (no-op when reduce is set). */ .reveal-on-enter { animation: fade-in-up 600ms cubic-bezier(0.16, 1, 0.3, 1) both; animation-delay: calc(var(--reveal-index, 0) * 80ms); } @media (prefers-reduced-motion: reduce) { .reveal-on-enter { animation: none; opacity: 1; transform: none; } } /* * Hairline cyan focus ring. Use on interactive elements that need * a more prominent affordance than the default ring var. */ .ring-cyan { outline: 2px solid transparent; outline-offset: 2px; box-shadow: 0 0 0 2px var(--background), 0 0 0 4px var(--accent-primary); } } @layer components { .docs-content h1 { @apply mt-8 mb-4 scroll-mt-24 text-4xl font-bold tracking-tight first:mt-0; } .docs-content h2 { @apply mt-12 mb-4 scroll-mt-24 text-2xl font-semibold tracking-tight; } .docs-content h3 { @apply mt-8 mb-3 scroll-mt-24 text-xl font-semibold tracking-tight; } .docs-content h4 { @apply mt-6 mb-2 scroll-mt-24 text-lg font-semibold tracking-tight; } .docs-content p { @apply text-muted-foreground my-4 leading-7; } .docs-content a { @apply text-primary font-medium underline underline-offset-4; } .docs-content ul { @apply text-muted-foreground my-4 ml-6 list-disc space-y-1; } .docs-content ol { @apply text-muted-foreground my-4 ml-6 list-decimal space-y-1; } .docs-content li { @apply leading-7; } .docs-content blockquote { @apply border-primary/40 my-6 border-l-4 pl-4 italic; } .docs-content code:not(pre code) { @apply bg-muted text-foreground rounded px-1.5 py-0.5 font-mono text-sm; } .docs-content pre { @apply border-border/50 my-4 overflow-x-auto rounded-lg border bg-[#1e1e2e] p-4 font-mono text-sm text-[#cdd6f4] shadow-sm; } .docs-content pre code { @apply bg-transparent p-0 text-inherit; } .docs-content table { @apply border-border my-6 w-full border-collapse border text-sm; } .docs-content thead { @apply bg-muted; } .docs-content th { @apply border-border border px-3 py-2 text-left font-semibold; } .docs-content td { @apply border-border text-muted-foreground border px-3 py-2; } .docs-content hr { @apply border-border my-8; } .docs-content strong { @apply text-foreground font-semibold; } }