body {
  font-family: -apple-system, Segoe UI, sans-serif;
  background: #1a1a1a;
  color: #ddd;
  margin: 0;
  padding: 0;
}

#topNav {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: #202020;
  border-bottom: 1px solid #333;
}

#topNav button {
  font-size: 13px;
  padding: 6px 10px;
  background: #383838;
  color: #ddd;
  border: 1px solid #4a4a4a;
  border-radius: 5px;
  cursor: pointer;
}

#topNav button:hover { background: #454545; }

#breadcrumb { font-size: 13px; color: #999; }
#breadcrumb a { color: #8ab4f8; cursor: pointer; text-decoration: none; }
#breadcrumb a:hover { text-decoration: underline; }

#songTabs {
  display: flex;
  gap: 6px;
  overflow-x: auto;
}
#songTabs:empty { display: none; }

.song-tab {
  all: unset;
  cursor: pointer;
  font-size: 13px;
  padding: 5px 10px;
  background: #2c2c38;
  color: #b8c4f0;
  border: 1px solid #3d3d54;
  border-radius: 5px;
  white-space: nowrap;
}
.song-tab:hover { background: #363648; }

.page-view { display: none; }
.page-view.active { display: block; }
#editorView.active { display: block; } /* its own children keep their existing flex/block layouts */

/* Hidden by default (not a .page-view) so there's nothing to flash before
   the boot IIFE's /api/auth/me check resolves and JS explicitly shows
   either this or #loginView - a blank instant beats a flash of the full
   app UI (or the login form) guessed wrong. */
#appShell { display: none; }

#topNavUser { font-size: 13px; color: #999; margin-left: auto; }

#loginView { display: flex; align-items: center; justify-content: center; min-height: 100vh; }
#loginView.active { display: flex; } /* overrides .page-view.active's block, keeps the centering */
#loginBox {
  width: 100%;
  max-width: 320px;
  padding: 28px;
  background: #202020;
  border: 1px solid #333;
  border-radius: 10px;
}
#loginBox h2 { margin: 0 0 18px; text-align: center; }
#loginForm { display: flex; flex-direction: column; gap: 10px; }
#loginForm input {
  font-size: 14px;
  padding: 9px 10px;
  background: #232323;
  color: #ddd;
  border: 1px solid #4a4a4a;
  border-radius: 5px;
  box-sizing: border-box;
}
#loginSubmitBtn {
  font-size: 14px;
  padding: 9px 10px;
  background: #383838;
  color: #ddd;
  border: 1px solid #4a4a4a;
  border-radius: 5px;
  cursor: pointer;
}
#loginSubmitBtn:hover { background: #454545; }
#loginError { color: #e06c6c; min-height: 16px; }
#loginToggleMode { font-size: 13px; color: #8ab4f8; text-decoration: none; text-align: center; }
#loginToggleMode:hover { text-decoration: underline; }

#sessionsView, #sessionSongsView, #songDetailView {
  padding: 16px 20px;
}

#sessionsView, #sessionSongsView { max-width: 900px; }
/* songDetailView deliberately has no max-width - the Blocs palette and
   Arrangement area both want to use the full desktop width available
   rather than being squeezed into a narrow single column. */

#sessionSearch {
  font-size: 14px;
  padding: 8px 10px;
  width: 100%;
  max-width: 400px;
  margin-bottom: 14px;
  background: #232323;
  color: #ddd;
  border: 1px solid #4a4a4a;
  border-radius: 5px;
  box-sizing: border-box;
}

.list-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  margin-bottom: 6px;
  background: #232323;
  border: 1px solid #383838;
  border-radius: 6px;
  cursor: pointer;
}

