@bongos/core 1.25.6 → 1.25.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +37 -27
- package/docs/copy-inventory.md +9 -8
- package/docs/copy-registry.json +20 -11
- package/docs/module-api-changelog.md +2 -2
- package/docs/page-readings.json +37 -37
- package/modules/hall-ui/public/shell-game.js +98 -2
- package/modules/hall-ui/public/style.css +59 -0
- package/modules/hall-ui/public/visor.css +11 -0
- package/modules/hall-ui/public/visor.js +14 -5
- package/modules/hall-ui/records/game-menu.md +22 -0
- package/modules/hall-ui/records/game-mode.md +2 -2
- package/modules/hall-ui/records/options-menu.md +1 -1
- package/modules/hall-ui/records/start-screen.md +2 -2
- package/modules/hall-ui/records/visor.md +4 -0
- package/modules/ui-design/public/brand.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -1
- package/src/module-api.js +1 -1
- package/tests/hall_game_menu.mjs +195 -0
- package/tests/hall_options_menu.mjs +4 -1
- package/tests/hall_visor.mjs +40 -5
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# The game menu — game mode's Escape: options, log out, exit (task 1005250)
|
|
2
|
+
|
|
3
|
+
Covers: every game place (`shell-game.js` `openMenu`, `style.css` `.game-menu`), and the visor's two ways in (`visor.js`). Game mode itself is in `game-mode.md`; the options window it opens is in `options-menu.md`.
|
|
4
|
+
|
|
5
|
+
## What it settled (owner, 2026-11-12: "a game menu like in WoW")
|
|
6
|
+
|
|
7
|
+
- **Why.** Game mode has no sidebar, so it had no Sign out and no way to quit. Escape opened the options straight away, and the options held neither.
|
|
8
|
+
- **One small menu over the place.** In game mode the last Escape (one no dialog, sheet, picker or scene used) opens it; Escape again, the scrim or Return to game shuts it. It is the hall's shared dialog (`OTBDialog.bind`): Escape, the scrim, the focus trap and the focus return are the dialog's. The arrows walk the rows.
|
|
9
|
+
- **The rows** (`GAME_MENU`), in three runs: **Options** (shuts the menu and opens the options window), **Change character** (craft-mode's own `changeCharacter`, with its own confirm; no row on a page without it); **Log out**, **Exit game**; **Return to game**, the one lit row.
|
|
10
|
+
- **Log out is a link to the sign-out address.** `shell.js` already turns a click on any such link into the real sign-out (the POST, the cookies, the bounce to the front page), so the menu writes no sign-out of its own. Signing in again passes the view chooser and the start screen, as every sign-in does.
|
|
11
|
+
- **Exit game closes the tab**, and does not sign out (the start screen's Quit, the same way). A browser only closes a tab a script opened; when the tab is still there 300ms later the menu says "Your browser kept this tab open. Close it to quit."
|
|
12
|
+
- **The visor.** The Actions sheet's last row is "Game menu" on M (it was "Options" on O), and M on the glass opens it too. Escape is on the glass nowhere: one owner per key (task 1005248), and the shell's last Escape is not a visor key. The row is a link to `/settings` carrying `data-game-menu`; `shell-game.js` opens the menu for such a link, and the address is the fallback. A plain link to `/settings` (the profile chip, the start screen's Options) still opens the options window directly.
|
|
13
|
+
- **Where it does not open.** On the options menu's own page and inside its frame, Escape is the options menu's, as before. Outside game mode there is no game menu: classic has the sidebar's Sign out. A page that cannot draw it (no `OTBDialog`) opens the options, as before the menu existed.
|
|
14
|
+
- **A visor fix that came with it.** `visor.js` `busy()` counted a hidden dialog as up: a dialog bound once keeps `aria-modal` while hidden, so after the options window (or this menu) had been opened and shut once, the visor's letter keys stayed dead until a reload. It now skips a dialog inside `[hidden]`.
|
|
15
|
+
- **A new advanced action** is one row in `GAME_MENU` and one line in `onMenuClick`.
|
|
16
|
+
|
|
17
|
+
## Not done
|
|
18
|
+
|
|
19
|
+
- The start screen is not shown again on Log out without a sign-in in between; "back to the start screen, still signed in" would be its own row.
|
|
20
|
+
- Exit game does not sign out. If it should, it is one line in `exitGame`.
|
|
21
|
+
|
|
22
|
+
Tests: `tests/hall_game_menu.mjs` (the real `shell-game.js`, `hall-dialog.js` and `visor.js` in a real browser: Escape, each row, the visor's two ways in, a phone width, classic mode); `tests/hall_visor.mjs` (the hint and the sheet row); `tests/hall_options_menu.mjs` (the tip, and the fallback to the options window).
|
|
@@ -8,7 +8,7 @@ Covers: every shelled hall page (`shell-game.js`, `shell.js`). Spec: `docs/specs
|
|
|
8
8
|
- **Game mode is the existing full-screen switch, made hall-wide. There is no second full-screen mode.** The switch was already on every page (task 1004430) but remembered per page, so a reader had to turn it on 33 times. Game mode is one `localStorage` key, `hall-game`; while it is `on`, `shell.js` `storedFullscreen()` answers yes for every page, whatever that page remembers. What hides, the corner button and the Escape hand-off are the shell's, unchanged.
|
|
9
9
|
- **`shell-game.js` holds the mode and nothing else**: `window.OTBShellGame` = `on()`, `set(bool)`, `hint()`. It stamps `html[data-game="on"]` for a sheet or script that wants to read the mode. `shell.js` reads it through a fallback object, so a page without the file is never in game mode. It is its own file because `shell.js` sits on the 1,500-line ratchet; the start screen and options menu (R03, R04) are expected to grow here, not in `shell.js`.
|
|
10
10
|
- **Load order**: `shell-game.js` before `shell-trail.js` / `craft-mode.js` / `shell.js`, loaded the same way (deferred or not) as the shell on that page. Test-pinned.
|
|
11
|
-
- **Game or classic, never both (task 1005200, owner 2026-11-11).** Inside game mode there is no way back to the bars: the corner button is hidden (`style.css`) and does nothing if pressed, Escape opens the options menu, and the "how to leave" line is never shown. The only switch is Options → Preferences → View (`settings-view.js`), plus the chooser at every sign-in (`records/start-screen.md`). A page's own `hall-fullscreen:<page>` memory is still never overwritten, so switching to classic hands each page back what it remembered.
|
|
11
|
+
- **Game or classic, never both (task 1005200, owner 2026-11-11).** Inside game mode there is no way back to the bars: the corner button is hidden (`style.css`) and does nothing if pressed, Escape opens the game menu (options, log out, exit; task 1005250, `records/game-menu.md`), and the "how to leave" line is never shown. The only switch is Options → Preferences → View (`settings-view.js`), plus the chooser at every sign-in (`records/start-screen.md`). A page's own `hall-fullscreen:<page>` memory is still never overwritten, so switching to classic hands each page back what it remembered.
|
|
12
12
|
- **Game mode reaches only the game's places** (`shell-game.js` `PLACES`: home, city, goal-map, thinking, atlas, settings, profile). Any other hall page `location.replace`s to the city on load, and so does switching to game on one. A screen embedded in the options menu is exempt. The visor drops an action whose `href` is not a place (`visor.js` `inGame`). A page joins `PLACES` when it has a game version.
|
|
13
13
|
- **The choice is kept on the account**: `GET/PATCH /api/bongos/me/hall-view` (`modules/builder-settings/hall-view-prefs.js`, key `hall_view` in `behavior_prefs`, null = never chosen). `hall-game` in localStorage is only the copy a page paints from; `sync()` reads the account on every page load and switches if another browser changed it.
|
|
14
14
|
- **No page may opt out.** `<body data-fullscreen-switch="off">` would keep that page's sidebar in game mode; the test fails on one. A new hall page needs `#app-topbar` and the `shell-game.js` tag, like the rest.
|
|
@@ -17,6 +17,6 @@ Covers: every shelled hall page (`shell-game.js`, `shell.js`). Spec: `docs/specs
|
|
|
17
17
|
## For the tasks after this one
|
|
18
18
|
|
|
19
19
|
- A HUD or options menu that wants Escape must call `preventDefault()` on the press. `shell.js` `onFullscreenKey` waits one tick before leaving so a listener added after it still wins.
|
|
20
|
-
- Since R04 (task 1005144, ADR 0401) the last Escape in game mode
|
|
20
|
+
- Since R04 (task 1005144, ADR 0401) the last Escape in game mode was the options menu's (`shell-game.js` `onEscape`); since task 1005250 it opens the game menu, whose Options row opens the options (`records/game-menu.md`). On the options menu's own page it still closes it. Since task 1005200 there is no way back to the bars inside game mode.
|
|
21
21
|
|
|
22
22
|
Tests: `tests/hall_fullscreen.mjs` (the eight `game mode:` cases run the real `shell-game.js` + `shell.js`), and the script lists in `tests/hall_city.mjs`, `tests/hall_street.mjs`, `tests/hall_my_agents.mjs`, `tests/goal_map_page.mjs`.
|
|
@@ -27,7 +27,7 @@ The menu is a Helm screen, written from the hall tier's tokens alone (`settings.
|
|
|
27
27
|
|
|
28
28
|
## The options window (owner, 2026-11-11: "WoW sizing, an overlay")
|
|
29
29
|
|
|
30
|
-
- **In game mode the menu opens over the place, not as a page.**
|
|
30
|
+
- **In game mode the menu opens over the place, not as a page.** The game menu's Options row (task 1005250, `records/game-menu.md`; until then Escape itself), or a click on any link to `/settings` (the profile chip), draws one window (`shell-game.js` `openOverlay`, `window.OTBOptionsOverlay`), built on the shared dialog (`OTBDialog.bind`: Escape, scrim, close button, focus trap and return), with the page behind made `inert` while it is up, holding the menu framed with `?embed=1`; the place stays drawn behind it. Escape, the scrim or the × shuts it; `options-menu.js` `close()` shuts the window when it is in one. A page that cannot draw it falls back to the menu page. A plain visit to `/settings` is the page, as before.
|
|
31
31
|
- **Window sized, see-through.** The window is `min(1040px, …) × min(720px, …)` of glass at 48% of the ground with a light blur, over the shared `--scrim` at a third. Every embedded screen is drawn at `zoom: 0.82` with no ground of its own (`style.css`), and the menu inside it takes smaller words (`settings.css`, `html[data-embed="on"]`); a window-high length divides by the zoom (`--opt-vh`).
|
|
32
32
|
- **One review palette.** A framed screen docks no artist palette of its own (`craft-mode.js` `applyDocked`); the page around it has one.
|
|
33
33
|
- **Tests:** `tests/hall_options_menu.mjs` ("away from the menu, Escape opens the options as a window…"), `tests/page_notes_panel.mjs` (the frame docks no panel).
|
|
@@ -8,9 +8,9 @@ Covers: Home (`shell-game.js` `start()`, `shell-game.css`, the hand-off in `welc
|
|
|
8
8
|
- **Five choices, one column: Start, Options, Achievements, Extras, Quit.** Start is the one filled pill. Options is a link to `/settings`, which IS the one options menu since task 1005144 (`records/options-menu.md`); Achievements is `/profile`. Extras opens three links under the menu (the thinking sky, the atlas, the docs). Quit calls `window.close()`; a browser only closes a tab a script opened, so when the tab is still there 300ms later the screen says "Close it to quit" instead of doing nothing.
|
|
9
9
|
- **Start turns game mode on** (`set(true)`), then shows the load screen. Nothing else in the hall's interface sets it.
|
|
10
10
|
- **The load screen is the still, a tip, and the city building up.** The still is the welcome's painting for the time of day, handed in by `welcome-boot.js` (this file names no picture). In a card of the hall's own tokens, the project city is drawn by `home-city-draw.js` `citySvg` from the one bounded read Home already uses (`GET /home/city?weeks=10`), at 31 stops from the oldest week to now, about three seconds, with "The city, N weeks ago" under it. Each stop is a whole drawing set as state; nothing animates in JavaScript. With reduced motion it is the finished city at once. With no city to draw (the read failed, the scripts are missing) the still and the tip stand for 1.4s. Either way the world opens.
|
|
11
|
-
- **Tips rotate** (`localStorage 'hall-game-tip'` counts them), so each load shows the next one. A tip must be true of the hall today; the first one is the Escape rule from `game-mode.md` (rewritten by task 1005144: Escape opens the
|
|
11
|
+
- **Tips rotate** (`localStorage 'hall-game-tip'` counts them), so each load shows the next one. A tip must be true of the hall today; the first one is the Escape rule from `game-mode.md` (rewritten by task 1005144, and again by task 1005250: Escape opens the game menu).
|
|
12
12
|
- **The craft picker waits for the world.** While the start screen is up the shell asks no picker (`onAccess` returned true). `done` runs once the screen is gone and asks `OTBCraftMode.onAccess` then.
|
|
13
|
-
- **Keys.** While either screen is up it keeps every key: the arrows and Tab walk the menu, Escape folds Extras away and does nothing else, so the shell's Escape cannot flip the bars underneath. Once the world shows, the last Escape opens the
|
|
13
|
+
- **Keys.** While either screen is up it keeps every key: the arrows and Tab walk the menu, Escape folds Extras away and does nothing else, so the shell's Escape cannot flip the bars underneath. Once the world shows, the last Escape opens the game menu (task 1005250; the options menu until then); the screen's capture listener calls `preventDefault`, so the menu never opens from under it.
|
|
14
14
|
- **The look is Helm (task 1005192, [ADR 0402](../../../docs/adr/0402-helm-is-the-halls-look-and-the-hall-is-dark-only.md)).** The start screen is one full-height night panel over the painting (`--night-glass`, an ice hairline left and right at `--line-strong`), `--helm-panel-w` wide. On a desk it stands off the left edge by `--helm-inset`; that token is a `clamp`, so on a phone the panel is the whole width and the sheet still has no `@media`. In it: the mark (the project's logo when it has one) over the name in the name voice; Start as a full-width accent bar under `--accent-on` that names its key ("Enter", drawn by CSS so the choice's own text stays "Start"); the other four as quiet rows on `--rule-soft` hairlines; and at the foot, over the strong hairline, the tip the load screen will show next (`#gs-line`), with the Quit note under it when the browser keeps the tab. The rows are list rows in a panel, so they are bars, not cut buttons. A row's focus is the inset two-tone ring (`--press-focus`), which is what makes focus visible on the accent bar.
|
|
15
15
|
- **The load screen is the same panel, centred** over the painting under the hall's `--scrim`: the week in the name voice (`#gs-when`), one segment per week of the history (`#gs-segs`, the shared `.segs` / `.seg`; filled up to the week being shown, counted the way the sentence words it, and hidden from a screen reader because the sentence says the same), the city, and the tip under a hairline. With no city there are no segments.
|
|
16
16
|
- **The literal floor is zero.** Every colour, size, corner, shadow, face and measure in `shell-game.css` is a hall-tier token (`style.css`); `tests/hall_start_screen.mjs` fails on a typed one. The fade into the world is one CSS opacity transition, stopped by the hall's reduced-motion rule.
|
|
@@ -12,6 +12,9 @@ The visor is the control and the scene is the view: every main call to action in
|
|
|
12
12
|
- **The rule.** A key in `ACTIONS` or a scene's registration is a recommendation. `resolveKeys(id)` in `visor.js` hands every key out once, and the glass, the sheet and `keyFor` all read it; nothing else names a key. Who keeps a key, in order: the visor's own (A Actions, Escape Close); the keys a scene binds itself (an action without `bind`, the `keys` lines), because the visor cannot move a key it does not bind, so a second claim on one shows no key; the character's actions; the scene's `bind` actions; Options. A later claimant moves to the next free letter of its own name, then of the alphabet, never onto a key a scene binds on its page (`AVOID`: L 0 / ? F K + - =); with none free it has no key.
|
|
13
13
|
- **Options is only in the sheet** (the owner likes it there), on O, or its next free letter (the Patron's O is the Board room, so P). Pressing it opens the options window over the place, like a click. Escape on the glass is the sheet's Close only. The shell's "last Escape opens the options menu" (`shell-game.js`, ADR 0399 §2.4) is not a visor key and is unchanged.
|
|
14
14
|
- **Tests:** `tests/hall_visor.mjs` proves no shared key for every character over the sky, the city and Home, and over a hostile scene that claims A, Escape, a character key and one key twice.
|
|
15
|
+
## The game menu on the glass (task 1005250)
|
|
16
|
+
|
|
17
|
+
The Actions sheet's last row is "Game menu" on M, where it was "Options" on O: it opens the game menu (options, log out, exit; `records/game-menu.md`), and the options are a row inside that. The key rule above is unchanged: Escape is on the glass nowhere, and the shell's last Escape now opens the game menu. `busy()` no longer counts a hidden dialog as up. Where an older bullet below says "Options (Esc)", this is current.
|
|
15
18
|
|
|
16
19
|
## A place's own buttons on the glass (task 1005209, the Governor City first)
|
|
17
20
|
|
|
@@ -55,6 +58,7 @@ The glass was redrawn to the owner's mock-up "Cloud city: in the visor, minimal"
|
|
|
55
58
|
- **The four progress segments (task 1005203).** Under the place: the version the project is building, in quarters, then the same reading in words (`BONGOS-V2 · 89%`; the screen reader hears the version's name too). The owner chose the measure (2026-11-11): the version's `percent_complete` from the public `GET /versions/progress`, the number /status reports. The version is the starred focus (`GET /versions/focus`) while it is still open, else the first one `building`; with neither, or a failed read, no segments. A quarter wholly built is the soft ink, the quarter being built is the accent, the rest are outlines; each wears an outline of the night, and the words stand on a night plate (`--night-plate`, the rule task 1005196 set), for a midday sky. The arc band is `--visor-arc` (64px) and the scene inset grew to 88px (`--visor-inset-top`), so the sky's top offsets in `thinking.css` grew by 24px. Hidden on a phone, with the place. Harness fixture: `versions__progress.json`.
|
|
56
59
|
- **In the mock-up, not built, because the visor has no data for it:** the marker and name on the building in view (the visor owns no camera, ADR 0399 §2.2), and the party bars with a speaker's name and a Voice key. Each is a scene or a later task handing the visor real data; none is drawn empty.
|
|
57
60
|
- **It reads over any sky, with no per-hour style, and it darkens none of it** (task 1005196, owner 2026-11-11: "I don't like how dark the edges of the view are"). The glass paints nothing of its own: the bands of `--night-glass` at its top and bottom edge are gone, and so is the dark halo round its type. The marks carry themselves. The place, each key hint and your name and credits stand on a small cut plate of the night (`--night-plate`, the ground at 88%), sized to the words; every line is drawn twice (a wider solid stroke of the night under the ice hairline, `.visor__line--under`), so an arc is ice on night and a dark line on cream cloud; a key sits on a chip of the night. One new token, `--night-plate`. Tried first and dropped: a 4px night stroke round each letter with no plate, which filled the condensed capitals in.
|
|
61
|
+
- **The plates are smoked glass** (task 1005252, the owner's pick from a lab of seven treatments, 2026-11-12). Reviewing a screenshot of the hall put a second visor under ours, and solid plates stacked on its plates. Where the browser can blur, the place, each hint, your name and credits and the progress words are panes: the scene behind them blurred, slightly dimmed and greyed (`--smoke-blur`), a lighter tint of the night (`--smoke`, 62%), a faint sheen (`--smoke-sheen`) and a lit top edge (`--smoke-edge`). Still sized to the words, so the sky outside them is untouched. Asking for less transparency, or a browser without backdrop blur, gets the night plate (the fallback is in style.css, because visor.css carries no media query). Tried and not picked: glass bands top and foot (bring back the band task 1005196 removed), a blurred lens rim, and halos only (too weak over a white sky). On a phone (the shared 640px block in style.css) the hints and your credits keep the night plate: a live blur under a HUD the scene pans beneath costs every frame, and a phone has the weakest GPU. Every colour in the four smoke tokens derives from `--bg` or `--ink-soft`. **Seen and approved (2026-11-12):** the builder who asked for it picked smoked glass in the live lab (all seven treatments over four backdrops), then saw before/after renders of the real visor sheets (a midday sky, and a screenshot of the visor under the visor) and said "Ship it". They then saw it staged: the real hall served by the local preview harness (Home in game mode, the artisan held, the city pannable under the glass), and answered "Looks good, land it". Not yet looked at: the night hour.
|
|
58
62
|
- **A phone.** The shared phone block in `style.css` (no breakpoint of the visor's own): the top arc, its notch and the place step aside (the top of a phone is the scene's and the shell's); the foot row stays one line with nothing leaning (the sprite, the count over its word, the accent button whose name may wrap and whose key is left to the sheet, and of the hints only Actions, as three dots on a night chip). Between a phone and a wide desk the hints wrap onto a second line, right-aligned, rather than run into the button.
|
|
59
63
|
- **Scenes.** The top arc, the notch and the place sit inside the top 64px (`--visor-arc`; the segments under them take the inset to 88px, `--visor-inset-top`), so no scene's top row is struck through. Home no longer shifts its greeting row left (there is no pill top-right to clear). The city's door rises above the foot row at every width, because the accent button is centred where the door stood. The sky's `visor-on` offsets are unchanged.
|
|
60
64
|
- **Looking at it.** The stand-in scene in `tests/hall_visor.mjs` over the hall's real sheets; put a bright gradient behind it to check midday.
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
<ul class="ref-list" role="list"><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--ok)" aria-hidden="true"></span><code class="ref-name">--ok</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#187444</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4ade80</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--ok-weak)" aria-hidden="true"></span><code class="ref-name">--ok-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, #187444 12%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, #4ade80 14%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--warn)" aria-hidden="true"></span><code class="ref-name">--warn</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#895c00</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fbbf24</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--warn-weak)" aria-hidden="true"></span><code class="ref-name">--warn-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, #895c00 14%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, #fbbf24 14%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--danger)" aria-hidden="true"></span><code class="ref-name">--danger</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#b42318</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f87171</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--danger-weak)" aria-hidden="true"></span><code class="ref-name">--danger-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, #b42318 10%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, #f87171 14%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--info)" aria-hidden="true"></span><code class="ref-name">--info</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sea) 86%, #000000)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sea) 80%, #ffffff)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--info-weak)" aria-hidden="true"></span><code class="ref-name">--info-weak</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--info) 9%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--info) 14%, var(--bg-card))</code></span></li></ul>
|
|
52
52
|
<h3 class="ref-sub">Derived colours</h3>
|
|
53
53
|
<p class="ref-note">Mixed from the thirteen, never typed as a new colour. Black and white with alpha appear only as a scrim, a shadow or glass.</p>
|
|
54
|
-
<ul class="ref-list" role="list"><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass)" aria-hidden="true"></span><code class="ref-name">--glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .05)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .1)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-strong)" aria-hidden="true"></span><code class="ref-name">--glass-strong</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .08)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-edge)" aria-hidden="true"></span><code class="ref-name">--glass-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .2)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void)" aria-hidden="true"></span><code class="ref-name">--void</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050508</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-ink)" aria-hidden="true"></span><code class="ref-name">--void-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffffff</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--ink)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-edge)" aria-hidden="true"></span><code class="ref-name">--void-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .4)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--skeleton)" aria-hidden="true"></span><code class="ref-name">--skeleton</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-ink)" aria-hidden="true"></span><code class="ref-name">--accent-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 45%, #240e00)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-lift)" aria-hidden="true"></span><code class="ref-name">--accent-lift</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-tint)" aria-hidden="true"></span><code class="ref-name">--accent-tint</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 30%, #fffdf9)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 22%, #050d16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-on)" aria-hidden="true"></span><code class="ref-name">--accent-on</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a1305</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a1305</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--focus)" aria-hidden="true"></span><code class="ref-name">--focus</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent-deep) 82%, #3a1400)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--scrim)" aria-hidden="true"></span><code class="ref-name">--scrim</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(0, 0, 0, .55)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(0, 0, 0, .55)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--surface-2)" aria-hidden="true"></span><code class="ref-name">--surface-2</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 5%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 6%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-glass)" aria-hidden="true"></span><code class="ref-name">--night-glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-plate)" aria-hidden="true"></span><code class="ref-name">--night-plate</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-top)" aria-hidden="true"></span><code class="ref-name">--sky-night-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#02060c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#02060c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-mid)" aria-hidden="true"></span><code class="ref-name">--sky-night-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#07121f</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#07121f</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#456780</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#456780</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1a3348</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1a3348</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-roof)" aria-hidden="true"></span><code class="ref-name">--sky-night-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a475e</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a475e</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lit)" aria-hidden="true"></span><code class="ref-name">--sky-night-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#10263a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#10263a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#081522</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#081522</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-base)" aria-hidden="true"></span><code class="ref-name">--sky-night-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3c5d75</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3c5d75</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-night-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe9c9</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe9c9</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-line)" aria-hidden="true"></span><code class="ref-name">--sky-night-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#8fb3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#8fb3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-top)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050d16</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#17334a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#17334a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fbe3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fbe3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#b08e8c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#b08e8c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a9c0cc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a9c0cc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3f5b70</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3f5b70</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1f3a50</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1f3a50</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-base)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f0c9ab</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f0c9ab</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-line)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f4b61</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f4b61</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-top)" aria-hidden="true"></span><code class="ref-name">--sky-midday-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1d5687</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1d5687</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-mid)" aria-hidden="true"></span><code class="ref-name">--sky-midday-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a90c2</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a90c2</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#e8d2a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#e8d2a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-roof)" aria-hidden="true"></span><code class="ref-name">--sky-midday-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff3d4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff3d4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lit)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#dcc79c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#dcc79c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#7f93a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#7f93a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-base)" aria-hidden="true"></span><code class="ref-name">--sky-midday-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe6b3</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe6b3</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-line)" aria-hidden="true"></span><code class="ref-name">--sky-midday-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f679a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f679a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-top)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#0a0f24</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#0a0f24</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a2552</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a2552</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffc79a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffc79a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a8748a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a8748a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#c7a3b0</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#c7a3b0</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a4470</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a4470</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#231f44</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#231f44</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-base)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f6b596</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f6b596</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-line)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#302b55</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#302b55</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-haze)" aria-hidden="true"></span><code class="ref-name">--sky-now-haze</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-glow)" aria-hidden="true"></span><code class="ref-name">--sky-now-glow</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span></li></ul>
|
|
54
|
+
<ul class="ref-list" role="list"><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass)" aria-hidden="true"></span><code class="ref-name">--glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .05)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .1)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-strong)" aria-hidden="true"></span><code class="ref-name">--glass-strong</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .08)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--glass-edge)" aria-hidden="true"></span><code class="ref-name">--glass-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .2)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void)" aria-hidden="true"></span><code class="ref-name">--void</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050508</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-ink)" aria-hidden="true"></span><code class="ref-name">--void-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffffff</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--ink)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--void-edge)" aria-hidden="true"></span><code class="ref-name">--void-edge</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(23, 24, 26, .12)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(200, 241, 247, .4)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--skeleton)" aria-hidden="true"></span><code class="ref-name">--skeleton</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 10%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-ink)" aria-hidden="true"></span><code class="ref-name">--accent-ink</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 45%, #240e00)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-lift)" aria-hidden="true"></span><code class="ref-name">--accent-lift</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 58%, #ffffff)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-tint)" aria-hidden="true"></span><code class="ref-name">--accent-tint</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent) 30%, #fffdf9)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--accent) 22%, #050d16)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--accent-on)" aria-hidden="true"></span><code class="ref-name">--accent-on</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a1305</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a1305</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--focus)" aria-hidden="true"></span><code class="ref-name">--focus</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--accent-deep) 82%, #3a1400)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>var(--accent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--scrim)" aria-hidden="true"></span><code class="ref-name">--scrim</code><span class="ref-val"><span class="ref-val__k">light</span> <code>rgba(0, 0, 0, .55)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>rgba(0, 0, 0, .55)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--surface-2)" aria-hidden="true"></span><code class="ref-name">--surface-2</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--ink) 5%, var(--bg-card))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--ink) 6%, var(--bg-card))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-glass)" aria-hidden="true"></span><code class="ref-name">--night-glass</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 72%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--night-plate)" aria-hidden="true"></span><code class="ref-name">--night-plate</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 88%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--smoke)" aria-hidden="true"></span><code class="ref-name">--smoke</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--bg) 62%, transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--bg) 62%, transparent)</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-top)" aria-hidden="true"></span><code class="ref-name">--sky-night-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#02060c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#02060c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-mid)" aria-hidden="true"></span><code class="ref-name">--sky-night-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#07121f</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#07121f</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#456780</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#456780</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1a3348</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1a3348</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-roof)" aria-hidden="true"></span><code class="ref-name">--sky-night-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a475e</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a475e</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lit)" aria-hidden="true"></span><code class="ref-name">--sky-night-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#10263a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#10263a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-shade)" aria-hidden="true"></span><code class="ref-name">--sky-night-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#081522</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#081522</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-base)" aria-hidden="true"></span><code class="ref-name">--sky-night-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3c5d75</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3c5d75</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-night-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe9c9</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe9c9</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-night-line)" aria-hidden="true"></span><code class="ref-name">--sky-night-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#8fb3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#8fb3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-top)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#050d16</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#050d16</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#17334a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#17334a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fbe3c8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fbe3c8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#b08e8c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#b08e8c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a9c0cc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a9c0cc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#3f5b70</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#3f5b70</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1f3a50</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1f3a50</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-base)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f0c9ab</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f0c9ab</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dawn-line)" aria-hidden="true"></span><code class="ref-name">--sky-dawn-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f4b61</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f4b61</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-top)" aria-hidden="true"></span><code class="ref-name">--sky-midday-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#1d5687</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#1d5687</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-mid)" aria-hidden="true"></span><code class="ref-name">--sky-midday-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a90c2</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a90c2</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#e8d2a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#e8d2a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-roof)" aria-hidden="true"></span><code class="ref-name">--sky-midday-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff3d4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff3d4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lit)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#dcc79c</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#dcc79c</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-shade)" aria-hidden="true"></span><code class="ref-name">--sky-midday-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#7f93a8</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#7f93a8</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-base)" aria-hidden="true"></span><code class="ref-name">--sky-midday-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe6b3</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe6b3</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-midday-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#fff6dc</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#fff6dc</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-midday-line)" aria-hidden="true"></span><code class="ref-name">--sky-midday-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2f679a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2f679a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-top)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-top</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#0a0f24</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#0a0f24</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-mid)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-mid</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#2a2552</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#2a2552</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffc79a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffc79a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-cloud-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-cloud-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#a8748a</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#a8748a</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-roof)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-roof</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#c7a3b0</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#c7a3b0</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lit)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lit</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#4a4470</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#4a4470</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-shade)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-shade</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#231f44</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#231f44</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-base)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-base</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#f6b596</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#f6b596</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-lamp)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-lamp</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#ffe2c4</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#ffe2c4</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-dusk-line)" aria-hidden="true"></span><code class="ref-name">--sky-dusk-line</code><span class="ref-val"><span class="ref-val__k">light</span> <code>#302b55</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>#302b55</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-haze)" aria-hidden="true"></span><code class="ref-name">--sky-now-haze</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-mid) 55%, var(--sky-now-cloud))</code></span></li><li class="ref-row ref-row--colour"><span class="ref-swatch" style="background: var(--sky-now-glow)" aria-hidden="true"></span><code class="ref-name">--sky-now-glow</code><span class="ref-val"><span class="ref-val__k">light</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span><span class="ref-val"><span class="ref-val__k">dark</span> <code>color-mix(in srgb, var(--sky-now-lamp) calc(var(--sky-now-windows) * 100%), transparent)</code></span></li></ul>
|
|
55
55
|
</section>
|
|
56
56
|
<section class="scroll ref-sec" id="ref-type" aria-labelledby="ref-type-h">
|
|
57
57
|
<h2 class="scroll__h" id="ref-type-h">Type</h2>
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.7",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.25.
|
|
9
|
+
"version": "1.25.7",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.7",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -11729,7 +11729,22 @@
|
|
|
11729
11729
|
"text": "The fleet view can now show which projects get automatic patch upgrades, and the nightly upgrade run says so out loud when it has nothing to do."
|
|
11730
11730
|
}
|
|
11731
11731
|
],
|
|
11732
|
-
"1.25.
|
|
11732
|
+
"1.25.7": [
|
|
11733
|
+
{
|
|
11734
|
+
"id": "1005252",
|
|
11735
|
+
"text": "In game mode the visor's labels now sit on smoked glass that blurs whatever is behind them, so a busy scene, or a screenshot of the hall being reviewed, no longer looks like a second visor."
|
|
11736
|
+
},
|
|
11737
|
+
{
|
|
11738
|
+
"id": "1005251",
|
|
11739
|
+
"text": "In game mode, Escape now only ever closes things; it no longer opens the options menu. Also fixed the visor's keys going dead after Options had been opened once."
|
|
11740
|
+
},
|
|
11741
|
+
{
|
|
11742
|
+
"text": "Escape opens the game menu (owner 2026-11-13, task 1005250 wins); keep the closed-dialog key test (task 1005251)"
|
|
11743
|
+
},
|
|
11744
|
+
{
|
|
11745
|
+
"id": "1005250",
|
|
11746
|
+
"text": "Game mode now has a game menu on Escape: players can open options, change character, log out or quit the game from one place."
|
|
11747
|
+
},
|
|
11733
11748
|
{
|
|
11734
11749
|
"id": "1005036",
|
|
11735
11750
|
"text": "An archon can now create a test project: a project marked for trying features that are not finished. It stays off the public map, does not use up anyone's one free hosted project, and is the only kind where the guided setup ca"
|
package/src/module-api.js
CHANGED
|
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
|
|
|
81
81
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
82
82
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
83
83
|
|
|
84
|
-
const CORE_VERSION = '1.25.
|
|
84
|
+
const CORE_VERSION = '1.25.7'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
85
85
|
|
|
86
86
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
87
87
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// tests/hall_game_menu.mjs — the game menu (task 1005250).
|
|
2
|
+
//
|
|
3
|
+
// WHY. Game mode has no sidebar, so a player could neither sign out nor quit. The game menu is
|
|
4
|
+
// the one way to do both, so a menu that draws but whose rows do nothing, or an Escape that
|
|
5
|
+
// still opens the options straight away, would leave the player locked in again. This RUNS the
|
|
6
|
+
// real shell-game.js, hall-dialog.js and visor.js in a real browser over a stand-in place
|
|
7
|
+
// (skipped where there is no browser) and presses what a player presses.
|
|
8
|
+
//
|
|
9
|
+
// Run: node tests/hall_game_menu.mjs
|
|
10
|
+
import assert from 'node:assert/strict';
|
|
11
|
+
import { test, after } from 'node:test';
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
19
|
+
const HALL = path.join(ROOT, 'modules', 'hall-ui', 'public');
|
|
20
|
+
|
|
21
|
+
const lib = require(path.join(ROOT, 'modules', 'ui-design', 'kit', 'lib.js'));
|
|
22
|
+
let browser = null;
|
|
23
|
+
try { browser = await lib.launchBrowser(); } catch (e) { if (!(e instanceof lib.NoBrowserError)) throw e; }
|
|
24
|
+
after(() => browser && browser.close());
|
|
25
|
+
const skip = !browser && 'no system Edge or Chrome';
|
|
26
|
+
|
|
27
|
+
const ORIGIN = 'http://hall.test';
|
|
28
|
+
const TYPES = { '.js': 'text/javascript', '.css': 'text/css', '.png': 'image/png', '.svg': 'image/svg+xml' };
|
|
29
|
+
// The stand-in place: a character (with or without "change character"), a scene for the visor,
|
|
30
|
+
// and a listener where shell.js's sign-out sits (a click on a link to the logout address).
|
|
31
|
+
const SCENE = (character) => `<script>
|
|
32
|
+
window.signedOut = 0; window.changed = 0; window.closeCalls = 0;
|
|
33
|
+
window.close = function () { window.closeCalls++; }; // a browser keeps a tab it did not open
|
|
34
|
+
document.addEventListener('click', function (e) {
|
|
35
|
+
var a = e.target.closest && e.target.closest('a');
|
|
36
|
+
if (a && /\\/auth\\/logout\\/?$/.test(a.getAttribute('href') || '')) { e.preventDefault(); window.signedOut++; }
|
|
37
|
+
});
|
|
38
|
+
window.OTBCraftMode = { character() { return 'artisan'; }, current() { return null; }, me() { return { builder: { total_credits: 5 } }; },
|
|
39
|
+
spriteSrc() { return ''; }, openTool() {}${character ? ', changeCharacter() { window.changed++; }' : ''} };
|
|
40
|
+
window.__visorScene = { name: 'test', place: 'Test city', actions: [], keys: [] };
|
|
41
|
+
</script>`;
|
|
42
|
+
const PAGE = (game, character) => `<!doctype html><html data-theme="dark" data-faces="helm"${game ? ' data-game="on"' : ''}><head><meta charset="utf-8">
|
|
43
|
+
<link rel="stylesheet" href="/builders/style.css"><link rel="stylesheet" href="/builders/visor.css"></head>
|
|
44
|
+
<body data-page="city"><main id="place"><button id="in-place">a button in the place</button></main>${SCENE(character)}
|
|
45
|
+
<script src="/builders/hall-dialog.js"></script><script src="/builders/shell-game.js"></script><script src="/builders/visor.js"></script></body></html>`;
|
|
46
|
+
|
|
47
|
+
async function open({ game = true, character = true, width = 1280, height = 800 } = {}) {
|
|
48
|
+
const ctx = await browser.newContext({ viewport: { width, height } });
|
|
49
|
+
await ctx.route(ORIGIN + '/**', (route) => {
|
|
50
|
+
const u = new URL(route.request().url());
|
|
51
|
+
const p = u.pathname;
|
|
52
|
+
if (p === '/city') return route.fulfill({ contentType: 'text/html', body: PAGE(game, character) });
|
|
53
|
+
if (p === '/settings') return route.fulfill({ contentType: 'text/html', body: '<!doctype html><title>options</title>' });
|
|
54
|
+
const f = p.startsWith('/modules/') ? path.join(ROOT, p) : path.join(HALL, p.replace(/^\/builders\//, ''));
|
|
55
|
+
if ((p.startsWith('/builders/') || p.startsWith('/modules/')) && TYPES[path.extname(p)] && fs.existsSync(f)) return route.fulfill({ contentType: TYPES[path.extname(p)], body: fs.readFileSync(f) });
|
|
56
|
+
if (p.startsWith('/api/')) return route.fulfill({ status: 401, contentType: 'application/json', body: '{}' });
|
|
57
|
+
return route.fulfill({ status: 404, body: '' });
|
|
58
|
+
});
|
|
59
|
+
const page = await ctx.newPage();
|
|
60
|
+
const errors = [];
|
|
61
|
+
page.on('pageerror', (e) => errors.push(String(e.message)));
|
|
62
|
+
await page.addInitScript((g) => { try { localStorage.setItem('hall-game', g ? 'on' : 'off'); window.OTB = { escapeHtml: (s) => String(s) }; } catch (_) { /* none */ } }, game);
|
|
63
|
+
await page.goto(ORIGIN + '/city');
|
|
64
|
+
await page.waitForFunction(() => !!window.OTBVisor && !!window.OTBShellGame);
|
|
65
|
+
return { ctx, page, errors };
|
|
66
|
+
}
|
|
67
|
+
const menuUp = (page) => page.evaluate(() => !!window.OTBGameMenu && window.OTBGameMenu.isOpen());
|
|
68
|
+
const optionsUp = (page) => page.evaluate(() => window.OTBOptionsOverlay.isOpen());
|
|
69
|
+
async function escape(page) { await page.keyboard.press('Escape'); await page.waitForTimeout(40); }
|
|
70
|
+
|
|
71
|
+
test('Escape in a game place opens the game menu, not the options; Escape again returns to the game', { skip }, async () => {
|
|
72
|
+
const { ctx, page, errors } = await open();
|
|
73
|
+
await escape(page);
|
|
74
|
+
assert.equal(await menuUp(page), true);
|
|
75
|
+
assert.equal(await optionsUp(page), false, 'the options stay shut until asked for');
|
|
76
|
+
const m = await page.evaluate(() => ({
|
|
77
|
+
title: document.querySelector('.game-menu__title').textContent,
|
|
78
|
+
rows: [...document.querySelectorAll('.game-menu__item')].map((r) => r.textContent),
|
|
79
|
+
shown: getComputedStyle(document.querySelector('.game-menu')).display,
|
|
80
|
+
modal: document.querySelector('.game-menu__box').getAttribute('aria-modal'),
|
|
81
|
+
focusIn: document.querySelector('.game-menu').contains(document.activeElement),
|
|
82
|
+
}));
|
|
83
|
+
assert.deepEqual(m, { title: 'Game menu', rows: ['Options', 'Change character', 'Log out', 'Exit game', 'Return to game'], shown: 'grid', modal: 'true', focusIn: true });
|
|
84
|
+
// the arrows walk the rows and wrap
|
|
85
|
+
await page.keyboard.press('ArrowUp');
|
|
86
|
+
assert.equal(await page.evaluate(() => document.activeElement.textContent), 'Return to game');
|
|
87
|
+
await page.keyboard.press('ArrowDown');
|
|
88
|
+
assert.equal(await page.evaluate(() => document.activeElement.textContent), 'Options');
|
|
89
|
+
await escape(page);
|
|
90
|
+
assert.equal(await menuUp(page), false, 'the second Escape shuts it');
|
|
91
|
+
assert.equal(await page.evaluate(() => getComputedStyle(document.querySelector('.game-menu')).display), 'none');
|
|
92
|
+
assert.deepEqual(errors, []);
|
|
93
|
+
await ctx.close();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('Return to game shuts the menu; Options opens the options window in its place', { skip }, async () => {
|
|
97
|
+
const { ctx, page, errors } = await open();
|
|
98
|
+
await escape(page);
|
|
99
|
+
await page.click('[data-gm="return"]');
|
|
100
|
+
assert.equal(await menuUp(page), false);
|
|
101
|
+
await escape(page);
|
|
102
|
+
await page.click('[data-gm="options"]');
|
|
103
|
+
assert.equal(await menuUp(page), false, 'one window at a time');
|
|
104
|
+
assert.equal(await optionsUp(page), true);
|
|
105
|
+
assert.equal(await page.evaluate(() => document.querySelector('.opt-window__frame').getAttribute('src')), '/settings?embed=1', 'the one options menu, framed');
|
|
106
|
+
// (in the hall the framed menu hands its Escape up; this stand-in frame has no script, so press it on the window)
|
|
107
|
+
await page.evaluate(() => document.querySelector('.opt-window__box').focus());
|
|
108
|
+
await escape(page);
|
|
109
|
+
assert.equal(await optionsUp(page), false, 'Escape shuts the options');
|
|
110
|
+
assert.equal(await menuUp(page), false, 'and lands in the game, not back on the menu');
|
|
111
|
+
assert.deepEqual(errors, []);
|
|
112
|
+
await ctx.close();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('Log out is a link to the sign-out address, so the shell signs the player out', { skip }, async () => {
|
|
116
|
+
const { ctx, page, errors } = await open();
|
|
117
|
+
await escape(page);
|
|
118
|
+
assert.equal(await page.evaluate(() => document.querySelector('[data-gm="logout"]').getAttribute('href')), '/api/bongos/auth/logout');
|
|
119
|
+
await page.click('[data-gm="logout"]');
|
|
120
|
+
assert.equal(await page.evaluate(() => window.signedOut), 1, 'the click reached the sign-out listener, once');
|
|
121
|
+
assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').textContent), 'Logging out');
|
|
122
|
+
// the real listener: shell.js turns exactly such a click into the POST and the bounce home
|
|
123
|
+
const shell = fs.readFileSync(path.join(HALL, 'shell.js'), 'utf8');
|
|
124
|
+
assert.match(shell, /if \(\/\\\/auth\\\/logout\\\/\?\$\/\.test\(a\.getAttribute\('href'\) \|\| ''\)\) \{\s*e\.preventDefault\(\);\s*doLogout\(\);/);
|
|
125
|
+
assert.deepEqual(errors, []);
|
|
126
|
+
await ctx.close();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('Exit game closes the tab, and says so when the browser keeps it', { skip }, async () => {
|
|
130
|
+
const { ctx, page, errors } = await open();
|
|
131
|
+
await escape(page);
|
|
132
|
+
assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').hidden), true, 'no note until there is something to say');
|
|
133
|
+
await page.click('[data-gm="exit"]');
|
|
134
|
+
assert.equal(await page.evaluate(() => window.closeCalls), 1, 'it asked the browser to close the tab');
|
|
135
|
+
await page.waitForFunction(() => !document.querySelector('.game-menu__note').hidden);
|
|
136
|
+
assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').textContent), 'Your browser kept this tab open. Close it to quit.');
|
|
137
|
+
// Exit, then shut and reopen at once: the pending check must not speak into the new opening
|
|
138
|
+
await escape(page); await escape(page);
|
|
139
|
+
await page.click('[data-gm="exit"]');
|
|
140
|
+
await page.keyboard.press('Escape'); await page.keyboard.press('Escape');
|
|
141
|
+
await page.waitForTimeout(450);
|
|
142
|
+
assert.equal(await menuUp(page), true);
|
|
143
|
+
assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').hidden), true, 'a stale Exit check stays quiet');
|
|
144
|
+
// a fresh opening starts with no note
|
|
145
|
+
await escape(page); await escape(page);
|
|
146
|
+
assert.equal(await page.evaluate(() => document.querySelector('.game-menu__note').hidden), true);
|
|
147
|
+
assert.deepEqual(errors, []);
|
|
148
|
+
await ctx.close();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('Change character hands over to the character\'s own flow, and is absent where there is none', { skip }, async () => {
|
|
152
|
+
const { ctx, page } = await open();
|
|
153
|
+
await escape(page);
|
|
154
|
+
await page.click('[data-gm="character"]');
|
|
155
|
+
assert.deepEqual(await page.evaluate(() => [window.changed, window.OTBGameMenu.isOpen()]), [1, false]);
|
|
156
|
+
await ctx.close();
|
|
157
|
+
const bare = await open({ character: false });
|
|
158
|
+
await escape(bare.page);
|
|
159
|
+
assert.deepEqual(await bare.page.$$eval('.game-menu__item', (r) => r.map((x) => x.textContent)), ['Options', 'Log out', 'Exit game', 'Return to game']);
|
|
160
|
+
await bare.ctx.close();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('the visor opens it: its own key, and the Actions sheet\'s last row; its keys work again afterwards', { skip }, async () => {
|
|
164
|
+
const { ctx, page, errors } = await open();
|
|
165
|
+
assert.equal(await page.$('.visor__hint--options'), null, 'Escape is on the glass nowhere (task 1005248)');
|
|
166
|
+
await page.keyboard.press('m');
|
|
167
|
+
assert.equal(await menuUp(page), true, 'the game menu key');
|
|
168
|
+
assert.equal(await optionsUp(page), false);
|
|
169
|
+
await page.click('[data-gm="return"]');
|
|
170
|
+
await page.keyboard.press('a');
|
|
171
|
+
assert.equal(await page.evaluate(() => OTBVisor.isOpen()), true, 'a shut menu does not hold the visor\'s keys');
|
|
172
|
+
await page.click('.visor__sheet [data-game-menu]');
|
|
173
|
+
assert.deepEqual(await page.evaluate(() => [window.OTBGameMenu.isOpen(), OTBVisor.isOpen()]), [true, false], 'the sheet\'s Game menu row opens it and folds the sheet');
|
|
174
|
+
// while the menu is up, the place behind is not reachable by a letter key
|
|
175
|
+
await page.keyboard.press('a');
|
|
176
|
+
assert.equal(await page.evaluate(() => OTBVisor.isOpen()), false);
|
|
177
|
+
assert.deepEqual(errors, []);
|
|
178
|
+
await ctx.close();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('the menu holds at a phone width, and classic mode has no game menu', { skip }, async () => {
|
|
182
|
+
const phone = await open({ width: 390, height: 780 });
|
|
183
|
+
await escape(phone.page);
|
|
184
|
+
const box = await phone.page.evaluate(() => { const r = document.querySelector('.game-menu__box').getBoundingClientRect(); return { l: r.left, r: r.right, t: r.top, b: r.bottom, sw: document.documentElement.scrollWidth }; });
|
|
185
|
+
assert.ok(box.l >= 16 && box.r <= 374 && box.t >= 0 && box.b <= 780, 'the whole menu is on the screen');
|
|
186
|
+
assert.equal(box.sw, 390, 'the page does not scroll sideways');
|
|
187
|
+
const small = await phone.page.$$eval('.game-menu__item', (r) => r.filter((x) => x.getBoundingClientRect().height < 24).length);
|
|
188
|
+
assert.equal(small, 0, 'every row is a full target');
|
|
189
|
+
await phone.ctx.close();
|
|
190
|
+
const classic = await open({ game: false });
|
|
191
|
+
await escape(classic.page);
|
|
192
|
+
assert.equal(await menuUp(classic.page), false, 'outside game mode Escape is the shell\'s, as before');
|
|
193
|
+
assert.equal(await classic.page.evaluate(() => document.querySelector('.game-menu')), null);
|
|
194
|
+
await classic.ctx.close();
|
|
195
|
+
});
|
|
@@ -241,6 +241,9 @@ test('GAME MODE: on the menu itself the last Escape closes it; outside game mode
|
|
|
241
241
|
assert.deepEqual(off.assigned, [], 'outside game mode the press stays the shell\'s');
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
// Since task 1005250 the last Escape opens the GAME MENU, whose Options row opens this window
|
|
245
|
+
// (tests/hall_game_menu.mjs presses both in a real browser). This stub page can draw no game
|
|
246
|
+
// menu, so the press falls through to the window itself, which is what is tested here.
|
|
244
247
|
test('GAME MODE: away from the menu, Escape opens the options as a window over the place, and Escape again shuts it', () => {
|
|
245
248
|
const city = bootGame({ game: true, framed: false, path: '/city', dom: true });
|
|
246
249
|
city.press('Escape');
|
|
@@ -301,6 +304,6 @@ test('every pop-up that closes on Escape spends the press, so the menu never ope
|
|
|
301
304
|
test('the start screen\'s Options is the menu, and its first tip says what Escape does now', () => {
|
|
302
305
|
const src = read('shell-game.js');
|
|
303
306
|
assert.match(src, /\{ id: 'options', label: 'Options', href: '\/settings' \}/, 'Options opens the one options menu');
|
|
304
|
-
assert.match(src, /'Escape opens the
|
|
307
|
+
assert.match(src, /'Escape opens the game menu: options, log out and exit\.'/, 'task 1005250: Escape is the game menu\'s');
|
|
305
308
|
assert.doesNotMatch(src, /Escape brings the navigation back/, 'no tip promises what Escape no longer does');
|
|
306
309
|
});
|