{ "_comment": "SHOP UI — the buy/sell (and buyback) screen over the shop clip (data/shopui.json). LAYOUT: the SELL grid (the player's cargo bays) sits on the LEFT, the BUY list (the shop's stock, as a scrollable list of wide rows) RIGHT NEXT TO it with just a bit of padding between (grid.centerW) — the panel is pure selection. The panel SPANS the screen: the SELL grid's left edge is flush with the planet text (data/landing.json → landing.hud.marginX), and the BUY list stretches to the same right padding. The trade ACTIONS (Confirm/Clear) + the live NET-credits readout ride on the TAB SUB-BAR (→ tabs/preview/buttons), and the tab sub-bar toggles Buy/Sell ↔ Buyback (Buyback is disabled until the player has SOLD something this session). The panels are semi-transparent so the shop clip shows through; items + text are full alpha. SELL CELLS show the good's ICON only — the name + price appear in a hover TOOLTIP (→ tooltip) instead of over the icon. BUY ROWS carry their name + description (wraps to two lines, never over the price/stepper) + price INLINE (no tooltip — the row is wide enough). GEOMETRY (slot/gap/grid/centerW) is primitives the code (js/ui/shop/ShopView.js) lays out against the live scene size — not pixel positions. The ECONOMY itself (prices, stock) is Economy.js + data/goods.json + data/economy.json; this file is only presentation.", "enabled": true, "tabs": { "_comment": "The tab sub-bar (the deck's cyberpunk style — js/ui/MenuButton.js): [Buy/Sell][Buyback] │ [Clear][Confirm] │ NET — the tabs, the trade ACTIONS (→ buttons), and the live NET readout (→ preview), past hairline dividers, on ONE console. Buy/Sell opens the trade panel; Buyback opens the buyback panel (goods sold this session, session-local only). Size/palette come from data/save.json → subBar + colors (the Menu sub-bar recipe); this section just holds the labels + Buy/Sell accent. The sub-bar rests above the command deck, anchored to the deck's Shop button (SurfaceScene.shopAnchor).", "buySell": "Buy/Sell", "buyback": "Buyback", "activeAccent": "#00e5ff", "disabledAlpha": 0.34 }, "panel": { "_comment": "The semi-transparent panel behind each side (the SELL grid's bays / the BUY list's rows) — the shop clip shows through it (bgAlpha < 1) but the goods + labels sit at full alpha on top.", "bgColor": "#0a1120", "bgAlpha": 0.7, "border": "#22405f", "pad": 16, "title": { "fontSize": 21, "color": "#eaf6ff", "h": 34 } }, "grid": { "_comment": "The SELL side's 4×4 bay grid (data/economy.json → cargo.maxSlots = 16 slots): the first `capacity` cells are live cargo bays (one good each), the rest are locked (the hold's upgrade room). `centerW` is the small PADDING gap between the SELL grid and the BUY list (the panels sit side by side; the trade actions live on the tab sub-bar — → buttons). (The BUY side is a list now — → buyList.)", "cols": 4, "rows": 4, "slot": 96, "gap": 10, "centerW": 16 }, "slot": { "_comment": "A single SELL bay cell. `bg` is the cell plate, `selected` the SELL-check highlight (a bay marked to sell), `selBgColor`/`selBgAlpha` the slightly lifted green-tinted fill a checked bay gets, and `check` the green CHECKMARK badge in the checked bay's upper-left corner (a second tap reverts all of it). `lockAlpha` dims the locked/empty cells. `iconScale` sizes the good icon, which fills the cell (the name + price live in the hover tooltip, not over the icon). `name`/`price` colors feed the tooltip's name/price lines. Colors follow the theme (green = queued/sell, cyan = info, magenta = bad).", "bgColor": "#0e1728", "border": "#1d2e4c", "selected": "#7ce8a4", "selBgColor": "#152a22", "selBgAlpha": 0.95, "check": { "size": 11, "inset": 7, "color": "#7ce8a4", "badgeBg": "#0a1410", "badgeAlpha": 0.85 }, "lockAlpha": 0.3, "iconScale": 0.62, "name": { "fontSize": 11, "color": "#eaf6ff" }, "price": { "fontSize": 12, "sell": "#7ce8a4" }, "emptyLabel": "—", "lockLabel": "locked" }, "buyList": { "_comment": "The BUY side (js/ui/shop/BuyList.js): the shop's stock as a SCROLLABLE LIST of WIDE ROWS — line 1 (the TITLE line): [icon] NAME … (padding) INVENTORY (\"N left\" / \"SOLD OUT\", the origin's remaining daily batch — model v2) … (padding) PRICE, − qty +; line 2: the good's `flavor` (data/goods.json), wrapped to the row's full width (desc.maxLines). The name is truncated to the title line's budget so it can never collide with the inventory strip or the price (`stock.gap` is the padding between name→inventory and inventory→price; `stock.w` reserves the strip's width). Live, ShopView STRETCHES the list from just past the SELL grid out to the right padding (data/landing.json → landing.hud.marginX) — `w` is only the fallback when no width is passed (headless/dev). Sized to the SELL grid's height so the panels align top AND bottom; the list scrolls (drag on the body / mouse wheel) when the stock outgrows the viewport — rows outside it are hidden (row-based clipping; this Phaser build has no camera/mask clip). A row in the pending trade (qty > 0) gets the accent border + lit qty. `rowH` is tall enough for the two lines. `pad` insets rows from the panel edge; the title bar reuses panel.title.", "w": 560, "pad": 14, "rowH": 72, "rowGap": 6, "icon": 44, "iconGap": 12, "name": { "fontSize": 14, "color": "#eaf6ff" }, "desc": { "fontSize": 11, "color": "#7d92c4", "maxLines": 2 }, "price": { "fontSize": 14, "color": "#ffc94d", "w": 64 }, "rowBg": "#0e1728", "rowBgAlpha": 0.55, "rowBorder": "#1d2e4c", "rowSelBg": "#12283a", "rowSelBgAlpha": 0.85, "selected": "#00e5ff", "focus": { "_comment": "The light stroke around the SCOUTED row (the player tapped its box — the scout panel shows its strategy). A soft wide glow under a bright thin core; it follows the row as the list scrolls and vanishes when the row clips out. (js/ui/shop/BuyList.js → _renderFocus.)", "color": "#00e5ff", "alpha": 0.95, "glow": 5, "glowAlpha": 0.3, "core": 1.5 }, "stock": { "w": 78, "gap": 16, "fontSize": 14, "color": "#ffc94d" } }, "tooltip": { "_comment": "The hover tooltip — one per SELL grid (shared), revealed when the pointer is over a usable bay: the good's NAME + the sell-price line (\"sell for N cr\"). Anchored above the cell, or below when there's no room (top row); centred on the cell, clamped to the panel. Size/palette follow the theme; text is the body face (Centauri). (The BUY list has no tooltip — its rows carry the name/price inline.)", "bgColor": "#0a1120", "bgAlpha": 0.96, "border": "#22405f", "pad": 10, "gap": 8, "nameFontSize": 14, "priceFontSize": 13 }, "stepper": { "_comment": "The BUY list's per-row quantity stepper (− n +): clicking −/+ adjusts that good's buy quantity (the qty tap = +1); the live preview recalcs. `w` is the stepper block's width (sizes the price gap). The sell side is bay-based (each bay = 1 unit, tap to check), so it has no stepper.", "fontSize": 19, "w": 88, "color": "#eaf6ff", "btn": "#7d92c4", "activeColor": "#00e5ff" }, "preview": { "_comment": "The live NET-credits readout — on the TAB SUB-BAR, right of the Buy/Sell + Buyback buttons, past a hairline divider (→ divider): tabs AND the pending trade's credit delta on one console, one glance apart. Positive (you're up) = green, negative (a net spend) = the value shown in magenta, zero = dim (entry state / nothing selected). The value is right-aligned at the bar's end so longer numbers (+1,240 cr) never resize the bar. Confirm is disabled while the trade is invalid (can't go negative, hold overflows).", "label": "NET", "labelColor": "#7d92c4", "labelFontSize": 12, "valueFontSize": 22, "zeroColor": "#7d92c4", "posColor": "#7ce8a4", "negColor": "#ff2d6f", "gap": 12, "divider": { "width": 2, "height": 26, "color": "#22405f", "alpha": 0.9 } }, "buttons": { "_comment": "Confirm (execute the trade) + Clear (reset this side's selection) — on the TAB SUB-BAR (→ tabs), between the tabs and the NET readout: they appear once the player starts checking/stepping items, and serve BOTH the trade and the buyback tabs. Confirm is grayed (disabled) while the trade is invalid. Button size/palette come from data/save.json → subBar (the same MenuButtons as the tabs); this section just holds the labels + accents.", "confirmLabel": "Confirm", "clearLabel": "Clear", "confirmAccent": "#7ce8a4", "clearAccent": "#7d92c4" }, "animation": { "_comment": "Reveal: the SELL grid slides in from the left, the BUY list from the right (data/shopui.json → animation). A short stagger keeps it feeling assembled rather than popped.", "slideMs": 340, "staggerMs": 26, "ease": "Cubic.Out" }, "scout": { "_comment": "The TRADE SCOUT — the strategy panel that replaces the cargo grid when the player taps a BUY-list row (outside the stepper). Tap the same box again, the list dead space, or the panel itself to close it (the cargo grid returns) — EXCEPT the best-exit rows: tapping one offers the SET DESTINATION popup (the destination names the exit's WORLD — its planet of that class, the station, or the home world — not just the system; each exit carries objectId/objectName; setDestination below; the scene's ConfirmOverlay, same dialog as the map's). Data: js/economy/TradeScout.js (pure); UI: js/ui/shop/ScoutPanel.js. It FILLS the SELL grid box — only type/ink/colors live here.", "topN": 3, "setDestination": { "width": 520, "height": 176 }, "revealMs": 140, "pad": 18, "title": { "label": "TRADE SCOUT", "fontSize": 18, "color": "#eaf6ff" }, "icon": 88, "name": { "fontSize": 19, "color": "#eaf6ff" }, "meta": { "fontSize": 11, "color": "#7d92c4" }, "priceBuy": { "fontSize": 12, "color": "#ffc94d" }, "flavor": { "fontSize": 12, "color": "#7d92c4" }, "section": { "fontSize": 10, "color": "#3d4c74" }, "chip": { "fontSize": 11, "color": "#eaf6ff" }, "exitRow": { "h": 40, "fontSize": 13, "color": "#eaf6ff" }, "exitPrice": { "fontSize": 13, "color": "#7ce8a4" }, "exitProfit": { "fontSize": 11, "posColor": "#7ce8a4", "negColor": "#ff2d6f" }, "barColor": "#7ce8a4", "ranks": [ "#ffc94d", "#c8d4e8", "#d09058" ], "empty": "No charted exit yet — every CAPITAL buys everything. Chart a world that wants this good (or a capital) and it will rank here." } }