.list-row:hover { background: #2b2b2b; border-color: #4a4a4a; }

.list-row-title { font-size: 14px; color: #ddd; }
.list-row-sub { font-size: 12px; color: #888; margin-top: 2px; }
.list-row-meta { font-size: 12px; color: #777; white-space: nowrap; }

.session-name-input {
  font-size: 14px;
  background: transparent;
  color: #ddd;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 2px 4px;
  width: 100%;
}

.session-name-input:hover, .session-name-input:focus {
  background: #1a1a1a;
  border-color: #4a4a4a;
  outline: none;
}

.bloc-row-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  background: #3a3a3a;
  color: #bbb;
  margin-right: 6px;
}

.bloc-row-tag.linked { background: #2a3a4a !important; color: #8ab4f8 !important; }

.empty-state { color: #777; font-size: 13px; padding: 10px 0; }

/* Heading + its own controls share one row instead of each getting a
   full line to itself - raised directly against real vertical-space
   pressure ("Link locked loop types" should be on the same line as
   Blocs..." / "Play arrangement button should maybe be on the same line
   as Arrangement"). h3's own default block margins already give this
   row breathing room above/below, so nothing extra needed here beyond
   the row layout itself. */
.section-heading-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px 20px;
}

#paletteLinkCollapseLabel {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #aaa;
  cursor: pointer;
  width: fit-content;
}

/* Palette - a wrapping grid of cards rather than a single narrow column,
   so a desktop window actually uses its width once there are many blocs
   to choose from (the "20 different verses" scaling problem). Each card
   is itself the drag source for adding to the arrangement below. */
#songDetailBlocs {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 10px;
}

/* Each tag group is its own column: swatch, then each session's own
   block stacked below it (see renderPaletteBlocs). Column sizing means
   the group's width is just its widest child's max-content width, with
   no percentage-based sizing anywhere - a row-wrap group has no
   definite width of its own (it's sized from its content), so a
   full-width divider inside it previously had nothing definite to
   resolve 100% against, which made the group claim far more horizontal
   space than its actual cards needed and pushed every later group onto
   its own new row instead of flowing next to it. */
.palette-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.palette-card {
  width: 190px;
  padding: 10px 12px;
  background: #232323;
  border: 1px solid #383838;
  border-radius: 6px;
  cursor: grab;
  /* Without this, a mousedown that lands on the card's own text (its note,
     tag, timestamp) can start a text-selection drag instead of a native
     element drag - the browser prioritizes text selection by default,
     and once it wins that race the element drag never initiates at all. */
  user-select: none;
  -webkit-user-select: none;
}
.palette-card:hover { background: #2b2b2b; border-color: #4a4a4a; }
.palette-card:active { cursor: grabbing; }
.palette-card.dragging { opacity: 0.4; }

.palette-card-time {
  font-family: 'Consolas', monospace;
  font-size: 11px;
  color: #777;
}

/* Swatch - a tag's own always-visible nav item; click toggles whether
   its cards (immediately following it, same flex-wrap flow, no wrapper
   needed) are shown at all. */
.palette-swatch {
  all: unset;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 6px;
  align-self: flex-start;
}
.palette-swatch:hover { filter: brightness(1.1); }
.palette-swatch-count {
  font-weight: 400;
  opacity: 0.75;
  font-size: 11px;
}

/* Density tiers - a group's own bloc count decides which one it renders
   at (see PALETTE_OPEN_DEFAULT_MAX/PALETTE_TIER2_MAX).

   Tier 1 is a miniature of the editor's OWN bloc card language (§24) -
   solid-color header, darker tinted body, circular play button - not a
   scaled-down version of the flat badge+text list row the palette used
   to always use regardless of density. */
.palette-card.tier-1 {
  width: 148px;
  padding: 0;
  overflow: hidden;
}
.palette-card-header {
  padding: 6px 8px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.palette-card-body {
  padding: 10px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.palette-card-play {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  flex-shrink: 0;
}

/* Tiers 2/3 - solid tag-colored fill, no header/body split (there isn't
   room for one), a small play glyph rather than a full circle button. */
.palette-card.tier-2, .palette-card.tier-3 {
  border: none;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.palette-card.tier-2 { width: 104px; padding: 6px 8px; min-height: 46px; }
.palette-card.tier-3 { width: 38px; padding: 3px 4px; min-height: 30px; }

.palette-card-label {
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.palette-card.tier-3 .palette-card-label { font-size: 9px; }

.palette-card-play-mini {
  font-size: 10px;
  opacity: 0.85;
  align-self: flex-start;
  margin-top: 4px;
}
.palette-card.tier-3 .palette-card-play-mini { font-size: 8px; }

/* Secondary line under the "Loop N" label - the manual note (§17's
   disambiguator), full text at tier 1, still real words but CSS-
   truncated at tier 2, initials only at tier 3 (see abbreviateToInitials
   - there's no room left for words at all by then). */
.palette-card-note {
  font-size: 10px;
  opacity: 0.85;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.palette-card.tier-1 .palette-card-note { font-size: 11px; text-align: center; }
.palette-card.tier-3 .palette-card-note { font-size: 9px; }

/* One session's slice of an expanded tag group: its divider stacked
   above its own row-wrap card list. Wrapping in .palette-group's column
   flow (rather than relying on flex-basis:100% inside a row) is what
   gives the divider its line break now - no percentage sizing involved,
   so nothing depends on an ambiguous parent width. */
.palette-session-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.palette-session-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
/* A 10px gap reads as generous spacing at tier-1's 148px cards but as
   nearly as much empty space as card itself once cards shrink to
   tier-3's 38px - scale the gap down with the card width instead of
   leaving it fixed. */
.palette-session-cards.tier-2 { gap: 6px; }
.palette-session-cards.tier-3 { gap: 4px; }

/* Session sub-header inside an expanded tag group - so "Loop N"
   resetting per session (see renderPaletteBlocs) has a visible reason
   why the numbers start over partway through the group. Background is
   set inline per-render to the tag's own darkened color (same `dark` as
   the tier-1 card body), not a neutral gray - the divider reads as part
   of that tag's group, not a generic UI chrome element. */
.palette-session-divider {
  font-size: 11px;
  padding: 4px 10px;
  margin-top: 2px;
  border-left: 3px solid;
  border-radius: 3px;
}

/* Arrangement - a distinct, delineated drop zone (colored/dashed border so
   it visually reads as "things go here"), laid out as a horizontal
   wrapping row of cards (a timeline, not a vertical list) so drag-reorder
   can part two neighbors left/right around an incoming card. */
#arrangementControls {
  display: flex;
  align-items: center;
  gap: 10px;
}
#arrangementControls button {
  font-size: 13px;
  padding: 6px 12px;
  background: #383838;
  color: #ddd;
  border: 1px solid #4a4a4a;
  border-radius: 5px;
  cursor: pointer;
}
#arrangementControls button:hover { background: #454545; }

/* A single scrollable row, not a wrapping grid - a real timeline like
   the editor's own waveform (§28 follow-up: "They should be on one long
   draggable timeline too. like the recording view"). overflow-x:auto on
   a native block gets touch-swipe-with-momentum for free on any mobile
   browser - no custom inertia/deceleration physics to write, since
   that's exactly what native touch scrolling already does, tuned per
   platform better than a hand-rolled version would be. Desktop keeps
   working via trackpad horizontal scroll, shift+wheel, or the existing
   mouse drag-to-reorder (HTML5 drag-and-drop doesn't fire from touch
   input at all, so enabling touch scroll here doesn't take anything
   away from touch - reordering was already desktop-only in practice). */
/* Background area is deliberately taller than a single row of cards
   needs (cards themselves stay their normal size, anchored to the top
   via align-items:flex-start) - raised directly: more room for a
   finger to actually land on while swiping the timeline (§29's
   touch-swipe-via-native-overflow-scroll relies on the container itself
   being a real target, not just the cards packed edge-to-edge with the
   background), and headroom for a future second/third stacked row of
   blocks (overdubbing - simultaneous layers at the same timeline
   position, not built yet, but the space needs to already exist for it
   rather than requiring another height change later). */
#songDetailArrangement {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 10px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding: 14px;
  min-height: 340px;
  background: rgba(67, 99, 216, 0.06);
  border: 1px dashed #3d4d7a;
  border-radius: 8px;
}
#songDetailArrangement.drag-over { background: rgba(67, 99, 216, 0.12); border-color: #4363d8; }

/* Same header/body/play-button card as the palette's tier-1 dispenser
   card (§27) - raised directly against the old flat list-row style
   ("Maybe the blocks can be the larger dispensor blocks too"). Reuses
   the .palette-card-header/-body/-note/-play classes as-is (they're
   standalone selectors, not scoped under .palette-card, so they render
   correctly under this container too) rather than duplicating that
   CSS for a second card type. */
.arrangement-row {
  width: 148px;
  flex-shrink: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid #383838;
  border-radius: 6px;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  transition: transform 0.15s ease, opacity 0.15s ease;
  position: relative;
}
.arrangement-row:active { cursor: grabbing; }
.arrangement-row.dragging { opacity: 0.4; }
.arrangement-row.part-left { transform: translateX(-14px); }
.arrangement-row.part-right { transform: translateX(14px); }

/* Dark overlay chips rather than plain text - the header bar behind
   them is now a per-part color (was a fixed dark background before),
   so a fixed text color could land unreadable against some parts. */
.arrangement-row-index {
  position: absolute;
  top: 4px;
  right: 4px;
  font-family: 'Consolas', monospace;
  color: #fff;
  background: rgba(0, 0, 0, 0.45);
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 8px;
  pointer-events: none;
}

.arrangement-row-remove {
  all: unset;
  position: absolute;
  top: 2px;
  left: 4px;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 2px 5px;
  color: #fff;
  background: rgba(0, 0, 0, 0.45);
  border-radius: 8px;
}
.arrangement-row-remove:hover { background: rgba(0, 0, 0, 0.7); }

/* The index/remove chips overlay the header bar (see above) - without
   this the header's own text (partType, left-aligned) collides with the
   remove button sitting right on top of its first character(s). */
.arrangement-row .palette-card-header {
  padding-left: 26px;
  padding-right: 24px;
}

.arrangement-row.playing {
  outline: 2px solid #4363d8;
  outline-offset: -2px;
}

#toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: #262626;
  border-bottom: 1px solid #3a3a3a;
}

#toolbar select, #toolbar button {
  font-size: 14px;
  padding: 6px 10px;
  background: #383838;
  color: #ddd;
  border: 1px solid #4a4a4a;
  border-radius: 5px;
  cursor: pointer;
}

#toolbar button:hover { background: #454545; }
#toolbar button:active { background: #303030; }
#toolbar button:disabled { opacity: 0.4; cursor: default; }
#toolbar button:disabled:hover { background: #383838; }

#zoomInBtn, #zoomOutBtn {
  padding: 6px 12px;
  font-weight: bold;
}

.sep {
  width: 1px;
  height: 22px;
  background: #444;
  margin: 0 2px;
}

#status { color: #999; font-size: 13px; }

#timeDisplay, #zoomDisplay {
  font-family: 'Consolas', monospace;
  color: #bbb;
  font-size: 13px;
  min-width: 60px;
  text-align: center;
}

#help {
  padding: 8px 14px;
  font-size: 12px;
  color: #888;
  border-bottom: 1px solid #333;
}

