/* ════════════════════════════════════════════════════════════════════
   CHORD PAGE CONTROL-BAR VISIBILITY TABLE  (single source of truth)
   ════════════════════════════════════════════════════════════════════
   Each cell carries `data-ctrl-key`.  Rules below hide cells per
   context.  Two attribute gates:

     data-active-tab="<root>"   set by _syncControlsActiveTab().
                                Mirrors the active section (path[0]):
                                voicings | full-fretboard | arpeggios |
                                scales | suites | articles.

     data-map-mode="1"          set by _syncControlsActiveTab() when
                                pageMode='collection' AND toolbar's
                                view='overlay'.  Independent of tab.

   ┌─────────────┬─────┬───────┬────────┬────────┬───────┬───────┬─────┐
   │ data-ctrl-  │ All │ Voic- │  Full  │  Arp-  │ Scal- │ Suit- │ Map │
   │  key →      │ tab │ ings  │  Frb.  │ eggios │  es   │  es   │mode │
   ├─────────────┼─────┼───────┼────────┼────────┼───────┼───────┼─────┤
   │ chords      │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   ✓   │  ✓  │
   │ key-display │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   ✓   │  ✓  │
   │ strings     │  ✓  │   ✓   │   ✓    │   —    │   —   │   —   │  ✓  │ ← labeled "Notes & String Set"
   │ voicings    │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   ✓   │  ✓  │
   │ span        │  ✓  │   ✓   │   ✓    │   —    │   —   │   —   │  ✓  │
   │ order       │  ✓  │   ✓   │   ✓    │   —    │   —   │   —   │  —  │ ← hidden in Map
   │ connections │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   —   │  ✓  │
   │ ghosts      │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   —   │  ✓  │
   │ diagrams    │  ✓  │   ✓   │   —    │   —    │   —   │   —   │  ✓  │ ← always hidden outside Voicings
   │ view        │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   ✓   │  ✓  │ ← drives Map + scales Browse/List
   │ source(SRC) │  ✓  │   ✓   │   ✓    │   —    │   —   │   —   │  ✓  │
   │ collection  │  ✓  │   ✓   │   ✓    │   ✓    │   ✓   │   ✓   │  ✓  │
   └─────────────┴─────┴───────┴────────┴────────┴───────┴───────┴─────┘

   Toolbar-row controls (cv-toolbar, beneath the control grid in
   collection mode):
   ┌─────────────────┬───────┬──────┬──────┬─────────────────────────┐
   │ control         │ Cards │ List │ Map  │ Notes                   │
   ├─────────────────┼───────┼──────┼──────┼─────────────────────────┤
   │ Cards pill      │   ✓   │  ✓   │  ✓   │                          │
   │ List pill       │   ✓   │  ✓   │  ✓   │                          │
   │ Map pill        │   ✓¹  │  ✓¹  │  ✓¹  │ ¹ only at leaf-bucket    │
   │ Multi color     │   —   │  —   │  ✓   │ overlay-only             │
   │ Cols (1-4)      │   ✓   │  ✓   │  —   │                          │
   │ Sort dropdown   │   ✓   │  ✓   │  —   │ hidden in Map            │
   │ Filter input    │   ✓   │  ✓   │  —   │ hidden in Map            │
   │ Pager Prev/Next │   —   │  —²  │  ✓²  │ ² visible when totalPages>1
   │ Browse button   │   —   │  —   │  —   │ REMOVED 2026-05-15.       │
   │                 │       │      │      │ Page's main VIEW switch   │
   │                 │       │      │      │ drives browse/list now.   │
   └─────────────────┴───────┴──────┴──────┴─────────────────────────┘

   Card-chrome action cluster (segmented group, .cpg-area .spg-area-card-actions):
   ┌─────────────────┬────────┬────────┬─────────────────────────────┐
   │ button          │ Browse │  List  │ Notes                        │
   ├─────────────────┼────────┼────────┼─────────────────────────────┤
   │ Diagram (jump)  │   ✓    │   ✓    │ disabled on Arpeggios path   │
   │ Copy / Export   │   ✓    │   ✓    │ wired by FretboardActions    │
   │ Map             │   ✓¹   │   ✓¹   │ ¹ when voicings path length≥2│
   │ Add (to coll.)  │   ✓    │   ✓    │                              │
   └─────────────────┴────────┴────────┴─────────────────────────────┘


   NOTE (owner 2026-07-11): visibility above is orthogonal to
   ENABLED/DISABLED.  On Full Fretboard, connections / ghosts /
   strings / view stay VISIBLE (per this table) but are DISABLED
   (dim + inert) -- they have no effect on the single every-tone
   shape.  Single source of truth: ChordPage._isFullFretboardView
   in page.js (full-fretboard.js#isFullFretboardPath).  Extend the
   gated-control list there, not with a new CSS visibility rule.
   When changing any visibility rule, update BOTH the CSS block(s)
   AND this table.  No exceptions.
   ════════════════════════════════════════════════════════════════════ */

/* Map (overlay) mode — hide ORDER cell (no position/string-set axis
   applies to a map view).  Per user 2026-05-15. */
.scp-ctrl-grid[data-map-mode="1"] > .scp-ctrl-cell[data-ctrl-key="order"] {
  display: none;
}

/* Control-bar contextual visibility — `data-active-tab` mirrors
   the sidebar's active tab, and each control cell carries
   `data-ctrl-key` identifying which knob it is.  Cells that don't
   apply to the active tab are hidden so the bar stays focused on
   what the user can actually change.  Per user 2026-05-13
   connection map B1/B2.

   SOURCE (Voicings) cell visible ONLY on All + Voicings tabs.  Per
   user 2026-05-13: voicing-vocabulary filter belongs to voicing
   browsing only; on Full Fretboard / Arpeggios / Scales / Suites /
   Articles the source filter is meaningless. */
/* Default = Voicings: all cells visible (no hide rules needed). */



/* Full Fretboard tab — per user 2026-05-14: keep Voicings (SOURCE)
   cell + voicing-related cells VISIBLE so the user has quick access
   to switch back to voicings from the HOME / Full Fretboard view
   via the Voicings dropdown or the STRINGS / SPAN / ORDER controls.
   Earlier 2026-05-13 spec hid them; superseded.  DIAGRAMS still
   hidden because the diagrams panel is voicings-only. */
.scp-ctrl-grid[data-active-tab="full-fretboard"] > .scp-ctrl-cell[data-ctrl-key="diagrams"] {
  display: none;
}

/* Arpeggios tab — Voicing-internal knobs (STRINGS/SPAN/ORDER/
   DIAGRAMS/SOURCE) don't apply; CONNECTIONS / GHOST NOTES /
   VIEW / KEY&DISPLAY stay. */
.scp-ctrl-grid[data-active-tab="arpeggios"] > .scp-ctrl-cell[data-ctrl-key="strings"],
.scp-ctrl-grid[data-active-tab="arpeggios"] > .scp-ctrl-cell[data-ctrl-key="span"],
.scp-ctrl-grid[data-active-tab="arpeggios"] > .scp-ctrl-cell[data-ctrl-key="order"],
.scp-ctrl-grid[data-active-tab="arpeggios"] > .scp-ctrl-cell[data-ctrl-key="diagrams"],
.scp-ctrl-grid[data-active-tab="arpeggios"] > .scp-ctrl-cell[data-ctrl-key="source"] {
  display: none;
}

/* Scales tab — same as Arpeggios.  VIEW (Browse/List) IS visible
   per user 2026-05-15: scales support stacked-list view.  SOURCE
   pill bar IS visible per user 2026-05-15: shows scale-bucket
   pills (All / 5-Note / 6-Note / etc.) instead of voicing pills. */
