HERMES-GIELIE/static
Nathan Esquenazi ba66872f70 fix(sidebar): align collapse CSS breakpoint with JS _isDesktopWidth (641px)
`_isDesktopWidth()` in boot.js gates every collapse path on
`matchMedia('(min-width:641px)')` — matching where the rail itself becomes
visible. The CSS rules driving the actual visual collapse were nested inside
the workspace-panel block at `@media(min-width:901px)` — a threshold copied
from the right-panel collapse but with no functional reason to apply here.

Behavioural consequence in the 641–900 px band (tablet portrait + small
laptop windows):

  - Rail is visible, user clicks the active icon
  - JS adds `.layout.sidebar-collapsed` and writes localStorage='1'
  - JS sets aria-expanded='false' on the active rail button
  - CSS at min-width:901px does NOT apply → sidebar stays at 300 px width
  - User sees no visual change; screen reader announces collapsed state for
    a sidebar that is still visible; localStorage silently persists
  - Resize to ≥901 px later → sidebar suddenly collapses (surprise state)

Fix: hoist the three `.sidebar-collapsed` / flash-prevention rules out of
the workspace-panel @media block and into their own `@media(min-width:641px)`
block. The rail visibility breakpoint, the JS gate, and the CSS gate now
all agree.

`:not(.mobile-open)` is preserved on both selectors so the mobile slide-in
overlay (handled in the `max-width:640px` block) is never targeted — the
new @641 boundary doesn't change that contract.

Verified breakpoint matrix end-to-end (Node harness over real boot.js +
style.css):

  Width | JS desktop | CSS applies | Effect
  ------|------------|-------------|------------
   640  | no         | no          | no-op (mobile overlay)
   641  | yes        | yes         | collapses ✓
   700  | yes        | yes         | collapses ✓
   768  | yes        | yes         | collapses ✓
   900  | yes        | yes         | collapses ✓
   1024 | yes        | yes         | collapses ✓

Regression test added: `test_css_breakpoint_matches_js_isdesktopwidth`
parses boot.js for the `_isDesktopWidth` matchMedia query, walks CSS to
find the @media block enclosing `.layout.sidebar-collapsed`, and asserts
the thresholds match. Locks the invariant so a future refactor can't
re-introduce the asymmetric-band silent-state-leak.

Test counts:
  - tests/test_sidebar_collapse_toggle.py: 35/35 pass (was 34, +1 regression)
  - Full suite (Python 3.14, local): 5040 passed, 0 failed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 21:57:47 -07:00
..
vendor chore: vendor streaming-markdown@0.2.15, remove CDN dependency 2026-04-24 01:05:20 +00:00
apple-touch-icon.png feature: add manifest and icons to enable app install on android 2026-05-02 19:06:39 +02:00
boot.js feat(ux): collapse sidebar by clicking the active rail icon (fuses #1884 + #1924) 2026-05-11 04:49:18 +00:00
commands.js fix(i18n): localize /goal runtime status strings 2026-05-10 15:21:24 +08:00
favicon-32.png fix: add favicon (SVG + PNG + ICO), fix static MIME types (#613) 2026-04-16 20:11:02 -07:00
favicon-192.png feature: add manifest and icons to enable app install on android 2026-05-02 19:06:39 +02:00
favicon-512.png feature: add manifest and icons to enable app install on android 2026-05-02 19:06:39 +02:00
favicon-512.svg feature: add manifest and icons to enable app install on android 2026-05-02 19:06:39 +02:00
favicon.ico fix: add favicon (SVG + PNG + ICO), fix static MIME types (#613) 2026-04-16 20:11:02 -07:00
favicon.svg fix: add favicon (SVG + PNG + ICO), fix static MIME types (#613) 2026-04-16 20:11:02 -07:00
i18n.js Clarify one-shot cron schedules 2026-05-11 07:03:17 +08:00
icons.js fix(composer): distinct voice-mode icon, descriptive labels, opt-in pref (#1488) 2026-05-02 22:16:23 +00:00
index.html feat(ux): collapse sidebar by clicking the active rail icon (fuses #1884 + #1924) 2026-05-11 04:49:18 +00:00
login.js fix(login): retry connectivity probe every 3s, auto-reload when server recovers 2026-05-01 19:54:47 +00:00
manifest.json feat: add browser offline recovery and PWA cache hardening 2026-05-08 21:16:17 +00:00
messages.js Stage 333: PR #2009 — feat(context): live status tracking during streaming by @dobby-d-elf 2026-05-10 18:16:59 +00:00
onboarding.js docs: clarify Anthropic auth choices in onboarding 2026-05-06 06:26:43 +00:00
panels.js feat(ux): collapse sidebar by clicking the active rail icon (fuses #1884 + #1924) 2026-05-11 04:49:18 +00:00
sessions.js Stage 333: PR #2009 — feat(context): live status tracking during streaming by @dobby-d-elf 2026-05-10 18:16:59 +00:00
style.css fix(sidebar): align collapse CSS breakpoint with JS _isDesktopWidth (641px) 2026-05-10 21:57:47 -07:00
sw.js feat: add browser offline recovery and PWA cache hardening 2026-05-08 21:16:17 +00:00
terminal.js fix: anchor active sessions per browser tab 2026-05-01 19:52:05 +08:00
ui.js Merge remote-tracking branch 'origin/master' into stage-332 2026-05-10 18:07:50 +00:00
workspace.js fix: keep workspace open from preview breadcrumb 2026-05-07 06:25:17 +00:00