diff --git a/NEXT-STEPS.md b/NEXT-STEPS.md index 5643951..bf8a7ba 100644 --- a/NEXT-STEPS.md +++ b/NEXT-STEPS.md @@ -112,7 +112,8 @@ The viewer still works as an observer/debug client first. Recommended work: -- fix the current `followedShipId` regression in `GameViewer.ts` +- keep tuning the tactical and `camera-follow` camera feel +- add clearer camera mode affordances in the HUD / ship rail - show station module state and construction state - show dock occupancy and waiting ships - expose fuel-chain health diff --git a/SESSION.md b/SESSION.md index b51313c..5271acc 100644 --- a/SESSION.md +++ b/SESSION.md @@ -49,19 +49,24 @@ The viewer currently supports: - structures - celestials - `WASD` panning on the `XZ` plane -- middle-mouse orbit camera +- middle-mouse tactical orbit camera - smooth wheel zoom across local, system, and universe scales - layered system presentation - one active local system with detailed content - non-local systems projected as distant shell markers - procedurally animated planets and moons from orbital metadata - ringed planets, binary star presentation, and richer resource visuals -- follow-camera behavior for selected ships +- explicit camera modes + - tactical free-move / orbit camera + - `camera-follow` third-person trailing camera for ships - dedicated `System` and `Focus` panels on the right HUD - hover labels for projected system markers - a bottom ship list with horizontally scrolling ship cards - - card click selects and follows the ship + - card click selects the ship + - card double-click selects, focuses, and enables `camera-follow` + - cards now span the full screen width as a compact bottom rail - cards show ship name, class, fuel, energy, state, and order + - cards include a compact history icon button under the ship-class tag - multiple floating history windows for debugging - openable from ship cards - independently movable and resizable @@ -159,6 +164,8 @@ The runtime model still follows the intended layered control architecture: - added viewer-side interpolation / short extrapolation for movement - added a plain-text network statistics readout - reworked the camera with smoother zoom, orbit, panning, and marquee selection +- split viewer camera behavior into tactical and `camera-follow` modes +- added ship-card double-click to focus and enter follow mode - cleaned up several viewer HUD elements and removed redundant panel content - expanded the backend world into a large procedural galaxy with elevated vertical variance - added deterministic orbital metadata for planets and client-side orbital animation in the viewer @@ -204,7 +211,7 @@ The runtime model still follows the intended layered control architecture: - no command submission UI yet - local / projected / galaxy presentation is now workable but still needs tuning - shell marker art direction and scaling still need polish - - local camera feel still needs iteration + - tactical/follow camera tuning still needs iteration - projected-system composition is still a viewer illusion, not a full multi-layer renderer - the galaxy is much larger now, so viewer performance and visual density need active tuning - moon rendering is procedural from counts, not authored moon-by-moon data @@ -216,7 +223,6 @@ The runtime model still follows the intended layered control architecture: - constructor logic only builds from station-local inventory - it does not yet fetch module materials from other stations or ships - station installed modules and active construction are not yet exposed in the viewer contract -- some viewer follow-camera code is currently broken by a pre-existing missing `followedShipId` property - piracy and faction growth are still functional rather than strategically deep - no persistence for saves, seeds, or reconnect state diff --git a/apps/viewer/src/style.css b/apps/viewer/src/style.css index b1c4d14..0ab761d 100644 --- a/apps/viewer/src/style.css +++ b/apps/viewer/src/style.css @@ -326,31 +326,34 @@ canvas { .ship-strip { position: absolute; - left: 20px; - bottom: 20px; - width: min(920px, calc(100vw - 440px)); - min-height: 140px; - border-radius: 24px; - padding: 16px; + left: 0; + right: 0; + bottom: 0; + width: 100vw; + min-height: 128px; + border-radius: 0; + padding: 0; display: flex; align-items: stretch; - gap: 12px; + gap: 0; overflow-x: auto; overflow-y: hidden; pointer-events: auto; scrollbar-width: thin; + background: linear-gradient(180deg, rgba(5, 10, 18, 0), rgba(5, 10, 18, 0.92) 28%); } .ship-card { - border-radius: 18px; - border: 1px solid rgba(127, 214, 255, 0.14); - background: linear-gradient(180deg, rgba(11, 23, 43, 0.85), rgba(7, 15, 28, 0.9)); - padding: 14px; - min-width: 220px; - max-width: 220px; + border-radius: 0; + border-top: 1px solid rgba(127, 214, 255, 0.14); + border-right: 1px solid rgba(127, 214, 255, 0.1); + background: linear-gradient(180deg, rgba(10, 20, 36, 0.96), rgba(6, 12, 22, 0.98)); + padding: 10px 12px 12px; + min-width: 208px; + max-width: 208px; display: flex; flex-direction: column; - gap: 8px; + gap: 6px; color: var(--text); cursor: pointer; transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease, background 140ms ease; @@ -363,7 +366,7 @@ canvas { } .ship-card.is-selected { - border-color: rgba(255, 191, 105, 0.82); + border-top-color: rgba(255, 191, 105, 0.82); background: linear-gradient(180deg, rgba(31, 33, 20, 0.9), rgba(20, 18, 10, 0.92)); } @@ -378,28 +381,66 @@ canvas { gap: 10px; } +.ship-card h3 { + font-size: 0.82rem; + line-height: 1.15; + letter-spacing: 0.04em; +} + +.ship-card-meta { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 6px; +} + .ship-card-badge { - padding: 4px 8px; + padding: 3px 8px; border-radius: 999px; background: rgba(127, 214, 255, 0.12); color: var(--accent); - font-size: 0.68rem; + font-size: 0.64rem; letter-spacing: 0.12em; text-transform: uppercase; } .ship-card p { - margin: 6px 0 0; + margin: 2px 0 0; color: var(--muted); - line-height: 1.45; + line-height: 1.35; font-family: "IBM Plex Mono", "SFMono-Regular", monospace; - font-size: 0.77rem; + font-size: 0.72rem; +} + +.ship-card-header + p { + font-size: 0.62rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.ship-card-ai { + margin-top: 2px; + padding-top: 6px; + border-top: 1px solid rgba(127, 214, 255, 0.08); +} + +.ship-card-section-title { + margin: 0; + color: var(--accent); + letter-spacing: 0.14em; + text-transform: uppercase; } .ship-card-history-button { - margin-top: auto; - padding: 8px 12px; - align-self: flex-start; + width: 24px; + height: 24px; + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; + align-self: flex-end; + font-size: 0.78rem; + line-height: 1; } .swatch { @@ -411,8 +452,7 @@ canvas { @media (max-width: 1080px) { .ship-strip { - right: 20px; - width: auto; + width: 100vw; } } @@ -452,11 +492,11 @@ canvas { } .ship-strip { - left: 20px; - right: 20px; - bottom: 20px; - width: auto; - min-height: 126px; + left: 0; + right: 0; + bottom: 0; + width: 100vw; + min-height: 120px; } .history-window {