@import "tailwindcss"; @custom-variant dark (&:where(.dark, .dark *)); /* Pointer-aware variants: `coarse:` = touch devices, `fine:` = mouse/trackpad. */ @custom-variant coarse (@media (pointer: coarse)); @custom-variant fine (@media (pointer: fine)); @custom-variant standalone (@media (display-mode: standalone)); @theme { --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; --font-mono: var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; /* ---- Semantic colors (values live in :root / .dark below) ---------------- */ --color-bg: var(--bg); --color-bg-subtle: var(--bg-subtle); --color-bg-muted: var(--bg-muted); --color-bg-elevated: var(--bg-elevated); --color-bg-overlay: var(--bg-overlay); --color-bg-inset: var(--bg-inset); --color-fg: var(--fg); --color-fg-muted: var(--fg-muted); --color-fg-subtle: var(--fg-subtle); --color-border: var(--border); --color-border-strong: var(--border-strong); --color-hairline: var(--hairline); --color-accent: var(--accent); --color-accent-fg: var(--accent-fg); --color-accent-soft: var(--accent-soft); --color-accent-strong: var(--accent-strong); --color-success: var(--success); --color-success-soft: var(--success-soft); --color-warning: var(--warning); --color-warning-soft: var(--warning-soft); --color-danger: var(--danger); --color-danger-soft: var(--danger-soft); --color-info: var(--info); --color-info-soft: var(--info-soft); --color-ring: var(--accent); --color-openai: var(--p-openai); --color-anthropic: var(--p-anthropic); --color-gemini: var(--p-gemini); --color-xai: var(--p-xai); --color-mistral: var(--p-mistral); --color-deepseek: var(--p-deepseek); --color-kimi: var(--p-kimi); --color-openrouter: var(--p-openrouter); --color-cerebras: var(--p-cerebras); --color-custom: var(--p-custom); /* ---- Radii ---------------------------------------------------------------- */ --radius-xs: 4px; --radius-sm: 6px; --radius-md: 8px; --radius-lg: 12px; --radius-xl: 16px; --radius-2xl: 22px; --radius-3xl: 28px; /* ---- Elevation: soft, layered, low-contrast -------------------------------- */ --shadow-xs: 0 1px 2px rgb(15 17 26 / 0.05); --shadow-sm: 0 1px 2px rgb(15 17 26 / 0.06), 0 2px 6px -2px rgb(15 17 26 / 0.06); --shadow-md: 0 2px 4px -1px rgb(15 17 26 / 0.06), 0 10px 24px -8px rgb(15 17 26 / 0.12); --shadow-lg: 0 4px 8px -2px rgb(15 17 26 / 0.08), 0 24px 56px -16px rgb(15 17 26 / 0.22); --shadow-sheet: 0 -8px 40px -12px rgb(15 17 26 / 0.28); --shadow-glow: 0 0 0 1px var(--accent-soft), 0 8px 32px -8px color-mix(in srgb, var(--accent) 55%, transparent); --shadow-ring: 0 0 0 1px var(--border); /* ---- Type scale (fluid on small screens) ----------------------------------- */ --text-2xs: 10.5px; --text-2xs--line-height: 14px; --text-xs: 11.5px; --text-xs--line-height: 16px; --text-sm: 13px; --text-sm--line-height: 18px; --text-base: 15px; --text-base--line-height: 22px; --text-lg: 17px; --text-lg--line-height: 24px; --text-xl: 20px; --text-xl--line-height: 26px; --text-2xl: 24px; --text-2xl--line-height: 30px; --text-3xl: clamp(28px, 2.4vw + 18px, 34px); --text-3xl--line-height: 1.15; --text-4xl: clamp(34px, 3.2vw + 20px, 46px); --text-4xl--line-height: 1.08; --text-5xl: clamp(40px, 4.4vw + 22px, 62px); --text-5xl--line-height: 1.02; /* ---- Motion --------------------------------------------------------------- */ --ease-out-soft: cubic-bezier(0.16, 1, 0.3, 1); --ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1); --animate-fade-in: fade-in 0.18s ease-out both; --animate-fade-out: fade-out 0.16s ease-in both; --animate-fade-up: fade-up 0.32s var(--ease-out-soft) both; --animate-scale-in: scale-in 0.18s var(--ease-out-soft) both; --animate-scale-out: scale-out 0.14s ease-in both; --animate-sheet-in: sheet-in 0.32s var(--ease-out-soft) both; --animate-sheet-out: sheet-out 0.22s ease-in both; --animate-drawer-in: drawer-in 0.28s var(--ease-out-soft) both; --animate-drawer-out: drawer-out 0.2s ease-in both; --animate-slide-down-in: slide-down-in 0.22s var(--ease-out-soft) both; --animate-blink: blink 1s steps(2, start) infinite; --animate-shimmer: shimmer 1.6s linear infinite; --animate-pulse-soft: pulse-soft 2s ease-in-out infinite; --animate-pop: pop 0.32s var(--ease-spring) both; --animate-marquee: marquee 48s linear infinite; --animate-stream-glow: stream-glow 1.8s ease-in-out infinite; @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } @keyframes scale-in { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: scale(1); } } @keyframes scale-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.97); } } @keyframes sheet-in { from { transform: translateY(100%); } to { transform: translateY(0); } } @keyframes sheet-out { from { transform: translateY(0); } to { transform: translateY(100%); } } @keyframes drawer-in { from { transform: translateX(-100%); } to { transform: translateX(0); } } @keyframes drawer-out { from { transform: translateX(0); } to { transform: translateX(-100%); } } @keyframes slide-down-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } } @keyframes blink { to { visibility: hidden; } } @keyframes shimmer { from { background-position: -200% 0; } to { background-position: 200% 0; } } @keyframes pulse-soft { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } } @keyframes pop { 0% { transform: scale(0.6); opacity: 0; } 60% { transform: scale(1.12); opacity: 1; } 100% { transform: scale(1); } } @keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } } @keyframes stream-glow { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); } 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent); } } } /* --------------------------------------------------------------------------- Palette — warm graphite neutrals + iris accent. Light and dark are tuned to the same perceptual contrast so components need no per-theme overrides. --------------------------------------------------------------------------- */ :root { color-scheme: light; --bg: #f7f7f5; --bg-subtle: #f1f1ee; --bg-muted: #e9e9e5; --bg-elevated: #ffffff; --bg-inset: #ececea; --bg-overlay: rgb(247 247 245 / 0.9); --fg: #14151a; --fg-muted: #5c6070; --fg-subtle: #8b8f9d; --border: #e3e3df; --border-strong: #cdcdc8; --hairline: rgb(20 21 26 / 0.07); --accent: #5457d6; --accent-strong: #4144c4; --accent-fg: #ffffff; --accent-soft: #e8e8fb; --success: #1c9a5d; --success-soft: #e1f5e9; --warning: #b8720f; --warning-soft: #fbefd6; --danger: #d03540; --danger-soft: #fbe4e6; --info: #2779cf; --info-soft: #e1eefb; --p-openai: #10a37f; --p-anthropic: #d97757; --p-gemini: #3b82f6; --p-xai: #303540; --p-mistral: #e8590c; --p-deepseek: #4d6bfe; --p-kimi: #0f766e; --p-openrouter: #6b46c1; --p-cerebras: #c2410c; --p-custom: #64748b; --selection: rgb(84 87 214 / 0.18); --sat: env(safe-area-inset-top, 0px); --sab: env(safe-area-inset-bottom, 0px); --sal: env(safe-area-inset-left, 0px); --sar: env(safe-area-inset-right, 0px); /* Height of the mobile bottom navigation (without the safe area). */ --bottom-nav-h: 56px; /* Set by the keyboard hook: pixels hidden by the on-screen keyboard. */ --kb: 0px; } .dark { color-scheme: dark; --bg: #0b0c10; --bg-subtle: #10121a; --bg-muted: #171923; --bg-elevated: #13151d; --bg-inset: #0e0f15; --bg-overlay: rgb(11 12 16 / 0.9); --fg: #f1f2f6; --fg-muted: #9a9fb1; --fg-subtle: #676d7e; --border: #1f222c; --border-strong: #2c3040; --hairline: rgb(241 242 246 / 0.07); --accent: #8b8dff; --accent-strong: #a3a5ff; --accent-fg: #0b0c10; --accent-soft: rgb(139 141 255 / 0.14); --success: #3ccf82; --success-soft: rgb(60 207 130 / 0.14); --warning: #f0b35a; --warning-soft: rgb(240 179 90 / 0.14); --danger: #ff6b70; --danger-soft: rgb(255 107 112 / 0.14); --info: #5aa8ff; --info-soft: rgb(90 168 255 / 0.14); --p-openai: #34c99b; --p-anthropic: #e69375; --p-gemini: #6aa2ff; --p-xai: #d5d8e0; --p-mistral: #ff8a3d; --p-deepseek: #7d93ff; --p-kimi: #2dd4bf; --p-openrouter: #a78bfa; --p-cerebras: #fb923c; --p-custom: #9aa3b5; --selection: rgb(139 141 255 / 0.28); } @layer base { * { border-color: var(--border); } html { -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; scroll-behavior: auto; /* iOS: never let the root rubber-band; scroll containers own overscroll. */ overscroll-behavior: none; -webkit-tap-highlight-color: transparent; } body { background: var(--bg); color: var(--fg); font-family: var(--font-sans); font-feature-settings: "cv11", "ss01", "ss03"; -webkit-font-smoothing: antialiased; overscroll-behavior-y: none; min-height: 100dvh; } ::selection { background: var(--selection); } :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; } button, [role="button"] { cursor: pointer; touch-action: manipulation; } button:disabled { cursor: not-allowed; } input, textarea, select { font: inherit; } /* iOS zooms into inputs below 16px; keep them at 16px on coarse pointers. */ @media (pointer: coarse) { input, textarea, select { font-size: max(16px, 1em); } } code, kbd, pre, samp { font-family: var(--font-mono); font-feature-settings: "liga" 0; } @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; } } } @layer components { .scrollbar-thin { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; } .scrollbar-thin::-webkit-scrollbar { width: 8px; height: 8px; } .scrollbar-thin::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; } .scrollbar-none { scrollbar-width: none; } .scrollbar-none::-webkit-scrollbar { display: none; } .glass { background: var(--bg-overlay); backdrop-filter: saturate(160%) blur(16px); -webkit-backdrop-filter: saturate(160%) blur(16px); } .glass-strong { background: color-mix(in srgb, var(--bg-elevated) 88%, transparent); backdrop-filter: saturate(180%) blur(24px); -webkit-backdrop-filter: saturate(180%) blur(24px); } .text-gradient { background: linear-gradient(120deg, var(--accent) 0%, #b58cff 55%, #ff8fab 100%); -webkit-background-clip: text; background-clip: text; color: transparent; } .surface { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); } /* Soft, borderless grouping — preferred over cards for dense professional UI. */ .panel { background: var(--bg-subtle); border-radius: var(--radius-xl); } .hairline-b { box-shadow: inset 0 -1px 0 var(--hairline); } .hairline-t { box-shadow: inset 0 1px 0 var(--hairline); } .kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 1.4rem; height: 1.25rem; padding: 0 0.35rem; border-radius: 5px; border: 1px solid var(--border-strong); background: var(--bg-subtle); color: var(--fg-muted); font-family: var(--font-mono); font-size: 10.5px; line-height: 1; } .shimmer { background: linear-gradient(90deg, var(--bg-muted) 25%, var(--bg-subtle) 50%, var(--bg-muted) 75%); background-size: 200% 100%; animation: var(--animate-shimmer); } .caret::after { content: "▍"; color: var(--accent); animation: var(--animate-blink); margin-left: 1px; } .dot-grid { background-image: radial-gradient(var(--border-strong) 1px, transparent 1px); background-size: 22px 22px; } /* Minimum 44px hit area regardless of the visual size. */ .tap { position: relative; } .tap::after { content: ""; position: absolute; inset: 50% auto auto 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%); } /* Safe-area helpers */ .pt-safe { padding-top: var(--sat); } .pb-safe { padding-bottom: var(--sab); } .pl-safe { padding-left: var(--sal); } .pr-safe { padding-right: var(--sar); } .px-safe { padding-left: var(--sal); padding-right: var(--sar); } .mb-safe { margin-bottom: var(--sab); } /* Space reserved for the mobile bottom navigation. */ .pb-nav { padding-bottom: calc(var(--bottom-nav-h) + var(--sab)); } /* Full app height that tracks the on-screen keyboard (set by useKeyboardInset). */ .h-app { height: calc(100dvh - var(--kb)); } .min-h-app { min-height: calc(100dvh - var(--kb)); } /* Sheet drag handle */ .sheet-handle { width: 36px; height: 5px; border-radius: 999px; background: var(--border-strong); margin: 8px auto 4px; } /* Horizontal snap carousel (Arena / compare panels on mobile) */ .snap-row { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; } .snap-row::-webkit-scrollbar { display: none; } .snap-row > * { scroll-snap-align: center; scroll-snap-stop: always; flex: 0 0 100%; } /* Hide only the scroll chaining, keep the scroll */ .contain-scroll { overscroll-behavior: contain; } .touch-pan-y { touch-action: pan-y; } .touch-pan-x { touch-action: pan-x; } /* Hover-revealed controls: always visible on touch devices. */ .hover-reveal { opacity: 0; transition: opacity 150ms; } .group:hover .hover-reveal, .group:focus-within .hover-reveal, .hover-reveal:focus-visible { opacity: 1; } @media (pointer: coarse) { .hover-reveal { opacity: 1; } } /* Marquee strip */ .marquee { display: flex; width: max-content; animation: var(--animate-marquee); } .marquee:hover { animation-play-state: paused; } .mask-x { mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); } .mask-b { mask-image: linear-gradient(180deg, #000 70%, transparent); } .tabular { font-variant-numeric: tabular-nums; } .text-balance { text-wrap: balance; } .text-pretty { text-wrap: pretty; } } /* Markdown (chat messages) */ .prose-chat { line-height: 1.65; font-size: 15px; word-break: break-word; overflow-wrap: anywhere; } .prose-chat > * + * { margin-top: 0.75em; } .prose-chat h1, .prose-chat h2, .prose-chat h3, .prose-chat h4 { font-weight: 650; letter-spacing: -0.01em; line-height: 1.3; margin-top: 1.2em; } .prose-chat h1 { font-size: 1.35em; } .prose-chat h2 { font-size: 1.2em; } .prose-chat h3 { font-size: 1.08em; } .prose-chat h4 { font-size: 1em; } .prose-chat p { margin: 0; } .prose-chat p + p { margin-top: 0.75em; } .prose-chat a { color: var(--accent); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); text-underline-offset: 3px; } .prose-chat ul, .prose-chat ol { padding-left: 1.4em; } .prose-chat ul { list-style: disc; } .prose-chat ol { list-style: decimal; } .prose-chat li + li { margin-top: 0.25em; } .prose-chat li > ul, .prose-chat li > ol { margin-top: 0.25em; } .prose-chat blockquote { border-left: 3px solid var(--border-strong); padding-left: 0.9em; color: var(--fg-muted); } .prose-chat hr { border: 0; border-top: 1px solid var(--border); margin: 1.2em 0; } .prose-chat :not(pre) > code { font-size: 0.86em; background: var(--bg-muted); border: 1px solid var(--border); padding: 0.1em 0.38em; border-radius: 5px; } .prose-chat pre { margin: 0; } .prose-chat table { width: 100%; border-collapse: collapse; font-size: 0.92em; display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; } .prose-chat th, .prose-chat td { border: 1px solid var(--border); padding: 0.4em 0.7em; text-align: left; vertical-align: top; } .prose-chat th { background: var(--bg-subtle); font-weight: 600; } .prose-chat img { max-width: 100%; border-radius: 8px; } .prose-chat.wrap-code pre code { white-space: pre-wrap; word-break: break-word; } .prose-chat .katex-display { overflow-x: auto; overflow-y: hidden; padding: 0.2em 0; } /* Shiki */ .shiki, .shiki span { background-color: transparent !important; } .dark .shiki, .dark .shiki span { color: var(--shiki-dark) !important; } /* Recharts: inherit the type system */ .recharts-text { font-family: var(--font-sans); } .recharts-default-tooltip { border-radius: 10px !important; border: 1px solid var(--border) !important; background: var(--bg-elevated) !important; box-shadow: var(--shadow-md); } /* Standalone PWA: reserve the status bar area */ @media (display-mode: standalone) { body { padding-top: 0; } }