Every scrolling surface carries the kit's .ui-scroll, which
draws the thin themed scrollbar from --scroll-thumb and --scroll-track; the
Context panel and others drew the platform's light scrollbar because the
page declares no dark color-scheme. The per-panel scrollbar rules go; Cyber
sets the two tokens and Cockpit's HUD windows keep their accent tint.
Selects draw .gev-field's own chevron instead of the platform arrow, the
voice selects join .gev-field, number fields keep dark spinners, and the
Street Level range uses the shared slider in its green.
VisualSettings no longer toggles the style buttons' active class or writes
the dock's style mini status and the ACTIVE STYLE corner. It publishes the
active style and its label to the gev-display store; CommandDockView and
SceneChromeView render them. The buttons keep their owner's listeners, and
the initial label renders through t().
CctvControls presents the switch, navigation and toggle buttons, the CAL
chip and the meta line with a pure presentCctvPanel() and publishes them
to the gev-cctv store; CctvPanel renders them. The controls keep their
listeners on the same elements, and still write the picker, frame, source
badge, calibration readout and summary, which carry no bindings.
A page that imports ui/cctv with its own markup no longer has these
elements painted for it, as with Street Level.
The scene chrome, cockpit, Display controls, command dock, layer panels,
Context rail, welcome card and Provider Settings move verbatim into
src/ui/views and mount into their hosts before the page is translated and
wired. Each view renders the same elements, attributes and text as its
template; Vue keeps whitespace between elements as one space, and no view
markup sits under a white-space: pre rule.
Template asset URLs stay literal, view files are left out of Prettier so
the markup is not reflowed, and the Node component loader moves to build/
and is exported as build/register-vue for host test runners. Hosts that do
not initialize Core's locale pass localePicker: false instead of editing
the markup.
The merge from main kept this branch's side of four conflicts, which dropped the Snow PR's changes: tests expected Snow again, the share-link table lost its retired mark, and the voice pins lost the Snow restore. Keep both retirements, and re-derive the full-payload digest for both enum removals.
Operator was the only layout that displayed the top banner bar. Its markup, styles and keep-out selectors are removed, and the Cyber style test now checks that none remain.
CI failed at format:check: the format scope still listed the deleted
panelChrome.radioOwnership test, and panelRails.test.mjs needed Prettier
after its glow list shrank.
The new Context title colour outranked Cyber's red panel titles, and the
collapsed Context launcher came out brighter than its siblings; the rule
now applies only to the expanded panel outside Cyber. Cyber's layout-focus
standby card had relied on the old dashed border and centring, so it
drew a 3px frame with its text off the radar art; it now names its own
1px frame, padding and centring. Cyber also drops the shared segmented
track, which drew a third frame around its already framed mode buttons.
Tests now pin the Context header to its title and collapse control, the
segmented control, 10px type, the missing halo and the scoped title
colour, plus the Cyber standby and track overrides. Each fails on the
previous CSS or markup.
qa-radio enables Radio and starts the first Play from the visible
controls, expanding Context and Radio the way a person must, then puts
the panels back. The Escape test and its mutation describe what they
still protect. CURRENT-STATE no longer describes the removed Radio icon
or compact player.
qa-radio cycles Minimal, off, on, then Tactical, so the HUD toggle must
restore a non-default layout, and expects that sequence instead of the
removed Operator step.
The share-link test pins the exact hudVariant codes, so dropping or
moving operator's reserved code fails it. A live IntelHUD test checks
that a retired Operator layout falls back to Tactical, and the Cyber
test stub themes from the normalized value.
The share-link table marks operator as retired, and the zh-CN glossary
drops the removed string.
Snow is no longer offered anywhere a style can be chosen: the Visual
Presets tray, keyboard shortcut 7, the Cockpit vision carousel, and the
set_visual_style voice action. The shader and its labels go with it;
weather snowfall and the SNOW weather condition are unaffected.
Share links keep working. Snow's enum code (6) stays reserved, so a
compact or long-form link that names it opens on Normal and drops the
Snow shader parameters without reporting them as unknown. A Scene
Director shot saved with Snow plays on Normal too. Snow's frozen share
defaults matched Normal's apart from those parameters, so no other
setting in an old link changes meaning.
The legacy voice-schema pins restore Snow before hashing, so the
unchanged pins still prove nothing else moved; the complete Realtime
payload digest is re-derived.
Display > HUD > Layout and the set_hud voice action now offer Tactical,
Minimal and Cyber. The Operator option, its CSS and its QA coverage are
removed, and the unused "Operator" translations are pruned.
Share-link codes are append-only, so operator keeps its hudVariant code.
A link, scene or saved state that names it restores the default Tactical
layout. The voice schema pins keep their legacy digests by restoring the
retired value before comparing; the full-payload digest is re-derived.
Mark every UI string the unmarked-text check reported (534) plus text it
cannot see (helpers, joined labels, runtime-built panels), and translate
the result to Spanish and Russian: 1,679 messages each.
- Kept on purpose, with the reason where the text lives: provider and
product names, place and camera names, codes and units, dB values, the HUD
terminal readouts, demo shot titles that saved projects look up by title,
and text for AI tools and the voice model.
- Modules shared with the server or AI tools stay free of the i18n import
(local msg); the wind reading and voice session stay English and are
translated where the page shows them.
- npm test now runs the unmarked-text check.
- Fixes on the way: a duplicated radio privacy paragraph, the contact panel
toggle saying Expand while open, the CSS filter mistaking & for CSS.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The right rail took its top from the left stack's bounding rect while the
left stack's `top` was still transitioning (150 ms): the left layout sets
its target and calls onAligned() synchronously, the right pass runs a
frame later mid-transition, and nothing re-ran it when the transition
ended. The rail then sat ~32 px off and jumped on the next unrelated
relayout - under the pointer in CI's panel gates, which is why a header
press missed on every run.
settledLeftRailTop() reads the end value of a running `top` transition
(falling back to dataset.safeTopPct, then the rect). A settled stack is
read from its rect as before, which keeps Cyber's CSS top override (and
cockpit's transition: none) exactly as they were. The Cyber test's
pinned pattern follows the new helper.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
From gekh's review of #768, each with a test that fails before:
- P2: the panel no longer reopens on every page load. The shell reports
who asked for Street Level to switch on; only a user, voice or tool
request (isExplicitLayerStateOrigin) or an opening photo opens it, and
those automatic opens are never stored. Without the hook, a stored or
shared "collapsed" choice wins during the restore window.
- P2: the expanded photo hides in Clean View, recording and the cockpit,
and holds neither Esc nor Tab while hidden.
- Esc/Tab are taken only from the viewer, body or globe, not app-wide;
FIT/FILL show the right choice while expanded; a 0x0 viewer is never
resized (no z=NaN tile request); the expanded viewer keeps the panel's
CSS tokens; KEY REQUIRED hides the raw "no_key" code.
- Share links carry the panel's collapsed state (ui token t); the Cyber
theme frames the panel like its rail peers (the pinned Cyber selector
tests now list it).
- Accessibility: radiogroups move with arrow keys and are one tab stop,
their focus ring is no longer clipped, and the provider chips sit
outside the disabled fieldset so the "how to add the key" hint stays
reachable (a gated chip explains instead of toggling).
- Renders write only changed attributes (the rail's MutationObserver
relaid out on every write); one coalesced resize per open; the legacy
render-mode key migration is gone.
Co-Authored-By: Claude Opus 5.5 <[email protected]>