@tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { /* Sidebar tokens (consumed by tailwind colors in tailwind.config.js). Stored as raw hex so we can reference them via theme() if needed. */ --sidebar-bg: #1a1a1a; --sidebar-fg: rgba(255, 255, 255, 0.72); --sidebar-border: rgba(64, 64, 64, 0.5); --sidebar-accent: rgba(255, 255, 255, 0.06); --sidebar-accent-fg: #ffffff; --sidebar-ring: rgba(45, 129, 255, 0.4); /* shadcn design tokens consumed by @storyteller/ui-video-editor. Dark-theme palette (the editor only runs in dark mode today). --primary matches the webapp's brand blue (#2d81ff). */ --background: 0 0% 9%; --foreground: 0 0% 98%; --card: 0 0% 12%; --card-foreground: 0 0% 98%; --popover: 0 0% 12%; --popover-foreground: 0 0% 98%; --primary: 216 100% 59%; --primary-foreground: 0 0% 98%; --secondary: 0 0% 24%; --secondary-foreground: 0 0% 98%; --muted: 0 0% 18%; --muted-foreground: 0 0% 64%; --accent: 0 0% 16%; --accent-foreground: 0 0% 98%; --destructive: 0 70% 50%; --destructive-foreground: 0 0% 98%; --border: 0 0% 18%; --input: 0 0% 18%; --ring: 217 91% 60%; /* ── Motion tokens ────────────────────────────────────────────────── Shared easing curves + durations so motion across the app feels like one system, not a pile of one-offs. Mirrored as JS constants in src/lib/motion.ts for framer-motion. "Balanced" direction: chrome and navigation stay restrained; the creative canvas gets to be expressive. Curves: --ease-out decelerate-to-rest; the default for things entering. --ease-in-out symmetric; for things that move and settle in place. --ease-spring gentle overshoot; for playful, tactile moments. --ease-emphasis Apple/Linear "expo" curve; for confident, premium slides. */ --ease-out: cubic-bezier(0.22, 1, 0.36, 1); --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); --ease-emphasis: cubic-bezier(0.32, 0.72, 0, 1); /* Durations — keep chrome snappy, reserve longer ones for canvas drama. */ --dur-fast: 140ms; --dur-base: 220ms; --dur-slow: 340ms; --dur-page: 260ms; } /* Respect users who ask for less motion: collapse durations to near-zero so transitions become instant cuts rather than being removed wholesale. */ @media (prefers-reduced-motion: reduce) { :root { --dur-fast: 1ms; --dur-base: 1ms; --dur-slow: 1ms; --dur-page: 1ms; } } } * { scrollbar-width: thin; scrollbar-color: #363636 #171717; } *::-webkit-scrollbar { width: 8px; } *::-webkit-scrollbar-track { background: #171717; } *::-webkit-scrollbar-thumb { background-color: #363636; border-radius: 4px; border: 2px solid #171717; } .scrollbar-hidden { -ms-overflow-style: none; scrollbar-width: none; } .scrollbar-hidden::-webkit-scrollbar { display: none; } @layer base { h1, h2, h3, h4, h5, h6 { font-family: "Outfit", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; letter-spacing: -0.02em; } body { font-family: "Source Sans 3", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; color: #ffffff; background-color: #121212; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .font-serif-italic { font-family: "Instrument Serif", Georgia, "Times New Roman", serif; font-style: italic; font-weight: 400; letter-spacing: -0.01em; } } /* Shared component utilities (matching desktop app theme) */ .bg-ui-badge { background-color: rgba(0, 0, 0, 0.4); } .icon-auto-contrast { filter: invert(1); } /* Gradient panel surface used by pagescene + lib components. */ .bg-ui-panel-gradient { background: radial-gradient( 60.68% 60.68% at 50% 0%, rgba(255, 255, 255, 0.08) 0%, rgba(0, 0, 0, 0) 70% ), #1f1f1f; background-color: #1f1f1f; } .prevent-select { -webkit-user-select: none; -ms-user-select: none; user-select: none; pointer-events: none; } /* three-dots loading spinners — used inside upload-modal + pagescene. */ .dot-typing { position: relative; left: -9999px; width: 10px; height: 10px; border-radius: 5px; background-color: #ffffff30; color: #ffffff30; box-shadow: 9984px 0 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; animation: dot-typing 1.5s infinite linear; } @keyframes dot-typing { 0% { box-shadow: 9984px 0 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; } 16.667% { box-shadow: 9984px -10px 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; } 33.333% { box-shadow: 9984px 0 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; } 50% { box-shadow: 9984px 0 0 0 #ffffff30, 9999px -10px 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; } 66.667% { box-shadow: 9984px 0 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; } 83.333% { box-shadow: 9984px 0 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px -10px 0 0 #ffffff30; } 100% { box-shadow: 9984px 0 0 0 #ffffff30, 9999px 0 0 0 #ffffff30, 10014px 0 0 0 #ffffff30; } } @layer components { .glass { @apply relative border border-white/10 shadow-lg backdrop-blur-3xl transition-colors duration-300; @apply bg-[#303032]/90 !important; } } .liquid-glass { background: #232323c0; border: 1px solid #ffffff14; backdrop-filter: blur(18px) saturate(180%); -webkit-backdrop-filter: blur(12px) saturate(180%); box-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.6); } /* Minimal thin scrollbar for prompt textareas */ .promptbox-scrollbar { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.2) transparent; } .promptbox-scrollbar::-webkit-scrollbar { width: 4px; } .promptbox-scrollbar::-webkit-scrollbar-track { background: transparent; } .promptbox-scrollbar::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.2); border-radius: 9999px; } .promptbox-scrollbar::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.35); } /* Hide the native resize grip (Chromium draws different grips for textareas vs contenteditable divs) and draw one consistent grip on the wrapper so the plain and @-mention prompt editors look identical. */ .promptbox-scrollbar::-webkit-resizer { background: transparent; border: none; } .promptbox-resize-wrap { position: relative; } .promptbox-resize-wrap::after { content: ""; position: absolute; bottom: 2px; right: 2px; width: 10px; height: 10px; pointer-events: none; background: linear-gradient( 135deg, transparent 40%, rgba(255, 255, 255, 0.5) 40%, rgba(255, 255, 255, 0.5) 45%, transparent 45%, transparent 55%, rgba(255, 255, 255, 0.5) 55%, rgba(255, 255, 255, 0.5) 60%, transparent 60%, transparent 70%, rgba(255, 255, 255, 0.5) 70%, rgba(255, 255, 255, 0.5) 75%, transparent 75% ); } @keyframes fade-in-up { from { opacity: 0; translate: 0 12px; } to { opacity: 1; translate: 0 0; } } /* backdrop blur bug on site so i disabled - bflat */ /* .animate-fade-in-up { animation: fade-in-up 0.2s ease-out both; } */ @keyframes toast-in { from { opacity: 0; translate: 0 8px; } to { opacity: 1; translate: 0 0; } } .animate-toast-in { animation: toast-in 0.2s ease-out both; } /* Prompt box drag & drop overlay */ @keyframes promptbox-drop-overlay-in { from { opacity: 0; } to { opacity: 1; } } .promptbox-drop-overlay { animation: promptbox-drop-overlay-in 0.15s ease-out both; } @keyframes promptbox-drop-chip-in { from { opacity: 0; translate: 0 6px; scale: 0.9; } to { opacity: 1; translate: 0 0; scale: 1; } } .promptbox-drop-chip { animation: promptbox-drop-chip-in 0.25s cubic-bezier(0.22, 1, 0.36, 1) both; } @keyframes marquee { 0% { transform: translateX(0); } 100% { transform: translateX(-100%); } } @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } .animate-shimmer { background: linear-gradient( 90deg, transparent 0%, rgba(255, 255, 255, 0.08) 50%, transparent 100% ); background-size: 200% 100%; animation: shimmer 1.5s ease-in-out infinite; } .bg-dots { background-image: radial-gradient(#ffffff20 1px, transparent 0); background-color: #101014; background-size: 33px 33px; @apply bg-center; } @property --angle { syntax: ""; inherits: false; initial-value: 0deg; } @keyframes rotate { 0% { --angle: 0deg; } 100% { --angle: 360deg; } } .glow-border-animated { position: relative; overflow: hidden; } .glow-border-animated::before { content: ""; position: absolute; inset: -3px; background: conic-gradient( from var(--angle), transparent 0%, transparent 80%, rgba(147, 197, 253, 0.4) 85%, rgba(191, 219, 254, 0.9) 90%, rgba(255, 255, 255, 1) 92.5%, rgba(191, 219, 254, 0.9) 95%, rgba(147, 197, 253, 0.4) 100%, transparent 100% ); border-radius: inherit; animation: rotate 2.2s linear infinite; z-index: -1; } .glow-border-animated::after { content: ""; position: absolute; inset: 2px; background: inherit; border-radius: inherit; z-index: -1; } /* Mobile bottom-sheet (SettingsDrawer). The shadcn Sheet relies on the tailwindcss-animate plugin, which isn't enabled here, so we drive the slide ourselves off Radix's data-state. Defining a closed-state animation lets Radix delay unmount until the slide-down finishes. */ @keyframes ac-drawer-up { from { transform: translateY(100%); } to { transform: translateY(0); } } /* --ac-drawer-drag-y: set inline by SettingsDrawer when a pull-down gesture dismisses the sheet, so the slide-down starts from where the finger let go instead of snapping back to the top first. Fresh mounts default to 0. */ @keyframes ac-drawer-down { from { transform: translateY(var(--ac-drawer-drag-y, 0px)); } to { transform: translateY(100%); } } .ac-drawer-content[data-state="open"] { animation: ac-drawer-up 0.32s cubic-bezier(0.32, 0.72, 0, 1); } .ac-drawer-content[data-state="closed"] { animation: ac-drawer-down 0.22s ease-in forwards; } @keyframes ac-sheet-fade { from { opacity: 0; } to { opacity: 1; } } .ac-sheet-overlay[data-state="open"] { animation: ac-sheet-fade 0.25s ease-out; } .ac-sheet-overlay[data-state="closed"] { animation: ac-sheet-fade 0.2s ease-in reverse forwards; }