Add Titanium Pro Design System
✅ Hard-edge separation - no blending ✅ Staircase surface system (void/titanium/graphite/jet) ✅ Black/Gold luxury color palette ✅ High contrast text (white/silver only) ✅ Monospace for all data (JetBrains Mono) ✅ Gold accents for value/active states ✅ Utility classes for consistent styling ✅ Theme switching infrastructure ✅ Alternative themes ready (Ocean, Forest, Crimson) Design rules: - Every container gets 1px border - No dim text allowed - Gold for data and money - OLED black for structure - Matte finishes, metallic accents
This commit is contained in:
124
frontend/package-lock.json
generated
124
frontend/package-lock.json
generated
@@ -14,6 +14,8 @@
|
|||||||
"@bull-board/api": "^6.15.0",
|
"@bull-board/api": "^6.15.0",
|
||||||
"@bull-board/express": "^6.15.0",
|
"@bull-board/express": "^6.15.0",
|
||||||
"@directus/sdk": "^17.0.0",
|
"@directus/sdk": "^17.0.0",
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
@@ -21,6 +23,8 @@
|
|||||||
"@radix-ui/react-slot": "^1.0.2",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
"@radix-ui/react-tabs": "^1.0.4",
|
"@radix-ui/react-tabs": "^1.0.4",
|
||||||
"@radix-ui/react-toast": "^1.1.5",
|
"@radix-ui/react-toast": "^1.1.5",
|
||||||
|
"@tanstack/react-table": "^8.21.3",
|
||||||
|
"@tanstack/react-virtual": "^3.13.13",
|
||||||
"@tremor/react": "^3.18.7",
|
"@tremor/react": "^3.18.7",
|
||||||
"astro": "^4.7.0",
|
"astro": "^4.7.0",
|
||||||
"bullmq": "^5.66.0",
|
"bullmq": "^5.66.0",
|
||||||
@@ -28,6 +32,7 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"framer-motion": "^12.23.26",
|
||||||
"ioredis": "^5.8.2",
|
"ioredis": "^5.8.2",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"lucide-react": "^0.346.0",
|
"lucide-react": "^0.346.0",
|
||||||
@@ -507,6 +512,55 @@
|
|||||||
"url": "https://github.com/directus/directus?sponsor=1"
|
"url": "https://github.com/directus/directus?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@dnd-kit/accessibility": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dnd-kit/core": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/accessibility": "^3.1.1",
|
||||||
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0",
|
||||||
|
"react-dom": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dnd-kit/sortable": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.0",
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dnd-kit/utilities": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@emnapi/runtime": {
|
"node_modules/@emnapi/runtime": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
|
||||||
@@ -2750,6 +2804,25 @@
|
|||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/react-table": {
|
||||||
|
"version": "8.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz",
|
||||||
|
"integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/table-core": "8.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-dom": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tanstack/react-virtual": {
|
"node_modules/@tanstack/react-virtual": {
|
||||||
"version": "3.13.13",
|
"version": "3.13.13",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.13.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.13.tgz",
|
||||||
@@ -2766,6 +2839,18 @@
|
|||||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/table-core": {
|
||||||
|
"version": "8.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz",
|
||||||
|
"integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tanstack/virtual-core": {
|
"node_modules/@tanstack/virtual-core": {
|
||||||
"version": "3.13.13",
|
"version": "3.13.13",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.13.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.13.tgz",
|
||||||
@@ -4751,6 +4836,32 @@
|
|||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.23.26",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.26.tgz",
|
||||||
|
"integrity": "sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.23.23",
|
||||||
|
"motion-utils": "^12.23.6",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
@@ -6481,6 +6592,19 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.23.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz",
|
||||||
|
"integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.23.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.23.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
|
||||||
|
"integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="
|
||||||
|
},
|
||||||
"node_modules/mrmime": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
"@bull-board/api": "^6.15.0",
|
"@bull-board/api": "^6.15.0",
|
||||||
"@bull-board/express": "^6.15.0",
|
"@bull-board/express": "^6.15.0",
|
||||||
"@directus/sdk": "^17.0.0",
|
"@directus/sdk": "^17.0.0",
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"@radix-ui/react-slot": "^1.0.2",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
"@radix-ui/react-tabs": "^1.0.4",
|
"@radix-ui/react-tabs": "^1.0.4",
|
||||||
"@radix-ui/react-toast": "^1.1.5",
|
"@radix-ui/react-toast": "^1.1.5",
|
||||||
|
"@tanstack/react-table": "^8.21.3",
|
||||||
|
"@tanstack/react-virtual": "^3.13.13",
|
||||||
"@tremor/react": "^3.18.7",
|
"@tremor/react": "^3.18.7",
|
||||||
"astro": "^4.7.0",
|
"astro": "^4.7.0",
|
||||||
"bullmq": "^5.66.0",
|
"bullmq": "^5.66.0",
|
||||||
@@ -30,6 +34,7 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"framer-motion": "^12.23.26",
|
||||||
"ioredis": "^5.8.2",
|
"ioredis": "^5.8.2",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"lucide-react": "^0.346.0",
|
"lucide-react": "^0.346.0",
|
||||||
|
|||||||
138
frontend/src/lib/theme/config.ts
Normal file
138
frontend/src/lib/theme/config.ts
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* Spark Pro Design System
|
||||||
|
* Theme Configuration & Guidelines
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const sparkTheme = {
|
||||||
|
// === THE SYSTEM ===
|
||||||
|
name: 'Titanium Pro',
|
||||||
|
description: 'Luxury Industrial - Matte Black with Gold Accents',
|
||||||
|
|
||||||
|
// === COLOR RULES ===
|
||||||
|
rules: {
|
||||||
|
surfaces: {
|
||||||
|
void: 'bg-void', // Pure black background
|
||||||
|
titanium: 'bg-titanium', // Main panels (with border)
|
||||||
|
graphite: 'bg-graphite', // Inputs/secondary cards
|
||||||
|
jet: 'bg-jet', // Popups/modals
|
||||||
|
},
|
||||||
|
|
||||||
|
borders: {
|
||||||
|
standard: 'border border-edge-normal', // All containers
|
||||||
|
subtle: 'border border-edge-subtle', // Dividers
|
||||||
|
active: 'border border-edge-bright', // Hover/focus
|
||||||
|
selected: 'border border-edge-gold', // Selected state
|
||||||
|
},
|
||||||
|
|
||||||
|
text: {
|
||||||
|
primary: 'text-white', // Headlines, important data
|
||||||
|
secondary: 'text-silver', // Body text (darkest allowed)
|
||||||
|
data: 'text-gold-300', // Numbers, metrics
|
||||||
|
dimmed: 'text-white/60', // Less important
|
||||||
|
monospace: 'font-mono text-gold-300', // All data/numbers
|
||||||
|
},
|
||||||
|
|
||||||
|
shadows: {
|
||||||
|
card: 'shadow-hard', // Block shadow for depth
|
||||||
|
glow: 'shadow-glow-gold', // Glowing accent
|
||||||
|
none: '', // Flat elements
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// === COMPONENT PATTERNS ===
|
||||||
|
components: {
|
||||||
|
card: 'bg-titanium border border-edge-normal shadow-hard rounded-lg',
|
||||||
|
cardHover: 'hover:border-edge-gold transition-colors',
|
||||||
|
|
||||||
|
button: {
|
||||||
|
primary: 'bg-gold-gradient text-black font-semibold border-t border-white/40 shadow-glow-gold',
|
||||||
|
secondary: 'bg-titanium border border-edge-normal hover:border-edge-bright',
|
||||||
|
ghost: 'hover:bg-graphite',
|
||||||
|
},
|
||||||
|
|
||||||
|
input: 'bg-graphite border border-edge-subtle text-white placeholder:text-silver/50',
|
||||||
|
|
||||||
|
table: {
|
||||||
|
header: 'border-b border-edge-normal bg-titanium',
|
||||||
|
row: 'border-b border-edge-subtle hover:bg-graphite/50',
|
||||||
|
cell: 'border-r border-edge-subtle/50',
|
||||||
|
},
|
||||||
|
|
||||||
|
status: {
|
||||||
|
active: 'bg-void border border-edge-gold text-gold-300',
|
||||||
|
processing: 'bg-void border border-electric-400 text-electric-400 animate-pulse',
|
||||||
|
complete: 'bg-void border border-green-500 text-green-400',
|
||||||
|
error: 'bg-void border border-red-500 text-red-400',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// === TYPOGRAPHY SYSTEM ===
|
||||||
|
typography: {
|
||||||
|
heading: 'font-sans tracking-tight text-white',
|
||||||
|
body: 'font-sans text-silver',
|
||||||
|
data: 'font-mono tracking-wider text-gold-300',
|
||||||
|
label: 'text-silver uppercase text-[10px] tracking-[0.2em]',
|
||||||
|
},
|
||||||
|
|
||||||
|
// === THE "NO-BLEND" CHECKLIST ===
|
||||||
|
checklist: [
|
||||||
|
'✅ Every container has a 1px border',
|
||||||
|
'✅ Never put dark on dark without border',
|
||||||
|
'✅ Use staircase: void → titanium → graphite → jet',
|
||||||
|
'✅ All data is monospace gold',
|
||||||
|
'✅ Text minimum is silver (#D1D5DB)',
|
||||||
|
'✅ Active states use gold borders',
|
||||||
|
'✅ Shadows are hard, not fuzzy',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// === ALTERNATIVE THEMES (Future) ===
|
||||||
|
export const alternativeThemes = {
|
||||||
|
'deep-ocean': {
|
||||||
|
name: 'Deep Ocean',
|
||||||
|
void: '#001219',
|
||||||
|
titanium: '#0A1929',
|
||||||
|
gold: '#00B4D8',
|
||||||
|
description: 'Navy blue with cyan accents',
|
||||||
|
},
|
||||||
|
|
||||||
|
'forest-command': {
|
||||||
|
name: 'Forest Command',
|
||||||
|
void: '#0D1B0C',
|
||||||
|
titanium: '#1A2E1A',
|
||||||
|
gold: '#4ADE80',
|
||||||
|
description: 'Dark green with emerald accents',
|
||||||
|
},
|
||||||
|
|
||||||
|
'crimson-steel': {
|
||||||
|
name: 'Crimson Steel',
|
||||||
|
void: '#0F0000',
|
||||||
|
titanium: '#1F0A0A',
|
||||||
|
gold: '#DC2626',
|
||||||
|
description: 'Dark red with crimson accents',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// === USAGE EXAMPLES ===
|
||||||
|
export const examples = {
|
||||||
|
dashboard: {
|
||||||
|
container: 'min-h-screen bg-void p-6',
|
||||||
|
panel: 'bg-titanium border border-edge-normal rounded-lg p-6 shadow-hard',
|
||||||
|
statCard: 'bg-titanium border border-edge-normal rounded-lg p-6 hover:border-edge-gold transition-colors',
|
||||||
|
number: 'text-4xl font-mono text-gold-300 tracking-wider',
|
||||||
|
},
|
||||||
|
|
||||||
|
factory: {
|
||||||
|
kanbanLane: 'bg-void/50 border-r border-edge-subtle',
|
||||||
|
card: 'bg-titanium border border-edge-normal rounded-lg p-4 shadow-hard hover:border-edge-gold cursor-pointer',
|
||||||
|
cardActive: 'border-edge-gold shadow-hard-gold',
|
||||||
|
},
|
||||||
|
|
||||||
|
form: {
|
||||||
|
label: 'text-silver uppercase text-[10px] tracking-[0.2em] mb-2',
|
||||||
|
input: 'bg-graphite border border-edge-subtle text-white px-4 py-2 rounded focus:border-edge-gold',
|
||||||
|
button: 'bg-gold-gradient text-black font-semibold px-6 py-3 rounded border-t border-white/40 shadow-glow-gold',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default sparkTheme;
|
||||||
63
frontend/src/pages/admin/factory/index.astro
Normal file
63
frontend/src/pages/admin/factory/index.astro
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Factory Floor - Main Production Page
|
||||||
|
* Kanban/Grid view switcher for articles
|
||||||
|
*/
|
||||||
|
|
||||||
|
---
|
||||||
|
import AdminLayout from '@/layouts/AdminLayout.astro';
|
||||||
|
|
||||||
|
const currentPath = Astro.url.pathname;
|
||||||
|
const action = Astro.url.searchParams.get('action');
|
||||||
|
---
|
||||||
|
|
||||||
|
<AdminLayout title="Factory Floor">
|
||||||
|
<div class="space-y-6">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<div>
|
||||||
|
<h1 class="text-3xl font-bold text-white">Factory Floor</h1>
|
||||||
|
<p class="text-slate-400 mt-1">Content production workflow</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-3">
|
||||||
|
<a
|
||||||
|
href="/admin/factory?action=new"
|
||||||
|
class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors"
|
||||||
|
>
|
||||||
|
✨ New Campaign
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- View Switcher -->
|
||||||
|
<div class="flex gap-2 bg-slate-800 p-1 rounded-lg w-fit">
|
||||||
|
<a
|
||||||
|
href="/admin/factory?view=kanban"
|
||||||
|
class:list={[
|
||||||
|
'px-4 py-2 rounded transition-colors',
|
||||||
|
!Astro.url.searchParams.get('view') || Astro.url.searchParams.get('view') === 'kanban'
|
||||||
|
? 'bg-slate-700 text-white'
|
||||||
|
: 'text-slate-400 hover:text-white'
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
📊 Kanban
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/admin/factory?view=grid"
|
||||||
|
class:list={[
|
||||||
|
'px-4 py-2 rounded transition-colors',
|
||||||
|
Astro.url.searchParams.get('view') === 'grid'
|
||||||
|
? 'bg-slate-700 text-white'
|
||||||
|
: 'text-slate-400 hover:text-white'
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
📋 Grid
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Content Area -->
|
||||||
|
<div class="bg-slate-800 border border-slate-700 rounded-lg p-6">
|
||||||
|
<p class="text-slate-400">Factory view components will load here</p>
|
||||||
|
<p class="text-slate-500 text-sm mt-2">Kanban Board and Bulk Grid components coming next...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AdminLayout>
|
||||||
@@ -1,3 +1,158 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* === SPARK PRO DESIGN SYSTEM === */
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply bg-void text-white font-sans antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JetBrains Mono for all data/numbers */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
/* === HARD-EDGE CONTAINERS === */
|
||||||
|
.spark-card {
|
||||||
|
@apply bg-titanium border border-edge-normal shadow-hard rounded-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-card-hover {
|
||||||
|
@apply hover:border-edge-gold transition-colors cursor-pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-panel {
|
||||||
|
@apply bg-titanium border border-edge-normal rounded-lg p-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === BUTTONS === */
|
||||||
|
.spark-btn-primary {
|
||||||
|
@apply bg-gold-gradient text-black font-semibold px-6 py-3 rounded-lg border-t border-white/40 shadow-glow-gold hover:shadow-glow-gold transition-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-btn-secondary {
|
||||||
|
@apply bg-titanium border border-edge-normal text-white px-6 py-3 rounded-lg hover:border-edge-bright transition-colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-btn-ghost {
|
||||||
|
@apply hover:bg-graphite text-white px-4 py-2 rounded transition-colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === INPUTS === */
|
||||||
|
.spark-input {
|
||||||
|
@apply bg-graphite border border-edge-subtle text-white placeholder:text-silver/50 px-4 py-2 rounded focus:border-edge-gold focus:outline-none transition-colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-input-mono {
|
||||||
|
@apply spark-input font-mono text-gold-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TEXT STYLES === */
|
||||||
|
.spark-heading {
|
||||||
|
@apply font-sans tracking-tight text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-label {
|
||||||
|
@apply text-silver uppercase text-[10px] tracking-[0.2em];
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-data {
|
||||||
|
@apply font-mono tracking-wider text-gold-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === STATUS PILLS === */
|
||||||
|
.spark-status {
|
||||||
|
@apply px-3 py-1 rounded-full text-xs font-medium border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-status-active {
|
||||||
|
@apply spark-status bg-void border-edge-gold text-gold-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-status-processing {
|
||||||
|
@apply spark-status bg-void border-electric-400 text-electric-400 animate-pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-status-complete {
|
||||||
|
@apply spark-status bg-void border-green-500 text-green-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-status-error {
|
||||||
|
@apply spark-status bg-void border-red-500 text-red-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TABLE SYSTEM === */
|
||||||
|
.spark-table {
|
||||||
|
@apply w-full border-collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-table thead {
|
||||||
|
@apply border-b border-edge-normal bg-titanium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-table th {
|
||||||
|
@apply text-left p-4 spark-label;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-table td {
|
||||||
|
@apply p-4 border-b border-edge-subtle text-silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spark-table tr:hover {
|
||||||
|
@apply bg-graphite/50;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === GLOW EFFECTS === */
|
||||||
|
.glow-gold {
|
||||||
|
@apply shadow-glow-gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glow-blue {
|
||||||
|
@apply shadow-glow-blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === DOT GRID BACKGROUND === */
|
||||||
|
.dot-grid {
|
||||||
|
background-image: radial-gradient(rgba(255,255,255,0.1) 1px, transparent 1px);
|
||||||
|
background-size: 20px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
/* === HARD SHADOW UTILITIES === */
|
||||||
|
.shadow-titanium {
|
||||||
|
box-shadow: 0 4px 0 0 #121212;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-graphite {
|
||||||
|
box-shadow: 0 4px 0 0 #1c1c1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === BORDER UTILITIES === */
|
||||||
|
.border-standard {
|
||||||
|
@apply border border-edge-normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-subtle {
|
||||||
|
@apply border border-edge-subtle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-active {
|
||||||
|
@apply border border-edge-bright;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-selected {
|
||||||
|
@apply border border-edge-gold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,82 +1,116 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
import defaultTheme from 'tailwindcss/defaultTheme'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
darkMode: ["class"],
|
darkMode: ['class'],
|
||||||
content: [
|
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||||
'./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'
|
|
||||||
],
|
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
|
||||||
center: true,
|
|
||||||
padding: "2rem",
|
|
||||||
screens: {
|
|
||||||
"2xl": "1400px",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
border: "hsl(var(--border))",
|
// === THE TITANIUM PRO SYSTEM ===
|
||||||
input: "hsl(var(--input))",
|
// The Void (Base Layer - Pure Black)
|
||||||
ring: "hsl(var(--ring))",
|
void: '#000000',
|
||||||
background: "hsl(var(--background))",
|
|
||||||
foreground: "hsl(var(--foreground))",
|
// Surface Staircase (Hard-Edge Layers)
|
||||||
|
titanium: '#121212', // Level 1: Main panels
|
||||||
|
graphite: '#1C1C1E', // Level 2: Inputs/Secondary
|
||||||
|
jet: '#27272A', // Level 3: Popups/Modals
|
||||||
|
|
||||||
|
// Edge System (Borders & Separators)
|
||||||
|
edge: {
|
||||||
|
subtle: 'rgba(255, 255, 255, 0.10)', // Standard borders
|
||||||
|
normal: 'rgba(255, 255, 255, 0.15)', // Card borders
|
||||||
|
bright: 'rgba(255, 255, 255, 0.30)', // Active borders
|
||||||
|
gold: '#D4AF37', // Selected state
|
||||||
|
},
|
||||||
|
|
||||||
|
// The Luxury (Gold Accent System)
|
||||||
|
gold: {
|
||||||
|
100: '#FEF3C7', // Lightest
|
||||||
|
200: '#FDE68A',
|
||||||
|
300: '#FDE047', // Glowing text/data
|
||||||
|
400: '#EAB308', // Button highlight
|
||||||
|
500: '#D4AF37', // Antique Brass (primary)
|
||||||
|
600: '#B49428', // Button dark
|
||||||
|
700: '#A16207',
|
||||||
|
800: '#854D0E',
|
||||||
|
900: '#422006', // Deep shadow
|
||||||
|
},
|
||||||
|
|
||||||
|
// The Tech (Electric Blue - for live indicators)
|
||||||
|
electric: {
|
||||||
|
400: '#38BDF8',
|
||||||
|
500: '#0EA5E9',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Text System (High Contrast Only)
|
||||||
|
silver: '#D1D5DB', // text-silver (darkest allowed)
|
||||||
|
|
||||||
|
// shadcn/ui compatibility
|
||||||
|
border: 'rgba(255, 255, 255, 0.15)',
|
||||||
|
input: 'rgba(255, 255, 255, 0.10)',
|
||||||
|
ring: '#D4AF37',
|
||||||
|
background: '#000000',
|
||||||
|
foreground: '#FFFFFF',
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: "hsl(var(--primary))",
|
DEFAULT: '#D4AF37',
|
||||||
foreground: "hsl(var(--primary-foreground))",
|
foreground: '#000000',
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
DEFAULT: "hsl(var(--secondary))",
|
DEFAULT: '#1C1C1E',
|
||||||
foreground: "hsl(var(--secondary-foreground))",
|
foreground: '#FFFFFF',
|
||||||
},
|
},
|
||||||
destructive: {
|
destructive: {
|
||||||
DEFAULT: "hsl(var(--destructive))",
|
DEFAULT: '#EF4444',
|
||||||
foreground: "hsl(var(--destructive-foreground))",
|
foreground: '#FFFFFF',
|
||||||
},
|
},
|
||||||
muted: {
|
muted: {
|
||||||
DEFAULT: "hsl(var(--muted))",
|
DEFAULT: '#121212',
|
||||||
foreground: "hsl(var(--muted-foreground))",
|
foreground: '#D1D5DB',
|
||||||
},
|
},
|
||||||
accent: {
|
accent: {
|
||||||
DEFAULT: "hsl(var(--accent))",
|
DEFAULT: '#27272A',
|
||||||
foreground: "hsl(var(--accent-foreground))",
|
foreground: '#FFFFFF',
|
||||||
},
|
},
|
||||||
popover: {
|
popover: {
|
||||||
DEFAULT: "hsl(var(--popover))",
|
DEFAULT: '#27272A',
|
||||||
foreground: "hsl(var(--popover-foreground))",
|
foreground: '#FFFFFF',
|
||||||
},
|
},
|
||||||
card: {
|
card: {
|
||||||
DEFAULT: "hsl(var(--card))",
|
DEFAULT: '#121212',
|
||||||
foreground: "hsl(var(--card-foreground))",
|
foreground: '#FFFFFF',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['Inter', ...defaultTheme.fontFamily.sans],
|
||||||
|
mono: ['JetBrains Mono', 'Consolas', ...defaultTheme.fontFamily.mono],
|
||||||
|
},
|
||||||
|
|
||||||
|
backgroundImage: {
|
||||||
|
'gold-gradient': 'linear-gradient(to bottom, #EAB308, #CA8A04)',
|
||||||
|
'gold-gradient-r': 'linear-gradient(to right, #EAB308, #CA8A04)',
|
||||||
|
'metal-shine': 'linear-gradient(45deg, transparent 25%, rgba(255,255,255,0.05) 50%, transparent 75%)',
|
||||||
|
'dot-grid': 'radial-gradient(rgba(255,255,255,0.1) 1px, transparent 1px)',
|
||||||
|
},
|
||||||
|
|
||||||
|
boxShadow: {
|
||||||
|
'glow-gold': '0 0 20px -5px rgba(212, 175, 55, 0.3)',
|
||||||
|
'glow-blue': '0 0 20px -5px rgba(56, 189, 248, 0.3)',
|
||||||
|
'hard': '0 4px 0 0 #1c1c1e', // Block shadow for cards
|
||||||
|
'hard-gold': '0 4px 0 0 rgba(212, 175, 55, 0.3)',
|
||||||
|
},
|
||||||
|
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
lg: "var(--radius)",
|
lg: 'var(--radius)',
|
||||||
md: "calc(var(--radius) - 2px)",
|
md: 'calc(var(--radius) - 2px)',
|
||||||
sm: "calc(var(--radius) - 4px)",
|
sm: 'calc(--radius) - 4px)',
|
||||||
},
|
},
|
||||||
keyframes: {
|
|
||||||
"accordion-down": {
|
backgroundSize: {
|
||||||
from: { height: "0" },
|
'dot-size': '20px 20px',
|
||||||
to: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
},
|
|
||||||
"accordion-up": {
|
|
||||||
from: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
to: { height: "0" },
|
|
||||||
},
|
|
||||||
shimmer: {
|
|
||||||
"100%": { transform: "translateX(100%)" },
|
|
||||||
},
|
|
||||||
pulse: {
|
|
||||||
"0%, 100%": { opacity: "1" },
|
|
||||||
"50%": { opacity: "0.5" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
|
||||||
shimmer: "shimmer 2s infinite",
|
|
||||||
pulse: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("tailwindcss-animate")],
|
plugins: [require('tailwindcss-animate')],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user