v0.114.0 — New Retro
Merged 2026-10-03 (147e3a08) — built on version/0.114.0; the tag is in
the changelog. No module release.
New Retro: a new theme in light and dark with a System / Light / Dark setting, the chat and Settings redesigns, the installed phone app around the Dynamic Island, and Mini-Me fixes. Three of its last commits missed the squash and shipped as v0.114.1.
New Retro
- [x] A new theme with light and dark mode: the "Modern Retro VTT Style Guide" as two skins, parchment (
new-retro-light) and dungeon stone (new-retro-dark) — cardstock grain on panels, hard offset shadows, 2px corners, Cinzel / Crimson Text / Courier Prime;theme/newRetroTheme.tsbuilt on the modern theme withmergeThemeOverrides, so its layer and clamp fixes are inherited - [x] A light / dark setting (System by default, following the device live): Settings → Theme picks the family (Retro TTRPG, Modern, New Retro), Light or dark the scheme; Retro TTRPG is dark only and says so.
skinStoreholds the family and the mode and resolves the skin; a stored Modern Light / Dark stays an explicit choice - [x] Mini-Me fixes: a menu widens to fit its rows and gives the scrollbar its own gutter (the powers menu clipped its … buttons); name and bar labels left-aligned; a gradient bar colour fills (it was set as
backgroundColorand dropped); the panel at least the portrait's height; status chips that would wrap drop their labels for the glyph or an initial; their tooltips above the play bar
Chat redesign
- [x] The Timeline strip is the viewport's right edge and the chat sidebar sits to its left (the resize handle measures from the strip); the Timeline tab is the rightmost; the mini initiative bar is off in the chat log (
SHOW_MINI_INITIATIVE_IN_CHAT) - [x] The channel header: a back button at the left (to the conversation list, carrying the other channels' unread count; none on the list itself), the channel's glyph and name centred over a status line (
n online,Private · n people,GM only until revealed, …), opening a description of the channel — what a map / campaign / DM / Secret / Personal / custom channel is, a DM's members, and who is connected now from socket presence, scoped to the channel's audience (channelDescription.ts) - [x] From the "Redesign Chat and Timeline" Figma, the Chat Log's parts in the skin's tokens: message runs (one sender's consecutive messages within 5 minutes; action docs stand alone) with the avatar and name at the head and the time and send status at the foot (
chatRuns.ts); your bubbles in the primary (or your chat colour), others' as cards; New Retro's own shape (8px corners with a 2px tuck, cardstock grain, hard shadow); a slide-in for new messages; the composer in tokens with the send button beside the field
Settings redesign
- [x] From the "Usable Settings Menu" Figma, with our settings: a category nav (Appearance, Map, Notifications, Account, AI, Modules, then one per module settings panel) beside headed sections of rows — name and hint left, control right. These save as they change, so the design's Save / Cancel is a note. Lays out by its own width (it is also the
/playsidebar's Settings): narrow, the categories are pills.?section=<id>opens one - [x] genai's AI Generation panel is a section of AI, not a category of its own (
PANEL_HOME) - [x] Roadmap opened up past v0.114.0: the wiki's hosting and across roots, the System 8 sheet and the creation walkthrough (queued as v0.114.0–v0.117.0) are unslotted; New Retro holds v0.114.0; v0.113.0's notes written (v0.113.0)
- [x] Roadmap: User preferences — the per-person settings worth building next, starting with the natural 1 / natural 20 effect (a user request) and the reduced-motion gap it exposed
Mobile
- [x] Specifically when installed as a home screen app, the browser chrome disappears, granting more space on the top and bottom of the screen. Hopefully styles can be applied specific to whether the browser chrome is hidden or not. —
@media (display-mode: standalone), plus:root[data-standalone]set at startup from iOS'snavigator.standalone(markStandalone), drive two tokens in_base.css:--vtt-standalone-top-insetand--vtt-footer-safe-bottom. Both are 0 / the plain safe area in a browser tab. Verified on an iPhone (ariadne.local) 2026-10-03. Pages off the map clear the same inset on a phone (.mainContentpads by--vtt-standalone-top-inset), which Settings needed- [x] Major: on iPhone, the "nub" on /play is so high up it gets blurred out because it's approaching the Dynamic Island. Add a buffer zone of the prevailing background color (same bgcolor as PlayTopBar) to the top of the viewport, setting a minimum height which the map's topmost extent (and the nub's top coordinate) is displaced from the viewport top, to avoid this scenario. —
StandaloneTopBandon the phone's map:max(safe-area-top + 23px, 46px)(82px under a Dynamic Island; raised ~15% after the first device look) of the play bar's colour, published as--vtt-top-chrome(as the mobile bar publishes--vtt-bottom-chrome); the map starts below it (marginTop, height reduced — pointer maths reads the canvas rect, so nothing else moves) and so does the nub. The Me / Chat tab screens clear the same inset - [x] Minor: without browser chrome, the bottom footer is a bit too large (about 80% bigger than necessary). Reducing its height would reclaim a bit of precious screen space. — standalone, the footer keeps 26px less of the home indicator's inset (34px → 8px on an iPhone: 66px → 40px), which still clears the indicator; everything bottom-anchored follows through
--vtt-footer-height
- [x] Major: on iPhone, the "nub" on /play is so high up it gets blurred out because it's approaching the Dynamic Island. Add a buffer zone of the prevailing background color (same bgcolor as PlayTopBar) to the top of the viewport, setting a minimum height which the map's topmost extent (and the nub's top coordinate) is displaced from the viewport top, to avoid this scenario. —
Misc
- [x] When the user clicks a token, thus impersonating the token (or linked character), show the Mini-Me element, but don't open the Me tab if not already open. Clicking the Me tab button, or pressing the 'Full Character Sheet' button in Mini-Me, will still open the Me tab. — UI.tsx's impersonation effect now opens the sheet only when the left sidebar already shows Me (
meTabShowing, judged against the PREVIOUS impersonation's character), so an open Me follows the new token and a closed one, or another tab, is left alone. Applies to every impersonation, including the automatic one on arrival - [x] In the Character Context, add "Refresh from Character" as an action button, replacing the ... button which contains "Refresh from Character" currently. The other options in that ... menu will no longer be available. — a
refresh-kind tab action (so it sits by the spec's priority and collapses into the row's own…last-but-one), and a plain button in the header outside a tab; shown when the impersonated token links to a character, "Refreshing…" and disabled while it runs. Move to Map and Copy Token (never implemented) and Edit this Character (the sheet's Edit) are gone from this context; the error state keeps Focus / Zoom for recovery. The unlinked token's context keeps its menu