#waveformWrap {
  padding: 20px 14px 4px 14px;
  background: #202020;
}

#waveform {
  display: block;
  cursor: crosshair;
  border-radius: 6px;
}

#scrollbar {
  display: block;
  width: calc(100% - 28px);
  margin: 4px 14px 16px 14px;
  accent-color: #4363d8;
}

.edit-popup {
  display: none;
  position: fixed;
  z-index: 1000;
  flex-direction: column;
  gap: 5px;
  padding: 7px;
  background: #2e2e2e;
  border: 1px solid #666;
  border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.5);
}

.edit-popup select, .edit-popup input {
  font-size: 13px;
  padding: 5px 8px;
  background: #232323;
  color: #ddd;
  border: 1px solid #555;
  border-radius: 4px;
}

.edit-popup select { cursor: pointer; }
.edit-popup input { min-width: 200px; }

.linked-song-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.linked-song-list:empty { display: none; }

.linked-song-chip {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  padding: 3px 4px 3px 8px;
  background: #3a3a3a;
  border: 1px solid #555;
  border-radius: 10px;
  color: #ddd;
}

.linked-song-chip button {
  all: unset;
  cursor: pointer;
  color: #999;
  padding: 0 3px;
  line-height: 1;
}

.linked-song-chip button:hover { color: #fff; }