.scp-ctrl-grid[data-active-tab="scales"] > .scp-ctrl-cell[data-ctrl-key="strings"],
.scp-ctrl-grid[data-active-tab="scales"] > .scp-ctrl-cell[data-ctrl-key="span"],
.scp-ctrl-grid[data-active-tab="scales"] > .scp-ctrl-cell[data-ctrl-key="order"],
.scp-ctrl-grid[data-active-tab="scales"] > .scp-ctrl-cell[data-ctrl-key="diagrams"] {
  display: none;
}

/* Suites / Articles — only KEY&DISPLAY + VIEW + COLLECTION are
   meaningful; everything voicing-related is hidden. */
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="strings"],
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="span"],
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="order"],
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="connections"],
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="ghosts"],
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="diagrams"],
.scp-ctrl-grid[data-active-tab="suites"] > .scp-ctrl-cell[data-ctrl-key="source"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="strings"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="span"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="order"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="connections"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="ghosts"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="diagrams"],
.scp-ctrl-grid[data-active-tab="articles"] > .scp-ctrl-cell[data-ctrl-key="source"] {
  display: none;
}

/* ════════════════════════════════════════════════════════════════════
   CONTROL-BAR FIT — reclaim horizontal slack (keep every cell + caption)
   ════════════════════════════════════════════════════════════════════
   The chord bar carries more cells than the scale bar, so at common
   widths the single row (nowrap; overflow:hidden) clips the rightmost
   cells.  Instead of hiding controls or captions (both looked worse) or
   collapsing them into a dropdown (a Lab paradigm, not wanted here), we
   trim the unused slack: tighter inter-cell padding, slightly narrower
   edge cells, and lower floors on the value selects.  Every control
   stays visible + captioned and the bar height is unchanged.
   Chord-page scoped via .cpg-root.  Reversible: delete this block. */
.cpg-root .scp-ctrl-grid > .scp-ctrl-cell {
  padding-left: 4px;
  padding-right: 4px;
}
.cpg-root .scp-ctrl-cell--edge {
  padding-left: 8px;
  padding-right: 8px;
}
.cpg-root .scp-ctrl-cell--edge:first-child { flex-basis: 118px; }
.cpg-root .scp-ctrl-cell--edge:last-child  { flex-basis: 148px; }
.cpg-root .scp-ctrl-cell select.scp-kd-select   { min-width: 44px; }
.cpg-root .scp-ctrl-cell select.scp-ctrl-select { min-width: 56px; }
.cpg-root .scp-ctrl-cell .scp-switch { gap: 5px; }
.cpg-root .scp-ctrl-cell .scp-kd-row { gap: 4px; }

/* ── ALWAYS side-scroll instead of the desktop hamburger (owner 2026-07-13) ──
   The fully-captioned chord bar is wider than the scale bar and doesn't fit
   below ~1460px. Previously it collapsed to a hamburger there (and on any
   laptop). Owner prefers the mobile-style horizontal side-scroll at every
   desktop width: the inner control grid scrolls sideways instead of clipping,
   and the hamburger is never used on the chord page.
   SCOPED to html:not(.chrome-mobile-on) so the mobile shell (html.chrome-mobile-on)
   keeps its own control-bar handling — this only governs the DESKTOP path.
   A slim scrollbar is the affordance for mouse users who can't touch-scroll;
   clickable scroll-arrows can be layered on later (FT-090). */
html:not(.chrome-mobile-on) .cpg-root .scp-ctrl-shell {
  display: grid;
  /* Middle track must be able to shrink below its content, otherwise the
     grid child grows and pushes the whole page wider instead of scrolling.
     minmax(0,1fr) lets it shrink so the child's overflow-x:auto engages. */
  grid-template-columns: var(--scp-ctrl-edge-l, auto) minmax(0, 1fr) var(--scp-ctrl-edge-r, auto);
}   /* never collapse */
html:not(.chrome-mobile-on) .cpg-root .scp-app-ham    { display: none; }   /* no hamburger */
html:not(.chrome-mobile-on) .cpg-root .scp-ctrl-shell > .scp-ctrl-grid {
  /* Grid item's automatic minimum is its max-content width, so without
     min-width:0 it refuses to shrink below its content, overflows its
     track and paints over the fixed right-edge cell instead of scrolling. */
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-padding-inline: 8px;
}
/* No visible scrollbar on the control grid, in any mode — the desktop
   affordance is the side-scroll arrows and touch devices finger-scroll.
   Hidden across every engine.  Scrolling itself stays fully functional. */
.cpg-root .scp-ctrl-shell > .scp-ctrl-grid {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* legacy Edge */
}
.cpg-root .scp-ctrl-shell > .scp-ctrl-grid::-webkit-scrollbar {
  height: 0;
  width: 0;
  display: none;                  /* WebKit / Blink (Safari, Chrome) */
}

/* Control-bar side-scroll arrows (desktop only).  A subtle affordance
   for mouse users who cannot touch-scroll: left/right buttons overlaid
   at the inner edges of the scrolling grid track, each fading in (via
   `.is-visible`, toggled from page.js) only when the bar can scroll that
   way.  A short gradient scrim lets controls slide legibly under them.
   NOTE: arrows anchor to `.scp-ctrl-shell`, which is already
   `position: sticky` (a positioned value) and thus a valid containing
   block for these absolute children.  Do NOT override it to
   `position: relative` — that drops the sticky pin and lets its `top`
   offset displace the bar, leaving a grey gap above the control bar. */
