···1111- Calendar: topbar settings button now renders as a proper 8-tooth gear glyph instead of a sunburst that was visually indistinguishable from the adjacent theme-toggle sun (v0.62.4, #697). The old `#btn-cal-settings` SVG was a circle-with-8-radiating-lines (`circle r=2.5` + eight `M..v.. / M..h..` rays) and the theme-toggle `#btn-theme-toggle` right next to it was the same circle-with-8-rays pattern at `r=3.5` — users clicked the wrong one constantly, with the settings panel hiding some destructive controls. Replaced the settings icon with a true 32-vertex 8-tooth gear polygon (outer tooth tip radius 6.8, valley radius 4.6, hub circle r=2.2) traced in `src/calendar/index.html`. Added an `icon-gear` marker class so future refactors can't silently regress to a sunburst, plus four Playwright regression tests in `e2e/calendar.spec.ts` that pin the contract: (1) the icon carries the `icon-gear` class; (2) the settings path `d` attribute differs from the theme-toggle path; (3) the path has either curves, a closed subpath, or >24 draw commands (sunburst had ~16 and no close); (4) both buttons remain visible and adjacent. Also added `aria-label` + `aria-hidden` attributes that the theme-toggle already had for a11y parity. (#697)
12121313### Fixed
1414+- Docs: TipTap v3 StarterKit config no longer emits duplicate-extension and Collaboration/UndoRedo-conflict warnings (v0.62.5, #710). PR #409 (the v2→v3 migration for #692) passed `history: false` to StarterKit.configure, but v3 renamed the History extension to UndoRedo — `history: false` is a silent no-op, so StarterKit's UndoRedo stayed active and fought Yjs for undo state. StarterKit v3 also vendors Link and Underline, so our explicit `@tiptap/extension-link` + `@tiptap/extension-underline` imports registered duplicates of those extensions. Updated `src/docs/main.ts` to use `StarterKit.configure({ undoRedo: false, codeBlock: false, link: { openOnClick: false } })` and removed the explicit Link/Underline imports. Dropped the two packages from package.json. Added `tests/tiptap-v3-no-warnings.test.ts` (2 tests: jsdom editor-construction with zero TipTap warnings, plus static scan of src/docs/main.ts for deprecated v2 patterns). Caught live by inspecting the browser console on a deployed doc. (#710)
1415- Calendar: mini-calendar date cells now expose a full spoken date via `aria-label` (v0.62.3, #696). Previously the `.cal-mini-day` buttons contained only the day number as text, so screen readers announced "button, 29" with no month/year/weekday context — unusable for non-sighted navigation. `renderMiniCalendar` now builds an `aria-label` like `"Tuesday, March 29, 2026"` (plus `, today`, `, selected`, and `, N events` suffixes when applicable) using a new shared `formatLongDate(d)` helper in `src/calendar/helpers.ts` that wraps `toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })`. The today cell also carries `aria-current="date"` and the selected cell carries `aria-pressed="true"` so state is conveyed through standard AT semantics rather than class names alone. 4 regression tests in `tests/calendar-mini-day-aria.test.ts` pin the helper output and verify every emitted `.cal-mini-day` button tag carries an `aria-label=` attribute. (#696)
1516- CSP: externalized 3 inline scripts from every page template so the app's `script-src 'self'` CSP stops silently blocking them (v0.62.2, #694). Theme init (FOUC prevention, reads localStorage before paint), theme-toggle click handler, and service-worker update→reload handler now live in `public/theme-init.js`, `public/theme-toggle.js`, and `public/sw-reload.js` respectively, loaded via `<script src="...">` so they satisfy the strict CSP without needing nonces or `unsafe-inline`. Before: the theme toggle button did nothing, dark-mode users saw a flash of light theme on every page load, and users never auto-reloaded when a new version deployed. All 7 HTML templates (landing + 6 editors) had the inline blocks; all 7 are now externalized. Added `tests/csp-no-inline-scripts.test.ts` which scans every template for inline `<script>` blocks and fails if any are reintroduced. Caught live by driving the deployed v0.62.1 app via Playwright MCP. (#694)
1617- Sheets: first printable keystroke against an empty cell no longer duplicates the character (v0.62.1, #693). The grid's keydown handler for printable chars in `src/sheets/keyboard-handler.ts` entered edit mode and set `editor.value = key` but never called `e.preventDefault()`, so the browser's native keypress/input pipeline on the now-focused cell-editor input also inserted the same character — pressing `5` produced `55`, pressing `1`→`0`→Enter produced `110`. Added the missing `preventDefault()` plus a targeted regression test in `tests/sheets-keyboard-handler.test.ts` (3 new tests: preventDefault invariant, single-char-not-doubled invariant, and the pre-existing Cmd+key-skip invariant). Caught live by driving the deployed app in a real browser via Playwright MCP during TipTap v3 post-ship smoke testing. (#693)