diff --git a/src/components/GlanceRail.jsx b/src/components/GlanceRail.jsx
index ecba23b..fb0fe9f 100644
--- a/src/components/GlanceRail.jsx
+++ b/src/components/GlanceRail.jsx
@@ -1,185 +1,271 @@
-// GlanceRail — the playhead accordion (task L-33, per docs/design/glance-mode.md §1–§4).
+// GlanceRail — ALL loop stations expanded, always (task D-41, per
+// docs/design/integrated-glance.md §4; supersedes the L-33 playhead accordion).
//
-// A station-aligned rail under the RoadmapTrack: columns mirror the Roadmap's
-// stations (canonical KB order, same labels/rn). The column at `activeIndex`
-// (the playhead) is EXPANDED to the full VoicingBrowser gallery — every
-// placeable guitar shape, or every piano style, side by side — while every
-// other column keeps its recommended thumb (the KB play's shape / the threaded
-// piano voicing). The expansion ADVANCES WITH THE PLAYHEAD: over one loop cycle
-// the player is shown every variation of every chord with zero clicks (user
-// directive 2026-07-10). Constant footprint — expanding one column collapses
-// the previous.
+// One VERTICAL ROW per loop station, canonical KB order (the same order the
+// banner's loop shows after rotation). Every row renders its full voicing
+// gallery PERMANENTLY — the playhead HIGHLIGHTS the active row (accent ring +
+// "now" badge + aria-current) and never hides, collapses, or reveals content.
+// User directive 2026-07-10: "i'd like to see all the chords and their
+// voicings … so you can follow and potentially learn new ways to play it while
+// you are playing the loop. scrolling is easier then clicking."
//
-// Pinning (D-31 §4): tapping a collapsed column pins its gallery open and halts
-// auto-follow; unpin by tapping the pinned column's header or the "follow the
-// jam" chip. The PARENT owns the pin state and the onFocusChord emission — this
-// component never emits focus-chord and NEVER triggers audio on its own
-// (auto-follow must not feed the mic; every ▶ inside the gallery is a gesture).
+// Row anatomy (D-40 §4):
+// header — chord label + rn (the focus toggle) · "now" badge / "next" tag ·
+// solo-scale label · aim dots (3rd filled accent, 7th hollow —
+// RoadmapTrack's GuideDot language, honest "5th" fallback kept) ·
+// transition chip ("next F→E · ½ step down"; the last row wraps:
+// "loop"). This is where the retired RoadmapTrack's education
+// folds in (D-40 §2) — theory.js `guideTones` / `voiceLeadingPairs`
+// / `soloScale`, read-only imports.
+// gallery — first cell = the station's OWN voicing (guitar: the KB play's
+// recommended shape badged "play", when present; piano: the
+// threaded/authored voicing labeled honestly, e.g. "LH 3-5-7-9" —
+// the accordion's collapsed-thumb value survives here) + the full
+// VoicingBrowser gallery (show={instrument}, dense). Cells
+// FLEX-WRAP — rows never scroll horizontally; the piano worst case
+// (~1,470px of cells) wraps to a second cell line instead (§4).
//
-// Space honesty (D-31 §3): cells are never shrunk below the D-30 sizes — the
-// rail scrolls horizontally, USER-OWNED. The old auto-centre effect was deleted
-// in L-40 (D-40 §4/§6.1): the rail now lives in page flow (the Jam Guide band,
-// no 70vh scroller), where scrollIntoView's nearest scroller is the DOCUMENT —
-// every playhead advance would yank the whole page. Scrolling is the piano
-// rail's NORMAL state on most loops (a rootless 7th-chord gallery is ~940px on
-// its own). Narrow (<640px, D-31 §3): one thing per row — the current
-// station's full gallery (cells wrap), then a single "next" thumb; the loop
-// display up top (ProgressionBanner) still shows the whole loop.
+// Focus semantics (D-40 §4 — the pin, simplified): with everything always
+// expanded there is nothing left to hold open, so tapping a row header TOGGLES
+// that station as focused. The PARENT owns the state and the onFocusChord
+// emission (the D-03 fretboard guide-tone contract, byte-compatible); a focused
+// row shows an "aim on fretboard" chip; tap again (or the loop changes) to
+// clear. This component never emits focus-chord itself and NEVER triggers
+// audio on its own — every ▶ lives inside the gallery, behind a user gesture.
//
-// Pure presentational. Props (the D-31 §5 contract):
-// stations — [{ shape, voicing, rootPc, quality, label, rn }] canonical order
-// activeIndex — playhead station (canonicalPos); -1 = loop known, playhead
-// not — station 0 expands, but nothing is marked "now" (§2.1)
-// pinnedIndex — the pinned station index, or null (= follow the jam)
-// onPin — fn(index|null): pin a station / unpin
-// instrument — 'guitar' | 'piano' (VoicingBrowser `show`)
-// keyRoot — key tonic pitch class 0–11 (ChordDiagram fret placement)
+// NO auto-scroll (D-40 §4/§6.2 step 1): the band lives in page flow, where
+// scrollIntoView's nearest scroller is the DOCUMENT — it would yank the whole
+// page mid-jam. The L-33 auto-centre effect was deleted in L-40 and must never
+// return; the highlight travels, the user owns the scrollbar.
+//
+// Pure presentational. Props:
+// stations — [{ shape, voicing, rootPc, quality, label, rn }] canonical order
+// activeIndex — playhead station (canonicalPos); -1 = loop known, playhead
+// not — no row is marked "now" (content never changes either way)
+// focusedIndex — the focused station index, or null (nothing focused)
+// onFocus — fn(index|null): toggle a station's focus
+// instrument — 'guitar' | 'piano' (VoicingBrowser `show`; bass never mounts
+// this rail — JamGuide renders BassGuideRows instead, D-40 §3)
+// keyRoot — key tonic pitch class 0–11 (ChordDiagram fret placement)
+// keyMode — key mode name (soloScale's minor-key dominant nudge)
+import { NOTES, guideTones, voiceLeadingPairs, soloScale } from '../lib/theory'
import ChordDiagram from './ChordDiagram'
import MiniPiano from './MiniPiano'
import VoicingBrowser from './VoicingBrowser'
+const pcName = (pc) => NOTES[((pc % 12) + 12) % 12]
+
+// ─── Header atoms (exported — BassGuideRows in JamGuide.jsx composes the same
+// anatomy for visual parity across instruments, D-40 §3) ──────────────────
+
+// Solo-scale label: "solo · G mixolydian" (theory.js snake_case → spaces).
+export function SoloLabel({ rootPc, quality, keyMode }) {
+ const { name } = soloScale(quality, keyMode)
+ return (
+
+ solo ·
+ {pcName(rootPc)} {name.replace(/_/g, ' ')}
+
+ )
+}
+
+// One guide-tone dot: note name in a small circle + its honest kind label.
+// Filled accent = the 3rd; hollow = the 7th (or the "5th" fallback — never
+// badge a 5th as a 7th). Filled text is BLACK on accent (#a855f7 vs black
+// ≈5.3:1 — AA; white would be ~4.0), matching VoicingBrowser's ▶ hover.
+function GuideDot({ pc, kind, filled }) {
+ return (
+
+
+ {pcName(pc)}
+
+ {kind}
+
+ )
+}
+
+// The "aim" pair — the RoadmapTrack TARGET lane, folded to one header line.
+export function AimDots({ rootPc, quality }) {
+ const g = guideTones(rootPc, quality)
+ const seventhKind = g.hasSeventh ? '7th' : '5th'
+ return (
+
+ aim
+
root {NOTES[st.rootPc]} · fifth {NOTES[fifthPc]} @@ -479,7 +496,7 @@ function BassGuideRows({ stations = [], activeIndex = -1, live = false }) {
> )} - +Previews play through your speakers — while the mic is live, detection may hear them.