.cpg-root .scp-ctrl-arrow {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 40px;
  display: none;
  align-items: center;
  padding: 0;
  border: 0;
  cursor: pointer;
  color: var(--text-muted, #6b6459);
  z-index: 4;
  opacity: 0;
  transition: opacity .15s ease;
  pointer-events: none;
}
.cpg-root .scp-ctrl-arrow.is-visible {
  display: flex;
  opacity: 1;
  pointer-events: auto;
}
.cpg-root .scp-ctrl-arrow--left {
  left: var(--scp-ctrl-edge-l, 0);
  justify-content: flex-start;
  padding-left: 3px;
  background: linear-gradient(to right, var(--surface, #fff) 45%, transparent);
}
.cpg-root .scp-ctrl-arrow--right {
  right: var(--scp-ctrl-edge-r, 0);
  justify-content: flex-end;
  padding-right: 3px;
  background: linear-gradient(to left, var(--surface, #fff) 45%, transparent);
}
/* Distinct chip behind the chevron so the control clearly reads as a
   clickable button, not just a glyph on a fade: tinted background,
   defined border and a soft shadow; accent tint on hover. */
.cpg-root .scp-ctrl-arrow svg {
  width: 16px;
  height: 16px;
  padding: 6px;
  box-sizing: content-box;
  border-radius: 50%;
  background: var(--surface, #fff);
  border: 1px solid var(--border-strong, #cfc9bd);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
  transition: color .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.cpg-root .scp-ctrl-arrow:hover svg {
  color: var(--accent, #e8853c);
  border-color: var(--accent, #e8853c);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.16);
}
html.chrome-mobile-on .cpg-root .scp-ctrl-arrow { display: none !important; }
/* Touch-capable devices can finger-scroll, so the arrows are just clutter —
   hide them whenever ANY available pointer is coarse (phones, tablets, and
   touchscreen laptops even while a mouse is also attached). */
@media (any-pointer: coarse) {
  .cpg-root .scp-ctrl-arrow { display: none !important; }
}

/* Styled-select trigger buttons (Key, Span — select-popover.js).  Look
   like a value box with a caret; click opens the chip-grid popover. */
.cpg-pick-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.cpg-pick-trigger::after {
  content: '▾';
  font-size: 10px;
  opacity: 0.6;
}
/* Locked/disabled picker trigger (source-locked Notes count, or String
   set when count = All) — dim + non-interactive, matching the old
   disabled <select>. */
.cpg-pick-trigger.cpg-pick-disabled {
  opacity: 0.5;
  pointer-events: none;
}
.cpg-pick-trigger.cpg-pick-disabled::after { display: none; }

/* Overlay view-mode — one card per string set, each showing every
   voicing on that string set unioned into a single VoicingBoard.
   Stacked vertically.  Per user 2026-05-13.  Scoped via the grid
   pane's `.scp-grid-host` parent so the rule never leaks. */
.scp-grid-host > .scp-overlay-card {   /* wrapper around stacked cards */
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.cpg-overlay-card {           /* per-string-set card */
  background: var(--surface-1, #fff);
  border: 1px solid var(--border-1, rgba(0,0,0,0.08));
  border-radius: var(--radius-md);
  padding: var(--space-sm) var(--space-md);
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.cpg-overlay-board {
  margin-top: var(--space-xs);
  cursor: pointer;
}

/* Overlay card actions row — status badge + Reset + admin Make/Clear
   default.  Per user 2026-05-14: chrome must match the rest of the
   app and the text must fit without buttons jumping width during
   flash states. */
.cpg-overlay-actions {
  margin-left: auto;
  display: flex;
  gap: var(--space-xs, 6px);
  align-items: center;
}
.cpg-overlay-status {
  font-size: var(--font-xs, 11px);
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 3px 10px;
  border-radius: var(--radius-full, 999px);
  background: transparent;
  color: var(--text-muted, #888);
  white-space: nowrap;
  user-select: none;
}
.cpg-overlay-status--user {
  background: rgba(242, 169, 59, 0.14);
  color: #a35f00;
}
.cpg-overlay-status--admin {
  background: rgba(52, 152, 219, 0.12);
  color: #1d5fbb;
}
.cpg-overlay-btn {
  appearance: none;
  -webkit-appearance: none;
  font-family: inherit;
  font-size: var(--font-xs, 11px);
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 4px 12px;
  height: 26px;
  min-width: 96px;
  border: 1px solid var(--border, #d6d2c9);
  background: var(--bg-1, #fff);
  color: var(--text-strong, #1a1a18);
  border-radius: var(--radius-md, 6px);
  cursor: pointer;
  white-space: nowrap;
  text-align: center;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.cpg-overlay-btn:hover:not(:disabled) {
  background: var(--bg-2, #f7f4ee);
  border-color: var(--text-muted, #888);
}
.cpg-overlay-btn:active:not(:disabled) {
  background: var(--bg-3, #ede9e1);
}
.cpg-overlay-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.cpg-overlay-btn--flash-ok {
  background: rgba(74, 222, 128, 0.18);
  border-color: rgba(20, 150, 70, 0.5);
  color: #0e7b3a;
}
.cpg-overlay-btn--flash-error {
  background: rgba(239, 68, 68, 0.14);
  border-color: rgba(200, 50, 50, 0.5);
  color: #a01616;
}

/* Custom arpeggio builder — cmd+click flow on the Full Fretboard.
   Hint banner + per-draft card chrome.  Per user 2026-05-13. */
.cpg-arp-build-hint {
  background: var(--accent-soft, #fff3e0);
  border: 1px solid var(--accent, #4a90e2);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-md);
  margin: 0 0 var(--space-sm) 0;
  font-size: var(--font-sm);
  color: var(--text-strong, #222);
}
.cpg-arp-draft-card {
  margin-top: var(--space-md);
  border: 2px dashed var(--accent, #4a90e2);
}
.cpg-arp-draft-form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  align-items: end;
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--border-1, rgba(0,0,0,0.08));
}
.cpg-arp-draft-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}
.cpg-arp-draft-field-label {
  font-size: var(--font-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted, #666);
}
.cpg-arp-draft-name,
.cpg-arp-draft-folder,
.cpg-arp-draft-newfolder {
  font-size: var(--font-base);
  padding: var(--ctl-pad-y) var(--ctl-pad-x);
  border: 1px solid var(--border-1, rgba(0,0,0,0.15));
  border-radius: var(--radius-sm);
  background: var(--surface-1, #fff);
  height: var(--ctl-h-md);
  box-sizing: border-box;
}
.cpg-arp-draft-name      { min-width: 240px; }
.cpg-arp-draft-folder    { min-width: 160px; }
.cpg-arp-draft-newfolder { min-width: 160px; }
.cpg-arp-draft-btns {
  display: flex;
  gap: var(--space-xs);
  margin-left: auto;
}
.cpg-arp-draft-save,
.cpg-arp-draft-cancel {
  font-size: var(--font-sm);
  padding: var(--ctl-pad-y) var(--space-lg);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-1, rgba(0,0,0,0.15));
  cursor: pointer;
  height: var(--ctl-h-md);
}
.cpg-arp-draft-save {
  background: var(--accent, #4a90e2);
  color: #fff;
  border-color: var(--accent, #4a90e2);
}
.cpg-arp-draft-save:disabled { opacity: 0.6; cursor: progress; }
.cpg-arp-draft-cancel { background: var(--surface-1, #fff); }
.cpg-arp-draft-board {
  padding: var(--space-sm) var(--space-md) var(--space-md);
  background: var(--surface-0, #fafafa);
  cursor: pointer;   /* chord-tone cells inside are clickable */
}
.cpg-arp-draft-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-sm);
  color: var(--text-strong, #222);
}
.cpg-arp-draft-toggle--admin {
  color: var(--accent, #4a90e2);
  font-weight: 500;
}

/* Sidebar arpeggio context menu — opened on cmd/ctrl+click or
   right-click on a user-saved arp row.  Floats over the sidebar. */
.cpg-arp-ctx-menu {
  background: var(--surface-1, #fff);
  border: 1px solid var(--border-1, rgba(0,0,0,0.12));
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  padding: var(--space-xs) 0;
  min-width: 220px;
  z-index: 1200;
  display: flex;
  flex-direction: column;
}
.cpg-arp-ctx-item {
  display: block;
  text-align: left;
  background: transparent;
  border: 0;
  width: 100%;
  font-size: var(--font-sm);
  padding: var(--space-xs) var(--space-md);
  cursor: pointer;
  color: var(--text-strong, #222);
}
.cpg-arp-ctx-item:hover { background: var(--surface-2, rgba(0,0,0,0.05)); }
.cpg-arp-ctx-item--danger { color: var(--danger, #c0392b); }
.cpg-arp-ctx-item--danger:hover { background: rgba(192, 57, 43, 0.08); }
.cpg-arp-ctx-sep {
  height: 1px;
  background: var(--border-1, rgba(0,0,0,0.08));
  margin: var(--space-xs) 0;
}
.cpg-arp-ctx-hdr {
  font-size: var(--font-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-xs) var(--space-md) var(--space-sm);
  color: var(--text-muted, #666);
  font-weight: 600;
  border-bottom: 1px solid var(--border-1, rgba(0,0,0,0.08));
  margin-bottom: var(--space-xs);
}
.cpg-arp-ctx-info {
  padding: var(--space-xs) var(--space-md);
  font-size: var(--font-sm);
  color: var(--text-muted, #666);
  font-style: italic;
  max-width: 260px;
}

/* Custom arpeggio editor — modal overlay opened from the
   Arpeggios tab "+ Add" affordance.  Single source of truth for
   the editor chrome; per-element rules tokenised so admin Display
   prefs propagate.  Per user 2026-05-13. */
.cpg-arp-editor-overlay {
  position: fixed;
  inset: 0;
  z-index: 1100;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
}
.cpg-arp-editor {
  background: var(--surface-1, #fff);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
  width: min(96vw, 1100px);
  max-height: 92vh;
  overflow: auto;
  display: flex;
  flex-direction: column;
}
.cpg-arp-editor-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  border-bottom: 1px solid var(--border-1, rgba(0,0,0,0.08));
}
.cpg-arp-editor-title {
  margin: 0;
  font-size: var(--font-lg);
  font-weight: 600;
}
.cpg-arp-editor-close {
  background: transparent;
  border: 0;
  font-size: var(--font-xl);
  line-height: 1;
  cursor: pointer;
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-sm);
}
.cpg-arp-editor-close:hover { background: var(--surface-2, rgba(0,0,0,0.05)); }
.cpg-arp-editor-ctrls {
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding: var(--space-md) var(--space-lg);
  border-bottom: 1px solid var(--border-1, rgba(0,0,0,0.08));
}
.cpg-arp-editor-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}
.cpg-arp-editor-field-label {
  font-size: var(--font-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted, #666);
}
.cpg-arp-editor-name,
.cpg-arp-editor-num {
  font-size: var(--font-base);
  padding: var(--ctl-pad-y) var(--ctl-pad-x);
  border: 1px solid var(--border-1, rgba(0,0,0,0.15));
  border-radius: var(--radius-sm);
  background: var(--surface-1, #fff);
  height: var(--ctl-h-md);
  box-sizing: border-box;
}
.cpg-arp-editor-name { min-width: 260px; }
.cpg-arp-editor-num  { width: 80px; }
.cpg-arp-editor-board {
  padding: var(--space-md) var(--space-lg);
  background: var(--surface-0, #fafafa);
}
.cpg-arp-editor-svg { display: block; max-width: 100%; }
.cpg-arp-editor-hint {
  padding: 0 var(--space-lg) var(--space-md);
  font-size: var(--font-sm);
  color: var(--text-muted, #666);
}
.cpg-arp-editor-footer {
  display: flex;
  gap: var(--space-sm);
  justify-content: flex-end;
  padding: var(--space-md) var(--space-lg);
  border-top: 1px solid var(--border-1, rgba(0,0,0,0.08));
}
.cpg-arp-editor-save,
.cpg-arp-editor-cancel {
  font-size: var(--font-sm);
  padding: var(--ctl-pad-y) var(--space-lg);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-1, rgba(0,0,0,0.15));
  cursor: pointer;
  height: var(--ctl-h-md);
}
.cpg-arp-editor-save {
  background: var(--accent, #4a90e2);
  color: #fff;
  border-color: var(--accent, #4a90e2);
}
.cpg-arp-editor-save:disabled {
  opacity: 0.6;
  cursor: progress;
}
.cpg-arp-editor-cancel {
  background: var(--surface-1, #fff);
}

/* Diagram inspect overlay — opened via cmd/ctrl+click on any
   diagram card in the Diagrams panel.  Renders the chord-diagram
   SVG at a larger size so the user can study a single voicing
   without losing their current selection.  Distinct from
   FretlyInspector (the global fretboard inspect view) — this is
   diagram-only. */
.cpg-diag-inspect {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.cpg-diag-inspect-card {
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e0ddd5);
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
  max-width: min(520px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.cpg-diag-inspect-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border, #e0ddd5);
  background: var(--surface-2, #f7f6f3);
}
.cpg-diag-inspect-title {
  flex: 1 1 auto;
  font-weight: 600;
  font-size: 14px;
  color: var(--text-1, #222);
}
.cpg-diag-inspect-close {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--border, #e0ddd5);
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.cpg-diag-inspect-close:hover {
  background: var(--surface-2, #f5f0e6);
  color: var(--text-1, #222);
}
.cpg-diag-inspect-body {
  padding: 18px;
  overflow: auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cpg-diag-inspect-body svg { display: block; }

/* chord-page.css — chord-page v2 styles.
   ===========================================================================
   Mirrors scale-page.css structure.  Most chrome (header, ctrl grid,
   side panes, card chrome) inherits from scale-collection-page.css's
   `.scp-*` rules — chord-page only owns the `.cpg-*` overrides.
   Doctrine: NO inline CSS, NO duplication of scale-page rules. */

/* Layout inherits from .scp-* (scale-collection-page.css) — chord
   page reuses every shell rule.  The few chord-page-specific styles
   live below as `.cpg-*` overrides. */

/* ── Collection view (Browse-full Collection mode) ───────────────────
   Folder browser shown when `_pageMode === 'collection'`.  Sibling
   of `.spg-view-fretboard`; visibility swap driven by
   `.spg-content--collection` class on the content wrapper (CSS in
   scale-collection-page.css).  Layout-only — visual chrome reuses
   the page's existing surface tokens. */
.cpg-collection-view {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px;
  background: var(--surface, #fff);
  border-radius: 4px;
  min-height: 320px;
}
.cpg-collection-crumb {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--text-2, #555);
  flex-wrap: wrap;
}
.cpg-collection-crumb-home {
  color: var(--accent, #e8853c);
  text-decoration: none;
  font-weight: 600;
  cursor: pointer;
}
.cpg-collection-crumb-home:hover { text-decoration: underline; }
.cpg-collection-crumb-link {
  color: var(--text-2, #555);
  text-decoration: none;
  cursor: pointer;
}
.cpg-collection-crumb-link:hover { color: var(--accent, #e8853c); }
.cpg-collection-crumb-here {
  color: var(--text, #1a1a18);
  font-weight: 600;
}
.cpg-collection-crumb-sep { color: var(--text-3, #888); }
.cpg-collection-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
}
.cpg-collection-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 14px 14px 12px;
  border: 1px solid var(--border, #e0ddd5);
  border-radius: 6px;
  background: var(--surface, #fff);
  color: var(--text, #1a1a18);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 120ms, background 120ms, transform 80ms;
}
.cpg-collection-card:hover {
  border-color: var(--accent, #e8853c);
  background: rgba(232, 135, 74, 0.04);
}
.cpg-collection-card:active { transform: translateY(1px); }
.cpg-collection-card-icon {
  font-size: 20px;
  line-height: 1;
  color: var(--text-3, #888);
}
/* Voicing FRETBOARD preview on collection leaf cards — mirrors
   the main chord-page voicing-area.  Each card mounts a real
   `VoicingBoard` (same renderer the active voicing fretboard
   above the panels uses).  Distinct from the compact chord
   DIAGRAM in the DiagramsArea (5×5 box) — fretboard = full neck,
   diagram = single shape framed.  Leaf cards mirror the FRETBOARD
   to match the main page view. */
.cpg-collection-card-board {
  display: block;
  width: 100%;
  align-self: stretch;
}
.cpg-collection-card-board svg {
  display: block;
  width: 100%;
  height: auto;
}
.cpg-collection-card--leaf {
  align-items: stretch;
  width: 100%;
}
.cpg-collection-card--folder .cpg-collection-card-icon {
  color: var(--accent, #e8853c);
}
.cpg-collection-card-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text, #1a1a18);
}
.cpg-collection-card-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cpg-collection-card-sub {
  font-size: 11px;
  color: var(--text-3, #888);
}
.cpg-collection-card-count {
  font-size: 11px;
  color: var(--text-3, #888);
  font-variant-numeric: tabular-nums;
}
.cpg-collection-empty {
  padding: 24px;
  text-align: center;
  color: var(--text-3, #888);
  font-size: 13px;
}


.cpg-coll-stub {
  padding: 14px 16px;
  font-size: 12px;
  color: var(--text-3, #888);
  font-style: italic;
}

/* Inversions panel — clickable rows showing slash-bass + classification. */
.cpg-inv-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 4px;
}
.cpg-inv-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 10px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #ddd);
  border-radius: 4px;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  color: var(--text-2, #333);
  text-align: left;
}
.cpg-inv-row:hover {
  background: var(--surface-2, #f7f6f3);
  border-color: var(--accent, #e8853c);
}
/* Active slash-bass row — matches the accent-outlined "selected" chrome
   the scale/chord pages use for active leaves (Slash-chord support #6). */
.cpg-inv-row--active {
  background: var(--surface-2, #f7f6f3);
  border-color: var(--accent, #e8853c);
  box-shadow: inset 0 0 0 1px var(--accent, #e8853c);
}
.cpg-inv-symbol {
  font-weight: 600;
  font-feature-settings: "ss01" on;
}
.cpg-inv-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3, #888);
}

/* Chord-page Collection right-pane — sectioned list of voicings +
   charts using this chord.  Mirrors the scale-page list-pane chrome
   for visual consistency. */
.scp-shell-list--coll .scp-list-head {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border, #e0ddd5);
}
.scp-shell-list--coll .scp-list-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2, #555);
}
.scp-shell-list--coll .scp-list-group {
  padding: 8px 0;
  border-bottom: 1px solid var(--border, #ece8df);
}
.scp-shell-list--coll .scp-list-group:last-child { border-bottom: none; }
.scp-shell-list--coll .scp-list-group-head {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3, #888);
  padding: 0 10px 4px;
}
.scp-shell-list--coll .scp-list-row {
  display: block;
  font-size: 12px;
  color: var(--text-1, #222);
  padding: 4px 10px;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.scp-shell-list--coll a.scp-list-row:hover {
  color: var(--accent, #e8853c);
  background: var(--surface-2, #f6f3ec);
}

/* Pager — used by both the VoicingArea (List view) and DiagramsArea
   when the result set exceeds one page.  Same chrome both places. */
.cpg-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 12px 0;
  font-size: 12px;
  color: var(--text-2, #555);
}
.cpg-pager--top    { border-bottom: 1px solid var(--border, #ece8df); }
.cpg-pager--bottom { border-top:    1px solid var(--border, #ece8df); }
/* List pagers only apply to list view — hide them in browse mode
   where the cards are paginated to a single active card.  Per user
   2026-05-26: "the page browser persists in browse mode, but it's
   for list mode only." */
.cpg-area-boards[data-view="browse"] .cpg-pager { display: none; }
.cpg-pager-btn {
  height: 28px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 500;
  border: 1px solid var(--border, #e0ddd5);
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  border-radius: 4px;
  cursor: pointer;
}
.cpg-pager-btn:hover:not(:disabled) {
  border-color: var(--accent, #e8853c);
  color: var(--accent, #e8853c);
}
.cpg-pager-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.cpg-pager-info {
  font-variant-numeric: tabular-nums;
}

/* Shared CollectionGridPane pager — same visual treatment as
   .cpg-pager above so chord-page + scale-page Cards/List views
   inherit identical chrome.  Per user 2026-05-15. */
.scp-grid-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 12px 0;
  font-size: 12px;
  color: var(--text-2, #555);
}
.scp-grid-pager--top    { border-bottom: 1px solid var(--border, #ece8df); }
.scp-grid-pager--bottom { border-top:    1px solid var(--border, #ece8df); }
.scp-grid-pager-btn {
  height: 28px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 500;
  border: 1px solid var(--border, #e0ddd5);
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  border-radius: 4px;
  cursor: pointer;
}
.scp-grid-pager-btn:hover:not(:disabled) {
  border-color: var(--accent, #e8853c);
  color: var(--accent, #e8853c);
}
.scp-grid-pager-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.scp-grid-pager-info {
  font-variant-numeric: tabular-nums;
}

/* DiagramsArea — dedicated panel below the fretboard rendering the
   full legacy diagrams grid (STRINGS / FRETS / SORT / DISPLAY +
   grouped vertical chord cards).  Toggled on/off via the Diagrams
   cell in the controls grid (state.showDiagrams). */

/* Outer host — `display: contents` so the wrapper itself doesn't act
   as a flex item of `.scp-shell-content`.  When the inner
   `.cpg-diagrams-area` is `display: none` (showDiagrams === false),
   nothing in this branch contributes a flex item, so no surrounding
   flex `gap` is reserved for it.  When the diagrams panel IS visible,
   the inner element is the direct flex item — gap applies normally.
   Net effect: hiding diagrams collapses cleanly with zero residual
   spacing.  Removes the 12px ghost gap below the fretboard card at
   narrow viewports when diagrams is off. */
.spg-shell-diagrams { display: contents; }

.cpg-diagrams-area {
  background: var(--surface, #fff);
  border: var(--border-w) solid var(--border, #e0ddd5);
  border-radius: var(--radius-md);
  margin: var(--space-lg) 0 var(--space-xl);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
}
.cpg-diagrams-header {
  /* Title + controls + pager on a single row.  Title shrinks first;
     controls + pager keep their natural width. */
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
  padding-bottom: var(--space-sm);
  border-bottom: var(--border-w) solid var(--border, #e0ddd5);
}
/* Collapsed panel (owner 2026-07-08): caret header only — controls,
   pager and grid hide; the header loses its divider + spacing so the
   card reads as a slim closed bar (same feel as the Tablature card). */
.cpg-diagrams-area.cpg-diagrams-area--collapsed .cpg-diagrams-ctrls,
.cpg-diagrams-area.cpg-diagrams-area--collapsed .cpg-diagrams-pager-host,
.cpg-diagrams-area.cpg-diagrams-area--collapsed .cpg-diagrams-grid { display: none; }
.cpg-diagrams-area--collapsed .cpg-diagrams-header {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
}
.cpg-diagrams-area--collapsed { padding-bottom: var(--space-md); }
.cpg-diagrams-title {
  font-size: var(--font-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-1, #222);
  flex: 0 1 auto;     /* shrinkable, don't hog row width at narrow */
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cpg-diagrams-ctrls {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-sm);
  flex: 1 1 auto;     /* take the remaining row width on wide; wrap on narrow */
  min-width: 0;
  justify-content: flex-end;
}

/* Export dropdown — appears in the diagrams-panel controls row.
   Captures the panel via shared/dom-snapshot.js.  Single source of
   truth for "export this panel" UX, see diagrams-area.js
   _buildExportMenu. */
.cpg-diagrams-export {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.cpg-diagrams-export-btn {
  height: var(--ctl-h-md, 30px);
  min-width: var(--ctl-h-md, 30px);
  padding: 0 var(--space-xs);
  border: 1px solid var(--border, #d8d4c8);
  background: var(--surface, #fff);
  color: var(--text);
  border-radius: var(--radius-sm);
  font-size: var(--font-base);
  cursor: pointer;
}
.cpg-diagrams-export-btn:hover { background: var(--surface-2, #f1ede4); }
.cpg-diagrams-export-menu {
  position: absolute;
  top: calc(100% + var(--space-xs));
  right: 0;
  z-index: 50;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #d8d4c8);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 22px rgba(0,0,0,0.14);
  display: flex;
  flex-direction: column;
  min-width: 96px;
  padding: var(--space-xs) 0;
}
.cpg-diagrams-export-menu[hidden] { display: none; }
.cpg-diagrams-export-item {
  background: transparent;
  border: 0;
  text-align: left;
  padding: var(--space-xs) var(--space-md);
  font-size: var(--font-sm);
  cursor: pointer;
  color: var(--text);
}
.cpg-diagrams-export-item:hover { background: var(--surface-2, #f1ede4); }

/* Side-scrolling wrappers reverted 2026-05-10 — `min-width: 1000px`
   trick scaled the SVG dots/frets up at the same rate, producing
   massive elements in a 2-3 visible fret window.  Better approaches
   prototyped in /prototypes/fretboard-narrow-*.html. */

/* Narrow viewports — let the diagrams panel header AND the fretboard
   area toolbar wrap to a second row instead of clipping their
   controls.  Per user 2026-05-10: at ≤1100px the single-row layout
   becomes too tight (drawer-overlay panes give content full width
   but per-panel controls still need to fit); allow both panels'
   header rows to wrap so every cell stays reachable.  Critically,
   the controls CONTAINER must shrink (`flex: 1 1 auto; min-width:
   0`) so its children get a finite width budget — without that
   the container's `flex: 0 0 auto` claim makes flex-wrap inert. */
@media (max-width: 1100px) {
  .cpg-diagrams-header,
  .cpg-area-card-toolbar {
    flex-wrap: wrap;
    row-gap: 8px;
  }
  /* Title row 1 hosts the pager on the right (always small).
     Controls drop to row 2 as a compact group when row 1 can't hold
     them. */
  .cpg-diagrams-header .cpg-diagrams-pager-host {
    order: 2;          /* sit beside the title on row 1 */
    margin-left: auto;
  }
  .cpg-diagrams-header .cpg-diagrams-ctrls {
    order: 3;          /* line-break to row 2 */
    flex: 1 1 100%;
    min-width: 0;
    flex-wrap: wrap;
    row-gap: 6px;
    column-gap: var(--space-sm);
    justify-content: flex-start;
  }
  /* Compact controls at narrow widths.  Labels are HIDDEN — the
     select options themselves carry enough context ("Auto", "5
     frets", "By string set", "Notes", "6") so the textual labels
     are redundant + cost row space we need.  Selects shrink to
     content via `min-width: 0` so they don't claim 100 px each. */
  .cpg-diagrams-ctrl {
    gap: 3px;
  }
  .cpg-diagrams-ctrl .cpg-diagrams-ctrl-label {
    display: none;
  }
  .cpg-diagrams-select {
    min-width: 0;
    height: 26px;
    padding: 0 20px 0 8px;
    font-size: 12px;
  }
  .cpg-area-card-nav {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: wrap;
    row-gap: 6px;
  }
}
/* Even tighter at sub-720 px — squeeze padding a tad more. */
@media (max-width: 720px) {
  .cpg-diagrams-select {
    padding: 0 16px 0 5px;
    font-size: 11px;
    height: 24px;
  }
  .cpg-diagrams-ctrl { gap: 2px; }
}

/* Diagrams pager — header-mounted version sits to the right of the
   filters; styling stays light so it reads as a control, not a card.
   Hidden when there's only one page. */
.cpg-diagrams-pager-host {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}
.cpg-diagrams-pager-host:empty { display: none; }
.cpg-diagrams-pager-host .cpg-pager--diagrams {
  display: inline-flex;
  align-items: center;
  /* Prev / Next buttons are PAIRED — sit flush next to each other
     so they read as one control.  Page counter sits to the right
     with extra breathing room. */
  gap: 0;
  padding: 0;
  border: none;
  background: transparent;
}
.cpg-diagrams-pager-host .cpg-pager--diagrams .cpg-pager-btn + .cpg-pager-btn {
  margin-left: -1px;       /* collapse adjacent borders into a pair */
}
.cpg-diagrams-pager-host .cpg-pager--diagrams .cpg-pager-info {
  margin-left: 10px;
  white-space: nowrap;
}
.cpg-diagrams-ctrl {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
/* Specificity-boosted (`.cpg-diagrams-ctrl .cpg-diagrams-ctrl-label`,
   0/2/0) so this rule wins over `.scp-ctrl-label` (0/1/0) regardless
   of CSS source order — `scale-collection-page.css` is loaded AFTER
   `chord-page.css` in app.php, so an equal-specificity rule there
   would otherwise re-apply its 8px `margin-bottom` and push the
   labels above center. */
.cpg-diagrams-ctrl .cpg-diagrams-ctrl-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3, #888);
  margin: 0;
  padding: 0;
  height: 28px;
  line-height: 28px;
  display: inline-flex;
  align-items: center;
  align-self: center;
}
.cpg-diagrams-select {
  height: 28px;
  min-width: 100px;
}

/* Grid + groups + cards — class names (`dg-*`) match the legacy
   chord page exactly so any CSS authored against them keeps working. */
.cpg-diagrams-grid.dg-grid {
  display: block;
  padding: 8px 0 14px;
  /* Per user 2026-05-10: the diagrams panel must NEVER have its
     own scrollbar.  When content overflows, the PAGE grows; the
     viewport scrolls.  No fixed height, no `overflow: auto`, no
     `contain: strict` — just let the grid take its natural size.
     Was previously locked at 460px with internal scroll which
     created a nested scroll container the user explicitly does
     not want. */
}

/* Group blocks flow side-by-side via CSS Grid spanning.  The OUTER
   container is a grid with --dg-cols equal columns.  Each block
   claims `span N` outer columns where N = min(group.items.length,
   --dg-cols) — set inline by JS (`--block-span`).  Result: every
   card across every group has the same width (driven by COLS), small
   groups sit next to other small groups on the same row, and the
   grid naturally wraps when a row's column budget is exhausted.
   Per user 2026-05-12 — restores pre-2026-05-10 side-by-side
   behavior with the additional invariant that card widths align
   across groups (which the prior flex-wrap version did not). */
.cpg-diagrams-grid .dg-flow {
  display: grid;
  grid-template-columns: repeat(var(--dg-cols, 4), minmax(0, 1fr));
  align-items: start;
  column-gap: 18px;
  row-gap: 22px;
}
.cpg-diagrams-grid .dg-group-block {
  /* `--block-span` is set inline by JS for each block — defaults to
     full row if unset.  Block lays out its own heading + cards
     vertically. */
  grid-column: span var(--block-span, var(--dg-cols, 4));
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.cpg-diagrams-grid .dg-group-heading {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3, #888);
  padding: 0 0 4px;
  border-bottom: 1px solid var(--border, #e8e3d8);
  white-space: nowrap;
}
.cpg-diagrams-grid .dg-group-cards {
  /* Inner grid divides the block's allocated outer span into
     --block-span columns — i.e. one inner column per card.  Inner
     columns are 1fr each so widths align with neighbouring groups'
     cards on the same outer row. */
  display: grid;
  grid-template-columns: repeat(var(--block-span, var(--dg-cols, 4)), minmax(0, 1fr));
  gap: 12px;
}
.cpg-diagrams-grid .dg-card {
  /* Cards fill their grid track width; height is capped to the
     fretboard's rendered height (`--cpg-fretboard-h`, written by
     ChordPage's ResizeObserver) so cards never grow taller than
     the fretboard above them. `min-height: 0` is critical — grid
     items default to `min-height: auto` which sizes to content. */
  width: 100%;
  max-height: var(--cpg-fretboard-h, 360px);
  min-height: 0;
  min-width: 0;
  background: var(--surface, #fff);
  border: var(--border-w) solid var(--border, #e8e3d8);
  border-radius: var(--radius-md);
  padding: var(--space-sm) var(--space-sm) var(--space-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  box-sizing: border-box;
  overflow: hidden;
  /* Perf: let the browser skip layout/paint for diagram cards that
     are off-screen.  A typical chord page renders 10-30 cards; many
     are below the fold.  Per CLAUDE.md "HIGH-PRIORITY TODO - UI
     navigation performance audit" - remedy pattern
     `content-visibility: auto`.  `contain-intrinsic-size` reserves
     a placeholder height so scroll-position math stays stable
     before cards are realised. */
  content-visibility: auto;
  contain-intrinsic-size: var(--cpg-fretboard-h, 360px);
}
.cpg-diagrams-grid .dg-card svg {
  display: block;
  /* Leave room for the card's padding + label.  --space-2xl
     approximates the legacy 36 px reservation at 1x scale and
     grows proportionally with --ui-scale. */
  max-height: calc(var(--cpg-fretboard-h, 360px) - var(--space-2xl));
  width: auto;
  max-width: 100%;
  height: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.cpg-diagrams-grid .dg-card-label {
  font-size: var(--font-xs);
  color: var(--text-2, #555);
  text-align: center;
}
.cpg-diagrams-grid .ch-diagrams-empty {
  font-size: var(--font-sm);
  color: var(--text-3, #888);
  font-style: italic;
  padding: var(--space-lg) 0;
}

/* Jump-to-diagram button — small icon button in each fretboard
   card's title-row actions.  Clicking scrolls the corresponding
   diagram card into view + flashes it briefly so the user sees
   exactly which one matches. */
.cpg-jump-diag-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 13px;
  font-family: inherit;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e0ddd5);
  border-radius: 4px;
  color: var(--text-2, #555);
  cursor: pointer;
  transition: background 120ms, color 120ms, border-color 120ms;
}
.cpg-jump-diag-btn:hover:not(:disabled) {
  background: var(--accent, #e8853c);
  color: #fff;
  border-color: var(--accent, #e8853c);
}
.cpg-jump-diag-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  background: var(--surface, #fff);
  color: var(--text-3, #999);
  border-color: var(--border, #e0ddd5);
}

/* ── Card-chrome action cluster — segmented-group treatment ────────
   All action buttons (Diagram / Copy / Map / Add / Export) in the
   chord-page card toolbar share a single rounded container with
   hairline dividers between cells.  Treats the cluster as ONE
   visual unit.  Per user 2026-05-15. */
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e0ddd5);
  border-radius: 8px;
  overflow: hidden;
  height: 34px;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > button {
  border: 0;
  border-radius: 0;
  background: transparent;
  height: 100%;
  margin: 0;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--text-2, #555);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > button + button {
  border-left: 1px solid #ece9e2;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > button:hover:not(:disabled) {
  background: var(--accent-bg, #fff8f1);
  color: var(--accent, #e8853c);
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > button:active:not(:disabled) {
  background: var(--accent, #e8853c);
  color: #fff;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > button:disabled {
  opacity: 0.35;
  cursor: default;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > button > svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}
/* Icon-only cells stay square — no padding on the sides. */
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .cpg-jump-diag-btn,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-copy-btn,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .cpg-play-voicing-btn {
  width: 38px;
  padding: 0;
}
/* Existing per-button chrome (white bg, own border, own radius)
   would fight the cluster — null it out inside this scope. */
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .cpg-jump-diag-btn,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-copy-btn,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .atc-btn,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-btn,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .cpg-play-voicing-btn {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
}
/* Playing state — same red "live" cue as DiagramCardToolbar's
   .diagram-card-btn--playing (site.css), reused here for the fretboard
   card's own inline Play button (owner 2026-07-12). */
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .cpg-play-voicing-btn.is-playing {
  background: #e05555 !important;
  color: #fff;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .cpg-play-voicing-btn.is-playing:hover {
  background: #c94444 !important;
}
/* "Map" view-switch — a FLAT segment cell like its siblings.  The old
   pill (own border + 999px radius) sat inside the squared segmented
   cluster and read as "a round button in a square box" (owner
   2026-07-08).  Discoverability now comes from the accent colour of
   the icon+label, not extra chrome; hover/active come from the
   cluster's base rules. */
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-map-btn {
  display: inline-flex !important;
  align-items: center;
  gap: 5px;
  color: var(--accent, #e8853c);
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-map-btn svg { display: block; }
/* Map button DISABLED on the "All"/full-fretboard source (owner 2026-07-13):
   visible but inactive; active on every voicings source. */
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-map-btn:disabled,
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .fba-map-btn.fba-btn--disabled {
  color: var(--text-3, #b3b3b3);
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}
.cpg-area .spg-area-card-toolbar > .spg-area-card-actions > .atc-btn > svg { opacity: 1; }

/* Diagram card flash — applied for ~1.2s when the user uses the
   jump button to highlight which card was just brought into view. */
.cpg-diagrams-grid .dg-card--flash {
  animation: cpgDiagFlash 1.2s ease-out;
}
@keyframes cpgDiagFlash {
  0%   { box-shadow: 0 0 0 0 rgba(232, 135, 74, 0.7); border-color: var(--accent, #e8853c); }
  60%  { box-shadow: 0 0 0 8px rgba(232, 135, 74, 0); border-color: var(--accent, #e8853c); }
  100% { box-shadow: 0 0 0 0 rgba(232, 135, 74, 0); border-color: var(--border, #e8e3d8); }
}

/* Active diagram card — when state.voicingIndex matches a card's
   data-orig-idx, accent the border so users see which voicing the
   fretboard is currently showing. */
.cpg-diagrams-grid .dg-card--active {
  border-color: var(--accent, #e8853c);
  box-shadow: 0 0 0 2px rgba(232, 135, 74, 0.18);
}

/* Override badge — admin-edited canonical voicings carry the
   `_override` stamp; we mark the card with a faint dashed border-top
   so the badge reads at a glance without changing the chord-diagram
   chrome itself.  Mirror of scale-page card override hint.
   Phase 15: draft variant uses a muted grey so admins can tell at a
   glance which overrides are still drafts vs published. */
.cpg-diagrams-grid .dg-card--override {
  position: relative;
}
.cpg-diagrams-grid .dg-card--override::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  border-top: 2px dashed var(--accent, #e8853c);
  pointer-events: none;
  border-top-left-radius: inherit;
  border-top-right-radius: inherit;
}
.cpg-diagrams-grid .dg-card--draft::before {
  border-top-color: var(--muted, #9aa0a6);
}

/* Sources popover panel — orange-tinted row with category buttons,
   matching scale-page Fingerings popover idiom. */
.cpg-sources-inner {
  gap: 10px;
}
.cpg-sources-btn--stub {
  opacity: 0.45;
  cursor: not-allowed;
  font-style: italic;
}
.cpg-sources-btn--stub:hover { background: var(--surface, #fff); }

/* Active + hover — keep the orange/white treatment so the label
   stays readable.  Without this, the generic .spg-strip-tab:hover
   rule flips the background to a light tint while the active rule
   still sets text to #fff → low-contrast/illegible.  Mirrors the
   fix in scale-page.css. */
.spg-strip-tab.cpg-sources-btn:hover {
  color: var(--text-1, #222);
}
.spg-strip-tab--active.cpg-sources-btn,
.spg-strip-tab--active.cpg-sources-btn:hover {
  background: var(--accent, #e8853c);
  border-color: var(--accent, #e8853c);
  color: #fff;
}

/* Source menu close button — pushed to the right of the row, only
   visible at hamburger-mode viewports.  At wider widths the user
   closes the menu by clicking the trigger again, so the explicit
   close affordance would be visual noise. */
.cpg-sources-close {
  display: none;
  margin-left: auto;
  align-self: center;
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border, #e8e3d8);
  border-radius: 50%;
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.cpg-sources-close:hover {
  background: var(--surface-2, #f5f0e6);
  color: var(--text-1, #222);
}
@media (max-width: 1100px) {
  .cpg-sources-close { display: inline-flex; align-items: center; justify-content: center; }
}

/* When the source panel opens from inside the hamburger overflow
   popover, the host has no .scp-ctrl-shell ancestor — sit inline
   in the popover's vertical stack with consistent padding/borders. */
.cpg-sources-panel--inline {
  width: 100%;
  margin: 0;
  border-radius: 6px;
  border: 1px solid var(--border, #e8e3d8);
  border-bottom: 1px solid var(--border, #e8e3d8);
}
.cpg-sources-panel--inline .cpg-sources-inner {
  flex-wrap: wrap;
}

/* Chord list pane — same flat-table feel as scale-list. */
.cpg-list-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.cpg-list-title {
  flex: 1 1 auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3, #888);
}
.cpg-list-bulk {
  font-size: 11px;
  background: transparent;
  border: 1px solid var(--border, #ccc);
  color: var(--text-2, #555);
  border-radius: 4px;
  padding: 3px 8px;
  cursor: pointer;
}
.cpg-list-bulk:hover { background: var(--surface-2, #f7f6f3); }

.cpg-list-filter {
  width: 100%;
  padding: 6px 10px;
  font-size: 13px;
  border: 1px solid var(--border, #ccc);
  border-radius: 4px;
  background: var(--surface, #fff);
  margin-bottom: 8px;
  font-family: inherit;
}

.cpg-list-group { margin-bottom: 6px; }
.cpg-list-group-head {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 4px 6px;
  background: transparent;
  border: none;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-2, #555);
  cursor: pointer;
}
.cpg-list-group-head:hover { background: var(--surface-2, #f7f6f3); }
.cpg-list-group-caret { font-size: 10px; opacity: 0.6; width: 12px; }
.cpg-list-group-label { flex: 1 1 auto; text-align: left; }
.cpg-list-group-count { font-size: 10px; color: var(--text-3, #888); font-weight: 500; }

.cpg-list-types {
  list-style: none;
  margin: 0 0 4px 0;
  padding: 0 0 0 14px;
}
.cpg-list-type {
  padding: 4px 8px;
  font-size: 13px;
  cursor: pointer;
  border-radius: 4px;
  color: var(--text-2, #333);
}
.cpg-list-type:hover { background: var(--surface-2, #f7f6f3); }
.cpg-list-type--active {
  background: rgba(232, 133, 60, 0.10);
  color: var(--accent, #e8853c);
  font-weight: 500;
}

/* Voicing area — uses the SAME card chrome as scale-page's
   .spg-area-card (border + radius + flush toolbar).  Doctrine: single
   source of truth for fretboard-card chrome — every list/browse
   variant inherits from .spg-area-card so chord and scale pages stay
   visually identical.  No outer padding here — card spans the full
   content area so the fretboard reads at the same size as scale-page. */
.cpg-area {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0;
  width: 100%;
  /* Layout-stability rules (min-height + contain) live in
     scale-page.css under `.spg-shell-area` / `.spg-area-card` so
     both pages share the same logic.  No chord-specific
     duplicates here. */
}
.cpg-area-empty {
  padding: 32px 16px;
  text-align: center;
  font-style: italic;
  color: var(--text-3, #888);
}
.cpg-area-boards {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Card chrome inherited from scale-page's `.spg-area-card` — single
   source of truth for fretboard-card chrome.  Doctrine: chord page
   and scale page must read identically, no per-page chrome
   divergence. */

/* Tokens applied per CLAUDE.md design-tokens doctrine. */
.cpg-area-card-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-2, #f7f6f3);
  border-bottom: var(--border-w) solid var(--border, #e0ddd5);
}
.cpg-area-card-nav {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.cpg-area-card-nav--static {
  font-size: var(--font-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-3, #888);
  white-space: nowrap;
  padding: 0 var(--space-xs);
}
.cpg-area-card-counter {
  font-size: var(--font-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-3, #888);
  white-space: nowrap;
  padding: 0 var(--space-xs);
}
.cpg-area-card-navbtn {
  padding: var(--space-xs) var(--space-md);
  font-size: var(--font-sm);
  border: var(--border-w) solid var(--border, #ccc);
  border-radius: var(--radius-sm);
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  cursor: pointer;
}
.cpg-area-card-navbtn:hover:not(:disabled) {
  background: var(--surface-2, #f0eee9);
  color: var(--accent, #e8853c);
}
.cpg-area-card-navbtn:disabled {
  opacity: 0.4;
  cursor: default;
}

.cpg-area-card-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}
.cpg-area-card-top {
  font-size: var(--font-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3, #888);
  text-decoration: none;
  padding: 0 var(--space-xs);
}
.cpg-area-card-top:hover { color: var(--accent, #e8853c); }

/* ── Admin Edit / Add voicing affordances (2026-07-08) ─────────────
   Visible doors into the canonical voicing editor (was context-menu
   only) + the "＋ Add voicing" card/button.  All admin-gated in JS;
   CSS carries no gating.  scp-add-card lives here (not the shared
   collection css) because only the chord data source opts into the
   grid add-card today (ctx.addCard) — move to the shared sheet when
   a second page adopts it. */

/* Diagram-card corner Edit button — appears on hover (desktop). */
.cpg-diagrams-grid .dg-card { position: relative; }
.dg-card-edit-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 2;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: var(--border-w) solid var(--border, #e8e3d8);
  border-radius: var(--radius-sm, 6px);
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 120ms ease, color 120ms ease, border-color 120ms ease;
}
.dg-card:hover .dg-card-edit-btn,
.dg-card-edit-btn:focus-visible { opacity: 1; }
.dg-card-edit-btn:hover {
  color: var(--accent, #e8853c);
  border-color: var(--accent, #e8853c);
}

/* Empty-state "＋ Add voicing" button (voicing area). */
.cpg-add-voicing-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 12px auto 0;
  padding: 8px 16px;
  border: var(--border-w) dashed var(--border, #e8e3d8);
  border-radius: var(--radius-md, 8px);
  background: var(--surface, #fff);
  color: var(--text-2, #555);
  font: inherit;
  font-style: normal;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.cpg-area-empty .cpg-add-voicing-btn { display: flex; }
.cpg-add-voicing-btn:hover {
  color: var(--accent, #e8853c);
  border-color: var(--accent, #e8853c);
}

/* Collection-grid "＋ Add voicing" card (cards view) / row (list). */
.scp-add-card-host { margin-top: var(--space-sm, 8px); }
.scp-add-card {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 72px;
  border: var(--border-w) dashed var(--border, #e8e3d8);
  border-radius: var(--radius-md, 8px);
  background: transparent;
  color: var(--text-3, #888);
  font: inherit;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.scp-add-card--row { min-height: 44px; }
.scp-add-card:hover {
  color: var(--accent, #e8853c);
  border-color: var(--accent, #e8853c);
  background: var(--surface, #fff);
}
.scp-add-card-plus { font-size: 18px; line-height: 1; }
