@tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { /* Cool editorial palette — light */ --background: 220 30% 98%; --foreground: 230 25% 8%; --card: 0 0% 100%; --card-foreground: 230 25% 8%; --popover: 0 0% 100%; --popover-foreground: 230 25% 8%; --primary: 248 80% 56%; --primary-foreground: 0 0% 100%; --secondary: 220 20% 94%; --secondary-foreground: 230 20% 16%; --muted: 220 18% 95%; --muted-foreground: 225 10% 42%; --accent: 248 70% 96%; --accent-foreground: 248 70% 32%; --destructive: 0 72% 51%; --destructive-foreground: 0 0% 100%; --border: 225 16% 88%; --input: 225 16% 88%; --ring: 248 80% 56%; --radius: 0.75rem; /* Extended tokens */ --glow: 248 90% 62%; --glow-2: 280 85% 60%; --surface-elevated: 0 0% 100%; --hairline: 225 16% 88%; --success: 152 60% 40%; --warning: 38 92% 50%; --font-sans: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-display: "Syne", var(--font-sans); --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; --shadow-glow: 0 0 0 1px hsl(var(--primary) / 0.08), 0 8px 40px -12px hsl(var(--glow) / 0.35); --shadow-elevated: 0 1px 0 hsl(var(--foreground) / 0.04), 0 12px 40px -16px hsl(var(--foreground) / 0.18); } .dark { --background: 235 28% 5%; --foreground: 220 20% 96%; --card: 235 24% 7.5%; --card-foreground: 220 20% 96%; --popover: 235 24% 8.5%; --popover-foreground: 220 20% 96%; --primary: 248 90% 72%; --primary-foreground: 235 30% 8%; --secondary: 235 18% 14%; --secondary-foreground: 220 15% 92%; --muted: 235 16% 12%; --muted-foreground: 225 10% 62%; --accent: 248 40% 14%; --accent-foreground: 248 90% 82%; --destructive: 0 70% 48%; --destructive-foreground: 0 0% 100%; --border: 235 14% 16%; --input: 235 14% 16%; --ring: 248 90% 72%; --glow: 248 95% 70%; --glow-2: 290 90% 68%; --surface-elevated: 235 22% 9%; --hairline: 235 14% 18%; --success: 152 55% 48%; --warning: 38 92% 55%; --shadow-glow: 0 0 0 1px hsl(var(--primary) / 0.14), 0 12px 48px -12px hsl(var(--glow) / 0.45); --shadow-elevated: 0 1px 0 hsl(0 0% 100% / 0.04), 0 20px 50px -20px hsl(0 0% 0% / 0.65); } } @layer base { * { @apply border-border; } html { scroll-behavior: smooth; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } body { @apply bg-background text-foreground antialiased; font-family: var(--font-sans); font-feature-settings: "ss01" on, "cv11" on; min-height: 100dvh; } ::selection { background: hsl(var(--primary) / 0.22); color: hsl(var(--foreground)); } :focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: 2px; } /* Prefer keyboard ring over mouse outline noise on buttons/links handled by components */ .js-focus-visible :focus:not(.focus-visible) { outline: none; } } @layer components { /* Immersive canvas backdrop */ .app-canvas { position: relative; isolation: isolate; min-height: 100dvh; background-color: hsl(var(--background)); } .app-canvas::before { content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none; background: radial-gradient( 60% 50% at 88% -8%, hsl(var(--glow) / 0.18), transparent 70% ), radial-gradient( 50% 40% at -5% 30%, hsl(var(--glow-2) / 0.12), transparent 65% ), radial-gradient( 40% 35% at 50% 110%, hsl(var(--glow) / 0.08), transparent 60% ), hsl(var(--background)); } .app-canvas::after { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: 0.35; mix-blend-mode: overlay; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E"); } .dark .app-canvas::after { opacity: 0.22; mix-blend-mode: soft-light; } .display-font { font-family: var(--font-display); letter-spacing: -0.035em; } .text-gradient { background: linear-gradient( 125deg, hsl(var(--foreground)) 0%, hsl(var(--primary)) 45%, hsl(var(--glow-2)) 100% ); -webkit-background-clip: text; background-clip: text; color: transparent; } .text-gradient-brand { background: linear-gradient( 120deg, hsl(230 90% 58%) 0%, hsl(var(--primary)) 48%, hsl(var(--glow-2)) 100% ); -webkit-background-clip: text; background-clip: text; color: transparent; } .glass-panel { background: hsl(var(--card) / 0.72); border: 1px solid hsl(var(--border) / 0.8); backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2); box-shadow: var(--shadow-elevated); } .glass-header { background: hsl(var(--background) / 0.72); border-bottom: 1px solid hsl(var(--border) / 0.55); backdrop-filter: blur(18px) saturate(1.35); -webkit-backdrop-filter: blur(18px) saturate(1.35); } .surface-panel { background: hsl(var(--card) / 0.55); border: 1px solid hsl(var(--border) / 0.75); box-shadow: var(--shadow-elevated); } .glow-ring { box-shadow: var(--shadow-glow); } .grid-fade { background-image: linear-gradient(to right, hsl(var(--border) / 0.45) 1px, transparent 1px), linear-gradient(to bottom, hsl(var(--border) / 0.45) 1px, transparent 1px); background-size: 48px 48px; mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, black, transparent); } /* Feature card hover lift */ .feature-card { position: relative; overflow: hidden; transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1), border-color 200ms ease, box-shadow 280ms ease; } .feature-card::before { content: ""; position: absolute; inset: 0; background: radial-gradient( 120% 80% at 0% 0%, hsl(var(--primary) / 0.12), transparent 55% ); opacity: 0; transition: opacity 280ms ease; pointer-events: none; } @media (prefers-reduced-motion: no-preference) { .feature-card:hover { transform: translateY(-4px); border-color: hsl(var(--primary) / 0.35); box-shadow: var(--shadow-glow); } .feature-card:hover::before { opacity: 1; } } /* * Bookmark row states — keep focus (cursor) and selection (checked set) * visually distinct so single-click never looks like multi-select. */ .bookmark-row { background-color: transparent; box-shadow: none; } .bookmark-row.is-selected { background-color: hsl(var(--primary) / 0.09); box-shadow: inset 3px 0 0 0 hsl(var(--primary)); } .bookmark-row.is-selected:hover { background-color: hsl(var(--primary) / 0.13); } /* Focus cursor: outline only — no left bar (that means selected) */ .bookmark-row.is-focused { outline: none; background-color: hsl(var(--accent) / 0.55); box-shadow: inset 0 0 0 1px hsl(var(--ring) / 0.35); } .bookmark-row.is-selected.is-focused { background-color: hsl(var(--primary) / 0.14); box-shadow: inset 3px 0 0 0 hsl(var(--primary)), inset 0 0 0 1px hsl(var(--primary) / 0.35); } .bookmark-row:focus-visible { outline: none; } @media (prefers-reduced-motion: no-preference) { .bookmark-row { transition: background-color 140ms ease, box-shadow 140ms ease; } } /* Compact kbd chips */ kbd { @apply inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-muted px-1 font-mono text-2xs font-medium text-muted-foreground; box-shadow: 0 1px 0 hsl(var(--foreground) / 0.06); } /* Staggered entrance */ .reveal { animation: reveal-up 700ms cubic-bezier(0.22, 1, 0.36, 1) both; } .reveal-delay-1 { animation-delay: 80ms; } .reveal-delay-2 { animation-delay: 160ms; } .reveal-delay-3 { animation-delay: 240ms; } .reveal-delay-4 { animation-delay: 320ms; } .reveal-delay-5 { animation-delay: 400ms; } @media (prefers-reduced-motion: reduce) { .reveal, .reveal-delay-1, .reveal-delay-2, .reveal-delay-3, .reveal-delay-4, .reveal-delay-5 { animation: none; } .feature-card:hover { transform: none; } } /* Ambient orb (home hero) */ .orb { position: absolute; border-radius: 9999px; filter: blur(60px); pointer-events: none; will-change: transform; } .orb-a { background: hsl(var(--glow) / 0.35); animation: orb-drift-a 18s ease-in-out infinite alternate; } .orb-b { background: hsl(var(--glow-2) / 0.28); animation: orb-drift-b 22s ease-in-out infinite alternate; } @media (prefers-reduced-motion: reduce) { .orb-a, .orb-b { animation: none; } } /* emoji-picker-react inside nested dialog */ .emoji-picker-shell .EmojiPickerReact { --epr-emoji-size: 1.5rem; border: none !important; box-shadow: none !important; } .emoji-picker-shell .EmojiPickerReact .epr-body { pointer-events: auto; } /* Skip link */ .skip-link { position: absolute; left: 1rem; top: -100%; z-index: 100; border-radius: var(--radius); background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 600; transition: top 150ms ease; } .skip-link:focus { top: 1rem; } } @layer utilities { .font-display { font-family: var(--font-display); } .font-mono { font-family: var(--font-mono); } } @keyframes reveal-up { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } } @keyframes orb-drift-a { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(-8%, 12%, 0) scale(1.12); } } @keyframes orb-drift-b { from { transform: translate3d(0, 0, 0) scale(1.05); } to { transform: translate3d(10%, -10%, 0) scale(0.92); } } @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } /* Quick-start: two-chip drag-to-bookmarks-bar micro-demo (6.4s loop) * Chips sit in the same CSS grid columns as the bar slots, so they only * need a pure vertical flight (~5.15rem) into the matching slot. * * Timeline: * 0–8% rest * 8–28% chip A flies into left slot * 28–36% chip A settles / ghost A solid * 36–56% chip B flies into right slot * 56–74% both settled (hold) * 74–86% fade ghosts, reset chips * 86–100% rest at origin */ @keyframes drag-chip-a-fly { 0%, 8% { transform: translateY(0) scale(1); opacity: 1; } /* slight lift + grab */ 12% { transform: translateY(-0.45rem) scale(1.05); opacity: 1; } /* land in bar slot (chip near page bottom → bar row ≈ 7.6rem) */ 26%, 32% { transform: translateY(-7.6rem) scale(0.88); opacity: 1; } 35% { transform: translateY(-7.6rem) scale(0.7); opacity: 0; } 36%, 100% { transform: translateY(0) scale(1); opacity: 0; } } @keyframes drag-chip-b-fly { 0%, 36% { transform: translateY(0) scale(1); opacity: 1; } 40% { transform: translateY(-0.45rem) scale(1.05); opacity: 1; } 54%, 70% { transform: translateY(-7.6rem) scale(0.88); opacity: 1; } 74% { transform: translateY(-7.6rem) scale(0.7); opacity: 0; } 75%, 100% { transform: translateY(0) scale(1); opacity: 0; } } @keyframes drag-ghost-a-pop { 0%, 24% { opacity: 0; transform: scale(0.82); } 30%, 74% { opacity: 1; transform: scale(1); } 84%, 100% { opacity: 0; transform: scale(0.95); } } @keyframes drag-ghost-b-pop { 0%, 52% { opacity: 0; transform: scale(0.82); } 58%, 74% { opacity: 1; transform: scale(1); } 84%, 100% { opacity: 0; transform: scale(0.95); } } @keyframes drag-slot-a-pulse { 0%, 10% { border-color: hsl(var(--primary) / 0.3); background-color: hsl(var(--background) / 0.5); box-shadow: none; } 16%, 32% { border-color: hsl(var(--primary) / 0.9); background-color: hsl(var(--primary) / 0.16); box-shadow: 0 0 0 2px hsl(var(--primary) / 0.14); } 38%, 74% { border-style: solid; border-color: hsl(var(--primary) / 0.4); background-color: hsl(var(--primary) / 0.08); box-shadow: none; } 86%, 100% { border-style: dashed; border-color: hsl(var(--primary) / 0.3); background-color: hsl(var(--background) / 0.5); } } @keyframes drag-slot-b-pulse { 0%, 38% { border-color: hsl(var(--primary) / 0.3); background-color: hsl(var(--background) / 0.5); box-shadow: none; } 44%, 60% { border-color: hsl(var(--primary) / 0.9); background-color: hsl(var(--primary) / 0.16); box-shadow: 0 0 0 2px hsl(var(--primary) / 0.14); } 66%, 74% { border-style: solid; border-color: hsl(var(--primary) / 0.4); background-color: hsl(var(--primary) / 0.08); box-shadow: none; } 86%, 100% { border-style: dashed; border-color: hsl(var(--primary) / 0.3); background-color: hsl(var(--background) / 0.5); } } .drag-demo-page { overflow: visible; } .drag-demo-chip-a, .drag-demo-chip-b { z-index: 3; will-change: transform, opacity; } .drag-demo-chip-a { animation: drag-chip-a-fly 6.4s cubic-bezier(0.4, 0, 0.2, 1) infinite; } .drag-demo-chip-b { animation: drag-chip-b-fly 6.4s cubic-bezier(0.4, 0, 0.2, 1) infinite; } .drag-demo-ghost-a { animation: drag-ghost-a-pop 6.4s ease infinite; } .drag-demo-ghost-b { animation: drag-ghost-b-pop 6.4s ease infinite; } .drag-demo-slot-a { animation: drag-slot-a-pulse 6.4s ease infinite; } .drag-demo-slot-b { animation: drag-slot-b-pulse 6.4s ease infinite; } @media (prefers-reduced-motion: reduce) { .drag-demo-chip-a, .drag-demo-chip-b, .drag-demo-ghost-a, .drag-demo-ghost-b, .drag-demo-slot-a, .drag-demo-slot-b { animation: none; } .drag-demo-chip-a, .drag-demo-chip-b { opacity: 1; transform: none; } .drag-demo-ghost-a, .drag-demo-ghost-b { opacity: 1; } }