/* BooCode Override — effects layer. Full neon cyberpunk: heavy bloom/glow, chromatic-glitch wordmark, glitch-on-hover, strong scanlines, neon border pulses. Magenta #ff2d78 + cyan #00e5ff + violet #9b5de5 on blue-black. Scoping contract (immutable, same as boocode-classic-fx.css): - EVERY rule is scoped under `.theme-boocode-override` so the other 22 themes are byte-for-byte unaffected. - EVERY continuous keyframe animation is *additionally* scoped under `html.bc-anim-on.theme-boocode-override`. ThemeFx sets `bc-anim-on` only when the Animated-background toggle is ON *and* prefers-reduced-motion is not set — so toggling either off removes the class and freezes all motion. @keyframes names are global (CSS can't scope the at-rule itself); they are `bco-`-prefixed and only *referenced* under the gated selector. Static vs. gated split: - STATIC (always, under .theme-boocode-override): the neon palette, a bloom vignette painted on the app-shell background, static neon rims/glows on the primary action / cards / inputs, and a neon focus ring. This is the "static tint" fallback shown when the toggle is OFF or reduced-motion is on. - GATED (under html.bc-anim-on.theme-boocode-override): the NeonField canvas (mounted by ThemeFx), the scanline texture + moving sweep, the wordmark chromatic glitch, the hover glitch jitter, and the idle neon pulse. AA: neon is used ONLY for accents/borders/glow and the (large display) wordmark — never body text. Body/panel text keeps the light #cde0ff / #8aa9cd tokens over the high-alpha translucent surfaces (see boocode-override.css). Glitch uses transform / text-shadow / clip-path only, so it never reflows layout. */ .theme-boocode-override { --bco-magenta: #ff2d78; --bco-cyan: #00e5ff; --bco-violet: #9b5de5; --bco-glow-magenta: 0 0 22px color-mix(in srgb, var(--bco-magenta) 42%, transparent); --bco-glow-cyan: 0 0 22px color-mix(in srgb, var(--bco-cyan) 38%, transparent); } /* ── Bloom vignette on the app shell ────────────────────────────────────── Painted as background-image on the AppShell root (`.h-dvh.bg-background`, unique to App.tsx). The background-COLOR stays the translucent --background token so the NeonField canvas (z-0, behind the z-10 root) still shows through the panel gaps; these radial neon pools sit over the field for an atmospheric bloom. Static → this is part of the reduced-motion / toggle-off fallback. */ .theme-boocode-override .h-dvh.bg-background { background-color: var(--background); background-image: radial-gradient(125% 90% at 50% 8%, color-mix(in oklab, var(--bco-magenta) 12%, transparent), transparent 46%), radial-gradient(120% 85% at 6% 102%, color-mix(in oklab, var(--bco-cyan) 11%, transparent), transparent 50%), radial-gradient(120% 95% at 100% 100%, color-mix(in oklab, var(--bco-violet) 12%, transparent), transparent 52%), radial-gradient(140% 120% at 50% 50%, transparent 60%, rgba(2, 4, 10, 0.55) 100%); background-repeat: no-repeat; } /* ── Strong scanlines (gated) ───────────────────────────────────────────── ::before = a fine static CRT scanline texture; ::after = a bright neon band that sweeps the viewport. Both are `position: fixed` (never create document overflow), `pointer-events: none`, and use `mix-blend-mode: screen` so they only LIGHTEN — text underneath never loses contrast. Both live ONLY under the gate, so motion-off / reduced-motion removes scanlines entirely (the bloom vignette above is the static fallback). z-index:2/3 overlays the static panels inside the shell; portaled dialogs (separate stacking context) stay clean. */ html.bc-anim-on.theme-boocode-override .h-dvh.bg-background::before { content: ''; position: fixed; inset: 0; z-index: 2; pointer-events: none; background-image: repeating-linear-gradient( 0deg, color-mix(in srgb, var(--bco-cyan) 9%, transparent) 0px, color-mix(in srgb, var(--bco-cyan) 9%, transparent) 1px, transparent 1px, transparent 3px ); mix-blend-mode: screen; opacity: 0.55; } html.bc-anim-on.theme-boocode-override .h-dvh.bg-background::after { content: ''; position: fixed; inset: 0; z-index: 3; pointer-events: none; background: linear-gradient( 180deg, transparent 44%, color-mix(in srgb, var(--bco-cyan) 10%, transparent) 49%, color-mix(in srgb, var(--bco-magenta) 12%, transparent) 51%, transparent 56% ); mix-blend-mode: screen; animation: bco-scan-sweep 7s linear infinite; will-change: transform; } /* ── Neon chromatic-glitch wordmark ─────────────────────────────────────── The "BooCode" display heading (Home.tsx, additive `boocode-display` class — the same hook BooCode Classic restyles; only one theme is ever active). Orbitron 800 (JS-imported in main.tsx). A near-white core with stacked cyan + magenta glow gives the neon tube look; the gated glitch jitters the colour split + a clip slice via transform/text-shadow only → zero layout shift. */ .theme-boocode-override .boocode-display { font-family: 'Orbitron', var(--font-sans); font-weight: 800; letter-spacing: 0.08em; color: #eafaff; text-shadow: 0 0 2px color-mix(in srgb, var(--bco-cyan) 80%, transparent), -0.02em 0 0 color-mix(in srgb, var(--bco-magenta) 70%, transparent), 0.02em 0 0 color-mix(in srgb, var(--bco-cyan) 70%, transparent), 0 0 18px color-mix(in srgb, var(--bco-cyan) 55%, transparent), 0 0 34px color-mix(in srgb, var(--bco-magenta) 40%, transparent); } html.bc-anim-on.theme-boocode-override .boocode-display { animation: bco-glitch 5.5s steps(1, end) infinite; } /* ── Primary action: neon rim + idle pulse + hover bloom + press squash ──── The default-variant Button (Send / primary confirm). Static magenta rim + drop glow (always); a gentle idle pulse and a hover glitch jitter under the gate; box-shadow / transform / filter only → never reflows. */ .theme-boocode-override [data-slot="button"][data-variant="default"] { box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-magenta) 55%, transparent), 0 4px 20px -6px color-mix(in srgb, var(--bco-magenta) 60%, transparent); } .theme-boocode-override [data-slot="button"][data-variant="default"]:not([disabled]):hover { box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-magenta) 85%, transparent), 0 0 16px -2px color-mix(in srgb, var(--bco-magenta) 70%, transparent), 0 8px 30px -6px color-mix(in srgb, var(--bco-cyan) 55%, transparent); filter: brightness(1.08); } html.bc-anim-on.theme-boocode-override [data-slot="button"][data-variant="default"] { transition: box-shadow 200ms ease, transform 120ms ease, filter 160ms ease; animation: bco-pulse 3.4s ease-in-out infinite; } html.bc-anim-on.theme-boocode-override [data-slot="button"][data-variant="default"]:not([disabled]):hover { animation: bco-hover-glitch 320ms steps(1, end) 1; } html.bc-anim-on.theme-boocode-override [data-slot="button"][data-variant="default"]:not([disabled]):active { transform: translateY(0.5px) scale(0.985); } /* ── Cards: neon edge + hover glow/lift ─────────────────────────────────── shadcn Card primitive (`data-slot="card"`). Static cyan hairline; on hover a cyan/magenta rim glow + 1px lift (lift + transition gated). */ .theme-boocode-override [data-slot="card"] { box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-cyan) 12%, transparent); } .theme-boocode-override [data-slot="card"]:hover { border-color: color-mix(in srgb, var(--bco-cyan) 55%, transparent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-cyan) 38%, transparent), 0 0 22px -6px color-mix(in srgb, var(--bco-magenta) 45%, transparent), 0 8px 24px -10px color-mix(in srgb, var(--bco-cyan) 50%, transparent); } html.bc-anim-on.theme-boocode-override [data-slot="card"] { transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease; } html.bc-anim-on.theme-boocode-override [data-slot="card"]:hover { transform: translateY(-1px); } /* ── Sidebar edge-light + neon focus ring ───────────────────────────────── A static cyan inset hairline down the sidebar's trailing edge; a magenta neon focus ring on inputs/buttons (focus-visible only, static — focus feedback is acceptable under reduced motion). */ .theme-boocode-override .bg-sidebar { box-shadow: inset -1px 0 0 0 color-mix(in srgb, var(--bco-cyan) 16%, transparent); } .theme-boocode-override [data-slot="input"]:focus-visible, .theme-boocode-override [data-slot="button"]:focus-visible, .theme-boocode-override [data-slot="textarea"]:focus-visible { box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-magenta) 70%, transparent), 0 0 14px -2px color-mix(in srgb, var(--bco-magenta) 55%, transparent); outline: none; } /* ── Links / accent text glow ───────────────────────────────────────────── Anchors inside content get a soft cyan glow on hover — accent, not body. */ .theme-boocode-override a:hover { text-shadow: 0 0 10px color-mix(in srgb, var(--bco-cyan) 55%, transparent); } /* ── Keyframes (global names, referenced only under the gate above) ───────── */ /* Scanline sweep: a bright neon band drifts top→bottom. */ @keyframes bco-scan-sweep { 0% { transform: translateY(-100%); } 100% { transform: translateY(100%); } } /* Idle neon pulse on the primary action: the glow swells and settles. */ @keyframes bco-pulse { 0%, 100% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-magenta) 55%, transparent), 0 4px 20px -6px color-mix(in srgb, var(--bco-magenta) 55%, transparent); } 50% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--bco-magenta) 80%, transparent), 0 0 18px -2px color-mix(in srgb, var(--bco-magenta) 60%, transparent), 0 6px 26px -6px color-mix(in srgb, var(--bco-cyan) 45%, transparent); } } /* Wordmark chromatic glitch: mostly steady, with brief jitter bursts. Only transform / text-shadow / clip-path change → no reflow. */ @keyframes bco-glitch { 0%, 88%, 100% { transform: translate3d(0, 0, 0); clip-path: none; text-shadow: 0 0 2px color-mix(in srgb, var(--bco-cyan) 80%, transparent), -0.02em 0 0 color-mix(in srgb, var(--bco-magenta) 70%, transparent), 0.02em 0 0 color-mix(in srgb, var(--bco-cyan) 70%, transparent), 0 0 18px color-mix(in srgb, var(--bco-cyan) 55%, transparent), 0 0 34px color-mix(in srgb, var(--bco-magenta) 40%, transparent); } 90% { transform: translate3d(-2px, 0, 0); clip-path: inset(8% 0 62% 0); text-shadow: -0.08em 0 0 color-mix(in srgb, var(--bco-magenta) 90%, transparent), 0.08em 0 0 color-mix(in srgb, var(--bco-cyan) 90%, transparent), 0 0 22px color-mix(in srgb, var(--bco-cyan) 60%, transparent); } 92% { transform: translate3d(2px, 0, 0); clip-path: inset(54% 0 18% 0); text-shadow: 0.1em 0 0 color-mix(in srgb, var(--bco-magenta) 90%, transparent), -0.06em 0 0 color-mix(in srgb, var(--bco-cyan) 85%, transparent), 0 0 22px color-mix(in srgb, var(--bco-magenta) 60%, transparent); } 94% { transform: translate3d(-1px, 0, 0); clip-path: inset(34% 0 40% 0); text-shadow: -0.05em 0 0 color-mix(in srgb, var(--bco-cyan) 85%, transparent), 0.05em 0 0 color-mix(in srgb, var(--bco-magenta) 85%, transparent); } } /* Hover glitch on the primary button: a single quick colour-split jitter. */ @keyframes bco-hover-glitch { 0% { transform: translate3d(0, 0, 0); } 25% { transform: translate3d(-1.5px, 0, 0); } 50% { transform: translate3d(1.5px, 0, 0); } 75% { transform: translate3d(-0.5px, 0, 0); } 100% { transform: translate3d(0, 0, 0); } } /* ── Reduced-motion belt-and-suspenders ─────────────────────────────────── bc-anim-on already excludes reduced-motion (ThemeFx), but if the class ever lingered, this hard-stops every animation and the lift/jitter transforms. The static neon rims, bloom vignette and focus ring remain (the "static tint"). */ @media (prefers-reduced-motion: reduce) { .theme-boocode-override .boocode-display, .theme-boocode-override .h-dvh.bg-background::before, .theme-boocode-override .h-dvh.bg-background::after, .theme-boocode-override [data-slot="button"][data-variant="default"], .theme-boocode-override [data-slot="button"][data-variant="default"]:hover { animation: none; } .theme-boocode-override .h-dvh.bg-background::after { display: none; } .theme-boocode-override .boocode-display { transform: none; clip-path: none; } .theme-boocode-override [data-slot="card"], .theme-boocode-override [data-slot="button"][data-variant="default"] { transition: none; } .theme-boocode-override [data-slot="card"]:hover, .theme-boocode-override [data-slot="button"][data-variant="default"]:active { transform: none; } }