diff --git a/frontend/css/base/theme.css b/frontend/css/base/theme.css new file mode 100644 index 0000000..0c0c58a --- /dev/null +++ b/frontend/css/base/theme.css @@ -0,0 +1,62 @@ +/* Production - The Idle Game: Enterprise Design System & Layout */ + +:root { + --bg-app: #f8fafc; + --bg-surface: #ffffff; + --bg-surface-sub: #f1f5f9; + --bg-header: rgba(255, 255, 255, 0.95); + + --border-color: #e2e8f0; + --border-subtle: #cbd5e1; + --border-focus: #3b82f6; + + --text-primary: #0f172a; + --text-secondary: #475569; + --text-muted: #94a3b8; + + --primary-blue: #2563eb; + --primary-blue-hover: #1d4ed8; + --primary-blue-light: #eff6ff; + + --emerald-profit: #10b981; + --emerald-dark: #059669; + --emerald-light: #ecfdf5; + + --amber-warning: #f59e0b; + --amber-dark: #d97706; + --amber-light: #fffbeb; + + --purple-rnd: #7c3aed; + --purple-light: #f5f3ff; + + --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --font-mono: 'JetBrains Mono', monospace; + + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -1px rgba(0, 0, 0, 0.04); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.03); + + --radius-sm: 6px; + --radius-md: 10px; + --radius-lg: 14px; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; + -webkit-tap-highlight-color: transparent; +} + +body { + background-color: var(--bg-app); + color: var(--text-primary); + font-family: var(--font-sans); + min-height: 100vh; + overflow-x: hidden; +} + +.font-mono { + font-family: var(--font-mono); +} + diff --git a/frontend/css/layout/header.css b/frontend/css/layout/header.css new file mode 100644 index 0000000..a8a6e2d --- /dev/null +++ b/frontend/css/layout/header.css @@ -0,0 +1,193 @@ +/* ========================================================================== + EXECUTIVE STICKY HEADER & FINANCIAL HUD + ========================================================================== */ + +#executive-header { + position: sticky; + top: 0; + z-index: 100; + background: var(--bg-header); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-bottom: 1px solid var(--border-color); + box-shadow: var(--shadow-sm); +} + +#corporate-status-bar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 16px; + border-bottom: 1px solid var(--border-color); +} + +.corporate-brand { + display: flex; + align-items: center; + gap: 10px; +} + +.brand-logo-icon { + width: 32px; + height: 32px; + background: var(--primary-blue-light); + color: var(--primary-blue); + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.3rem; +} + +.brand-title { + font-size: 1rem; + font-weight: 800; + letter-spacing: -0.02em; + color: var(--text-primary); +} + +.brand-subtitle { + font-size: 0.72rem; + font-weight: 600; + color: var(--primary-blue); + margin-left: 6px; + background: var(--primary-blue-light); + padding: 2px 6px; + border-radius: 4px; +} + +.status-right { + display: flex; + align-items: center; + gap: 8px; +} + +.btn-icon-soft { + display: inline-flex; + align-items: center; + gap: 4px; + background: var(--bg-surface-sub); + border: 1px solid var(--border-color); + color: var(--text-secondary); + padding: 4px 8px; + border-radius: var(--radius-sm); + font-size: 0.75rem; + font-weight: 600; + cursor: pointer; + transition: background 0.2s; +} + +.btn-icon-soft:hover { + background: var(--border-color); + color: var(--text-primary); +} + +.btn-user-badge { + background: none; + border: 1px solid var(--border-color); + color: var(--primary-blue); + padding: 4px 8px; + border-radius: var(--radius-sm); + font-size: 0.75rem; + font-weight: 700; + cursor: pointer; + font-family: var(--font-mono); +} + +.btn-user-badge:hover { + background: var(--primary-blue-light); +} + +/* Financial HUD Grid */ +#financial-hud { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 12px; + padding: 10px 16px; + align-items: center; +} + +.hud-stat-box { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 8px 12px; + display: flex; + flex-direction: column; +} + +.primary-hud-box { + border-color: #bfdbfe; + background: #f8faff; +} + +.hud-label { + font-size: 0.72rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.hud-main-val { + font-size: 1.25rem; + font-weight: 700; + color: var(--text-primary); + line-height: 1.2; + margin: 2px 0; +} + +.hud-sub-val { + font-size: 0.75rem; + font-weight: 600; +} + +.rate-positive { + color: var(--emerald-dark); +} + +.text-equity { + color: var(--purple-rnd); +} + +.hud-multiplier-box { + display: flex; + align-items: center; + gap: 8px; + justify-content: flex-end; +} + +.multi-label { + font-size: 0.72rem; + font-weight: 700; + color: var(--text-secondary); +} + +.multi-button-group { + display: flex; + background: var(--bg-surface-sub); + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + padding: 2px; + gap: 2px; +} + +.btn-multi-pill { + background: transparent; + border: none; + padding: 4px 10px; + border-radius: 4px; + font-size: 0.75rem; + font-weight: 700; + color: var(--text-secondary); + cursor: pointer; + font-family: var(--font-mono); + transition: all 0.15s; +} + +.btn-multi-pill.active { + background: var(--primary-blue); + color: #ffffff; + box-shadow: var(--shadow-sm); +} + diff --git a/frontend/css/layout/responsive.css b/frontend/css/layout/responsive.css new file mode 100644 index 0000000..bcfb39b --- /dev/null +++ b/frontend/css/layout/responsive.css @@ -0,0 +1,234 @@ +/* ========================================================================== + MOBILE BOTTOM NAVIGATION & RESPONSIVE RULES + ========================================================================== */ + +#mobile-bottom-nav { + display: none; + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 60px; + background: var(--bg-header); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-top: 1px solid var(--border-color); + box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.04); + z-index: 100; + justify-content: space-around; + align-items: center; +} + +.nav-tab { + display: flex; + flex-direction: column; + align-items: center; + gap: 3px; + background: transparent; + border: none; + color: var(--text-secondary); + font-size: 0.7rem; + font-weight: 600; + cursor: pointer; + flex: 1; + padding: 8px 0; +} + +.nav-tab iconify-icon { + font-size: 1.3rem; +} + +.nav-tab.active { + color: var(--primary-blue); + font-weight: 700; +} + +/* Responsive Breakpoints */ +@media (max-width: 1023px) { + #desktop-nav-sidebar { + display: none; + } + + #desktop-inspector-panel { + display: none; + } + + #mobile-bottom-nav { + display: flex; + } + + #workspace-layout { + padding-bottom: 80px; + } + + .production-grid, .contracts-grid, .perks-grid, .achievements-grid { + grid-template-columns: 1fr; + } +} + +/* ========================================================================== + TOASTS & MODALS + ========================================================================== */ + +#toast-container { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 1000; + display: flex; + flex-direction: column; + gap: 8px; + pointer-events: none; +} + +@media (max-width: 1023px) { + #toast-container { + bottom: 74px; + left: 20px; + right: 20px; + } +} + +.toast-msg { + background: #1e293b; + color: #ffffff; + padding: 10px 16px; + border-radius: var(--radius-md); + box-shadow: var(--shadow-lg); + display: flex; + align-items: center; + gap: 10px; + font-size: 0.82rem; + font-weight: 600; + animation: slideInToast 0.25s ease-out; +} + +.toast-msg.toast-success { + border-left: 4px solid var(--emerald-profit); +} + +.toast-msg.toast-warning { + border-left: 4px solid var(--amber-dark); +} + +.toast-msg.toast-info { + border-left: 4px solid var(--primary-blue); +} + +.toast-msg.fade-out { + opacity: 0; + transform: translateY(10px); + transition: all 0.3s; +} + +@keyframes slideInToast { + from { + opacity: 0; + transform: translateY(15px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(15, 23, 42, 0.6); + backdrop-filter: blur(4px); + z-index: 200; + display: none; + align-items: center; + justify-content: center; + padding: 16px; +} + +.modal-overlay.open { + display: flex; +} + +.modal-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 24px; + max-width: 420px; + width: 100%; + box-shadow: var(--shadow-lg); + display: flex; + flex-direction: column; + gap: 16px; +} + +.modal-header { + display: flex; + align-items: center; + gap: 12px; +} + +.modal-icon { + font-size: 2rem; + color: var(--primary-blue); +} + +.modal-title { + font-size: 1.15rem; + font-weight: 800; +} + +.modal-subtitle { + font-size: 0.78rem; + color: var(--text-secondary); +} + +.input-field-group { + display: flex; + flex-direction: column; + gap: 4px; +} + +.input-field-group label { + font-size: 0.75rem; + font-weight: 700; + color: var(--text-secondary); +} + +.modal-input { + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + padding: 8px 12px; + font-size: 0.88rem; + font-family: var(--font-sans); + outline: none; +} + +.modal-input:focus { + border-color: var(--primary-blue); +} + +.modal-actions-row { + display: flex; + gap: 8px; +} + +.modal-actions-row button { + flex: 1; + padding: 10px; +} + +.btn-text-close { + background: none; + border: none; + font-size: 0.78rem; + color: var(--text-muted); + cursor: pointer; + text-align: center; +} + +.btn-text-close:hover { + color: var(--text-primary); +} diff --git a/frontend/css/layout/workspace.css b/frontend/css/layout/workspace.css new file mode 100644 index 0000000..bad2788 --- /dev/null +++ b/frontend/css/layout/workspace.css @@ -0,0 +1,318 @@ +/* ========================================================================== + WORKSPACE 3-COLUMN LAYOUT (DESKTOP) + ========================================================================== */ + +#workspace-layout { + display: flex; + width: 100%; + max-width: 1680px; + margin: 0 auto; + padding: 16px; + gap: 16px; + min-height: calc(100vh - 120px); +} + +/* Left Sidebar */ +#desktop-nav-sidebar { + width: 230px; + flex-shrink: 0; + display: flex; + flex-direction: column; + gap: 12px; +} + +.sidebar-section-title { + font-size: 0.72rem; + font-weight: 700; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.05em; + padding: 0 4px; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 4px; +} + +.nav-btn { + display: flex; + align-items: center; + gap: 10px; + padding: 9px 12px; + background: transparent; + border: 1px solid transparent; + border-radius: var(--radius-md); + color: var(--text-secondary); + font-size: 0.88rem; + font-weight: 600; + cursor: pointer; + text-align: left; + transition: all 0.15s; +} + +.nav-btn iconify-icon { + font-size: 1.2rem; +} + +.nav-btn:hover { + background: var(--bg-surface); + color: var(--text-primary); + border-color: var(--border-color); +} + +.nav-btn.active { + background: var(--primary-blue-light); + color: var(--primary-blue); + border-color: #bfdbfe; + font-weight: 700; +} + +.nav-pill-badge { + margin-left: auto; + background: var(--amber-dark); + color: #ffffff; + font-size: 0.7rem; + font-weight: 700; + padding: 2px 6px; + border-radius: 10px; +} + +.sidebar-divider { + height: 1px; + background: var(--border-color); + margin: 4px 0; +} + +.sidebar-sectors-list { + display: flex; + flex-direction: column; + gap: 4px; +} + +.sidebar-sector-btn { + display: flex; + justify-content: space-between; + align-items: center; + padding: 7px 10px; + background: transparent; + border: 1px solid transparent; + border-radius: var(--radius-sm); + cursor: pointer; + text-align: left; + transition: all 0.15s; + width: 100%; +} + +.sidebar-sector-btn:hover { + background: var(--bg-surface); + border-color: var(--border-color); +} + +.sidebar-sector-left { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.78rem; + font-weight: 600; + color: var(--text-primary); +} + +.sidebar-sector-left iconify-icon { + font-size: 1.1rem; +} + +.sidebar-sector-rate { + font-size: 0.72rem; + font-weight: 700; + color: var(--emerald-dark); +} + +.sector-pill-rate { + font-size: 0.72rem; + font-weight: 700; + color: var(--emerald-dark); + margin-left: 2px; + letter-spacing: -0.02em; + white-space: nowrap; +} + +/* Sector Output Summary Banner */ +.sector-summary-banner { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px 20px; + display: flex; + flex-direction: column; + gap: 14px; + box-shadow: var(--shadow-sm); +} + +.sector-summary-main { + display: flex; + gap: 14px; + align-items: center; +} + +.sector-summary-icon { + width: 48px; + height: 48px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.sector-summary-badge { + font-size: 0.7rem; + font-weight: 800; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 2px; +} + +.sector-summary-title { + font-size: 1.25rem; + font-weight: 800; + color: var(--text-primary); +} + +.sector-summary-desc { + font-size: 0.8rem; + color: var(--text-secondary); + margin-top: 2px; +} + +.sector-metrics-strip { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + gap: 10px; + background: var(--bg-surface-sub); + border-radius: var(--radius-md); + padding: 10px 14px; +} + +.sector-metric-cell { + display: flex; + flex-direction: column; +} + +.sec-metric-label { + font-size: 0.68rem; + font-weight: 600; + color: var(--text-muted); +} + +.sec-metric-val { + font-size: 0.95rem; + color: var(--text-primary); + margin-top: 2px; +} + +.text-profit { + color: var(--emerald-dark); +} + +/* All Sectors Overview Grid */ +.all-sectors-summary-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 12px; +} + +.sector-mini-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 12px; + display: flex; + flex-direction: column; + gap: 8px; + box-shadow: var(--shadow-sm); + cursor: pointer; + transition: all 0.15s; +} + +.sector-mini-card:hover { + box-shadow: var(--shadow-md); + border-color: #cbd5e1; + transform: translateY(-1px); +} + +.mini-card-header { + display: flex; + align-items: center; + gap: 10px; +} + +.mini-card-icon { + width: 32px; + height: 32px; + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.1rem; + flex-shrink: 0; +} + +.mini-card-title-wrap { + flex: 1; + min-width: 0; +} + +.mini-card-name { + font-size: 0.85rem; + font-weight: 700; + color: var(--text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.mini-card-sub { + font-size: 0.7rem; + color: var(--text-muted); +} + +.mini-card-stats { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + background: var(--bg-surface-sub); + padding: 6px 8px; + border-radius: var(--radius-sm); +} + +.mini-stat-cell { + display: flex; + flex-direction: column; +} + +.mini-stat-label { + font-size: 0.65rem; + color: var(--text-muted); +} + +.mini-stat-cell strong { + font-size: 0.78rem; +} + +/* Center Main Viewport */ +#main-viewport { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 16px; +} + +/* Right Inspector Panel (Desktop) */ +#desktop-inspector-panel { + width: 340px; + flex-shrink: 0; +} + diff --git a/frontend/css/style.css b/frontend/css/style.css index e9ce1d9..5dc5ddd 100644 --- a/frontend/css/style.css +++ b/frontend/css/style.css @@ -1,1899 +1,12 @@ -/* Production - The Idle Game: Enterprise Design System & Layout */ - -:root { - --bg-app: #f8fafc; - --bg-surface: #ffffff; - --bg-surface-sub: #f1f5f9; - --bg-header: rgba(255, 255, 255, 0.95); - - --border-color: #e2e8f0; - --border-subtle: #cbd5e1; - --border-focus: #3b82f6; - - --text-primary: #0f172a; - --text-secondary: #475569; - --text-muted: #94a3b8; - - --primary-blue: #2563eb; - --primary-blue-hover: #1d4ed8; - --primary-blue-light: #eff6ff; - - --emerald-profit: #10b981; - --emerald-dark: #059669; - --emerald-light: #ecfdf5; - - --amber-warning: #f59e0b; - --amber-dark: #d97706; - --amber-light: #fffbeb; - - --purple-rnd: #7c3aed; - --purple-light: #f5f3ff; - - --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - --font-mono: 'JetBrains Mono', monospace; - - --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); - --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -1px rgba(0, 0, 0, 0.04); - --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.03); - - --radius-sm: 6px; - --radius-md: 10px; - --radius-lg: 14px; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; - -webkit-tap-highlight-color: transparent; -} - -body { - background-color: var(--bg-app); - color: var(--text-primary); - font-family: var(--font-sans); - min-height: 100vh; - overflow-x: hidden; -} - -.font-mono { - font-family: var(--font-mono); -} - -/* ========================================================================== - EXECUTIVE STICKY HEADER & FINANCIAL HUD - ========================================================================== */ - -#executive-header { - position: sticky; - top: 0; - z-index: 100; - background: var(--bg-header); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-bottom: 1px solid var(--border-color); - box-shadow: var(--shadow-sm); -} - -#corporate-status-bar { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 16px; - border-bottom: 1px solid var(--border-color); -} - -.corporate-brand { - display: flex; - align-items: center; - gap: 10px; -} - -.brand-logo-icon { - width: 32px; - height: 32px; - background: var(--primary-blue-light); - color: var(--primary-blue); - border-radius: var(--radius-sm); - display: flex; - align-items: center; - justify-content: center; - font-size: 1.3rem; -} - -.brand-title { - font-size: 1rem; - font-weight: 800; - letter-spacing: -0.02em; - color: var(--text-primary); -} - -.brand-subtitle { - font-size: 0.72rem; - font-weight: 600; - color: var(--primary-blue); - margin-left: 6px; - background: var(--primary-blue-light); - padding: 2px 6px; - border-radius: 4px; -} - -.status-right { - display: flex; - align-items: center; - gap: 8px; -} - -.btn-icon-soft { - display: inline-flex; - align-items: center; - gap: 4px; - background: var(--bg-surface-sub); - border: 1px solid var(--border-color); - color: var(--text-secondary); - padding: 4px 8px; - border-radius: var(--radius-sm); - font-size: 0.75rem; - font-weight: 600; - cursor: pointer; - transition: background 0.2s; -} - -.btn-icon-soft:hover { - background: var(--border-color); - color: var(--text-primary); -} - -.btn-user-badge { - background: none; - border: 1px solid var(--border-color); - color: var(--primary-blue); - padding: 4px 8px; - border-radius: var(--radius-sm); - font-size: 0.75rem; - font-weight: 700; - cursor: pointer; - font-family: var(--font-mono); -} - -.btn-user-badge:hover { - background: var(--primary-blue-light); -} - -/* Financial HUD Grid */ -#financial-hud { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); - gap: 12px; - padding: 10px 16px; - align-items: center; -} - -.hud-stat-box { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - padding: 8px 12px; - display: flex; - flex-direction: column; -} - -.primary-hud-box { - border-color: #bfdbfe; - background: #f8faff; -} - -.hud-label { - font-size: 0.72rem; - font-weight: 600; - color: var(--text-secondary); - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.hud-main-val { - font-size: 1.25rem; - font-weight: 700; - color: var(--text-primary); - line-height: 1.2; - margin: 2px 0; -} - -.hud-sub-val { - font-size: 0.75rem; - font-weight: 600; -} - -.rate-positive { - color: var(--emerald-dark); -} - -.text-equity { - color: var(--purple-rnd); -} - -.hud-multiplier-box { - display: flex; - align-items: center; - gap: 8px; - justify-content: flex-end; -} - -.multi-label { - font-size: 0.72rem; - font-weight: 700; - color: var(--text-secondary); -} - -.multi-button-group { - display: flex; - background: var(--bg-surface-sub); - border: 1px solid var(--border-color); - border-radius: var(--radius-sm); - padding: 2px; - gap: 2px; -} - -.btn-multi-pill { - background: transparent; - border: none; - padding: 4px 10px; - border-radius: 4px; - font-size: 0.75rem; - font-weight: 700; - color: var(--text-secondary); - cursor: pointer; - font-family: var(--font-mono); - transition: all 0.15s; -} - -.btn-multi-pill.active { - background: var(--primary-blue); - color: #ffffff; - box-shadow: var(--shadow-sm); -} - -/* ========================================================================== - WORKSPACE 3-COLUMN LAYOUT (DESKTOP) - ========================================================================== */ - -#workspace-layout { - display: flex; - width: 100%; - max-width: 1680px; - margin: 0 auto; - padding: 16px; - gap: 16px; - min-height: calc(100vh - 120px); -} - -/* Left Sidebar */ -#desktop-nav-sidebar { - width: 230px; - flex-shrink: 0; - display: flex; - flex-direction: column; - gap: 12px; -} - -.sidebar-section-title { - font-size: 0.72rem; - font-weight: 700; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.05em; - padding: 0 4px; -} - -.sidebar-nav { - display: flex; - flex-direction: column; - gap: 4px; -} - -.nav-btn { - display: flex; - align-items: center; - gap: 10px; - padding: 9px 12px; - background: transparent; - border: 1px solid transparent; - border-radius: var(--radius-md); - color: var(--text-secondary); - font-size: 0.88rem; - font-weight: 600; - cursor: pointer; - text-align: left; - transition: all 0.15s; -} - -.nav-btn iconify-icon { - font-size: 1.2rem; -} - -.nav-btn:hover { - background: var(--bg-surface); - color: var(--text-primary); - border-color: var(--border-color); -} - -.nav-btn.active { - background: var(--primary-blue-light); - color: var(--primary-blue); - border-color: #bfdbfe; - font-weight: 700; -} - -.nav-pill-badge { - margin-left: auto; - background: var(--amber-dark); - color: #ffffff; - font-size: 0.7rem; - font-weight: 700; - padding: 2px 6px; - border-radius: 10px; -} - -.sidebar-divider { - height: 1px; - background: var(--border-color); - margin: 4px 0; -} - -.sidebar-sectors-list { - display: flex; - flex-direction: column; - gap: 4px; -} - -.sidebar-sector-btn { - display: flex; - justify-content: space-between; - align-items: center; - padding: 7px 10px; - background: transparent; - border: 1px solid transparent; - border-radius: var(--radius-sm); - cursor: pointer; - text-align: left; - transition: all 0.15s; - width: 100%; -} - -.sidebar-sector-btn:hover { - background: var(--bg-surface); - border-color: var(--border-color); -} - -.sidebar-sector-left { - display: flex; - align-items: center; - gap: 8px; - font-size: 0.78rem; - font-weight: 600; - color: var(--text-primary); -} - -.sidebar-sector-left iconify-icon { - font-size: 1.1rem; -} - -.sidebar-sector-rate { - font-size: 0.72rem; - font-weight: 700; - color: var(--emerald-dark); -} - -.sector-pill-rate { - font-size: 0.72rem; - font-weight: 700; - color: var(--emerald-dark); - margin-left: 2px; - letter-spacing: -0.02em; - white-space: nowrap; -} - -/* Sector Output Summary Banner */ -.sector-summary-banner { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px 20px; - display: flex; - flex-direction: column; - gap: 14px; - box-shadow: var(--shadow-sm); -} - -.sector-summary-main { - display: flex; - gap: 14px; - align-items: center; -} - -.sector-summary-icon { - width: 48px; - height: 48px; - border-radius: var(--radius-md); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.sector-summary-badge { - font-size: 0.7rem; - font-weight: 800; - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 2px; -} - -.sector-summary-title { - font-size: 1.25rem; - font-weight: 800; - color: var(--text-primary); -} - -.sector-summary-desc { - font-size: 0.8rem; - color: var(--text-secondary); - margin-top: 2px; -} - -.sector-metrics-strip { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); - gap: 10px; - background: var(--bg-surface-sub); - border-radius: var(--radius-md); - padding: 10px 14px; -} - -.sector-metric-cell { - display: flex; - flex-direction: column; -} - -.sec-metric-label { - font-size: 0.68rem; - font-weight: 600; - color: var(--text-muted); -} - -.sec-metric-val { - font-size: 0.95rem; - color: var(--text-primary); - margin-top: 2px; -} - -.text-profit { - color: var(--emerald-dark); -} - -/* All Sectors Overview Grid */ -.all-sectors-summary-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: 12px; -} - -.sector-mini-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - padding: 12px; - display: flex; - flex-direction: column; - gap: 8px; - box-shadow: var(--shadow-sm); - cursor: pointer; - transition: all 0.15s; -} - -.sector-mini-card:hover { - box-shadow: var(--shadow-md); - border-color: #cbd5e1; - transform: translateY(-1px); -} - -.mini-card-header { - display: flex; - align-items: center; - gap: 10px; -} - -.mini-card-icon { - width: 32px; - height: 32px; - border-radius: var(--radius-sm); - display: flex; - align-items: center; - justify-content: center; - font-size: 1.1rem; - flex-shrink: 0; -} - -.mini-card-title-wrap { - flex: 1; - min-width: 0; -} - -.mini-card-name { - font-size: 0.85rem; - font-weight: 700; - color: var(--text-primary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.mini-card-sub { - font-size: 0.7rem; - color: var(--text-muted); -} - -.mini-card-stats { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 6px; - background: var(--bg-surface-sub); - padding: 6px 8px; - border-radius: var(--radius-sm); -} - -.mini-stat-cell { - display: flex; - flex-direction: column; -} - -.mini-stat-label { - font-size: 0.65rem; - color: var(--text-muted); -} - -.mini-stat-cell strong { - font-size: 0.78rem; -} - -/* Center Main Viewport */ -#main-viewport { - flex: 1; - min-width: 0; - display: flex; - flex-direction: column; - gap: 16px; -} - -/* Right Inspector Panel (Desktop) */ -#desktop-inspector-panel { - width: 340px; - flex-shrink: 0; -} - -/* ========================================================================== - PRODUCTION FLOOR & FACILITY CARDS - ========================================================================== */ - -.production-toolbar { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - padding: 6px 8px; -} - -.sector-tabs-scroll { - display: flex; - gap: 6px; - width: 100%; -} - -.sector-pill { - flex: 1 1 0; - min-width: 0; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; - background: var(--bg-surface-sub); - border: 1px solid var(--border-color); - padding: 8px 6px; - border-radius: var(--radius-sm); - cursor: pointer; - white-space: nowrap; - transition: all 0.15s; - box-sizing: border-box; -} - -.sector-pill iconify-icon { - font-size: 1.15rem; - flex-shrink: 0; -} - -.sector-pill:hover { - border-color: var(--text-muted); -} - -.sector-pill.active { - background: var(--text-primary); - color: #ffffff; - border-color: var(--text-primary); -} - -.sector-pill.active iconify-icon { - color: #ffffff !important; -} - -.sector-pill.active .sector-pill-rate { - color: #a7f3d0; -} - -.production-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); - gap: 16px; -} - -.facility-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px; - box-shadow: var(--shadow-sm); - display: flex; - flex-direction: column; - justify-content: space-between; - min-height: 420px; - gap: 12px; - cursor: pointer; - transition: border-color 0.2s, box-shadow 0.2s; - position: relative; - box-sizing: border-box; -} - -.facility-card:hover { - border-color: #cbd5e1; - box-shadow: var(--shadow-md); -} - -.facility-card.selected { - border-color: var(--primary-blue); - box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.15); -} - -.facility-card.locked-card { - opacity: 0.85; - background: #fbfcfe; -} - -.facility-header { - display: flex; - gap: 12px; - align-items: flex-start; - min-height: 60px; - box-sizing: border-box; -} - -.facility-icon-wrap { - width: 44px; - height: 44px; - border-radius: var(--radius-md); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.icon-lg { - font-size: 1.6rem; -} - -.facility-title-wrap { - flex: 1; - min-width: 0; - overflow: hidden; -} - -.facility-meta-row { - display: flex; - justify-content: space-between; - align-items: center; - gap: 8px; - min-height: 22px; - height: 22px; - flex-wrap: nowrap; - margin-bottom: 2px; - box-sizing: border-box; -} - -.sector-badge { - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.03em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex: 1; - min-width: 0; -} - -.facility-name { - font-size: 1rem; - font-weight: 700; - color: var(--text-primary); - line-height: 1.2; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.facility-type-sub { - font-size: 0.75rem; - color: var(--text-secondary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.facility-desc { - font-size: 0.8rem; - color: var(--text-secondary); - line-height: 1.4; -} - -/* Status Badges */ -.status-badge { - display: inline-flex; - align-items: center; - gap: 4px; - font-size: 0.7rem; - font-weight: 700; - padding: 2px 8px; - border-radius: 12px; - white-space: nowrap; - flex-shrink: 0; - height: 20px; - line-height: 1; - box-sizing: border-box; -} - -.badge-success { - background: var(--emerald-light); - color: var(--emerald-dark); -} - -.badge-warning { - background: var(--amber-light); - color: var(--amber-dark); - animation: pulseWarning 1.5s infinite; -} - -@keyframes pulseWarning { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.75; } -} - -.badge-idle { - background: var(--bg-surface-sub); - color: var(--text-muted); -} - -/* Cycle Progress Track */ -.cycle-bar-track { - width: 100%; - height: 6px; - background: var(--bg-surface-sub); - border-radius: 3px; - overflow: hidden; -} - -.cycle-bar-fill { - height: 100%; - transition: width 0.1s linear; -} - -/* Facility Stats Grid */ -.facility-stats-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 8px; - background: var(--bg-surface-sub); - border-radius: var(--radius-sm); - padding: 8px 10px; - min-height: 84px; - box-sizing: border-box; -} - -.stat-cell { - display: flex; - flex-direction: column; - min-width: 0; -} - -.stat-label { - font-size: 0.65rem; - font-weight: 600; - color: var(--text-muted); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.stat-value { - font-size: 0.78rem; - color: var(--text-primary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.text-warning { - color: var(--amber-dark); -} - -/* Inputs Strip */ -.inputs-strip { - display: flex; - flex-direction: column; - gap: 4px; - padding: 6px 8px; - background: #f8fafc; - border: 1px dashed var(--border-color); - border-radius: var(--radius-sm); -} - -.inputs-label { - font-size: 0.68rem; - font-weight: 700; - color: var(--text-secondary); -} - -.inputs-chips { - display: flex; - flex-wrap: wrap; - gap: 6px; -} - -.input-chip { - display: inline-flex; - align-items: center; - gap: 4px; - font-size: 0.72rem; - background: var(--bg-surface); - border: 1px solid var(--border-color); - padding: 2px 6px; - border-radius: 4px; - color: var(--text-secondary); -} - -.input-chip.low-stock { - border-color: var(--amber-dark); - background: var(--amber-light); - color: var(--amber-dark); -} - -/* Action Buttons */ -.facility-actions-row { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-top: auto; -} - -.btn-primary-corp { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; - background: var(--primary-blue); - color: #ffffff; - border: none; - border-radius: var(--radius-sm); - padding: 8px 12px; - font-size: 0.78rem; - font-weight: 700; - cursor: pointer; - white-space: nowrap; - transition: background 0.15s, opacity 0.15s; -} - -.btn-primary-corp:hover:not(:disabled) { - background: var(--primary-blue-hover); -} - -.btn-primary-corp:disabled { - background: var(--border-subtle); - cursor: not-allowed; - opacity: 0.65; -} - -.btn-corp-action { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 4px; - background: var(--emerald-dark); - color: #ffffff; - border: none; - border-radius: var(--radius-sm); - padding: 8px 12px; - font-size: 0.78rem; - font-weight: 700; - cursor: pointer; - white-space: nowrap; -} - -.btn-corp-action:hover { - background: var(--emerald-profit); -} - -.btn-corp-secondary { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 4px; - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-sm); - padding: 7px 10px; - font-size: 0.75rem; - font-weight: 600; - color: var(--text-primary); - cursor: pointer; - white-space: nowrap; -} - -.btn-corp-secondary:hover:not(:disabled) { - background: var(--bg-surface-sub); -} - -.btn-corp-secondary:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.mgr-hired-badge { - display: inline-flex; - align-items: center; - gap: 4px; - background: var(--primary-blue-light); - color: var(--primary-blue); - font-size: 0.72rem; - font-weight: 700; - padding: 6px 10px; - border-radius: var(--radius-sm); - white-space: nowrap; -} - -/* ========================================================================== - B2B CONTRACTS BOARD - ========================================================================== */ - -.contracts-header-pane { - display: flex; - justify-content: space-between; - align-items: center; - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px 20px; -} - -.view-title { - font-size: 1.25rem; - font-weight: 800; - color: var(--text-primary); - display: flex; - align-items: center; - gap: 8px; -} - -.view-subtitle { - font-size: 0.82rem; - color: var(--text-secondary); - margin-top: 4px; -} - -.contracts-meta-badge { - background: var(--bg-surface-sub); - border: 1px solid var(--border-color); - padding: 6px 14px; - border-radius: var(--radius-md); - font-size: 0.8rem; - color: var(--text-secondary); -} - -.contracts-meta-badge strong { - color: var(--primary-blue); - margin-left: 4px; -} - -.contracts-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); - gap: 16px; -} - -.contract-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 18px; - display: flex; - flex-direction: column; - gap: 14px; - box-shadow: var(--shadow-sm); - transition: all 0.2s; -} - -.contract-card.ready-to-fulfill { - border-color: var(--emerald-profit); - box-shadow: 0 0 0 1px rgba(16, 185, 129, 0.2); -} - -.contract-client-row { - display: flex; - justify-content: space-between; - align-items: center; -} - -.client-brand { - display: flex; - align-items: center; - gap: 10px; -} - -.client-avatar { - width: 36px; - height: 36px; - background: var(--primary-blue-light); - color: var(--primary-blue); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.2rem; -} - -.client-name { - font-size: 0.9rem; - font-weight: 700; - color: var(--text-primary); -} - -.client-badge { - font-size: 0.7rem; - font-weight: 600; - color: var(--text-muted); -} - -.contract-timer { - display: inline-flex; - align-items: center; - gap: 4px; - background: var(--bg-surface-sub); - padding: 4px 8px; - border-radius: var(--radius-sm); - font-size: 0.75rem; - font-weight: 700; - color: var(--text-secondary); -} - -.timer-urgent { - background: var(--amber-light); - color: var(--amber-dark); -} - -.contract-title { - font-size: 1rem; - font-weight: 700; - color: var(--text-primary); - margin-bottom: 8px; -} - -.contract-req-row { - display: flex; - justify-content: space-between; - align-items: flex-end; - margin-bottom: 6px; -} - -.req-label { - font-size: 0.72rem; - color: var(--text-muted); -} - -.req-val-wrap { - display: flex; - align-items: center; - gap: 6px; - font-size: 0.85rem; -} - -.contract-progress-track { - width: 100%; - height: 8px; - background: var(--bg-surface-sub); - border-radius: 4px; - overflow: hidden; - margin-bottom: 12px; -} - -.contract-progress-fill { - height: 100%; - background: var(--primary-blue); - transition: width 0.3s; -} - -.contract-card.ready-to-fulfill .contract-progress-fill { - background: var(--emerald-profit); -} - -.contract-payout-box { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; - background: var(--bg-surface-sub); - padding: 10px; - border-radius: var(--radius-md); -} - -.payout-label { - font-size: 0.7rem; - color: var(--text-muted); -} - -.payout-val { - font-size: 0.95rem; - font-weight: 700; - color: var(--emerald-dark); -} - -/* ========================================================================== - BOARDROOM & IPO VIEW - ========================================================================== */ - -.boardroom-header-pane { - display: flex; - flex-direction: column; - gap: 16px; -} - -.boardroom-hero { - display: flex; - justify-content: space-between; - align-items: center; - background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); - color: #ffffff; - border-radius: var(--radius-lg); - padding: 24px; - box-shadow: var(--shadow-md); -} - -.executive-tag { - display: inline-flex; - align-items: center; - gap: 4px; - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.05em; - color: #93c5fd; - margin-bottom: 6px; -} - -.boardroom-title { - font-size: 1.5rem; - font-weight: 800; -} - -.boardroom-desc { - font-size: 0.85rem; - color: #94a3b8; - max-width: 600px; - margin-top: 6px; - line-height: 1.5; -} - -.hero-valuation-card { - background: rgba(255, 255, 255, 0.07); - border: 1px solid rgba(255, 255, 255, 0.12); - border-radius: var(--radius-md); - padding: 16px 20px; - text-align: right; -} - -.val-label { - font-size: 0.72rem; - color: #94a3b8; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.val-number { - font-size: 1.75rem; - font-weight: 800; - color: #ffffff; - margin: 4px 0; -} - -.val-lifetime { - font-size: 0.78rem; - color: #cbd5e1; -} - -.ipo-action-banner { - display: flex; - justify-content: space-between; - align-items: center; - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px 20px; -} - -.ipo-banner-info { - display: flex; - align-items: center; - gap: 16px; -} - -.ipo-shares-badge { - background: var(--purple-light); - color: var(--purple-rnd); - font-size: 1.1rem; - font-weight: 800; - padding: 10px 16px; - border-radius: var(--radius-md); - display: flex; - align-items: center; - gap: 6px; -} - -.boardroom-shares-summary { - display: flex; - gap: 12px; -} - -.shares-pill { - background: var(--bg-surface); - border: 1px solid var(--border-color); - padding: 8px 16px; - border-radius: var(--radius-md); - font-size: 0.85rem; - display: flex; - align-items: center; - gap: 8px; -} - -.shares-val { - color: var(--purple-rnd); - font-size: 1rem; -} - -.perks-section-title { - margin-top: 8px; -} - -.perks-section-title h3 { - font-size: 1.15rem; - font-weight: 800; - display: flex; - align-items: center; - gap: 6px; -} - -.perks-section-title span { - font-size: 0.8rem; - color: var(--text-secondary); -} - -.perks-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); - gap: 16px; -} - -.perk-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px; - display: flex; - flex-direction: column; - gap: 10px; -} - -.perk-header { - display: flex; - gap: 12px; - align-items: center; -} - -.perk-tier-badge { - font-size: 0.7rem; - font-weight: 700; - color: var(--primary-blue); -} - -.perk-name { - font-size: 0.95rem; - font-weight: 700; - color: var(--text-primary); -} - -.perk-desc { - font-size: 0.8rem; - color: var(--text-secondary); - line-height: 1.4; -} - -.perk-effect-box { - display: flex; - align-items: center; - gap: 6px; - background: var(--bg-surface-sub); - padding: 8px 10px; - border-radius: var(--radius-sm); - font-size: 0.75rem; - font-weight: 600; - color: var(--text-primary); -} - -.btn-corp-perk { - width: 100%; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; - background: var(--purple-rnd); - color: #ffffff; - border: none; - border-radius: var(--radius-sm); - padding: 8px 12px; - font-size: 0.78rem; - font-weight: 700; - cursor: pointer; -} - -.btn-corp-perk:disabled { - background: var(--border-subtle); - cursor: not-allowed; - opacity: 0.65; -} - -/* ========================================================================== - DESKTOP INSPECTOR PANEL - ========================================================================== */ - -.inspector-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 18px; - box-shadow: var(--shadow-sm); - display: flex; - flex-direction: column; - gap: 16px; - position: sticky; - top: 150px; -} - -.inspector-badge-row { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 6px; -} - -.sector-tag { - font-size: 0.72rem; - font-weight: 700; - padding: 2px 8px; - border-radius: 4px; - display: inline-flex; - align-items: center; - gap: 4px; -} - -.tier-tag { - font-size: 0.72rem; - font-weight: 700; - color: var(--text-muted); -} - -.inspector-title { - font-size: 1.15rem; - font-weight: 800; - color: var(--text-primary); -} - -.inspector-desc { - font-size: 0.8rem; - color: var(--text-secondary); - line-height: 1.4; - margin-top: 4px; -} - -.inspector-metrics-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; - background: var(--bg-surface-sub); - padding: 10px; - border-radius: var(--radius-md); -} - -.metric-box { - display: flex; - flex-direction: column; -} - -.metric-label { - font-size: 0.68rem; - color: var(--text-muted); -} - -.metric-val { - font-size: 0.88rem; - color: var(--text-primary); -} - -.inspector-section { - display: flex; - flex-direction: column; - gap: 8px; -} - -.section-heading { - font-size: 0.82rem; - font-weight: 700; - color: var(--text-primary); - display: flex; - align-items: center; - gap: 6px; -} - -.section-subtext { - font-size: 0.72rem; - color: var(--text-muted); -} - -.liquidation-buttons { - display: flex; - flex-direction: column; - gap: 8px; -} - -.liquidation-buttons button { - width: 100%; - display: flex; - justify-content: space-between; - align-items: center; - font-size: 0.78rem; - padding: 8px 12px; - white-space: nowrap; -} - -.liquidation-btn-label { - display: inline-flex; - align-items: center; - gap: 6px; - font-weight: 700; -} - -.liquidation-btn-val { - font-family: var(--font-mono); - font-weight: 700; -} - -.chain-box { - display: flex; - flex-direction: column; - gap: 6px; - background: #f8fafc; - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - padding: 10px; -} - -.chain-title { - font-size: 0.7rem; - font-weight: 700; - color: var(--text-secondary); - text-transform: uppercase; -} - -.chain-empty { - font-size: 0.75rem; - color: var(--text-muted); - font-style: italic; -} - -.chain-items { - display: flex; - flex-direction: column; - gap: 6px; -} - -.chain-item-row { - display: flex; - justify-content: space-between; - align-items: center; - background: var(--bg-surface); - border: 1px solid var(--border-color); - padding: 8px 10px; - border-radius: var(--radius-sm); - cursor: pointer; - transition: background 0.15s; - gap: 10px; -} - -.chain-item-row:hover { - background: var(--primary-blue-light); -} - -.chain-item-left { - display: flex; - align-items: center; - gap: 6px; - font-size: 0.78rem; - font-weight: 600; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; -} - -.chain-item-ratio { - font-size: 0.72rem; - color: var(--text-muted); - white-space: nowrap; - flex-shrink: 0; -} - -.chain-badge { - font-size: 0.68rem; - font-weight: 700; - padding: 2px 6px; - border-radius: 4px; -} - -.badge-open { - background: var(--emerald-light); - color: var(--emerald-dark); -} - -.badge-locked { - background: var(--bg-surface-sub); - color: var(--text-muted); -} - -/* ========================================================================== - ACHIEVEMENTS VIEW - ========================================================================== */ - -.achievements-header-pane { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px 20px; -} - -.achievements-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); - gap: 16px; -} - -.achievement-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 16px; - display: flex; - gap: 14px; - box-shadow: var(--shadow-sm); -} - -.ach-icon-circle { - width: 44px; - height: 44px; - background: var(--bg-surface-sub); - color: var(--text-muted); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.4rem; -} - -.ach-icon-circle.ach-unlocked { - background: #fef3c7; - color: #d97706; -} - -.ach-info-col { - flex: 1; -} - -.ach-title-row { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 2px; -} - -.ach-title { - font-size: 0.95rem; - font-weight: 700; -} - -.ach-tier-badge { - font-size: 0.7rem; - font-weight: 700; - color: var(--primary-blue); -} - -.ach-desc { - font-size: 0.78rem; - color: var(--text-secondary); - margin-bottom: 8px; -} - -.ach-progress-bar-track { - width: 100%; - height: 6px; - background: var(--bg-surface-sub); - border-radius: 3px; - overflow: hidden; - margin-bottom: 4px; -} - -.ach-progress-bar-fill { - height: 100%; - background: #f59e0b; -} - -.ach-progress-labels { - display: flex; - justify-content: space-between; - font-size: 0.7rem; - color: var(--text-muted); -} - -/* ========================================================================== - MOBILE BOTTOM NAVIGATION & RESPONSIVE RULES - ========================================================================== */ - -#mobile-bottom-nav { - display: none; - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 60px; - background: var(--bg-header); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-top: 1px solid var(--border-color); - box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.04); - z-index: 100; - justify-content: space-around; - align-items: center; -} - -.nav-tab { - display: flex; - flex-direction: column; - align-items: center; - gap: 3px; - background: transparent; - border: none; - color: var(--text-secondary); - font-size: 0.7rem; - font-weight: 600; - cursor: pointer; - flex: 1; - padding: 8px 0; -} - -.nav-tab iconify-icon { - font-size: 1.3rem; -} - -.nav-tab.active { - color: var(--primary-blue); - font-weight: 700; -} - -/* Responsive Breakpoints */ -@media (max-width: 1023px) { - #desktop-nav-sidebar { - display: none; - } - - #desktop-inspector-panel { - display: none; - } - - #mobile-bottom-nav { - display: flex; - } - - #workspace-layout { - padding-bottom: 80px; - } - - .production-grid, .contracts-grid, .perks-grid, .achievements-grid { - grid-template-columns: 1fr; - } -} - -/* ========================================================================== - TOASTS & MODALS - ========================================================================== */ - -#toast-container { - position: fixed; - bottom: 20px; - right: 20px; - z-index: 1000; - display: flex; - flex-direction: column; - gap: 8px; - pointer-events: none; -} - -@media (max-width: 1023px) { - #toast-container { - bottom: 74px; - left: 20px; - right: 20px; - } -} - -.toast-msg { - background: #1e293b; - color: #ffffff; - padding: 10px 16px; - border-radius: var(--radius-md); - box-shadow: var(--shadow-lg); - display: flex; - align-items: center; - gap: 10px; - font-size: 0.82rem; - font-weight: 600; - animation: slideInToast 0.25s ease-out; -} - -.toast-msg.toast-success { - border-left: 4px solid var(--emerald-profit); -} - -.toast-msg.toast-warning { - border-left: 4px solid var(--amber-dark); -} - -.toast-msg.toast-info { - border-left: 4px solid var(--primary-blue); -} - -.toast-msg.fade-out { - opacity: 0; - transform: translateY(10px); - transition: all 0.3s; -} - -@keyframes slideInToast { - from { - opacity: 0; - transform: translateY(15px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.modal-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(15, 23, 42, 0.6); - backdrop-filter: blur(4px); - z-index: 200; - display: none; - align-items: center; - justify-content: center; - padding: 16px; -} - -.modal-overlay.open { - display: flex; -} - -.modal-card { - background: var(--bg-surface); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: 24px; - max-width: 420px; - width: 100%; - box-shadow: var(--shadow-lg); - display: flex; - flex-direction: column; - gap: 16px; -} - -.modal-header { - display: flex; - align-items: center; - gap: 12px; -} - -.modal-icon { - font-size: 2rem; - color: var(--primary-blue); -} - -.modal-title { - font-size: 1.15rem; - font-weight: 800; -} - -.modal-subtitle { - font-size: 0.78rem; - color: var(--text-secondary); -} - -.input-field-group { - display: flex; - flex-direction: column; - gap: 4px; -} - -.input-field-group label { - font-size: 0.75rem; - font-weight: 700; - color: var(--text-secondary); -} - -.modal-input { - border: 1px solid var(--border-color); - border-radius: var(--radius-sm); - padding: 8px 12px; - font-size: 0.88rem; - font-family: var(--font-sans); - outline: none; -} - -.modal-input:focus { - border-color: var(--primary-blue); -} - -.modal-actions-row { - display: flex; - gap: 8px; -} - -.modal-actions-row button { - flex: 1; - padding: 10px; -} - -.btn-text-close { - background: none; - border: none; - font-size: 0.78rem; - color: var(--text-muted); - cursor: pointer; - text-align: center; -} - -.btn-text-close:hover { - color: var(--text-primary); -} +/* Production - The Idle Game: Enterprise Design System + Modular CSS bundle uniting design tokens, layout shell, views and responsive components */ + +@import './base/theme.css'; +@import './layout/header.css'; +@import './layout/workspace.css'; +@import './views/production.css'; +@import './views/contracts.css'; +@import './views/boardroom.css'; +@import './views/inspector.css'; +@import './views/achievements.css'; +@import './layout/responsive.css'; diff --git a/frontend/css/views/achievements.css b/frontend/css/views/achievements.css new file mode 100644 index 0000000..6dbdc62 --- /dev/null +++ b/frontend/css/views/achievements.css @@ -0,0 +1,93 @@ +/* ========================================================================== + ACHIEVEMENTS VIEW + ========================================================================== */ + +.achievements-header-pane { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px 20px; +} + +.achievements-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); + gap: 16px; +} + +.achievement-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px; + display: flex; + gap: 14px; + box-shadow: var(--shadow-sm); +} + +.ach-icon-circle { + width: 44px; + height: 44px; + background: var(--bg-surface-sub); + color: var(--text-muted); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.4rem; +} + +.ach-icon-circle.ach-unlocked { + background: #fef3c7; + color: #d97706; +} + +.ach-info-col { + flex: 1; +} + +.ach-title-row { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2px; +} + +.ach-title { + font-size: 0.95rem; + font-weight: 700; +} + +.ach-tier-badge { + font-size: 0.7rem; + font-weight: 700; + color: var(--primary-blue); +} + +.ach-desc { + font-size: 0.78rem; + color: var(--text-secondary); + margin-bottom: 8px; +} + +.ach-progress-bar-track { + width: 100%; + height: 6px; + background: var(--bg-surface-sub); + border-radius: 3px; + overflow: hidden; + margin-bottom: 4px; +} + +.ach-progress-bar-fill { + height: 100%; + background: #f59e0b; +} + +.ach-progress-labels { + display: flex; + justify-content: space-between; + font-size: 0.7rem; + color: var(--text-muted); +} + diff --git a/frontend/css/views/boardroom.css b/frontend/css/views/boardroom.css new file mode 100644 index 0000000..dbf3fac --- /dev/null +++ b/frontend/css/views/boardroom.css @@ -0,0 +1,213 @@ +/* ========================================================================== + BOARDROOM & IPO VIEW + ========================================================================== */ + +.boardroom-header-pane { + display: flex; + flex-direction: column; + gap: 16px; +} + +.boardroom-hero { + display: flex; + justify-content: space-between; + align-items: center; + background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); + color: #ffffff; + border-radius: var(--radius-lg); + padding: 24px; + box-shadow: var(--shadow-md); +} + +.executive-tag { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.05em; + color: #93c5fd; + margin-bottom: 6px; +} + +.boardroom-title { + font-size: 1.5rem; + font-weight: 800; +} + +.boardroom-desc { + font-size: 0.85rem; + color: #94a3b8; + max-width: 600px; + margin-top: 6px; + line-height: 1.5; +} + +.hero-valuation-card { + background: rgba(255, 255, 255, 0.07); + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: var(--radius-md); + padding: 16px 20px; + text-align: right; +} + +.val-label { + font-size: 0.72rem; + color: #94a3b8; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.val-number { + font-size: 1.75rem; + font-weight: 800; + color: #ffffff; + margin: 4px 0; +} + +.val-lifetime { + font-size: 0.78rem; + color: #cbd5e1; +} + +.ipo-action-banner { + display: flex; + justify-content: space-between; + align-items: center; + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px 20px; +} + +.ipo-banner-info { + display: flex; + align-items: center; + gap: 16px; +} + +.ipo-shares-badge { + background: var(--purple-light); + color: var(--purple-rnd); + font-size: 1.1rem; + font-weight: 800; + padding: 10px 16px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + gap: 6px; +} + +.boardroom-shares-summary { + display: flex; + gap: 12px; +} + +.shares-pill { + background: var(--bg-surface); + border: 1px solid var(--border-color); + padding: 8px 16px; + border-radius: var(--radius-md); + font-size: 0.85rem; + display: flex; + align-items: center; + gap: 8px; +} + +.shares-val { + color: var(--purple-rnd); + font-size: 1rem; +} + +.perks-section-title { + margin-top: 8px; +} + +.perks-section-title h3 { + font-size: 1.15rem; + font-weight: 800; + display: flex; + align-items: center; + gap: 6px; +} + +.perks-section-title span { + font-size: 0.8rem; + color: var(--text-secondary); +} + +.perks-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 16px; +} + +.perk-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px; + display: flex; + flex-direction: column; + gap: 10px; +} + +.perk-header { + display: flex; + gap: 12px; + align-items: center; +} + +.perk-tier-badge { + font-size: 0.7rem; + font-weight: 700; + color: var(--primary-blue); +} + +.perk-name { + font-size: 0.95rem; + font-weight: 700; + color: var(--text-primary); +} + +.perk-desc { + font-size: 0.8rem; + color: var(--text-secondary); + line-height: 1.4; +} + +.perk-effect-box { + display: flex; + align-items: center; + gap: 6px; + background: var(--bg-surface-sub); + padding: 8px 10px; + border-radius: var(--radius-sm); + font-size: 0.75rem; + font-weight: 600; + color: var(--text-primary); +} + +.btn-corp-perk { + width: 100%; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + background: var(--purple-rnd); + color: #ffffff; + border: none; + border-radius: var(--radius-sm); + padding: 8px 12px; + font-size: 0.78rem; + font-weight: 700; + cursor: pointer; +} + +.btn-corp-perk:disabled { + background: var(--border-subtle); + cursor: not-allowed; + opacity: 0.65; +} + diff --git a/frontend/css/views/contracts.css b/frontend/css/views/contracts.css new file mode 100644 index 0000000..30b0d87 --- /dev/null +++ b/frontend/css/views/contracts.css @@ -0,0 +1,184 @@ +/* ========================================================================== + B2B CONTRACTS BOARD + ========================================================================== */ + +.contracts-header-pane { + display: flex; + justify-content: space-between; + align-items: center; + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px 20px; +} + +.view-title { + font-size: 1.25rem; + font-weight: 800; + color: var(--text-primary); + display: flex; + align-items: center; + gap: 8px; +} + +.view-subtitle { + font-size: 0.82rem; + color: var(--text-secondary); + margin-top: 4px; +} + +.contracts-meta-badge { + background: var(--bg-surface-sub); + border: 1px solid var(--border-color); + padding: 6px 14px; + border-radius: var(--radius-md); + font-size: 0.8rem; + color: var(--text-secondary); +} + +.contracts-meta-badge strong { + color: var(--primary-blue); + margin-left: 4px; +} + +.contracts-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); + gap: 16px; +} + +.contract-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 18px; + display: flex; + flex-direction: column; + gap: 14px; + box-shadow: var(--shadow-sm); + transition: all 0.2s; +} + +.contract-card.ready-to-fulfill { + border-color: var(--emerald-profit); + box-shadow: 0 0 0 1px rgba(16, 185, 129, 0.2); +} + +.contract-client-row { + display: flex; + justify-content: space-between; + align-items: center; +} + +.client-brand { + display: flex; + align-items: center; + gap: 10px; +} + +.client-avatar { + width: 36px; + height: 36px; + background: var(--primary-blue-light); + color: var(--primary-blue); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.2rem; +} + +.client-name { + font-size: 0.9rem; + font-weight: 700; + color: var(--text-primary); +} + +.client-badge { + font-size: 0.7rem; + font-weight: 600; + color: var(--text-muted); +} + +.contract-timer { + display: inline-flex; + align-items: center; + gap: 4px; + background: var(--bg-surface-sub); + padding: 4px 8px; + border-radius: var(--radius-sm); + font-size: 0.75rem; + font-weight: 700; + color: var(--text-secondary); +} + +.timer-urgent { + background: var(--amber-light); + color: var(--amber-dark); +} + +.contract-title { + font-size: 1rem; + font-weight: 700; + color: var(--text-primary); + margin-bottom: 8px; +} + +.contract-req-row { + display: flex; + justify-content: space-between; + align-items: flex-end; + margin-bottom: 6px; +} + +.req-label { + font-size: 0.72rem; + color: var(--text-muted); +} + +.req-val-wrap { + display: flex; + align-items: center; + gap: 6px; + font-size: 0.85rem; +} + +.contract-progress-track { + width: 100%; + height: 8px; + background: var(--bg-surface-sub); + border-radius: 4px; + overflow: hidden; + margin-bottom: 12px; +} + +.contract-progress-fill { + height: 100%; + background: var(--primary-blue); + transition: width 0.3s; +} + +.contract-card.ready-to-fulfill .contract-progress-fill { + background: var(--emerald-profit); +} + +.contract-payout-box { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + background: var(--bg-surface-sub); + padding: 10px; + border-radius: var(--radius-md); +} + +.payout-label { + font-size: 0.7rem; + color: var(--text-muted); +} + +.payout-val { + font-size: 0.95rem; + font-weight: 700; + color: var(--emerald-dark); +} + diff --git a/frontend/css/views/inspector.css b/frontend/css/views/inspector.css new file mode 100644 index 0000000..27ae850 --- /dev/null +++ b/frontend/css/views/inspector.css @@ -0,0 +1,207 @@ +/* ========================================================================== + DESKTOP INSPECTOR PANEL + ========================================================================== */ + +.inspector-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 18px; + box-shadow: var(--shadow-sm); + display: flex; + flex-direction: column; + gap: 16px; + position: sticky; + top: 150px; +} + +.inspector-badge-row { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 6px; +} + +.sector-tag { + font-size: 0.72rem; + font-weight: 700; + padding: 2px 8px; + border-radius: 4px; + display: inline-flex; + align-items: center; + gap: 4px; +} + +.tier-tag { + font-size: 0.72rem; + font-weight: 700; + color: var(--text-muted); +} + +.inspector-title { + font-size: 1.15rem; + font-weight: 800; + color: var(--text-primary); +} + +.inspector-desc { + font-size: 0.8rem; + color: var(--text-secondary); + line-height: 1.4; + margin-top: 4px; +} + +.inspector-metrics-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + background: var(--bg-surface-sub); + padding: 10px; + border-radius: var(--radius-md); +} + +.metric-box { + display: flex; + flex-direction: column; +} + +.metric-label { + font-size: 0.68rem; + color: var(--text-muted); +} + +.metric-val { + font-size: 0.88rem; + color: var(--text-primary); +} + +.inspector-section { + display: flex; + flex-direction: column; + gap: 8px; +} + +.section-heading { + font-size: 0.82rem; + font-weight: 700; + color: var(--text-primary); + display: flex; + align-items: center; + gap: 6px; +} + +.section-subtext { + font-size: 0.72rem; + color: var(--text-muted); +} + +.liquidation-buttons { + display: flex; + flex-direction: column; + gap: 8px; +} + +.liquidation-buttons button { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.78rem; + padding: 8px 12px; + white-space: nowrap; +} + +.liquidation-btn-label { + display: inline-flex; + align-items: center; + gap: 6px; + font-weight: 700; +} + +.liquidation-btn-val { + font-family: var(--font-mono); + font-weight: 700; +} + +.chain-box { + display: flex; + flex-direction: column; + gap: 6px; + background: #f8fafc; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 10px; +} + +.chain-title { + font-size: 0.7rem; + font-weight: 700; + color: var(--text-secondary); + text-transform: uppercase; +} + +.chain-empty { + font-size: 0.75rem; + color: var(--text-muted); + font-style: italic; +} + +.chain-items { + display: flex; + flex-direction: column; + gap: 6px; +} + +.chain-item-row { + display: flex; + justify-content: space-between; + align-items: center; + background: var(--bg-surface); + border: 1px solid var(--border-color); + padding: 8px 10px; + border-radius: var(--radius-sm); + cursor: pointer; + transition: background 0.15s; + gap: 10px; +} + +.chain-item-row:hover { + background: var(--primary-blue-light); +} + +.chain-item-left { + display: flex; + align-items: center; + gap: 6px; + font-size: 0.78rem; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; +} + +.chain-item-ratio { + font-size: 0.72rem; + color: var(--text-muted); + white-space: nowrap; + flex-shrink: 0; +} + +.chain-badge { + font-size: 0.68rem; + font-weight: 700; + padding: 2px 6px; + border-radius: 4px; +} + +.badge-open { + background: var(--emerald-light); + color: var(--emerald-dark); +} + +.badge-locked { + background: var(--bg-surface-sub); + color: var(--text-muted); +} + diff --git a/frontend/css/views/production.css b/frontend/css/views/production.css new file mode 100644 index 0000000..5a3c313 --- /dev/null +++ b/frontend/css/views/production.css @@ -0,0 +1,395 @@ +/* ========================================================================== + PRODUCTION FLOOR & FACILITY CARDS + ========================================================================== */ + +.production-toolbar { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 6px 8px; +} + +.sector-tabs-scroll { + display: flex; + gap: 6px; + width: 100%; +} + +.sector-pill { + flex: 1 1 0; + min-width: 0; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + background: var(--bg-surface-sub); + border: 1px solid var(--border-color); + padding: 8px 6px; + border-radius: var(--radius-sm); + cursor: pointer; + white-space: nowrap; + transition: all 0.15s; + box-sizing: border-box; +} + +.sector-pill iconify-icon { + font-size: 1.15rem; + flex-shrink: 0; +} + +.sector-pill:hover { + border-color: var(--text-muted); +} + +.sector-pill.active { + background: var(--text-primary); + color: #ffffff; + border-color: var(--text-primary); +} + +.sector-pill.active iconify-icon { + color: #ffffff !important; +} + +.sector-pill.active .sector-pill-rate { + color: #a7f3d0; +} + +.production-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); + gap: 16px; +} + +.facility-card { + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: 16px; + box-shadow: var(--shadow-sm); + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 420px; + gap: 12px; + cursor: pointer; + transition: border-color 0.2s, box-shadow 0.2s; + position: relative; + box-sizing: border-box; +} + +.facility-card:hover { + border-color: #cbd5e1; + box-shadow: var(--shadow-md); +} + +.facility-card.selected { + border-color: var(--primary-blue); + box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.15); +} + +.facility-card.locked-card { + opacity: 0.85; + background: #fbfcfe; +} + +.facility-header { + display: flex; + gap: 12px; + align-items: flex-start; + min-height: 60px; + box-sizing: border-box; +} + +.facility-icon-wrap { + width: 44px; + height: 44px; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.icon-lg { + font-size: 1.6rem; +} + +.facility-title-wrap { + flex: 1; + min-width: 0; + overflow: hidden; +} + +.facility-meta-row { + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; + min-height: 22px; + height: 22px; + flex-wrap: nowrap; + margin-bottom: 2px; + box-sizing: border-box; +} + +.sector-badge { + font-size: 0.7rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.03em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; + min-width: 0; +} + +.facility-name { + font-size: 1rem; + font-weight: 700; + color: var(--text-primary); + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.facility-type-sub { + font-size: 0.75rem; + color: var(--text-secondary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.facility-desc { + font-size: 0.8rem; + color: var(--text-secondary); + line-height: 1.4; +} + +/* Status Badges */ +.status-badge { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 0.7rem; + font-weight: 700; + padding: 2px 8px; + border-radius: 12px; + white-space: nowrap; + flex-shrink: 0; + height: 20px; + line-height: 1; + box-sizing: border-box; +} + +.badge-success { + background: var(--emerald-light); + color: var(--emerald-dark); +} + +.badge-warning { + background: var(--amber-light); + color: var(--amber-dark); + animation: pulseWarning 1.5s infinite; +} + +@keyframes pulseWarning { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.75; } +} + +.badge-idle { + background: var(--bg-surface-sub); + color: var(--text-muted); +} + +/* Cycle Progress Track */ +.cycle-bar-track { + width: 100%; + height: 6px; + background: var(--bg-surface-sub); + border-radius: 3px; + overflow: hidden; +} + +.cycle-bar-fill { + height: 100%; + transition: width 0.1s linear; +} + +/* Facility Stats Grid */ +.facility-stats-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; + background: var(--bg-surface-sub); + border-radius: var(--radius-sm); + padding: 8px 10px; + min-height: 84px; + box-sizing: border-box; +} + +.stat-cell { + display: flex; + flex-direction: column; + min-width: 0; +} + +.stat-label { + font-size: 0.65rem; + font-weight: 600; + color: var(--text-muted); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.stat-value { + font-size: 0.78rem; + color: var(--text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.text-warning { + color: var(--amber-dark); +} + +/* Inputs Strip */ +.inputs-strip { + display: flex; + flex-direction: column; + gap: 4px; + padding: 6px 8px; + background: #f8fafc; + border: 1px dashed var(--border-color); + border-radius: var(--radius-sm); +} + +.inputs-label { + font-size: 0.68rem; + font-weight: 700; + color: var(--text-secondary); +} + +.inputs-chips { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.input-chip { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 0.72rem; + background: var(--bg-surface); + border: 1px solid var(--border-color); + padding: 2px 6px; + border-radius: 4px; + color: var(--text-secondary); +} + +.input-chip.low-stock { + border-color: var(--amber-dark); + background: var(--amber-light); + color: var(--amber-dark); +} + +/* Action Buttons */ +.facility-actions-row { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: auto; +} + +.btn-primary-corp { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + background: var(--primary-blue); + color: #ffffff; + border: none; + border-radius: var(--radius-sm); + padding: 8px 12px; + font-size: 0.78rem; + font-weight: 700; + cursor: pointer; + white-space: nowrap; + transition: background 0.15s, opacity 0.15s; +} + +.btn-primary-corp:hover:not(:disabled) { + background: var(--primary-blue-hover); +} + +.btn-primary-corp:disabled { + background: var(--border-subtle); + cursor: not-allowed; + opacity: 0.65; +} + +.btn-corp-action { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + background: var(--emerald-dark); + color: #ffffff; + border: none; + border-radius: var(--radius-sm); + padding: 8px 12px; + font-size: 0.78rem; + font-weight: 700; + cursor: pointer; + white-space: nowrap; +} + +.btn-corp-action:hover { + background: var(--emerald-profit); +} + +.btn-corp-secondary { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + padding: 7px 10px; + font-size: 0.75rem; + font-weight: 600; + color: var(--text-primary); + cursor: pointer; + white-space: nowrap; +} + +.btn-corp-secondary:hover:not(:disabled) { + background: var(--bg-surface-sub); +} + +.btn-corp-secondary:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.mgr-hired-badge { + display: inline-flex; + align-items: center; + gap: 4px; + background: var(--primary-blue-light); + color: var(--primary-blue); + font-size: 0.72rem; + font-weight: 700; + padding: 6px 10px; + border-radius: var(--radius-sm); + white-space: nowrap; +} + diff --git a/frontend/js/data/products.js b/frontend/js/data/products.js index 2fd3d0e..e95b138 100644 --- a/frontend/js/data/products.js +++ b/frontend/js/data/products.js @@ -1,569 +1,29 @@ // Production - The Idle Game: Product Catalog & Supply Chain Definitions -// Scalable data-driven structure supporting multi-tier inputs, sectors, and facilities +// Clean modular orchestrator combining sector definitions + +import { AGRICULTURE_SECTOR, AGRICULTURE_PRODUCTS } from './sectors/agriculture.js'; +import { MATERIALS_SECTOR, MATERIALS_PRODUCTS } from './sectors/materials.js'; +import { MINING_SECTOR, MINING_PRODUCTS } from './sectors/mining.js'; +import { CHEMICALS_SECTOR, CHEMICALS_PRODUCTS } from './sectors/chemicals.js'; +import { ELECTRONICS_SECTOR, ELECTRONICS_PRODUCTS } from './sectors/electronics.js'; +import { HEAVY_INDUSTRY_SECTOR, HEAVY_INDUSTRY_PRODUCTS } from './sectors/heavyIndustry.js'; export const SECTORS = [ - { - id: 'agriculture', - name: 'Agriculture & Food', - icon: 'lucide:wheat', - color: '#16a34a', // Emerald Green - description: 'Primary crops, livestock, milling, and commercial foodstuffs.' - }, - { - id: 'materials', - name: 'Forestry & Materials', - icon: 'lucide:trees', - color: '#ca8a04', // Amber/Wood - description: 'Timber harvesting, lumber mills, paper, and commercial furniture.' - }, - { - id: 'mining', - name: 'Mining & Metallurgy', - icon: 'lucide:pickaxe', - color: '#475569', // Slate/Steel - description: 'Ore extraction, blast furnaces, alloy smelting, and heavy frames.' - }, - { - id: 'chemicals', - name: 'Chemicals & Polymers', - icon: 'lucide:flask-conical', - color: '#0284c7', // Sky Blue - description: 'Crude oil refinement, plastics, polymers, and synthetic compounds.' - }, - { - id: 'electronics', - name: 'High-Tech & Electronics', - icon: 'lucide:cpu', - color: '#7c3aed', // Purple - description: 'Purified silicon, microchips, circuit assemblies, and smart devices.' - }, - { - id: 'heavy_industry', - name: 'Heavy Industry & Vehicles', - icon: 'lucide:truck', - color: '#ea580c', // Industrial Orange - description: 'Combustion engines, logistics fleets, industrial robotics, and transport.' - } + AGRICULTURE_SECTOR, + MATERIALS_SECTOR, + MINING_SECTOR, + CHEMICALS_SECTOR, + ELECTRONICS_SECTOR, + HEAVY_INDUSTRY_SECTOR ]; export const PRODUCTS = [ - // --- SECTOR 1: AGRICULTURE & FOOD --- - { - id: 'wheat', - name: 'Grain (Wheat)', - sector: 'agriculture', - tier: 1, - icon: 'lucide:wheat', - color: '#65a30d', - unit: 'bushels', - inputs: [], // Raw extraction - outputAmount: 1, - baseCycleTime: 1.0, - unlockCost: 0, - unlockedDefault: true, - baseFacilityCost: 15, - baseManagerCost: 100, - baseLogisticsCost: 80, - basePrice: 1.50, - facilityName: 'Wheat Field', - managerName: 'Farm Overseer', - logisticsName: 'Grain Sifter', - description: 'Golden wheat harvested from fertile corporate acreage.' - }, - { - id: 'flour', - name: 'Milled Flour', - sector: 'agriculture', - tier: 2, - icon: 'lucide:cookie', - color: '#84cc16', - unit: 'sacks', - inputs: [{ id: 'wheat', amount: 2 }], - outputAmount: 1, - baseCycleTime: 1.8, - unlockCost: 250, - unlockedDefault: false, - baseFacilityCost: 200, - baseManagerCost: 850, - baseLogisticsCost: 600, - basePrice: 6.20, - facilityName: 'Grain Mill', - managerName: 'Master Miller', - logisticsName: 'Flour Courier', - description: 'Fine milled wheat flour ready for commercial bakeries.' - }, - { - id: 'sugar_beet', - name: 'Sugar Beet', - sector: 'agriculture', - tier: 1, - icon: 'lucide:sprout', - color: '#a3e635', - unit: 'crates', - inputs: [], - outputAmount: 1, - baseCycleTime: 1.5, - unlockCost: 650, - unlockedDefault: false, - baseFacilityCost: 550, - baseManagerCost: 1800, - baseLogisticsCost: 1200, - basePrice: 4.80, - facilityName: 'Sugar Plantation', - managerName: 'Field Director', - logisticsName: 'Beet Hauler', - description: 'Sweet root vegetables cultivated for industrial sweetener extraction.' - }, - { - id: 'refined_sugar', - name: 'Refined Sugar', - sector: 'agriculture', - tier: 2, - icon: 'lucide:candy', - color: '#e2e8f0', - unit: 'bags', - inputs: [{ id: 'sugar_beet', amount: 3 }], - outputAmount: 1, - baseCycleTime: 2.2, - unlockCost: 2200, - unlockedDefault: false, - baseFacilityCost: 1800, - baseManagerCost: 4500, - baseLogisticsCost: 3200, - basePrice: 22.00, - facilityName: 'Refinery Plant', - managerName: 'Sugar Chemist', - logisticsName: 'Bulk Distributor', - description: 'Pure granulated sucrose ready for food production.' - }, - { - id: 'fresh_bread', - name: 'Artisan Bread', - sector: 'agriculture', - tier: 3, - icon: 'lucide:croissant', - color: '#f59e0b', - unit: 'loaves', - inputs: [{ id: 'flour', amount: 2 }, { id: 'refined_sugar', amount: 1 }], - outputAmount: 2, - baseCycleTime: 3.0, - unlockCost: 9500, - unlockedDefault: false, - baseFacilityCost: 7500, - baseManagerCost: 18000, - baseLogisticsCost: 12500, - basePrice: 58.00, - facilityName: 'Industrial Bakery', - managerName: 'Head Baker', - logisticsName: 'Delivery Fleet', - description: 'Freshly baked wholesale bread dispatched to grocery chains.' - }, - { - id: 'packaged_meals', - name: 'Packaged Meal Kits', - sector: 'agriculture', - tier: 4, - icon: 'lucide:utensils', - color: '#10b981', - unit: 'cases', - inputs: [{ id: 'fresh_bread', amount: 3 }], - outputAmount: 1, - baseCycleTime: 4.5, - unlockCost: 45000, - unlockedDefault: false, - baseFacilityCost: 36000, - baseManagerCost: 75000, - baseLogisticsCost: 55000, - basePrice: 260.00, - facilityName: 'Food Processing Line', - managerName: 'Operations Lead', - logisticsName: 'Refrigerated Transport', - description: 'Ready-to-eat branded meal kits with high retail margin.' - }, - - // --- SECTOR 2: FORESTRY & MATERIALS --- - { - id: 'timber', - name: 'Raw Timber', - sector: 'materials', - tier: 1, - icon: 'lucide:trees', - color: '#b45309', - unit: 'logs', - inputs: [], - outputAmount: 1, - baseCycleTime: 1.2, - unlockCost: 120, - unlockedDefault: false, - baseFacilityCost: 95, - baseManagerCost: 350, - baseLogisticsCost: 240, - basePrice: 2.80, - facilityName: 'Lumber Camp', - managerName: 'Forester Chief', - logisticsName: 'Log Carrier', - description: 'Mature softwood felled in managed timber estates.' - }, - { - id: 'planks', - name: 'Milled Planks', - sector: 'materials', - tier: 2, - icon: 'lucide:boxes', - color: '#d97706', - unit: 'bundles', - inputs: [{ id: 'timber', amount: 2 }], - outputAmount: 1, - baseCycleTime: 2.0, - unlockCost: 1200, - unlockedDefault: false, - baseFacilityCost: 950, - baseManagerCost: 2800, - baseLogisticsCost: 2000, - basePrice: 11.50, - facilityName: 'Sawmill', - managerName: 'Sawyer Foreman', - logisticsName: 'Lumber Flatbed', - description: 'Standardized structural lumber for construction and joinery.' - }, - { - id: 'paper', - name: 'Industrial Paper', - sector: 'materials', - tier: 2, - icon: 'lucide:file-text', - color: '#cbd5e1', - unit: 'rolls', - inputs: [{ id: 'timber', amount: 3 }], - outputAmount: 2, - baseCycleTime: 2.5, - unlockCost: 3500, - unlockedDefault: false, - baseFacilityCost: 2800, - baseManagerCost: 6500, - baseLogisticsCost: 4800, - basePrice: 16.00, - facilityName: 'Pulp Mill', - managerName: 'Chemical Pulpist', - logisticsName: 'Paper Dispatcher', - description: 'Heavy paper stock used for cardboard packaging and publishing.' - }, - { - id: 'furniture', - name: 'Office Furniture', - sector: 'materials', - tier: 3, - icon: 'lucide:armchair', - color: '#92400e', - unit: 'sets', - inputs: [{ id: 'planks', amount: 3 }], - outputAmount: 1, - baseCycleTime: 3.8, - unlockCost: 18000, - unlockedDefault: false, - baseFacilityCost: 14000, - baseManagerCost: 35000, - baseLogisticsCost: 26000, - basePrice: 95.00, - facilityName: 'Joinery Workshop', - managerName: 'Master Carpenter', - logisticsName: 'Showroom Distributor', - description: 'Ergonomic executive desks, cabinetry, and boardroom chairs.' - }, - - // --- SECTOR 3: MINING & METALLURGY --- - { - id: 'iron_ore', - name: 'Iron Ore', - sector: 'mining', - tier: 1, - icon: 'lucide:mountain', - color: '#64748b', - unit: 'tons', - inputs: [], - outputAmount: 1, - baseCycleTime: 1.6, - unlockCost: 1500, - unlockedDefault: false, - baseFacilityCost: 1200, - baseManagerCost: 3500, - baseLogisticsCost: 2400, - basePrice: 12.00, - facilityName: 'Open-Pit Iron Mine', - managerName: 'Mining Superintendant', - logisticsName: 'Ore Hopper Train', - description: 'Dense hematite extracted from open-pit mineral deposits.' - }, - { - id: 'coal', - name: 'Coking Coal', - sector: 'mining', - tier: 1, - icon: 'lucide:flame', - color: '#334155', - unit: 'tons', - inputs: [], - outputAmount: 1, - baseCycleTime: 1.8, - unlockCost: 2800, - unlockedDefault: false, - baseFacilityCost: 2200, - baseManagerCost: 5500, - baseLogisticsCost: 3800, - basePrice: 15.00, - facilityName: 'Coal Pit', - managerName: 'Pit Supervisor', - logisticsName: 'Coal Conveyor', - description: 'High-energy carbon fuel essential for blast furnace reduction.' - }, - { - id: 'steel_ingots', - name: 'Structural Steel', - sector: 'mining', - tier: 2, - icon: 'lucide:anvil', - color: '#94a3b8', - unit: 'billets', - inputs: [{ id: 'iron_ore', amount: 2 }, { id: 'coal', amount: 1 }], - outputAmount: 1, - baseCycleTime: 3.2, - unlockCost: 12500, - unlockedDefault: false, - baseFacilityCost: 9800, - baseManagerCost: 24000, - baseLogisticsCost: 17000, - basePrice: 72.00, - facilityName: 'Blast Smelter', - managerName: 'Foundry Master', - logisticsName: 'Heavy Rail Freight', - description: 'High-tensile carbon steel alloys for industrial manufacturing.' - }, - { - id: 'metal_frames', - name: 'Heavy Frameworks', - sector: 'mining', - tier: 3, - icon: 'lucide:construction', - color: '#475569', - unit: 'girders', - inputs: [{ id: 'steel_ingots', amount: 3 }], - outputAmount: 1, - baseCycleTime: 4.6, - unlockCost: 65000, - unlockedDefault: false, - baseFacilityCost: 52000, - baseManagerCost: 110000, - baseLogisticsCost: 80000, - basePrice: 320.00, - facilityName: 'Fabrication Plant', - managerName: 'Chief Fabricator', - logisticsName: 'Heavy Hauler', - description: 'Rigid reinforced metal chassis and skyscraper beams.' - }, - - // --- SECTOR 4: CHEMICALS & POLYMERS --- - { - id: 'crude_oil', - name: 'Crude Oil', - sector: 'chemicals', - tier: 1, - icon: 'lucide:droplet', - color: '#1e293b', - unit: 'barrels', - inputs: [], - outputAmount: 1, - baseCycleTime: 2.0, - unlockCost: 25000, - unlockedDefault: false, - baseFacilityCost: 20000, - baseManagerCost: 48000, - baseLogisticsCost: 35000, - basePrice: 55.00, - facilityName: 'Drilling Derrick', - managerName: 'Derrick Engineer', - logisticsName: 'Pipeline Station', - description: 'Black liquid gold pumped from deep continental wells.' - }, - { - id: 'silica_sand', - name: 'Silica Quartz Sand', - sector: 'chemicals', - tier: 1, - icon: 'lucide:sparkles', - color: '#38bdf8', - unit: 'drums', - inputs: [], - outputAmount: 1, - baseCycleTime: 2.2, - unlockCost: 45000, - unlockedDefault: false, - baseFacilityCost: 36000, - baseManagerCost: 75000, - baseLogisticsCost: 52000, - basePrice: 85.00, - facilityName: 'Quartz Quarry', - managerName: 'Geological Analyst', - logisticsName: 'Quartz Transport', - description: 'High-purity quartz crystals mined for semiconductor refining.' - }, - { - id: 'polymers', - name: 'Industrial Polymers', - sector: 'chemicals', - tier: 2, - icon: 'lucide:test-tube', - color: '#0ea5e9', - unit: 'pellets', - inputs: [{ id: 'crude_oil', amount: 2 }], - outputAmount: 1, - baseCycleTime: 3.5, - unlockCost: 110000, - unlockedDefault: false, - baseFacilityCost: 88000, - baseManagerCost: 175000, - baseLogisticsCost: 120000, - basePrice: 210.00, - facilityName: 'Cracking Facility', - managerName: 'Petrochemical Lead', - logisticsName: 'Chemical Tanker', - description: 'Versatile synthetic thermoplastic pellets for manufacturing.' - }, - { - id: 'silicon', - name: 'Purified Silicon', - sector: 'chemicals', - tier: 2, - icon: 'lucide:gem', - color: '#06b6d4', - unit: 'ingots', - inputs: [{ id: 'silica_sand', amount: 2 }], - outputAmount: 1, - baseCycleTime: 4.0, - unlockCost: 220000, - unlockedDefault: false, - baseFacilityCost: 175000, - baseManagerCost: 350000, - baseLogisticsCost: 240000, - basePrice: 420.00, - facilityName: 'Silicon Smelter', - managerName: 'Materials Scientist', - logisticsName: 'Clean Ingot Carrier', - description: '99.999% pure electronic grade monocrystalline silicon.' - }, - - // --- SECTOR 5: HIGH-TECH & ELECTRONICS --- - { - id: 'microchips', - name: 'Silicon Microchips', - sector: 'electronics', - tier: 3, - icon: 'lucide:cpu', - color: '#8b5cf6', - unit: 'chips', - inputs: [{ id: 'silicon', amount: 1 }, { id: 'polymers', amount: 1 }], - outputAmount: 2, - baseCycleTime: 4.8, - unlockCost: 550000, - unlockedDefault: false, - baseFacilityCost: 440000, - baseManagerCost: 850000, - baseLogisticsCost: 600000, - basePrice: 650.00, - facilityName: 'Cleanroom Fab', - managerName: 'Lithography Director', - logisticsName: 'Precision Courier', - description: 'Nanometer-scale integrated circuits etched via photolithography.' - }, - { - id: 'circuit_boards', - name: 'PCB Motherboards', - sector: 'electronics', - tier: 3, - icon: 'lucide:circuit-board', - color: '#a855f7', - unit: 'boards', - inputs: [{ id: 'microchips', amount: 2 }, { id: 'polymers', amount: 2 }], - outputAmount: 1, - baseCycleTime: 5.5, - unlockCost: 1500000, - unlockedDefault: false, - baseFacilityCost: 1200000, - baseManagerCost: 2400000, - baseLogisticsCost: 1600000, - basePrice: 2200.00, - facilityName: 'PCB Assembly Line', - managerName: 'SMT Chief', - logisticsName: 'Static-Safe Transport', - description: 'Multi-layer printed circuit boards populated with components.' - }, - { - id: 'smartphones', - name: 'Consumer Smartphones', - sector: 'electronics', - tier: 4, - icon: 'lucide:smartphone', - color: '#ec4899', - unit: 'devices', - inputs: [{ id: 'circuit_boards', amount: 1 }, { id: 'polymers', amount: 2 }], - outputAmount: 1, - baseCycleTime: 6.5, - unlockCost: 5000000, - unlockedDefault: false, - baseFacilityCost: 4000000, - baseManagerCost: 8000000, - baseLogisticsCost: 5500000, - basePrice: 6800.00, - facilityName: 'Tech Assembly Plant', - managerName: 'VP of Electronics', - logisticsName: 'Global Freight Air', - description: 'Flagship handheld smartphones shipped to worldwide retail.' - }, - - // --- SECTOR 6: HEAVY INDUSTRY & VEHICLES --- - { - id: 'engines', - name: 'Industrial Engines', - sector: 'heavy_industry', - tier: 3, - icon: 'lucide:cog', - color: '#f97316', - unit: 'motors', - inputs: [{ id: 'steel_ingots', amount: 3 }, { id: 'metal_frames', amount: 1 }], - outputAmount: 1, - baseCycleTime: 6.0, - unlockCost: 3500000, - unlockedDefault: false, - baseFacilityCost: 2800000, - baseManagerCost: 5500000, - baseLogisticsCost: 3800000, - basePrice: 4200.00, - facilityName: 'Motor Foundry', - managerName: 'Engine Master', - logisticsName: 'Crated Transport', - description: 'High-torque turbodiesel and hybrid electric powerplants.' - }, - { - id: 'commercial_trucks', - name: 'Commercial Trucks', - sector: 'heavy_industry', - tier: 4, - icon: 'lucide:truck', - color: '#dc2626', - unit: 'trucks', - inputs: [{ id: 'engines', amount: 1 }, { id: 'metal_frames', amount: 2 }, { id: 'circuit_boards', amount: 1 }], - outputAmount: 1, - baseCycleTime: 8.5, - unlockCost: 15000000, - unlockedDefault: false, - baseFacilityCost: 12000000, - baseManagerCost: 22000000, - baseLogisticsCost: 15000000, - basePrice: 26500.00, - facilityName: 'Vehicle Mega-Factory', - managerName: 'Plant General Manager', - logisticsName: 'Carrier Fleet', - description: 'Heavy duty articulated transport trucks for national logistics.' - } + ...AGRICULTURE_PRODUCTS, + ...MATERIALS_PRODUCTS, + ...MINING_PRODUCTS, + ...CHEMICALS_PRODUCTS, + ...ELECTRONICS_PRODUCTS, + ...HEAVY_INDUSTRY_PRODUCTS ]; // Helper to look up a product by ID diff --git a/frontend/js/data/sectors/agriculture.js b/frontend/js/data/sectors/agriculture.js new file mode 100644 index 0000000..1f94ee8 --- /dev/null +++ b/frontend/js/data/sectors/agriculture.js @@ -0,0 +1,143 @@ +// Sector 1: Agriculture & Food +export const AGRICULTURE_SECTOR = { + id: 'agriculture', + name: 'Agriculture & Food', + icon: 'lucide:wheat', + color: '#16a34a', + description: 'Primary crops, livestock, milling, and commercial foodstuffs.' +}; + +export const AGRICULTURE_PRODUCTS = [ + { + id: 'wheat', + name: 'Grain (Wheat)', + sector: 'agriculture', + tier: 1, + icon: 'lucide:wheat', + color: '#65a30d', + unit: 'bushels', + inputs: [], // Raw extraction + outputAmount: 1, + baseCycleTime: 1.0, + unlockCost: 0, + unlockedDefault: true, + baseFacilityCost: 15, + baseManagerCost: 100, + baseLogisticsCost: 80, + basePrice: 1.50, + facilityName: 'Wheat Field', + managerName: 'Farm Overseer', + logisticsName: 'Grain Sifter', + description: 'Golden wheat harvested from fertile corporate acreage.' + }, + { + id: 'flour', + name: 'Milled Flour', + sector: 'agriculture', + tier: 2, + icon: 'lucide:cookie', + color: '#84cc16', + unit: 'sacks', + inputs: [{ id: 'wheat', amount: 2 }], + outputAmount: 1, + baseCycleTime: 1.8, + unlockCost: 250, + unlockedDefault: false, + baseFacilityCost: 200, + baseManagerCost: 850, + baseLogisticsCost: 600, + basePrice: 6.20, + facilityName: 'Grain Mill', + managerName: 'Master Miller', + logisticsName: 'Flour Courier', + description: 'Fine milled wheat flour ready for commercial bakeries.' + }, + { + id: 'sugar_beet', + name: 'Sugar Beet', + sector: 'agriculture', + tier: 1, + icon: 'lucide:sprout', + color: '#a3e635', + unit: 'crates', + inputs: [], + outputAmount: 1, + baseCycleTime: 1.5, + unlockCost: 650, + unlockedDefault: false, + baseFacilityCost: 550, + baseManagerCost: 1800, + baseLogisticsCost: 1200, + basePrice: 4.80, + facilityName: 'Sugar Plantation', + managerName: 'Field Director', + logisticsName: 'Beet Hauler', + description: 'Sweet root vegetables cultivated for industrial sweetener extraction.' + }, + { + id: 'refined_sugar', + name: 'Refined Sugar', + sector: 'agriculture', + tier: 2, + icon: 'lucide:candy', + color: '#e2e8f0', + unit: 'bags', + inputs: [{ id: 'sugar_beet', amount: 3 }], + outputAmount: 1, + baseCycleTime: 2.2, + unlockCost: 2200, + unlockedDefault: false, + baseFacilityCost: 1800, + baseManagerCost: 4500, + baseLogisticsCost: 3200, + basePrice: 22.00, + facilityName: 'Refinery Plant', + managerName: 'Sugar Chemist', + logisticsName: 'Bulk Distributor', + description: 'Pure granulated sucrose ready for food production.' + }, + { + id: 'fresh_bread', + name: 'Artisan Bread', + sector: 'agriculture', + tier: 3, + icon: 'lucide:croissant', + color: '#f59e0b', + unit: 'loaves', + inputs: [{ id: 'flour', amount: 2 }, { id: 'refined_sugar', amount: 1 }], + outputAmount: 2, + baseCycleTime: 3.0, + unlockCost: 9500, + unlockedDefault: false, + baseFacilityCost: 7500, + baseManagerCost: 18000, + baseLogisticsCost: 12500, + basePrice: 58.00, + facilityName: 'Industrial Bakery', + managerName: 'Head Baker', + logisticsName: 'Delivery Fleet', + description: 'Freshly baked wholesale bread dispatched to grocery chains.' + }, + { + id: 'packaged_meals', + name: 'Packaged Meal Kits', + sector: 'agriculture', + tier: 4, + icon: 'lucide:utensils', + color: '#10b981', + unit: 'cases', + inputs: [{ id: 'fresh_bread', amount: 3 }], + outputAmount: 1, + baseCycleTime: 4.5, + unlockCost: 45000, + unlockedDefault: false, + baseFacilityCost: 36000, + baseManagerCost: 75000, + baseLogisticsCost: 55000, + basePrice: 260.00, + facilityName: 'Food Processing Line', + managerName: 'Operations Lead', + logisticsName: 'Refrigerated Transport', + description: 'Ready-to-eat branded meal kits with high retail margin.' + } +]; diff --git a/frontend/js/data/sectors/chemicals.js b/frontend/js/data/sectors/chemicals.js new file mode 100644 index 0000000..d6879cc --- /dev/null +++ b/frontend/js/data/sectors/chemicals.js @@ -0,0 +1,99 @@ +// Sector 4: Chemicals & Polymers +export const CHEMICALS_SECTOR = { + id: 'chemicals', + name: 'Chemicals & Polymers', + icon: 'lucide:flask-conical', + color: '#0284c7', + description: 'Crude oil refinement, plastics, polymers, and synthetic compounds.' +}; + +export const CHEMICALS_PRODUCTS = [ + { + id: 'crude_oil', + name: 'Crude Oil', + sector: 'chemicals', + tier: 1, + icon: 'lucide:droplet', + color: '#1e293b', + unit: 'barrels', + inputs: [], + outputAmount: 1, + baseCycleTime: 2.0, + unlockCost: 25000, + unlockedDefault: false, + baseFacilityCost: 20000, + baseManagerCost: 48000, + baseLogisticsCost: 35000, + basePrice: 55.00, + facilityName: 'Drilling Derrick', + managerName: 'Derrick Engineer', + logisticsName: 'Pipeline Station', + description: 'Black liquid gold pumped from deep continental wells.' + }, + { + id: 'silica_sand', + name: 'Silica Quartz Sand', + sector: 'chemicals', + tier: 1, + icon: 'lucide:sparkles', + color: '#38bdf8', + unit: 'drums', + inputs: [], + outputAmount: 1, + baseCycleTime: 2.2, + unlockCost: 45000, + unlockedDefault: false, + baseFacilityCost: 36000, + baseManagerCost: 75000, + baseLogisticsCost: 52000, + basePrice: 85.00, + facilityName: 'Quartz Quarry', + managerName: 'Geological Analyst', + logisticsName: 'Quartz Transport', + description: 'High-purity quartz crystals mined for semiconductor refining.' + }, + { + id: 'polymers', + name: 'Industrial Polymers', + sector: 'chemicals', + tier: 2, + icon: 'lucide:test-tube', + color: '#0ea5e9', + unit: 'pellets', + inputs: [{ id: 'crude_oil', amount: 2 }], + outputAmount: 1, + baseCycleTime: 3.5, + unlockCost: 110000, + unlockedDefault: false, + baseFacilityCost: 88000, + baseManagerCost: 175000, + baseLogisticsCost: 120000, + basePrice: 210.00, + facilityName: 'Cracking Facility', + managerName: 'Petrochemical Lead', + logisticsName: 'Chemical Tanker', + description: 'Versatile synthetic thermoplastic pellets for manufacturing.' + }, + { + id: 'silicon', + name: 'Purified Silicon', + sector: 'chemicals', + tier: 2, + icon: 'lucide:gem', + color: '#06b6d4', + unit: 'ingots', + inputs: [{ id: 'silica_sand', amount: 2 }], + outputAmount: 1, + baseCycleTime: 4.0, + unlockCost: 220000, + unlockedDefault: false, + baseFacilityCost: 175000, + baseManagerCost: 350000, + baseLogisticsCost: 240000, + basePrice: 420.00, + facilityName: 'Silicon Smelter', + managerName: 'Materials Scientist', + logisticsName: 'Clean Ingot Carrier', + description: '99.999% pure electronic grade monocrystalline silicon.' + } +]; diff --git a/frontend/js/data/sectors/electronics.js b/frontend/js/data/sectors/electronics.js new file mode 100644 index 0000000..29ee7bc --- /dev/null +++ b/frontend/js/data/sectors/electronics.js @@ -0,0 +1,77 @@ +// Sector 5: High-Tech & Electronics +export const ELECTRONICS_SECTOR = { + id: 'electronics', + name: 'High-Tech & Electronics', + icon: 'lucide:cpu', + color: '#7c3aed', + description: 'Purified silicon, microchips, circuit assemblies, and smart devices.' +}; + +export const ELECTRONICS_PRODUCTS = [ + { + id: 'microchips', + name: 'Silicon Microchips', + sector: 'electronics', + tier: 3, + icon: 'lucide:cpu', + color: '#8b5cf6', + unit: 'chips', + inputs: [{ id: 'silicon', amount: 1 }, { id: 'polymers', amount: 1 }], + outputAmount: 2, + baseCycleTime: 4.8, + unlockCost: 550000, + unlockedDefault: false, + baseFacilityCost: 440000, + baseManagerCost: 850000, + baseLogisticsCost: 600000, + basePrice: 650.00, + facilityName: 'Cleanroom Fab', + managerName: 'Lithography Director', + logisticsName: 'Precision Courier', + description: 'Nanometer-scale integrated circuits etched via photolithography.' + }, + { + id: 'circuit_boards', + name: 'PCB Motherboards', + sector: 'electronics', + tier: 3, + icon: 'lucide:circuit-board', + color: '#a855f7', + unit: 'boards', + inputs: [{ id: 'microchips', amount: 2 }, { id: 'polymers', amount: 2 }], + outputAmount: 1, + baseCycleTime: 5.5, + unlockCost: 1500000, + unlockedDefault: false, + baseFacilityCost: 1200000, + baseManagerCost: 2400000, + baseLogisticsCost: 1600000, + basePrice: 2200.00, + facilityName: 'PCB Assembly Line', + managerName: 'SMT Chief', + logisticsName: 'Static-Safe Transport', + description: 'Multi-layer printed circuit boards populated with components.' + }, + { + id: 'smartphones', + name: 'Consumer Smartphones', + sector: 'electronics', + tier: 4, + icon: 'lucide:smartphone', + color: '#ec4899', + unit: 'devices', + inputs: [{ id: 'circuit_boards', amount: 1 }, { id: 'polymers', amount: 2 }], + outputAmount: 1, + baseCycleTime: 6.5, + unlockCost: 5000000, + unlockedDefault: false, + baseFacilityCost: 4000000, + baseManagerCost: 8000000, + baseLogisticsCost: 5500000, + basePrice: 6800.00, + facilityName: 'Tech Assembly Plant', + managerName: 'VP of Electronics', + logisticsName: 'Global Freight Air', + description: 'Flagship handheld smartphones shipped to worldwide retail.' + } +]; diff --git a/frontend/js/data/sectors/heavyIndustry.js b/frontend/js/data/sectors/heavyIndustry.js new file mode 100644 index 0000000..b404f4d --- /dev/null +++ b/frontend/js/data/sectors/heavyIndustry.js @@ -0,0 +1,55 @@ +// Sector 6: Heavy Industry & Vehicles +export const HEAVY_INDUSTRY_SECTOR = { + id: 'heavy_industry', + name: 'Heavy Industry & Vehicles', + icon: 'lucide:truck', + color: '#ea580c', + description: 'Combustion engines, logistics fleets, industrial robotics, and transport.' +}; + +export const HEAVY_INDUSTRY_PRODUCTS = [ + { + id: 'engines', + name: 'Industrial Engines', + sector: 'heavy_industry', + tier: 3, + icon: 'lucide:cog', + color: '#f97316', + unit: 'motors', + inputs: [{ id: 'steel_ingots', amount: 3 }, { id: 'metal_frames', amount: 1 }], + outputAmount: 1, + baseCycleTime: 6.0, + unlockCost: 3500000, + unlockedDefault: false, + baseFacilityCost: 2800000, + baseManagerCost: 5500000, + baseLogisticsCost: 3800000, + basePrice: 4200.00, + facilityName: 'Motor Foundry', + managerName: 'Engine Master', + logisticsName: 'Crated Transport', + description: 'High-torque turbodiesel and hybrid electric powerplants.' + }, + { + id: 'commercial_trucks', + name: 'Commercial Trucks', + sector: 'heavy_industry', + tier: 4, + icon: 'lucide:truck', + color: '#dc2626', + unit: 'trucks', + inputs: [{ id: 'engines', amount: 1 }, { id: 'metal_frames', amount: 2 }, { id: 'circuit_boards', amount: 1 }], + outputAmount: 1, + baseCycleTime: 8.5, + unlockCost: 15000000, + unlockedDefault: false, + baseFacilityCost: 12000000, + baseManagerCost: 22000000, + baseLogisticsCost: 15000000, + basePrice: 26500.00, + facilityName: 'Vehicle Mega-Factory', + managerName: 'Plant General Manager', + logisticsName: 'Carrier Fleet', + description: 'Heavy duty articulated transport trucks for national logistics.' + } +]; diff --git a/frontend/js/data/sectors/materials.js b/frontend/js/data/sectors/materials.js new file mode 100644 index 0000000..fb1bcde --- /dev/null +++ b/frontend/js/data/sectors/materials.js @@ -0,0 +1,99 @@ +// Sector 2: Forestry & Materials +export const MATERIALS_SECTOR = { + id: 'materials', + name: 'Forestry & Materials', + icon: 'lucide:trees', + color: '#ca8a04', + description: 'Timber harvesting, lumber mills, paper, and commercial furniture.' +}; + +export const MATERIALS_PRODUCTS = [ + { + id: 'timber', + name: 'Raw Timber', + sector: 'materials', + tier: 1, + icon: 'lucide:trees', + color: '#b45309', + unit: 'logs', + inputs: [], + outputAmount: 1, + baseCycleTime: 1.2, + unlockCost: 120, + unlockedDefault: false, + baseFacilityCost: 95, + baseManagerCost: 350, + baseLogisticsCost: 240, + basePrice: 2.80, + facilityName: 'Lumber Camp', + managerName: 'Forester Chief', + logisticsName: 'Log Carrier', + description: 'Mature softwood felled in managed timber estates.' + }, + { + id: 'planks', + name: 'Milled Planks', + sector: 'materials', + tier: 2, + icon: 'lucide:boxes', + color: '#d97706', + unit: 'bundles', + inputs: [{ id: 'timber', amount: 2 }], + outputAmount: 1, + baseCycleTime: 2.0, + unlockCost: 1200, + unlockedDefault: false, + baseFacilityCost: 950, + baseManagerCost: 2800, + baseLogisticsCost: 2000, + basePrice: 11.50, + facilityName: 'Sawmill', + managerName: 'Sawyer Foreman', + logisticsName: 'Lumber Flatbed', + description: 'Standardized structural lumber for construction and joinery.' + }, + { + id: 'paper', + name: 'Industrial Paper', + sector: 'materials', + tier: 2, + icon: 'lucide:file-text', + color: '#cbd5e1', + unit: 'rolls', + inputs: [{ id: 'timber', amount: 3 }], + outputAmount: 2, + baseCycleTime: 2.5, + unlockCost: 3500, + unlockedDefault: false, + baseFacilityCost: 2800, + baseManagerCost: 6500, + baseLogisticsCost: 4800, + basePrice: 16.00, + facilityName: 'Pulp Mill', + managerName: 'Chemical Pulpist', + logisticsName: 'Paper Dispatcher', + description: 'Heavy paper stock used for cardboard packaging and publishing.' + }, + { + id: 'furniture', + name: 'Office Furniture', + sector: 'materials', + tier: 3, + icon: 'lucide:armchair', + color: '#92400e', + unit: 'sets', + inputs: [{ id: 'planks', amount: 3 }], + outputAmount: 1, + baseCycleTime: 3.8, + unlockCost: 18000, + unlockedDefault: false, + baseFacilityCost: 14000, + baseManagerCost: 35000, + baseLogisticsCost: 26000, + basePrice: 95.00, + facilityName: 'Joinery Workshop', + managerName: 'Master Carpenter', + logisticsName: 'Showroom Distributor', + description: 'Ergonomic executive desks, cabinetry, and boardroom chairs.' + } +]; diff --git a/frontend/js/data/sectors/mining.js b/frontend/js/data/sectors/mining.js new file mode 100644 index 0000000..6927ef1 --- /dev/null +++ b/frontend/js/data/sectors/mining.js @@ -0,0 +1,99 @@ +// Sector 3: Mining & Metallurgy +export const MINING_SECTOR = { + id: 'mining', + name: 'Mining & Metallurgy', + icon: 'lucide:pickaxe', + color: '#475569', + description: 'Ore extraction, blast furnaces, alloy smelting, and heavy frames.' +}; + +export const MINING_PRODUCTS = [ + { + id: 'iron_ore', + name: 'Iron Ore', + sector: 'mining', + tier: 1, + icon: 'lucide:mountain', + color: '#64748b', + unit: 'tons', + inputs: [], + outputAmount: 1, + baseCycleTime: 1.6, + unlockCost: 1500, + unlockedDefault: false, + baseFacilityCost: 1200, + baseManagerCost: 3500, + baseLogisticsCost: 2400, + basePrice: 12.00, + facilityName: 'Open-Pit Iron Mine', + managerName: 'Mining Superintendant', + logisticsName: 'Ore Hopper Train', + description: 'Dense hematite extracted from open-pit mineral deposits.' + }, + { + id: 'coal', + name: 'Coking Coal', + sector: 'mining', + tier: 1, + icon: 'lucide:flame', + color: '#334155', + unit: 'tons', + inputs: [], + outputAmount: 1, + baseCycleTime: 1.8, + unlockCost: 2800, + unlockedDefault: false, + baseFacilityCost: 2200, + baseManagerCost: 5500, + baseLogisticsCost: 3800, + basePrice: 15.00, + facilityName: 'Coal Pit', + managerName: 'Pit Supervisor', + logisticsName: 'Coal Conveyor', + description: 'High-energy carbon fuel essential for blast furnace reduction.' + }, + { + id: 'steel_ingots', + name: 'Structural Steel', + sector: 'mining', + tier: 2, + icon: 'lucide:anvil', + color: '#94a3b8', + unit: 'billets', + inputs: [{ id: 'iron_ore', amount: 2 }, { id: 'coal', amount: 1 }], + outputAmount: 1, + baseCycleTime: 3.2, + unlockCost: 12500, + unlockedDefault: false, + baseFacilityCost: 9800, + baseManagerCost: 24000, + baseLogisticsCost: 17000, + basePrice: 72.00, + facilityName: 'Blast Smelter', + managerName: 'Foundry Master', + logisticsName: 'Heavy Rail Freight', + description: 'High-tensile carbon steel alloys for industrial manufacturing.' + }, + { + id: 'metal_frames', + name: 'Heavy Frameworks', + sector: 'mining', + tier: 3, + icon: 'lucide:construction', + color: '#475569', + unit: 'girders', + inputs: [{ id: 'steel_ingots', amount: 3 }], + outputAmount: 1, + baseCycleTime: 4.6, + unlockCost: 65000, + unlockedDefault: false, + baseFacilityCost: 52000, + baseManagerCost: 110000, + baseLogisticsCost: 80000, + basePrice: 320.00, + facilityName: 'Fabrication Plant', + managerName: 'Chief Fabricator', + logisticsName: 'Heavy Hauler', + description: 'Rigid reinforced metal chassis and skyscraper beams.' + } +]; diff --git a/frontend/js/ui/production/facilityCard.js b/frontend/js/ui/production/facilityCard.js new file mode 100644 index 0000000..a07174f --- /dev/null +++ b/frontend/js/ui/production/facilityCard.js @@ -0,0 +1,310 @@ +// Production UI: Individual Facility Card (HTML Mount and Fine-grained DOM update) +import { getProduct, getNextMilestone, getUnitMilestoneMultiplier, SECTORS } from '../../data/products.js'; +import { fmtCurrency, fmtNum } from '../../core/formatters.js'; +import { calculateMultiCost, getProductOutputRates } from './ratesCalculator.js'; + +export function renderFacilityCardHtml(p, pState, state, buyMode) { + const sector = SECTORS.find(s => s.id === p.sector); + const isSelected = state.selectedProductId === p.id; + + if (!pState.unlocked) { + const canAffordUnlock = state.cash >= p.unlockCost; + return ` +
${p.description}
+ +${p.description}
- -