diff --git a/frontend/css/layout/header.css b/frontend/css/layout/header.css index a8a6e2d..97d99f8 100644 --- a/frontend/css/layout/header.css +++ b/frontend/css/layout/header.css @@ -98,48 +98,89 @@ background: var(--primary-blue-light); } -/* Financial HUD Grid */ +/* Financial HUD: Desktop 3-part layout (Left: Finances, Center: Sector Bar, Right: Dept Buttons & Multiplier) */ #financial-hud { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); - gap: 12px; - padding: 10px 16px; + display: flex; + justify-content: space-between; align-items: center; + gap: 16px; + padding: 8px 16px; + max-width: 1680px; + margin: 0 auto; + box-sizing: border-box; } -.hud-stat-box { - background: var(--bg-surface); - border: 1px solid var(--border-color); +/* Consolidated Executive Financial Hub */ +.executive-fin-hub { + display: flex; + flex-direction: row; + align-items: center; + gap: 14px; + padding: 6px 14px; border-radius: var(--radius-md); - padding: 8px 12px; + background: #f8faff; + border: 1px solid #bfdbfe; + flex-shrink: 0; + min-width: 270px; + box-shadow: var(--shadow-sm); +} + +.fin-hub-main { display: flex; flex-direction: column; } -.primary-hud-box { - border-color: #bfdbfe; - background: #f8faff; +.fin-hub-divider { + width: 1px; + height: 38px; + background: #cbd5e1; +} + +.fin-hub-details { + display: flex; + flex-direction: column; + gap: 2px; +} + +.fin-detail-row { + display: flex; + align-items: center; + gap: 6px; + font-size: 0.75rem; + white-space: nowrap; +} + +.fin-detail-label { + font-size: 0.68rem; + font-weight: 700; + color: var(--text-muted); + text-transform: uppercase; +} + +.fin-detail-val { + font-weight: 700; + color: var(--text-primary); } .hud-label { - font-size: 0.72rem; - font-weight: 600; + font-size: 0.68rem; + font-weight: 700; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.04em; } .hud-main-val { - font-size: 1.25rem; - font-weight: 700; + font-size: 1.20rem; + font-weight: 800; color: var(--text-primary); - line-height: 1.2; - margin: 2px 0; + line-height: 1.1; + margin: 1px 0; } .hud-sub-val { - font-size: 0.75rem; - font-weight: 600; + font-size: 0.72rem; + font-weight: 700; } .rate-positive { @@ -150,17 +191,100 @@ color: var(--purple-rnd); } +/* Centered Sector Container in Sticky Header */ +#header-sector-container { + flex: 1; + display: flex; + justify-content: center; + min-width: 0; + max-width: 820px; +} + +#header-sector-container .production-toolbar { + width: 100%; + background: var(--bg-surface); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 4px 6px; + box-sizing: border-box; + box-shadow: 0 1px 2px rgba(0,0,0,0.03); +} + +#header-sector-container .sector-pill { + padding: 6px 4px; +} + +/* Right Header Actions: Department Nav & Buy Multiplier */ +.header-right-actions { + display: flex; + align-items: center; + gap: 10px; + flex-shrink: 0; +} + +.header-nav-group { + display: flex; + align-items: center; + gap: 4px; + background: var(--bg-surface-sub); + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + padding: 3px; +} + +.header-nav-btn { + display: inline-flex; + align-items: center; + gap: 5px; + padding: 5px 10px; + background: transparent; + border: 1px solid transparent; + border-radius: 4px; + color: var(--text-secondary); + font-size: 0.78rem; + font-weight: 700; + cursor: pointer; + transition: all 0.15s; + white-space: nowrap; + text-decoration: none; + line-height: 1; +} + +.header-nav-btn iconify-icon { + font-size: 1.05rem; +} + +.header-nav-btn:hover { + background: var(--bg-surface); + color: var(--text-primary); + border-color: var(--border-color); +} + +.header-nav-btn.active { + background: var(--primary-blue); + color: #ffffff; + border-color: var(--primary-blue); + box-shadow: var(--shadow-sm); +} + +.header-nav-btn.active .nav-pill-badge { + background: #ffffff; + color: var(--primary-blue); +} + +.header-nav-btn.active iconify-icon { + color: #ffffff; +} + +.header-nav-btn .nav-pill-badge { + margin-left: 2px; + padding: 1px 5px; + font-size: 0.65rem; +} + .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 { @@ -175,7 +299,7 @@ .btn-multi-pill { background: transparent; border: none; - padding: 4px 10px; + padding: 4px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: 700; @@ -186,7 +310,7 @@ } .btn-multi-pill.active { - background: var(--primary-blue); + background: var(--text-primary); color: #ffffff; box-shadow: var(--shadow-sm); } diff --git a/frontend/css/layout/responsive.css b/frontend/css/layout/responsive.css index e58f688..5114f16 100644 --- a/frontend/css/layout/responsive.css +++ b/frontend/css/layout/responsive.css @@ -64,6 +64,26 @@ .production-grid, .contracts-grid, .perks-grid, .achievements-grid { grid-template-columns: 1fr; } + + .header-nav-group { + display: none; + } + + #financial-hud { + flex-wrap: wrap; + gap: 8px; + } + + .executive-fin-hub { + min-width: auto; + flex: 1; + } + + #header-sector-container { + order: 3; + width: 100%; + max-width: 100%; + } } /* Cramped / Mobile viewport: Hide sector pill numbers so only icons are displayed */ diff --git a/frontend/index.html b/frontend/index.html index 7eb1d10..851abcc 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -46,37 +46,66 @@ - +
-
-
Liquid Capital
-
$0.00
-
+$0.00/s
-
- -
-
Enterprise Valuation
-
$0.00
-
Asset Value & Equity
-
- -
-
Venture Capital ($V-Shares)
-
- - 0 + +
+
+
Capital & Valuation
+
$0.00
+
+$0.00/s
+
+
+
+
+ Valuation: + $0.00 +
+
+ V-Shares: + + + 0 + +
-
IPO Expansion Equity
- -
- Buy Batch: -
- - - - + +
+ +
+ + +
+ + + +
+
+ + + + +
diff --git a/frontend/js/app.js b/frontend/js/app.js index 8bb4cdd..e4ec9af 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -7,6 +7,7 @@ import { SyncManager } from './core/sync.js'; import { fmtCurrency, fmtNum, fmtRate, getNotation, setNotation } from './core/formatters.js'; import { PRODUCTS, SECTORS, getProduct } from './data/products.js'; import { mountProductionFloor, updateProductionFloor, calculateMultiCost } from './ui/productionView.js'; +import { renderSectorTabsHtml } from './ui/production/sectorBar.js'; import { mountContractsBoard, updateContractsBoard } from './ui/contractsView.js'; import { mountBoardroom, updateBoardroom } from './ui/boardroomView.js'; import { mountInspector, updateInspector } from './ui/inspectorView.js'; @@ -141,6 +142,12 @@ class ProductionApp { switch (action.type) { case 'SELECT_SECTOR': state.selectedSector = action.sector; + if (state.activeTab !== 'production') { + state.activeTab = 'production'; + document.querySelectorAll('.nav-btn, .nav-tab').forEach(b => { + b.classList.toggle('active', b.dataset.tab === 'production'); + }); + } this.mountActiveView(); break; @@ -466,6 +473,16 @@ class ProductionApp { } } + mountHeaderSectorBar() { + const headerSectorContainer = document.getElementById('header-sector-container'); + if (!headerSectorContainer) return; + const selectedSector = this.sm.state.selectedSector || 'all'; + headerSectorContainer.innerHTML = renderSectorTabsHtml(selectedSector, this.engine); + headerSectorContainer.querySelectorAll('.sector-pill').forEach(btn => { + btn.onclick = () => this.handleAction({ type: 'SELECT_SECTOR', sector: btn.dataset.sector }); + }); + } + /** * Mounts the main viewport view ONCE when the tab or sector changes */ @@ -478,6 +495,9 @@ class ProductionApp { this.currentMountedTab = tab; this.currentMountedSector = sector; + // Keep header sector tabs in sync with selectedSector + this.mountHeaderSectorBar(); + if (tab === 'production') { mountProductionFloor(container, this.sm.state, (a) => this.handleAction(a), this.engine); } else if (tab === 'contracts') { diff --git a/frontend/js/ui/production/sectorBar.js b/frontend/js/ui/production/sectorBar.js index 2072a5d..f1149ee 100644 --- a/frontend/js/ui/production/sectorBar.js +++ b/frontend/js/ui/production/sectorBar.js @@ -2,10 +2,8 @@ import { SECTORS } from '../../data/products.js'; import { fmtNum } from '../../core/formatters.js'; -export function renderSectorBarHtml(selectedSector, engine) { - const currentSectorObj = SECTORS.find(s => s.id === selectedSector); - - let html = ` +export function renderSectorTabsHtml(selectedSector, engine) { + return `
`; +} + +export function renderSectorSummariesHtml(selectedSector, engine) { + const currentSectorObj = SECTORS.find(s => s.id === selectedSector); + let html = ''; // 1. Single Sector Executive Summary Banner if (selectedSector !== 'all' && currentSectorObj) { @@ -99,6 +102,10 @@ export function renderSectorBarHtml(selectedSector, engine) { return html; } +export function renderSectorBarHtml(selectedSector, engine) { + return renderSectorTabsHtml(selectedSector, engine) + renderSectorSummariesHtml(selectedSector, engine); +} + export function updateSectorBarDom(selectedSector, engine) { const elPillRateAll = document.getElementById('pill-rate-all'); if (elPillRateAll) { diff --git a/frontend/js/ui/productionView.js b/frontend/js/ui/productionView.js index ed84706..583433c 100644 --- a/frontend/js/ui/productionView.js +++ b/frontend/js/ui/productionView.js @@ -2,7 +2,7 @@ // Clean modular orchestrator connecting sector toolbar, facility cards, and fine-grained DOM updating import { PRODUCTS } from '../data/products.js'; -import { renderSectorBarHtml, updateSectorBarDom } from './production/sectorBar.js'; +import { renderSectorBarHtml, renderSectorSummariesHtml, updateSectorBarDom } from './production/sectorBar.js'; import { renderFacilityCardHtml, updateFacilityCardDom } from './production/facilityCard.js'; export { calculateMultiCost, getProductOutputRates } from './production/ratesCalculator.js'; @@ -18,7 +18,7 @@ export function mountProductionFloor(container, state, onAction, engine) { return p.sector === selectedSector; }); - let html = renderSectorBarHtml(selectedSector, engine); + let html = renderSectorSummariesHtml(selectedSector, engine); html += `
`; for (const p of filteredProducts) {