@tailwind base; @tailwind components; @tailwind utilities; /* Accent palette defaults (emerald). Overridden at runtime by lib/accent.ts from the user's saved accent color / custom pick. Values are RGB triplets. */ :root { --ka-accent-50: 236 253 245; --ka-accent-100: 209 250 229; --ka-accent-200: 167 243 208; --ka-accent-300: 110 231 183; --ka-accent-400: 52 211 153; --ka-accent-500: 16 185 129; --ka-accent-600: 5 150 105; --ka-accent-700: 4 120 87; --ka-accent-800: 6 95 70; --ka-accent-900: 6 78 59; --ka-accent-950: 2 44 34; } html, body, #root { height: 100%; } /* Mobile browser chrome (URL bar) shrinks the visible area — dynamic viewport units keep the app glued to the real screen height. */ @supports (height: 100dvh) { html, body, #root { height: 100dvh; } } body { @apply bg-stone-100 text-stone-900 antialiased dark:bg-zinc-950 dark:text-zinc-100; /* Kill the 300ms tap delay, keep gestures app-like. */ touch-action: manipulation; overscroll-behavior-y: none; } /* slim scrollbars */ * { scrollbar-width: thin; scrollbar-color: rgb(0 0 0 / 0.2) transparent; } *::-webkit-scrollbar { width: 6px; height: 6px; } *::-webkit-scrollbar-thumb { background: rgb(0 0 0 / 0.2); border-radius: 999px; } /* markdown content */ .md p:first-child { margin-top: 0; } .md p:last-child { margin-bottom: 0; } /* Long unbroken strings (URLs, file paths, hashes, tokens) must wrap anywhere — otherwise they overflow the bubble, which then grows past its row and glues itself to the screen edge. `pre` keeps its own horizontal scroll (white-space:pre ignores wrapping). */ .md { overflow-wrap: anywhere; } .md pre { @apply relative overflow-x-auto rounded-2xl border border-stone-200 bg-stone-900 p-4 text-[13.5px] leading-relaxed text-stone-100 dark:border-zinc-700; } .md pre code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: none !important; padding: 0 !important; } .md :not(pre) > code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; @apply rounded-md bg-stone-200/70 px-1.5 py-0.5 text-[13px] dark:bg-zinc-800; } .md table { @apply w-full border-collapse overflow-hidden rounded-xl text-sm; } .md th, .md td { @apply border border-stone-200 px-3 py-1.5 dark:border-zinc-700; } .md th { @apply bg-stone-200/50 dark:bg-zinc-800; } .md a { @apply text-accent-600 underline dark:text-accent-400; } .md ul { @apply list-disc pl-5; } .md ol { @apply list-decimal pl-5; } .md blockquote { @apply border-l-4 border-accent-500/50 pl-3 italic opacity-80; } .typing-cursor::after { content: "▍"; animation: blink 1s steps(1) infinite; } @keyframes blink { 50% { opacity: 0; } } /* Loading flower: outer petals bloom in turn, inner petals follow softer, core breathes with an amber glow. */ .flower-petal, .flower-petal-inner, .flower-core { transform-box: fill-box; transform-origin: center; } .flower-petal { animation: bloom 2.4s ease-in-out infinite; } .flower-petal-inner { animation: bloom-inner 2.4s ease-in-out infinite; } @keyframes bloom { 0%, 100% { transform: scale(0.62); opacity: 0.35; } 50% { transform: scale(1); opacity: 1; } } @keyframes bloom-inner { 0%, 100% { transform: scale(0.55); opacity: 0.2; } 50% { transform: scale(1); opacity: 0.95; } } .flower-core { animation: core-breathe 2.4s ease-in-out infinite; } @keyframes core-breathe { 0%, 100% { transform: scale(0.9); } 50% { transform: scale(1.1); } } /* Smooth entrance for full-screen loaders. */ @keyframes loading-in { from { opacity: 0; transform: scale(0.94); } to { opacity: 1; transform: scale(1); } } .loading-enter { animation: loading-in 0.45s ease-out both; } /* Loader title: soft accent glow pulse. */ .loader-title { animation: title-glow 2.6s ease-in-out infinite; } @keyframes title-glow { 0%, 100% { opacity: 0.92; } 50% { opacity: 1; text-shadow: 0 0 18px rgb(var(--ka-accent-500) / 0.35); } } .loading-dots::after { content: ""; animation: dots 1.4s steps(4) infinite; } @keyframes dots { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } } /* Bottom pills: springy rise on appear, soft sink on dismiss. */ @keyframes toast-in { from { opacity: 0; transform: translateY(18px) scale(0.94); } to { opacity: 1; transform: translateY(0) scale(1); } } .toast-enter { animation: toast-in 0.38s cubic-bezier(0.21, 1.02, 0.73, 1) both; } @keyframes toast-out { from { opacity: 1; transform: translateY(0) scale(1); } to { opacity: 0; transform: translateY(12px) scale(0.95); } } .toast-exit { animation: toast-out 0.26s ease-in both; } @media (prefers-reduced-motion: reduce) { /* Brand flower intentionally exempt: it always animates, even when the browser requests reduced motion (battery saver / eco mode). */ .typing-cursor::after, .loading-dots::after { animation: none; } } /* Kill Chrome's yellow autofill background (login / password fields) */ input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus, input:-webkit-autofill:active { -webkit-box-shadow: 0 0 0 60px rgb(245 245 244) inset; /* stone-100, matches soft fields */ -webkit-text-fill-color: #1c1917; /* stone-900 */ caret-color: #1c1917; } .dark input:-webkit-autofill, .dark input:-webkit-autofill:hover, .dark input:-webkit-autofill:focus, .dark input:-webkit-autofill:active { -webkit-box-shadow: 0 0 0 60px #27272a inset; /* zinc-800 */ -webkit-text-fill-color: #f4f4f5; /* zinc-100 */ caret-color: #f4f4f5; }