+
Sm
diff --git a/src/components/ui/toggle/toggle.test.tsx b/src/components/ui/toggle/toggle.test.tsx
index 3ca61bd..2f52871 100644
--- a/src/components/ui/toggle/toggle.test.tsx
+++ b/src/components/ui/toggle/toggle.test.tsx
@@ -25,15 +25,6 @@ describe('Toggle', () => {
expect(ref.current).toBeInstanceOf(HTMLButtonElement);
});
- it('applies variant classes', () => {
- render(
-
- B
-
- );
- expect(screen.getByRole('button')).toHaveClass('border');
- });
-
it('calls onPressedChange when toggled', async () => {
const user = userEvent.setup();
const onPressedChange = vi.fn();
diff --git a/src/components/ui/toggle/toggle.tsx b/src/components/ui/toggle/toggle.tsx
index 3d38fed..77724d3 100644
--- a/src/components/ui/toggle/toggle.tsx
+++ b/src/components/ui/toggle/toggle.tsx
@@ -1,40 +1,26 @@
import * as TogglePrimitive from '@radix-ui/react-toggle';
-import { cva, type VariantProps } from 'class-variance-authority';
import * as React from 'react';
-import { cn } from '@/lib/utils';
+import { cx } from '@/lib/utils';
+import './toggle.css';
-const toggleVariants = cva(
- 'inline-flex items-center justify-center text-sm font-medium hover:bg-primary hover:text-primary-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50 border-2 border-primary data-[state=on]:bg-primary data-[state=on]:text-primary-foreground data-[state=off]:bg-transparent data-[state=off]:text-primary [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2 cursor-pointer',
- {
- variants: {
- variant: {
- default: 'bg-transparent',
- outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground',
- },
- size: {
- default: 'h-9 px-2 min-w-9',
- sm: 'h-8 px-1.5 min-w-8',
- lg: 'h-10 px-2.5 min-w-10',
- },
- },
- defaultVariants: {
- variant: 'default',
- size: 'default',
- },
- }
-);
+export type ToggleSize = 'default' | 'sm' | 'lg';
+
+export interface ToggleProps
+ extends React.ComponentPropsWithoutRef {
+ size?: ToggleSize;
+}
const Toggle = React.forwardRef<
React.ElementRef,
- React.ComponentPropsWithoutRef & VariantProps
->(({ className, variant, size, ...props }, ref) => (
+ ToggleProps
+>(({ className, size = 'default', ...props }, ref) => (
));
Toggle.displayName = TogglePrimitive.Root.displayName;
-export { Toggle, toggleVariants };
+export { Toggle };
diff --git a/src/components/ui/tooltip/tooltip.css b/src/components/ui/tooltip/tooltip.css
new file mode 100644
index 0000000..9ed1606
--- /dev/null
+++ b/src/components/ui/tooltip/tooltip.css
@@ -0,0 +1,11 @@
+/* Tooltip Component Styles */
+
+.scl-tooltip-content {
+ z-index: 50;
+ overflow: hidden;
+ background-color: var(--scl-primary);
+ padding: var(--scl-space-1-5) var(--scl-space-3);
+ font-size: var(--scl-text-xs);
+ font-family: var(--scl-font-mono);
+ color: var(--scl-primary-foreground);
+}
diff --git a/src/components/ui/tooltip/tooltip.tsx b/src/components/ui/tooltip/tooltip.tsx
index 7d673bb..cdb61dd 100644
--- a/src/components/ui/tooltip/tooltip.tsx
+++ b/src/components/ui/tooltip/tooltip.tsx
@@ -1,6 +1,7 @@
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import * as React from 'react';
-import { cn } from '@/lib/utils';
+import { cx } from '@/lib/utils';
+import './tooltip.css';
const TooltipProvider = ({
children,
@@ -13,7 +14,6 @@ const TooltipProvider = ({
TooltipProvider.displayName = 'TooltipProvider';
const Tooltip = TooltipPrimitive.Root;
-
const TooltipTrigger = TooltipPrimitive.Trigger;
const TooltipContent = React.forwardRef<
@@ -24,10 +24,7 @@ const TooltipContent = React.forwardRef<
diff --git a/src/index.ts b/src/index.ts
index 09e97b0..f044615 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,19 +1,13 @@
-// Components
+// Components - Pure Radix + CSS (no Tailwind, no shadcn)
export * from './components/ui/accordion';
export * from './components/ui/alert';
-export * from './components/ui/alert-dialog';
export * from './components/ui/avatar';
export * from './components/ui/badge';
export * from './components/ui/button';
export * from './components/ui/card';
export * from './components/ui/checkbox';
export * from './components/ui/collapsible';
-export * from './components/ui/combobox';
-export * from './components/ui/command';
export * from './components/ui/dialog';
-export * from './components/ui/dithered-image';
-export * from './components/ui/dropdown-menu';
-export * from './components/ui/form';
export * from './components/ui/input';
export * from './components/ui/label';
export * from './components/ui/popover';
@@ -22,20 +16,17 @@ export * from './components/ui/radio-group';
export * from './components/ui/scroll-area';
export * from './components/ui/select';
export * from './components/ui/separator';
-export * from './components/ui/sheet';
export * from './components/ui/skeleton';
export * from './components/ui/slider';
-export * from './components/ui/statusline';
export * from './components/ui/switch';
export * from './components/ui/table';
export * from './components/ui/tabs';
-export * from './components/ui/terminal-textarea';
export * from './components/ui/textarea';
export * from './components/ui/toggle';
export * from './components/ui/tooltip';
// Utilities
-export { cn } from './lib/utils';
+export { cx, cn } from './lib/utils';
// Tokens
export * from './tokens';
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 745504d..60fc44b 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,17 +1,19 @@
-import { type ClassValue, clsx } from 'clsx';
-import { twMerge } from 'tailwind-merge';
-
/**
- * Combines class names with Tailwind CSS merge support.
- * This utility merges Tailwind classes intelligently, avoiding conflicts.
+ * Combines class names, filtering out falsy values.
+ * Replacement for clsx/tailwind-merge without Tailwind dependency.
*
- * @param inputs - Class values to combine
- * @returns Merged class string
+ * @param classes - Class values to combine (strings, undefined, null, false)
+ * @returns Combined class string
*
* @example
- * cn('px-4 py-2', 'px-6') // Returns 'py-2 px-6'
- * cn('text-red-500', condition && 'text-blue-500')
+ * cx('scl-button', isActive && 'scl-button--active') // 'scl-button scl-button--active'
+ * cx('base', undefined, 'extra') // 'base extra'
*/
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs));
+export function cx(
+ ...classes: (string | undefined | null | false)[]
+): string {
+ return classes.filter(Boolean).join(' ');
}
+
+// Keep cn as alias for backwards compatibility during migration
+export const cn = cx;
diff --git a/src/styles/globals.css b/src/styles/globals.css
index f0c750b..5555e0f 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -1,300 +1,235 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+/* SCL Global Styles - Pure CSS (No Tailwind) */
+/* Font Face */
@font-face {
font-family: 'BigBlueTerm437';
src: url('/fonts/BigBlueTerm437.ttf') format('truetype');
}
-@layer base {
- :root {
- /* Color palette */
- --color-green: 120 100% 50%;
- --color-hotpink: 300 100% 50%;
- --color-yellow: 60 100% 50%;
- --color-blue: 240 100% 50%;
- --color-cyan: 180 100% 50%;
- --color-white: 0 0% 100%;
- --color-amber: 45 100% 50%;
- --color-red: 0 100% 50%;
-
- /* Statusline colors (vim powerline style) */
- --statusline-bg: 210 100% 35%;
- --statusline-fg: 60 100% 50%;
-
- /* Semantic colors (swappable) */
- --primary: var(--color-green);
- --primary-foreground: 0 0% 0%;
- --secondary: var(--color-hotpink);
- --secondary-foreground: 0 0% 0%;
-
- /* Core UI (derived from primary) */
- --background: 0 0% 0%;
- --foreground: var(--primary);
- --border: var(--primary);
- --input: 0 0% 0%;
- --ring: var(--primary);
-
- /* Card/popover */
- --card: 0 0% 0%;
- --card-foreground: var(--primary);
- --popover: 0 0% 0%;
- --popover-foreground: var(--primary);
-
- /* Muted */
- --muted: 0 0% 8%;
- --muted-foreground: var(--primary);
-
- /* Accent (secondary) */
- --accent: var(--secondary);
- --accent-foreground: var(--secondary-foreground);
-
- /* Destructive (always red) */
- --destructive: var(--color-red);
- --destructive-foreground: 0 0% 0%;
-
- /* Chart colors */
- --chart-1: var(--color-green);
- --chart-2: var(--color-yellow);
- --chart-3: var(--color-hotpink);
- --chart-4: var(--color-blue);
- --chart-5: var(--color-amber);
-
- /* Sidebar */
- --sidebar-background: 0 0% 0%;
- --sidebar-foreground: var(--primary);
- --sidebar-primary: var(--primary);
- --sidebar-primary-foreground: var(--primary-foreground);
- --sidebar-accent: var(--secondary);
- --sidebar-accent-foreground: var(--secondary-foreground);
- --sidebar-border: var(--primary);
- --sidebar-ring: var(--primary);
-
- --radius: 0px;
- }
-
- /* Theme utility classes for per-section color swapping */
- .theme-yellow {
- --primary: 60 100% 50%;
- }
- .theme-blue {
- --primary: 240 100% 50%;
- --primary-foreground: 0 0% 100%;
- }
- .theme-white {
- --primary: 0 0% 100%;
- }
- .theme-amber {
- --primary: 45 100% 50%;
- }
- .theme-hotpink {
- --primary: 300 100% 50%;
- }
- .theme-cyan {
- --primary: 180 100% 50%;
- }
- .theme-secondary {
- --primary: 300 100% 50%;
- --primary-foreground: 0 0% 0%;
- }
+/* CSS Custom Properties (Design Tokens) */
+:root {
+ /* Color Palette */
+ --scl-color-green: hsl(120, 100%, 50%);
+ --scl-color-hotpink: hsl(300, 100%, 50%);
+ --scl-color-yellow: hsl(60, 100%, 50%);
+ --scl-color-blue: hsl(240, 100%, 50%);
+ --scl-color-cyan: hsl(180, 100%, 50%);
+ --scl-color-white: hsl(0, 0%, 100%);
+ --scl-color-amber: hsl(45, 100%, 50%);
+ --scl-color-red: hsl(0, 100%, 50%);
+ --scl-color-black: hsl(0, 0%, 0%);
+
+ /* Semantic Colors */
+ --scl-primary: var(--scl-color-green);
+ --scl-primary-foreground: var(--scl-color-black);
+ --scl-secondary: var(--scl-color-hotpink);
+ --scl-secondary-foreground: var(--scl-color-black);
+ --scl-destructive: var(--scl-color-red);
+ --scl-destructive-foreground: var(--scl-color-black);
+
+ /* Background & Foreground */
+ --scl-background: var(--scl-color-black);
+ --scl-foreground: var(--scl-primary);
+
+ /* Border & Ring */
+ --scl-border: var(--scl-primary);
+ --scl-ring: var(--scl-primary);
+ --scl-input: var(--scl-color-black);
+
+ /* Muted */
+ --scl-muted: hsl(0, 0%, 8%);
+ --scl-muted-foreground: var(--scl-primary);
+
+ /* Card & Popover */
+ --scl-card: var(--scl-color-black);
+ --scl-card-foreground: var(--scl-primary);
+ --scl-popover: var(--scl-color-black);
+ --scl-popover-foreground: var(--scl-primary);
+
+ /* Accent */
+ --scl-accent: var(--scl-secondary);
+ --scl-accent-foreground: var(--scl-secondary-foreground);
+
+ /* Spacing Scale */
+ --scl-space-0: 0;
+ --scl-space-px: 1px;
+ --scl-space-0-5: 0.125rem;
+ --scl-space-1: 0.25rem;
+ --scl-space-1-5: 0.375rem;
+ --scl-space-2: 0.5rem;
+ --scl-space-2-5: 0.625rem;
+ --scl-space-3: 0.75rem;
+ --scl-space-3-5: 0.875rem;
+ --scl-space-4: 1rem;
+ --scl-space-5: 1.25rem;
+ --scl-space-6: 1.5rem;
+ --scl-space-7: 1.75rem;
+ --scl-space-8: 2rem;
+ --scl-space-9: 2.25rem;
+ --scl-space-10: 2.5rem;
+ --scl-space-11: 2.75rem;
+ --scl-space-12: 3rem;
+ --scl-space-14: 3.5rem;
+ --scl-space-16: 4rem;
+
+ /* Font Sizes */
+ --scl-text-xs: 0.75rem;
+ --scl-text-sm: 0.875rem;
+ --scl-text-base: 1rem;
+ --scl-text-lg: 1.125rem;
+ --scl-text-xl: 1.25rem;
+ --scl-text-2xl: 1.5rem;
+ --scl-text-3xl: 1.875rem;
+
+ /* Font Family */
+ --scl-font-mono: 'BigBlueTerm437', monospace;
+
+ /* Animation Durations */
+ --scl-duration-fast: 150ms;
+ --scl-duration-normal: 200ms;
+ --scl-duration-slow: 300ms;
+
+ /* Focus Ring */
+ --scl-focus-ring-width: 2px;
+ --scl-focus-ring-offset: 2px;
}
-@layer base {
- * {
- border-color: hsl(var(--border));
- }
-
- html {
- background-color: #000000;
- }
-
- body {
- background-color: hsl(var(--background));
- color: hsl(var(--primary));
- font-family: 'BigBlueTerm437', monospace;
- }
-
- /* Kill all shadows globally */
- *,
- *::before,
- *::after {
- box-shadow: none !important;
- text-shadow: none !important;
- }
-
- /* Kill all border radius globally */
- *,
- *::before,
- *::after {
- border-radius: 0 !important;
- }
+/* Theme Variants */
+.scl-theme-yellow {
+ --scl-primary: var(--scl-color-yellow);
+}
+.scl-theme-blue {
+ --scl-primary: var(--scl-color-blue);
+ --scl-primary-foreground: var(--scl-color-white);
+}
+.scl-theme-white {
+ --scl-primary: var(--scl-color-white);
+}
+.scl-theme-amber {
+ --scl-primary: var(--scl-color-amber);
+}
+.scl-theme-hotpink {
+ --scl-primary: var(--scl-color-hotpink);
+}
+.scl-theme-cyan {
+ --scl-primary: var(--scl-color-cyan);
+}
+
+/* Base Styles */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ border-radius: 0;
+ box-shadow: none;
+ text-shadow: none;
+}
+
+html {
+ background-color: var(--scl-background);
+}
+
+body {
+ background-color: var(--scl-background);
+ color: var(--scl-foreground);
+ font-family: var(--scl-font-mono);
+ line-height: 1.5;
+}
+
+/* Animations */
+@keyframes scl-accordion-down {
+ from { height: 0; }
+ to { height: var(--radix-accordion-content-height); }
+}
+
+@keyframes scl-accordion-up {
+ from { height: var(--radix-accordion-content-height); }
+ to { height: 0; }
+}
+
+@keyframes scl-collapsible-down {
+ from { height: 0; }
+ to { height: var(--radix-collapsible-content-height); }
+}
+
+@keyframes scl-collapsible-up {
+ from { height: var(--radix-collapsible-content-height); }
+ to { height: 0; }
+}
+
+@keyframes scl-fade-in {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+@keyframes scl-fade-out {
+ from { opacity: 1; }
+ to { opacity: 0; }
+}
+
+@keyframes scl-slide-in-from-top {
+ from { transform: translateY(-100%); }
+ to { transform: translateY(0); }
+}
+
+@keyframes scl-slide-in-from-bottom {
+ from { transform: translateY(100%); }
+ to { transform: translateY(0); }
+}
+
+@keyframes scl-slide-in-from-left {
+ from { transform: translateX(-100%); }
+ to { transform: translateX(0); }
+}
+
+@keyframes scl-slide-in-from-right {
+ from { transform: translateX(100%); }
+ to { transform: translateX(0); }
+}
+
+@keyframes scl-zoom-in {
+ from { transform: scale(0.95); opacity: 0; }
+ to { transform: scale(1); opacity: 1; }
+}
+
+@keyframes scl-zoom-out {
+ from { transform: scale(1); opacity: 1; }
+ to { transform: scale(0.95); opacity: 0; }
+}
+
+@keyframes scl-blink {
+ 0%, 100% { opacity: 1; }
+ 50% { opacity: 0; }
+}
+
+@keyframes scl-spin {
+ from { transform: rotate(0deg); }
+ to { transform: rotate(360deg); }
+}
+
+/* Win95 Scrollbar */
+.scl-win95-scroll {
+ scrollbar-width: auto;
+ scrollbar-color: #bcbcbc #d4d0c8;
+}
+
+.scl-win95-scroll::-webkit-scrollbar {
+ width: 16px;
+ background-color: #d4d0c8;
+}
+
+.scl-win95-scroll::-webkit-scrollbar-track {
+ background: linear-gradient(180deg, #f5f5f5 0%, #d4d0c8 100%);
+ border: 1px solid #808080;
}
-/* Win95 style scrollbar from original app */
-@layer components {
- .win95-scroll {
- scrollbar-width: auto;
- scrollbar-color: #bcbcbc #d4d0c8;
- }
-
- .win95-scroll::-webkit-scrollbar {
- width: 16px;
- background-color: #d4d0c8;
- }
-
- .win95-scroll::-webkit-scrollbar-track {
- background: linear-gradient(180deg, #f5f5f5 0%, #d4d0c8 100%);
- border: 1px solid #808080;
- }
-
- .win95-scroll::-webkit-scrollbar-thumb {
- background-color: #bcbcbc;
- border: 1px solid #808080;
- }
-
- .win95-scroll::-webkit-scrollbar-thumb:hover {
- background-color: #d6d6d6;
- }
-
- .win95-scroll::-webkit-scrollbar-button {
- height: 16px;
- background-color: #d4d0c8;
- border: 1px solid #808080;
- }
-
- /* Terminal header styles */
- .header-title {
- background: hsl(var(--primary));
- color: hsl(var(--primary-foreground));
- font-weight: bold;
- line-height: 1;
- display: inline-block;
- position: relative;
- }
-
- .header-title::after {
- content: '';
- position: absolute;
- top: 50%;
- transform: translateY(-50%);
- border-left-color: hsl(var(--primary));
- border-top-color: transparent;
- border-bottom-color: transparent;
- border-style: solid;
- border-top-width: 10px;
- border-bottom-width: 10px;
- border-left-width: 6px;
- right: -6px;
- }
-
- .header-button {
- position: absolute;
- right: 0;
- top: 0;
- bottom: 0;
- background: hsl(var(--background));
- padding-left: 0.5rem;
- padding-right: 0.5rem;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- color: hsl(var(--primary));
- transition: background-color 0.2s;
- display: flex;
- align-items: center;
- }
-
- .header-button:hover {
- background: hsl(var(--muted));
- }
-
- .header-button:focus {
- outline: 1px solid hsl(var(--primary));
- }
-
- .terminal-glow {
- box-shadow: 0 0 8px hsl(var(--primary) / 0.6) !important;
- }
+.scl-win95-scroll::-webkit-scrollbar-thumb {
+ background-color: #bcbcbc;
+ border: 1px solid #808080;
}
-/* Custom color utilities - workaround for Tailwind JIT not generating these */
-@layer utilities {
- .bg-primary {
- background-color: hsl(var(--primary));
- }
- .bg-secondary {
- background-color: hsl(var(--secondary));
- }
- .bg-destructive {
- background-color: hsl(var(--destructive));
- }
- .bg-muted {
- background-color: hsl(var(--muted));
- }
- .bg-accent {
- background-color: hsl(var(--accent));
- }
- .bg-card {
- background-color: hsl(var(--card));
- }
- .bg-popover {
- background-color: hsl(var(--popover));
- }
- .bg-background {
- background-color: hsl(var(--background));
- }
- .text-primary {
- color: hsl(var(--primary));
- }
- .text-secondary {
- color: hsl(var(--secondary));
- }
- .text-destructive {
- color: hsl(var(--destructive));
- }
- .text-primary-foreground {
- color: hsl(var(--primary-foreground));
- }
- .text-secondary-foreground {
- color: hsl(var(--secondary-foreground));
- }
- .text-destructive-foreground {
- color: hsl(var(--destructive-foreground));
- }
- .text-muted-foreground {
- color: hsl(var(--muted-foreground));
- }
- .text-card-foreground {
- color: hsl(var(--card-foreground));
- }
- .text-popover-foreground {
- color: hsl(var(--popover-foreground));
- }
- .border-primary {
- border-color: hsl(var(--primary));
- }
- .border-secondary {
- border-color: hsl(var(--secondary));
- }
- .border-destructive {
- border-color: hsl(var(--destructive));
- }
- .ring-primary {
- --tw-ring-color: hsl(var(--primary));
- }
-
- /* Blink animation utility - only blinks the fill, not the border */
- .animate-blink {
- animation: blink 0.25s step-end infinite;
- }
-
- @keyframes blink {
- 0%, 100% {
- background-color: hsl(var(--primary));
- }
- 50% {
- background-color: transparent;
- }
- }
+.scl-win95-scroll::-webkit-scrollbar-thumb:hover {
+ background-color: #d6d6d6;
}
diff --git a/tailwind.config.ts b/tailwind.config.ts
deleted file mode 100644
index e1210de..0000000
--- a/tailwind.config.ts
+++ /dev/null
@@ -1,145 +0,0 @@
-import type { Config } from 'tailwindcss'
-import tailwindcssAnimate from 'tailwindcss-animate'
-
-export default {
- darkMode: ['class'],
- content: ['./src/**/*.{ts,tsx}', './.storybook/**/*.{ts,tsx}'],
- safelist: [
- 'bg-primary',
- 'bg-secondary',
- 'bg-destructive',
- 'bg-accent',
- 'bg-muted',
- 'bg-card',
- 'bg-popover',
- 'bg-background',
- 'text-primary',
- 'text-secondary',
- 'text-destructive',
- 'text-primary-foreground',
- 'text-secondary-foreground',
- 'text-destructive-foreground',
- 'text-muted-foreground',
- 'text-card-foreground',
- 'text-popover-foreground',
- 'border-primary',
- 'border-secondary',
- 'border-destructive',
- 'ring-primary',
- 'ring-secondary',
- 'animate-blink',
- ],
- theme: {
- extend: {
- fontFamily: {
- mono: ['BigBlueTerm437', 'monospace'],
- terminal: ['BigBlueTerm437', 'monospace'],
- },
- colors: {
- border: 'hsl(var(--border))',
- input: 'hsl(var(--input))',
- ring: 'hsl(var(--ring))',
- background: 'hsl(var(--background))',
- foreground: 'hsl(var(--foreground))',
- primary: {
- DEFAULT: 'hsl(var(--primary))',
- foreground: 'hsl(var(--primary-foreground))',
- },
- secondary: {
- DEFAULT: 'hsl(var(--secondary))',
- foreground: 'hsl(var(--secondary-foreground))',
- },
- destructive: {
- DEFAULT: 'hsl(var(--destructive))',
- foreground: 'hsl(var(--destructive-foreground))',
- },
- muted: {
- DEFAULT: 'hsl(var(--muted))',
- foreground: 'hsl(var(--muted-foreground))',
- },
- accent: {
- DEFAULT: 'hsl(var(--accent))',
- foreground: 'hsl(var(--accent-foreground))',
- },
- popover: {
- DEFAULT: 'hsl(var(--popover))',
- foreground: 'hsl(var(--popover-foreground))',
- },
- card: {
- DEFAULT: 'hsl(var(--card))',
- foreground: 'hsl(var(--card-foreground))',
- },
- chart: {
- '1': 'hsl(var(--chart-1))',
- '2': 'hsl(var(--chart-2))',
- '3': 'hsl(var(--chart-3))',
- '4': 'hsl(var(--chart-4))',
- '5': 'hsl(var(--chart-5))',
- },
- sidebar: {
- DEFAULT: 'hsl(var(--sidebar-background))',
- foreground: 'hsl(var(--sidebar-foreground))',
- primary: 'hsl(var(--sidebar-primary))',
- 'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
- accent: 'hsl(var(--sidebar-accent))',
- 'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
- border: 'hsl(var(--sidebar-border))',
- ring: 'hsl(var(--sidebar-ring))',
- },
- },
- borderRadius: {
- lg: '0',
- md: '0',
- sm: '0',
- DEFAULT: '0',
- none: '0',
- full: '0',
- },
- boxShadow: {
- sm: 'none',
- DEFAULT: 'none',
- md: 'none',
- lg: 'none',
- xl: 'none',
- '2xl': 'none',
- inner: 'none',
- none: 'none',
- },
- keyframes: {
- 'accordion-down': {
- from: { height: '0' },
- to: { height: 'var(--radix-accordion-content-height)' },
- },
- 'accordion-up': {
- from: { height: 'var(--radix-accordion-content-height)' },
- to: { height: '0' },
- },
- 'collapsible-down': {
- from: { height: '0' },
- to: { height: 'var(--radix-collapsible-content-height)' },
- },
- 'collapsible-up': {
- from: { height: 'var(--radix-collapsible-content-height)' },
- to: { height: '0' },
- },
- scanline: {
- '0%': { transform: 'translateY(-100%)' },
- '100%': { transform: 'translateY(100%)' },
- },
- blink: {
- '0%, 100%': { opacity: '1' },
- '50%': { opacity: '0' },
- },
- },
- animation: {
- 'accordion-down': 'accordion-down 0.2s ease-out',
- 'accordion-up': 'accordion-up 0.2s ease-out',
- 'collapsible-down': 'collapsible-down 0.2s ease-out',
- 'collapsible-up': 'collapsible-up 0.2s ease-out',
- scanline: 'scanline 1.5s ease-in-out infinite',
- blink: 'blink 0.5s step-end infinite',
- },
- },
- },
- plugins: [tailwindcssAnimate],
-} satisfies Config
diff --git a/vite.config.ts b/vite.config.ts
index f283cdc..12a31b6 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -22,11 +22,15 @@ export default defineConfig({
output: {
preserveModules: true,
preserveModulesRoot: 'src',
+ assetFileNames: 'globals[extname]',
},
},
copyPublicDir: false,
cssCodeSplit: false,
},
+ css: {
+ // No PostCSS/Tailwind needed - pure CSS
+ },
resolve: {
alias: {
'@': resolve(__dirname, './src'),