SPB Git forge

spb/polyllm

Public
15commits 1branches 0releases
2.2 MBsize
maindefault branch
13 days agolast push
TypeScript 97.4% SQL 1% JavaScript 0.9% CSS 0.6%
16.6 KB · 362 lines css
Raw Blame History
1@import "tailwindcss";23@custom-variant dark (&:where(.dark, .dark *));4/* Pointer-aware variants: `coarse:` = touch devices, `fine:` = mouse/trackpad. */5@custom-variant coarse (@media (pointer: coarse));6@custom-variant fine (@media (pointer: fine));7@custom-variant standalone (@media (display-mode: standalone));89@theme {10  --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;11  --font-mono: var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;1213  /* ---- Semantic colors (values live in :root / .dark below) ---------------- */14  --color-bg: var(--bg);15  --color-bg-subtle: var(--bg-subtle);16  --color-bg-muted: var(--bg-muted);17  --color-bg-elevated: var(--bg-elevated);18  --color-bg-overlay: var(--bg-overlay);19  --color-bg-inset: var(--bg-inset);20  --color-fg: var(--fg);21  --color-fg-muted: var(--fg-muted);22  --color-fg-subtle: var(--fg-subtle);23  --color-border: var(--border);24  --color-border-strong: var(--border-strong);25  --color-hairline: var(--hairline);26  --color-accent: var(--accent);27  --color-accent-fg: var(--accent-fg);28  --color-accent-soft: var(--accent-soft);29  --color-accent-strong: var(--accent-strong);30  --color-success: var(--success);31  --color-success-soft: var(--success-soft);32  --color-warning: var(--warning);33  --color-warning-soft: var(--warning-soft);34  --color-danger: var(--danger);35  --color-danger-soft: var(--danger-soft);36  --color-info: var(--info);37  --color-info-soft: var(--info-soft);38  --color-ring: var(--accent);3940  --color-openai: var(--p-openai);41  --color-anthropic: var(--p-anthropic);42  --color-gemini: var(--p-gemini);43  --color-xai: var(--p-xai);44  --color-mistral: var(--p-mistral);45  --color-deepseek: var(--p-deepseek);46  --color-kimi: var(--p-kimi);47  --color-openrouter: var(--p-openrouter);48  --color-cerebras: var(--p-cerebras);49  --color-custom: var(--p-custom);5051  /* ---- Radii ---------------------------------------------------------------- */52  --radius-xs: 4px;53  --radius-sm: 6px;54  --radius-md: 8px;55  --radius-lg: 12px;56  --radius-xl: 16px;57  --radius-2xl: 22px;58  --radius-3xl: 28px;5960  /* ---- Elevation: soft, layered, low-contrast -------------------------------- */61  --shadow-xs: 0 1px 2px rgb(15 17 26 / 0.05);62  --shadow-sm: 0 1px 2px rgb(15 17 26 / 0.06), 0 2px 6px -2px rgb(15 17 26 / 0.06);63  --shadow-md: 0 2px 4px -1px rgb(15 17 26 / 0.06), 0 10px 24px -8px rgb(15 17 26 / 0.12);64  --shadow-lg: 0 4px 8px -2px rgb(15 17 26 / 0.08), 0 24px 56px -16px rgb(15 17 26 / 0.22);65  --shadow-sheet: 0 -8px 40px -12px rgb(15 17 26 / 0.28);66  --shadow-glow: 0 0 0 1px var(--accent-soft), 0 8px 32px -8px color-mix(in srgb, var(--accent) 55%, transparent);67  --shadow-ring: 0 0 0 1px var(--border);6869  /* ---- Type scale (fluid on small screens) ----------------------------------- */70  --text-2xs: 10.5px;71  --text-2xs--line-height: 14px;72  --text-xs: 11.5px;73  --text-xs--line-height: 16px;74  --text-sm: 13px;75  --text-sm--line-height: 18px;76  --text-base: 15px;77  --text-base--line-height: 22px;78  --text-lg: 17px;79  --text-lg--line-height: 24px;80  --text-xl: 20px;81  --text-xl--line-height: 26px;82  --text-2xl: 24px;83  --text-2xl--line-height: 30px;84  --text-3xl: clamp(28px, 2.4vw + 18px, 34px);85  --text-3xl--line-height: 1.15;86  --text-4xl: clamp(34px, 3.2vw + 20px, 46px);87  --text-4xl--line-height: 1.08;88  --text-5xl: clamp(40px, 4.4vw + 22px, 62px);89  --text-5xl--line-height: 1.02;9091  /* ---- Motion --------------------------------------------------------------- */92  --ease-out-soft: cubic-bezier(0.16, 1, 0.3, 1);93  --ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1);94  --animate-fade-in: fade-in 0.18s ease-out both;95  --animate-fade-out: fade-out 0.16s ease-in both;96  --animate-fade-up: fade-up 0.32s var(--ease-out-soft) both;97  --animate-scale-in: scale-in 0.18s var(--ease-out-soft) both;98  --animate-scale-out: scale-out 0.14s ease-in both;99  --animate-sheet-in: sheet-in 0.32s var(--ease-out-soft) both;100  --animate-sheet-out: sheet-out 0.22s ease-in both;101  --animate-drawer-in: drawer-in 0.28s var(--ease-out-soft) both;102  --animate-drawer-out: drawer-out 0.2s ease-in both;103  --animate-slide-down-in: slide-down-in 0.22s var(--ease-out-soft) both;104  --animate-blink: blink 1s steps(2, start) infinite;105  --animate-shimmer: shimmer 1.6s linear infinite;106  --animate-pulse-soft: pulse-soft 2s ease-in-out infinite;107  --animate-pop: pop 0.32s var(--ease-spring) both;108  --animate-marquee: marquee 48s linear infinite;109  --animate-stream-glow: stream-glow 1.8s ease-in-out infinite;110111  @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }112  @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }113  @keyframes fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }114  @keyframes scale-in { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: scale(1); } }115  @keyframes scale-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.97); } }116  @keyframes sheet-in { from { transform: translateY(100%); } to { transform: translateY(0); } }117  @keyframes sheet-out { from { transform: translateY(0); } to { transform: translateY(100%); } }118  @keyframes drawer-in { from { transform: translateX(-100%); } to { transform: translateX(0); } }119  @keyframes drawer-out { from { transform: translateX(0); } to { transform: translateX(-100%); } }120  @keyframes slide-down-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }121  @keyframes blink { to { visibility: hidden; } }122  @keyframes shimmer { from { background-position: -200% 0; } to { background-position: 200% 0; } }123  @keyframes pulse-soft { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }124  @keyframes pop { 0% { transform: scale(0.6); opacity: 0; } 60% { transform: scale(1.12); opacity: 1; } 100% { transform: scale(1); } }125  @keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }126  @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); } }127}128129/* ---------------------------------------------------------------------------130   Palette — warm graphite neutrals + iris accent. Light and dark are tuned to131   the same perceptual contrast so components need no per-theme overrides.132   --------------------------------------------------------------------------- */133:root {134  color-scheme: light;135  --bg: #f7f7f5;136  --bg-subtle: #f1f1ee;137  --bg-muted: #e9e9e5;138  --bg-elevated: #ffffff;139  --bg-inset: #ececea;140  --bg-overlay: rgb(247 247 245 / 0.9);141  --fg: #14151a;142  --fg-muted: #5c6070;143  --fg-subtle: #8b8f9d;144  --border: #e3e3df;145  --border-strong: #cdcdc8;146  --hairline: rgb(20 21 26 / 0.07);147  --accent: #5457d6;148  --accent-strong: #4144c4;149  --accent-fg: #ffffff;150  --accent-soft: #e8e8fb;151  --success: #1c9a5d;152  --success-soft: #e1f5e9;153  --warning: #b8720f;154  --warning-soft: #fbefd6;155  --danger: #d03540;156  --danger-soft: #fbe4e6;157  --info: #2779cf;158  --info-soft: #e1eefb;159160  --p-openai: #10a37f;161  --p-anthropic: #d97757;162  --p-gemini: #3b82f6;163  --p-xai: #303540;164  --p-mistral: #e8590c;165  --p-deepseek: #4d6bfe;166  --p-kimi: #0f766e;167  --p-openrouter: #6b46c1;168  --p-cerebras: #c2410c;169  --p-custom: #64748b;170171  --selection: rgb(84 87 214 / 0.18);172  --sat: env(safe-area-inset-top, 0px);173  --sab: env(safe-area-inset-bottom, 0px);174  --sal: env(safe-area-inset-left, 0px);175  --sar: env(safe-area-inset-right, 0px);176  /* Height of the mobile bottom navigation (without the safe area). */177  --bottom-nav-h: 56px;178  /* Set by the keyboard hook: pixels hidden by the on-screen keyboard. */179  --kb: 0px;180}181182.dark {183  color-scheme: dark;184  --bg: #0b0c10;185  --bg-subtle: #10121a;186  --bg-muted: #171923;187  --bg-elevated: #13151d;188  --bg-inset: #0e0f15;189  --bg-overlay: rgb(11 12 16 / 0.9);190  --fg: #f1f2f6;191  --fg-muted: #9a9fb1;192  --fg-subtle: #676d7e;193  --border: #1f222c;194  --border-strong: #2c3040;195  --hairline: rgb(241 242 246 / 0.07);196  --accent: #8b8dff;197  --accent-strong: #a3a5ff;198  --accent-fg: #0b0c10;199  --accent-soft: rgb(139 141 255 / 0.14);200  --success: #3ccf82;201  --success-soft: rgb(60 207 130 / 0.14);202  --warning: #f0b35a;203  --warning-soft: rgb(240 179 90 / 0.14);204  --danger: #ff6b70;205  --danger-soft: rgb(255 107 112 / 0.14);206  --info: #5aa8ff;207  --info-soft: rgb(90 168 255 / 0.14);208209  --p-openai: #34c99b;210  --p-anthropic: #e69375;211  --p-gemini: #6aa2ff;212  --p-xai: #d5d8e0;213  --p-mistral: #ff8a3d;214  --p-deepseek: #7d93ff;215  --p-kimi: #2dd4bf;216  --p-openrouter: #a78bfa;217  --p-cerebras: #fb923c;218  --p-custom: #9aa3b5;219220  --selection: rgb(139 141 255 / 0.28);221}222223@layer base {224  * { border-color: var(--border); }225  html {226    -webkit-text-size-adjust: 100%;227    text-rendering: optimizeLegibility;228    scroll-behavior: auto;229    /* iOS: never let the root rubber-band; scroll containers own overscroll. */230    overscroll-behavior: none;231    -webkit-tap-highlight-color: transparent;232  }233  body {234    background: var(--bg);235    color: var(--fg);236    font-family: var(--font-sans);237    font-feature-settings: "cv11", "ss01", "ss03";238    -webkit-font-smoothing: antialiased;239    overscroll-behavior-y: none;240    min-height: 100dvh;241  }242  ::selection { background: var(--selection); }243  :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }244  button, [role="button"] { cursor: pointer; touch-action: manipulation; }245  button:disabled { cursor: not-allowed; }246  input, textarea, select { font: inherit; }247  /* iOS zooms into inputs below 16px; keep them at 16px on coarse pointers. */248  @media (pointer: coarse) { input, textarea, select { font-size: max(16px, 1em); } }249  code, kbd, pre, samp { font-family: var(--font-mono); font-feature-settings: "liga" 0; }250  @media (prefers-reduced-motion: reduce) {251    *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }252  }253}254255@layer components {256  .scrollbar-thin { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }257  .scrollbar-thin::-webkit-scrollbar { width: 8px; height: 8px; }258  .scrollbar-thin::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; }259  .scrollbar-none { scrollbar-width: none; }260  .scrollbar-none::-webkit-scrollbar { display: none; }261262  .glass { background: var(--bg-overlay); backdrop-filter: saturate(160%) blur(16px); -webkit-backdrop-filter: saturate(160%) blur(16px); }263  .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); }264265  .text-gradient {266    background: linear-gradient(120deg, var(--accent) 0%, #b58cff 55%, #ff8fab 100%);267    -webkit-background-clip: text; background-clip: text; color: transparent;268  }269  .surface { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); }270  /* Soft, borderless grouping — preferred over cards for dense professional UI. */271  .panel { background: var(--bg-subtle); border-radius: var(--radius-xl); }272  .hairline-b { box-shadow: inset 0 -1px 0 var(--hairline); }273  .hairline-t { box-shadow: inset 0 1px 0 var(--hairline); }274  .kbd {275    display: inline-flex; align-items: center; justify-content: center; min-width: 1.4rem; height: 1.25rem; padding: 0 0.35rem;276    border-radius: 5px; border: 1px solid var(--border-strong); background: var(--bg-subtle); color: var(--fg-muted);277    font-family: var(--font-mono); font-size: 10.5px; line-height: 1;278  }279  .shimmer {280    background: linear-gradient(90deg, var(--bg-muted) 25%, var(--bg-subtle) 50%, var(--bg-muted) 75%);281    background-size: 200% 100%; animation: var(--animate-shimmer);282  }283  .caret::after { content: "▍"; color: var(--accent); animation: var(--animate-blink); margin-left: 1px; }284  .dot-grid {285    background-image: radial-gradient(var(--border-strong) 1px, transparent 1px);286    background-size: 22px 22px;287  }288  /* Minimum 44px hit area regardless of the visual size. */289  .tap { position: relative; }290  .tap::after { content: ""; position: absolute; inset: 50% auto auto 50%; width: max(100%, 44px); height: max(100%, 44px); transform: translate(-50%, -50%); }291  /* Safe-area helpers */292  .pt-safe { padding-top: var(--sat); }293  .pb-safe { padding-bottom: var(--sab); }294  .pl-safe { padding-left: var(--sal); }295  .pr-safe { padding-right: var(--sar); }296  .px-safe { padding-left: var(--sal); padding-right: var(--sar); }297  .mb-safe { margin-bottom: var(--sab); }298  /* Space reserved for the mobile bottom navigation. */299  .pb-nav { padding-bottom: calc(var(--bottom-nav-h) + var(--sab)); }300  /* Full app height that tracks the on-screen keyboard (set by useKeyboardInset). */301  .h-app { height: calc(100dvh - var(--kb)); }302  .min-h-app { min-height: calc(100dvh - var(--kb)); }303  /* Sheet drag handle */304  .sheet-handle { width: 36px; height: 5px; border-radius: 999px; background: var(--border-strong); margin: 8px auto 4px; }305  /* Horizontal snap carousel (Arena / compare panels on mobile) */306  .snap-row { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }307  .snap-row::-webkit-scrollbar { display: none; }308  .snap-row > * { scroll-snap-align: center; scroll-snap-stop: always; flex: 0 0 100%; }309  /* Hide only the scroll chaining, keep the scroll */310  .contain-scroll { overscroll-behavior: contain; }311  .touch-pan-y { touch-action: pan-y; }312  .touch-pan-x { touch-action: pan-x; }313  /* Hover-revealed controls: always visible on touch devices. */314  .hover-reveal { opacity: 0; transition: opacity 150ms; }315  .group:hover .hover-reveal, .group:focus-within .hover-reveal, .hover-reveal:focus-visible { opacity: 1; }316  @media (pointer: coarse) { .hover-reveal { opacity: 1; } }317  /* Marquee strip */318  .marquee { display: flex; width: max-content; animation: var(--animate-marquee); }319  .marquee:hover { animation-play-state: paused; }320  .mask-x { mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }321  .mask-b { mask-image: linear-gradient(180deg, #000 70%, transparent); }322  .tabular { font-variant-numeric: tabular-nums; }323  .text-balance { text-wrap: balance; }324  .text-pretty { text-wrap: pretty; }325}326327/* Markdown (chat messages) */328.prose-chat { line-height: 1.65; font-size: 15px; word-break: break-word; overflow-wrap: anywhere; }329.prose-chat > * + * { margin-top: 0.75em; }330.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; }331.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; }332.prose-chat p { margin: 0; }333.prose-chat p + p { margin-top: 0.75em; }334.prose-chat a { color: var(--accent); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); text-underline-offset: 3px; }335.prose-chat ul, .prose-chat ol { padding-left: 1.4em; }336.prose-chat ul { list-style: disc; } .prose-chat ol { list-style: decimal; }337.prose-chat li + li { margin-top: 0.25em; }338.prose-chat li > ul, .prose-chat li > ol { margin-top: 0.25em; }339.prose-chat blockquote { border-left: 3px solid var(--border-strong); padding-left: 0.9em; color: var(--fg-muted); }340.prose-chat hr { border: 0; border-top: 1px solid var(--border); margin: 1.2em 0; }341.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; }342.prose-chat pre { margin: 0; }343.prose-chat table { width: 100%; border-collapse: collapse; font-size: 0.92em; display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }344.prose-chat th, .prose-chat td { border: 1px solid var(--border); padding: 0.4em 0.7em; text-align: left; vertical-align: top; }345.prose-chat th { background: var(--bg-subtle); font-weight: 600; }346.prose-chat img { max-width: 100%; border-radius: 8px; }347.prose-chat.wrap-code pre code { white-space: pre-wrap; word-break: break-word; }348.prose-chat .katex-display { overflow-x: auto; overflow-y: hidden; padding: 0.2em 0; }349350/* Shiki */351.shiki, .shiki span { background-color: transparent !important; }352.dark .shiki, .dark .shiki span { color: var(--shiki-dark) !important; }353354/* Recharts: inherit the type system */355.recharts-text { font-family: var(--font-sans); }356.recharts-default-tooltip { border-radius: 10px !important; border: 1px solid var(--border) !important; background: var(--bg-elevated) !important; box-shadow: var(--shadow-md); }357358/* Standalone PWA: reserve the status bar area */359@media (display-mode: standalone) {360  body { padding-top: 0; }361}362