/* =========================================================================
   Spotify AI Analytics — Dark Theme Stylesheet
   =========================================================================
   Spotify-green accent: #1DB954
   Dark backgrounds: #121212 (primary), #1a1a2e (secondary), #1e1e2e (card)
   ========================================================================= */

[hidden] {
  display: none !important;
}

/* ── CSS Variables ─────────────────────────────────────────────────────── */


:root {
  --bg-primary: #121212;
  --bg-secondary: #1a1d23;
  --bg-card: #1e1e2e;
  --bg-card-hover: #252538;
  --bg-input: #2a2a3e;
  --bg-sidebar: #0d0d14;
  --bg-sidebar-hover: #1a1a2e;
  --text-primary: #eee;
  /* B-8 · the alias the shell reads; the value lives in design-tokens.css
     (the dark ramp had to move for the period pills to clear AA on the
     dark input tint). */
  --text-secondary: var(--color-text-secondary);
  /* B-7 contrast.  The dark muted grey used to be a much darker one, which left
     the metadata style.css paints with it below WCAG AA.  It is kept here in
     step with B-1's --color-text-muted, which now carries the same value. */
  --text-muted: #878787;
  --accent: #1DB954;
  --accent-hover: #1ed760;
  --accent-dim: rgba(29, 185, 84, 0.15);
  --danger: #e74c3c;
  --warning: #f39c12;
  --border-color: #2a2a3e;
  --border-subtle: #1e1e2e;
  --shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  --radius: 10px;
  --radius-sm: 6px;
  --radius-lg: 14px;
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace;
  --transition: 150ms ease;
  --sidebar-width: 220px;
  /* Narrow icon rail the sidebar collapses to at the 768px breakpoint.  The
     shell's margin and the chat page's full-bleed negative margin both need
     it, so it lives here as one value rather than three copies. */
  --sidebar-rail: 60px;
}

/* ── Reset & Base ──────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-sans);
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.5;
  min-height: 100vh;
  overflow-x: hidden;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--transition);
}

a:hover {
  color: var(--accent-hover);
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: none;
  color: inherit;
}

/* ── Scrollbar ─────────────────────────────────────────────────────────── */

::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #333;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: #555;
}

/* Firefox */
* {
  scrollbar-width: thin;
  scrollbar-color: #333 transparent;
}

/* ── App Layout ────────────────────────────────────────────────────────── */

.app-layout {
  display: flex;
  min-height: 100vh;
}

/* ── Sidebar ───────────────────────────────────────────────────────────── */

.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--sidebar-width);
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  z-index: 100;
  overflow-y: auto;
}

.sidebar-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px 18px 16px;
  border-bottom: 1px solid var(--border-color);
}

.sidebar-logo {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}

.sidebar-title {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
}

.sidebar-nav {
  flex: 1;
  padding: 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 0.95rem;
  font-weight: 500;
  transition: all var(--transition);
}

.sidebar-link:hover {
  background: var(--bg-sidebar-hover);
  color: var(--text-primary);
}

.sidebar-link.active {
  background: var(--accent-dim);
  /* B-8 · `var(--accent)` measured 4.29 to 1 on this tint in the light theme
     (axe color-contrast, serious, at the label's own size); the tint, the icon
     keep carrying the state, the label takes the text-safe token. */
  color: var(--nav-active-text);
}

.sidebar-link svg {
  flex-shrink: 0;
}

.sidebar-footer {
  padding: 12px 18px;
  border-top: 1px solid var(--border-color);
}

.sidebar-version {
  /* 0.75rem is 10.5px here (14px root): below the 11px floor, so pin a px minimum. */
  font-size: max(11px, 0.75rem);
  color: var(--text-muted);
}

/* The sign-out control: a form button that has to look like the sibling
   links, so it borrows .sidebar-link and only removes the button chrome. */
.sidebar-logout {
  margin-bottom: 8px;
}

.sidebar-logout-button {
  width: 100%;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  background: none;
  border: 0;
}

.sidebar-logout-button:hover {
  background: var(--bg-sidebar-hover);
  color: var(--text-primary);
}

/* ── Main Content ──────────────────────────────────────────────────────── */

.main-content {
  flex: 1;
  margin-left: var(--sidebar-width);
  min-height: 100vh;
  padding: 28px 32px 40px;
  max-width: calc(100vw - var(--sidebar-width));
}

/* ── Page Header ───────────────────────────────────────────────────────── */

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 28px;
}

.page-header-left {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.page-title {
  font-size: 1.65rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.2;
}

.page-subtitle {
  font-size: 0.95rem;
  color: var(--text-secondary);
}

.page-header-right {
  display: flex;
  gap: 8px;
  align-items: center;
}

.btn-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  transition: all var(--transition);
}

.btn-icon:hover {
  background: var(--bg-card-hover);
  color: var(--text-primary);
}

/* ── Stats Bar ─────────────────────────────────────────────────────────── */

.stats-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
  margin-bottom: 24px;
}

/* I-10 · the dashboard's own last-refresh stamp.  Sits inside the stats grid
   (which is what makes it swap with the numbers it describes) and spans the
   row so it reads as a caption, not a sixth stat.  Token values only, so the
   ad-hoc-CSS ratchet in tests/test_design_tokens.py does not move. */
.stats-refresh {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--text-muted);
}

.stats-refresh-label {
  text-transform: uppercase;
}

.stat-card {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  padding: 16px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  transition: all var(--transition);
}

.stat-card:hover {
  border-color: var(--accent-dim);
  background: var(--bg-card-hover);
}

.stat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.stat-icon-plays {
  background: rgba(29, 185, 84, 0.15);
  color: var(--accent);
}

.stat-icon-hours {
  background: rgba(52, 152, 219, 0.15);
  color: #3498db;
}

.stat-icon-artists {
  background: rgba(155, 89, 182, 0.15);
  color: #9b59b6;
}

.stat-icon-calendar {
  background: rgba(241, 196, 15, 0.15);
  color: #f1c40f;
}

.stat-icon-tracks {
  background: rgba(231, 76, 60, 0.15);
  color: #e74c3c;
}

.stat-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.stat-value {
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1.2;
  animation: countUp 0.5s ease-out;
}

.stat-label {
  font-size: 0.8rem;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Card ──────────────────────────────────────────────────────────────── */

.card {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color var(--transition);
}

.card:hover {
  border-color: rgba(255, 255, 255, 0.06);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border-color);
  gap: 12px;
  flex-wrap: wrap;
}

.card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-primary);
}

.card-title svg {
  color: var(--accent);
  flex-shrink: 0;
}

.card-body {
  padding: 14px 18px;
  position: relative;
  transition: opacity 0.3s ease;
}

/* ── Dashboard Grid ────────────────────────────────────────────────────── */

.dashboard-section {
  margin-bottom: 20px;
  transition: opacity 0.3s ease;
}

.dashboard-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.dashboard-grid-2 .card {
  min-width: 0;
}

.dashboard-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.dashboard-grid-3 .card {
  min-width: 0;
}

.track-card {
  transition: transform var(--transition), box-shadow var(--transition);
}

.track-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 32px rgba(29, 185, 84, 0.12);
}

/* ── Period Selector ───────────────────────────────────────────────────── */

.period-selector {
  display: flex;
  gap: 2px;
  background: var(--bg-input);
  border-radius: var(--radius-sm);
  padding: 2px;
  flex-shrink: 0;
}

.period-btn {
  padding: 4px 12px;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--text-secondary);
  border-radius: 4px;
  transition: all var(--transition);
}

.period-btn:hover {
  color: var(--text-primary);
}

.period-btn.active {
  background: var(--accent);
  color: var(--color-text-inverse);
}

.period-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ── Ranked List (Top Artists / Tracks) ────────────────────────────────── */

.ranked-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ranked-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 6px;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
  position: relative;
}

.ranked-item:hover {
  background: var(--bg-card-hover);
}

.rank-number {
  width: 24px;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text-muted);
  text-align: right;
  flex-shrink: 0;
}

.ranked-item:nth-child(1) .rank-number {
  color: #ffd700;
}

.ranked-item:nth-child(2) .rank-number {
  color: #c0c0c0;
}

.ranked-item:nth-child(3) .rank-number {
  color: #cd7f32;
}

.ranked-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ranked-name {
  font-size: 0.95rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ranked-sub {
  font-size: 0.78rem;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ranked-metrics {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
  align-items: center;
}

.ranked-plays {
  font-size: 0.85rem;
  font-weight: 600;
}

.ranked-hours {
  font-size: 0.78rem;
  color: var(--text-secondary);
}

.ranked-bar-wrapper {
  display: none;
  position: absolute;
  bottom: 0;
  left: 36px;
  right: 6px;
  height: 2px;
  background: var(--border-color);
  border-radius: 1px;
}

.ranked-item:hover .ranked-bar-wrapper {
  display: block;
}

.ranked-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 1px;
  transition: width 0.3s ease;
}

/* ── C-6 · the top-artists bar states its own count ────────────────────────
   The thin hover line above is the shared indicator every ranked list uses.
   The artists leaderboard's acceptance is stronger: the number *on* the bar has
   to equal the number in the label, so this list's bar is always visible and
   tall enough to carry its count, with a floor width so a one-play row still
   shows a legible number.  Scoped to ``data-ranked-list="artists"`` so no other
   list's geometry moves; every value is a token, so the ad-hoc-CSS census sees
   no new literal. */
[data-ranked-list="artists"] .ranked-bar-wrapper {
  display: block;
  position: relative;
  height: var(--space-md);
  background: var(--border-subtle);
  border-radius: var(--radius-sm);
}

[data-ranked-list="artists"] .ranked-bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: var(--space-3xl);
  height: 100%;
  border-radius: var(--radius-sm);
}

[data-ranked-list="artists"] .ranked-bar-count {
  padding: 0 var(--space-2xs);
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-inverse);
  white-space: nowrap;
}

[data-ranked-list="artists"] .ranked-name {
  color: var(--text-primary);
  text-decoration: none;
}

[data-ranked-list="artists"] .ranked-name:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* ── Genre Distribution ────────────────────────────────────────────────── */

.genre-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.genre-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.genre-label {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.genre-name {
  font-size: 0.88rem;
  font-weight: 500;
  text-transform: capitalize;
}

.genre-pct {
  font-size: 0.82rem;
  color: var(--text-secondary);
  font-weight: 600;
}

.genre-bar-track {
  height: 6px;
  background: var(--bg-input);
  border-radius: 3px;
  overflow: hidden;
}

.genre-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), #2ecc71);
  border-radius: 3px;
  transition: width 0.4s ease;
}

/* ── Platform Breakdown ────────────────────────────────────────────────── */

.platform-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.platform-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.platform-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.platform-name {
  font-size: 0.95rem;
  font-weight: 600;
  text-transform: capitalize;
}

.platform-stats {
  font-size: 0.82rem;
  color: var(--text-secondary);
}

.platform-bar-track {
  height: 8px;
  background: var(--bg-input);
  border-radius: 4px;
  overflow: hidden;
}

.platform-bar-fill {
  height: 100%;
  border-radius: 4px;
  transition: width 0.4s ease;
}

.platform-item:nth-child(1) .platform-bar-fill {
  background: linear-gradient(90deg, var(--accent), #2ecc71);
}

.platform-item:nth-child(2) .platform-bar-fill {
  background: linear-gradient(90deg, #3498db, #2980b9);
}

.platform-item:nth-child(3) .platform-bar-fill {
  background: linear-gradient(90deg, #9b59b6, #8e44ad);
}

.platform-item:nth-child(4) .platform-bar-fill {
  background: linear-gradient(90deg, #e67e22, #d35400);
}

.platform-item:nth-child(n+5) .platform-bar-fill {
  background: linear-gradient(90deg, var(--text-secondary), #666);
}

/* ── Daily Trend Chart ─────────────────────────────────────────────────── */

.trend-chart-container {
  width: 100%;
}

.trend-chart-svg {
  width: 100%;
  height: auto;
  max-height: 220px;
}

.trend-summary {
  display: flex;
  gap: 24px;
  padding: 12px 0 0;
  flex-wrap: wrap;
}

.trend-stat {
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.trend-stat strong {
  color: var(--text-primary);
  font-weight: 600;
}

/* ── Hourly Heatmap ────────────────────────────────────────────────────── */

.heatmap-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 6px;
}

.heatmap-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 4px;
  border-radius: var(--radius-sm);
  background: rgba(29, 185, 84, calc(var(--heat, 0) * 0.7));
  border: 1px solid rgba(255, 255, 255, calc(var(--heat, 0) * 0.08));
  cursor: default;
  transition: all var(--transition);
  min-height: 48px;
}

.heatmap-cell:hover {
  transform: scale(1.08);
  z-index: 1;
  border-color: var(--accent);
}

.heatmap-hour {
  font-size: 0.72rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.8);
}

.heatmap-value {
  font-size: 0.68rem;
  color: rgba(255, 255, 255, 0.6);
}

/* ── Mood Badges ───────────────────────────────────────────────────────── */

.mood-badge {
  display: inline-block;
  font-size: 0.7rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1.4;
}

.mood-happy {
  background: rgba(29, 185, 84, 0.18);
  color: #1DB954;
  border: 1px solid rgba(29, 185, 84, 0.35);
}

.mood-sad {
  background: rgba(52, 152, 219, 0.18);
  color: #3498db;
  border: 1px solid rgba(52, 152, 219, 0.35);
}

.mood-neutral {
  background: rgba(136, 136, 136, 0.18);
  color: #aaa;
  border: 1px solid rgba(136, 136, 136, 0.35);
}

.mood-excited {
  background: rgba(155, 89, 182, 0.18);
  color: #9b59b6;
  border: 1px solid rgba(155, 89, 182, 0.35);
}

.mood-frustrated {
  background: rgba(231, 76, 60, 0.18);
  color: #e74c3c;
  border: 1px solid rgba(231, 76, 60, 0.35);
}

/* ── Loading States ────────────────────────────────────────────────────── */

.htmx-indicator {
  opacity: 0;
  transition: opacity var(--transition);
}

.htmx-request .htmx-indicator {
  opacity: 1;
}

.htmx-request.htmx-indicator {
  opacity: 1;
}

.loading-spinner {
  display: inline-block;
  width: 24px;
  height: 24px;
  border: 2.5px solid var(--border-color);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -12px 0 0 -12px;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes countUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.loading-placeholder {
  text-align: center;
  padding: 32px 16px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.empty-state {
  text-align: center;
  padding: 24px 16px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.empty-state-full {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 80px 24px;
  text-align: center;
}

.empty-state-full h2 {
  font-size: 1.3rem;
  font-weight: 600;
  margin-top: 8px;
}

.empty-state-full p {
  color: var(--text-secondary);
  max-width: 420px;
  line-height: 1.6;
}

/* ── HTMX Swap Transitions ─────────────────────────────────────────────── */

.htmx-swapping {
  opacity: 0;
  transition: opacity 0.2s ease;
}

.htmx-settling {
  opacity: 0;
}

.htmx-settling.htmx-settled {
  opacity: 1;
  transition: opacity 0.2s ease;
}

/* ── Streak Card ───────────────────────────────────────────────────────── */

.streak-card {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 20px 22px;
  background: linear-gradient(135deg, rgba(255, 69, 0, 0.12), rgba(255, 165, 0, 0.08));
  border: 1px solid rgba(255, 69, 0, 0.25);
  border-radius: var(--radius);
  transition: all var(--transition);
}

.streak-card:hover {
  border-color: rgba(255, 69, 0, 0.5);
  background: linear-gradient(135deg, rgba(255, 69, 0, 0.18), rgba(255, 165, 0, 0.12));
}

.streak-fire {
  font-size: 2.8rem;
  line-height: 1;
  flex-shrink: 0;
  animation: fire-pulse 1.8s ease-in-out infinite;
}

@keyframes fire-pulse {
  0%, 100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.12);
  }
}

.streak-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.streak-count-wrapper {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.streak-label {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.streak-dates {
  font-size: 0.82rem;
  color: var(--text-muted);
}

.streak-comparison {
  font-size: 0.82rem;
  color: var(--text-secondary);
}

.streak-comparison strong {
  color: var(--accent);
  font-weight: 700;
}

/* ── Now Playing Placeholder ───────────────────────────────────────────── */

.now-playing-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 32px 24px;
  gap: 12px;
}

.now-playing-icon {
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent-dim);
  color: var(--accent);
  margin-bottom: 4px;
}

.now-playing-heading {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.3;
}

.now-playing-description {
  font-size: 0.88rem;
  color: var(--text-secondary);
  max-width: 320px;
  line-height: 1.5;
}

.btn-spotify {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 24px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-text-inverse);
  background: #1DB954;
  border-radius: 24px;
  transition: all var(--transition);
  text-decoration: none;
  margin-top: 4px;
}

.btn-spotify:hover {
  background: #1ed760;
  transform: translateY(-1px);
  box-shadow: 0 4px 20px rgba(29, 185, 84, 0.35);
  color: var(--color-text-inverse);
}

.btn-spotify svg {
  flex-shrink: 0;
}

/* ── Degraded Mode Banner ─────────────────────────────────────────────── */

.degraded-banner {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px 20px;
  margin-bottom: 24px;
  background: rgba(231, 76, 60, 0.1);
  border: 1px solid rgba(231, 76, 60, 0.3);
  border-radius: var(--radius);
  color: #e74c3c;
}

.degraded-banner svg {
  flex-shrink: 0;
  margin-top: 2px;
}

.degraded-banner strong {
  display: block;
  font-size: 1rem;
  margin-bottom: 4px;
}

.degraded-banner p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text-secondary);
  line-height: 1.5;
}

/* ── Chat Layout ───────────────────────────────────────────────────────── */

.chat-layout {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 56px); /* full viewport minus top padding */
  margin: -28px -32px 0;
  position: relative;
}

/* ── Chat Messages ─────────────────────────────────────────────────────── */

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px 32px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  scroll-behavior: smooth;
}

.chat-welcome {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 60px 24px 40px;
  text-align: center;
  flex: 1;
}

.chat-welcome h2 {
  font-size: 1.4rem;
  font-weight: 700;
  margin-top: 8px;
}

.chat-welcome p {
  color: var(--text-secondary);
  max-width: 500px;
}

.chat-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  max-width: 600px;
  margin-top: 4px;
}

.suggestion-chip {
  padding: 8px 16px;
  font-size: 0.85rem;
  font-weight: 500;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 20px;
  color: var(--text-secondary);
  transition: all var(--transition);
  cursor: pointer;
}

.suggestion-chip:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-dim);
}

/* Message bubbles */
.chat-msg {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 80%;
  animation: msg-fade-in 0.2s ease-out;
}

@keyframes msg-fade-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.chat-msg.user {
  align-self: flex-end;
}

.chat-msg.assistant {
  align-self: flex-start;
}

.chat-msg-role {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0 4px;
}

.chat-msg.user .chat-msg-role {
  color: var(--accent);
  text-align: right;
}

.chat-msg.assistant .chat-msg-role {
  color: #3498db;
}

.chat-msg-content {
  padding: 12px 16px;
  border-radius: var(--radius);
  line-height: 1.55;
  font-size: 0.95rem;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.chat-msg.user .chat-msg-content {
  background: var(--accent);
  color: var(--color-text-inverse);
  border-bottom-right-radius: 4px;
}

.chat-msg.assistant .chat-msg-content {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-bottom-left-radius: 4px;
}

.chat-msg-content p {
  margin: 0.5em 0;
}

.chat-msg-content p:first-child {
  margin-top: 0;
}

.chat-msg-content p:last-child {
  margin-bottom: 0;
}

.chat-msg-content code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  background: rgba(0, 0, 0, 0.3);
  padding: 2px 6px;
  border-radius: 3px;
}

.chat-msg-content pre {
  margin: 8px 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.chat-msg-content pre code {
  display: block;
  padding: 12px 14px;
  background: #0a0a14;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  overflow-x: auto;
  font-size: 0.82rem;
  line-height: 1.5;
}

/* SQL block with toggle */
.chat-sql-block {
  margin: 8px 0;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  overflow: hidden;
  position: relative;
}

.chat-sql-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-secondary);
  background: rgba(0, 0, 0, 0.2);
  cursor: pointer;
  border: none;
  width: 100%;
  text-align: left;
  transition: background var(--transition);
}

.chat-sql-toggle:hover {
  background: rgba(0, 0, 0, 0.35);
}

.chat-sql-toggle svg {
  transition: transform var(--transition);
}

.chat-sql-toggle.collapsed svg {
  transform: rotate(-90deg);
}

.chat-sql-body {
  max-height: 500px;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.chat-sql-body.collapsed {
  max-height: 0;
}

.chat-sql-body pre {
  margin: 0;
  border-radius: 0;
}

.chat-sql-body pre code {
  display: block;
  padding: 12px 14px;
  background: #0a0a14;
  overflow-x: auto;
  font-size: 0.82rem;
  line-height: 1.5;
}

/* ── Copy button for SQL blocks ────────────────────────────────────────── */

.chat-sql-block .copy-btn {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-secondary);
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--border-color);
  border-radius: 4px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--transition);
}

.chat-sql-block .copy-btn svg {
  width: 14px;
  height: 14px;
}

.chat-sql-block:hover .copy-btn {
  opacity: 1;
}

.chat-sql-block .copy-btn:hover {
  color: var(--accent);
  background: var(--accent-dim);
  border-color: var(--accent);
}

.copy-tooltip {
  position: absolute;
  top: -28px;
  right: 0;
  padding: 3px 8px;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--color-text-inverse);
  background: var(--accent);
  border-radius: 4px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.copy-tooltip.visible {
  opacity: 1;
  transform: translateY(0);
}

.copy-tooltip::after {
  content: "";
  position: absolute;
  bottom: -4px;
  right: 12px;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid var(--accent);
}

/* ── Thinking steps collapsible ────────────────────────────────────────── */

.thinking-steps {
  margin: 0 0 8px;
}

.thinking-step {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.15);
  overflow: hidden;
}

.thinking-step[open] {
  animation: thinking-expand 0.25s ease-out;
}

@keyframes thinking-expand {
  from {
    opacity: 0.6;
  }
  to {
    opacity: 1;
  }
}

.thinking-step summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
  list-style: none;
}

.thinking-step summary::-webkit-details-marker {
  display: none;
}

.thinking-step summary::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: thinking-pulse 1.5s ease-in-out infinite;
}

@keyframes thinking-pulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.5;
    transform: scale(0.85);
  }
}

.thinking-step[open] summary::before {
  animation: none;
  background: var(--accent);
  opacity: 0.7;
}

.thinking-step summary::after {
  content: "";
  margin-left: auto;
  width: 12px;
  height: 12px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E") center/contain no-repeat;
  transition: transform 0.2s ease;
}

.thinking-step[open] summary::after {
  transform: rotate(90deg);
}

.thinking-step-body {
  padding: 4px 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.thinking-step-item {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 0.8rem;
  padding: 3px 0;
}

.thinking-step-label {
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
  flex-shrink: 0;
}

.thinking-step-value {
  color: var(--text-primary);
  word-break: break-all;
}

.thinking-step-item code {
  font-family: var(--font-mono);
  font-size: 0.8em;
  color: var(--accent);
  word-break: break-all;
}

/* ── Memory indicator badge ────────────────────────────────────────────── */

.memory-indicator {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  font-size: 0.72rem;
  font-weight: 600;
  color: #bb86fc;
  background: rgba(187, 134, 252, 0.12);
  border: 1px solid rgba(187, 134, 252, 0.25);
  border-radius: 10px;
  white-space: nowrap;
}

.memory-indicator svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

.memory-indicator-multiple {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 4px 0;
}

/* ── Loading indicator in chat ─────────────────────────────────────────── */

.chat-loading {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.chat-loading-dots {
  display: flex;
  gap: 4px;
}

.chat-loading-dots span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  animation: bounce 1.2s ease-in-out infinite;
}

.chat-loading-dots span:nth-child(2) {
  animation-delay: 0.15s;
}

.chat-loading-dots span:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes bounce {
  0%, 80%, 100% {
    transform: scale(0.6);
    opacity: 0.4;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

/* ── Chat Error Toast ──────────────────────────────────────────────────── */

.chat-error {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  margin: 0 32px;
  background: rgba(231, 76, 60, 0.12);
  border: 1px solid rgba(231, 76, 60, 0.3);
  border-radius: var(--radius-sm);
  color: #e74c3c;
  font-size: 0.9rem;
  animation: slide-up 0.2s ease-out;
}

@keyframes slide-up {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.chat-error-retry {
  margin-left: auto;
  padding: 4px 12px;
  font-size: 0.82rem;
  font-weight: 600;
  background: rgba(231, 76, 60, 0.2);
  border-radius: var(--radius-sm);
  color: #e74c3c;
  transition: background var(--transition);
}

.chat-error-retry:hover {
  background: rgba(231, 76, 60, 0.35);
}

.chat-error-dismiss {
  font-size: 1.2rem;
  color: inherit;
  opacity: 0.7;
  padding: 0 4px;
}

.chat-error-dismiss:hover {
  opacity: 1;
}

/* ── Chat Input Bar ────────────────────────────────────────────────────── */

.chat-input-bar {
  padding: 12px 32px;
  border-top: 1px solid var(--border-color);
  background: var(--bg-primary);
}

.chat-input-form {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  max-width: 800px;
  margin: 0 auto;
  width: 100%;
}

.chat-input {
  flex: 1;
  padding: 10px 14px;
  font-family: inherit;
  font-size: 0.95rem;
  line-height: 1.4;
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  resize: none;
  outline: none;
  transition: border-color var(--transition);
  max-height: 160px;
  min-height: 42px;
}

.chat-input:focus {
  border-color: var(--accent);
}

.chat-input::placeholder {
  color: var(--text-muted);
}

.chat-send-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--color-text-inverse);
  transition: all var(--transition);
  flex-shrink: 0;
}

.chat-send-btn:hover:not(:disabled) {
  background: var(--accent-hover);
  transform: scale(1.05);
}

.chat-send-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ── Syntax Highlighting (minimal) ─────────────────────────────────────── */

.chat-msg-content pre code .sql-keyword {
  color: #ff79c6;
}

.chat-msg-content pre code .sql-function {
  color: #50fa7b;
}

.chat-msg-content pre code .sql-string {
  color: #f1fa8c;
}

.chat-msg-content pre code .sql-number {
  color: #bd93f9;
}

.chat-msg-content pre code .sql-comment {
  color: #6272a4;
}

/* ── Thinking / streaming cursor ───────────────────────────────────────── */

.typing-cursor::after {
  content: "";
  display: inline-block;
  width: 7px;
  height: 14px;
  background: var(--accent);
  margin-left: 2px;
  animation: blink 1s step-end infinite;
  vertical-align: text-bottom;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

/* ── Streak Card ─────────────────────────────────────────── */

.streak-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px 0;
}

.streak-fire {
  display: flex;
  align-items: center;
  gap: 8px;
}

.streak-fire--inactive {
  opacity: 0.5;
}

.streak-fire-emoji {
  font-size: 2.5rem;
  line-height: 1;
}

.streak-count {
  font-size: 2.8rem;
  font-weight: 800;
  line-height: 1;
  color: var(--accent);
}

.streak-fire--inactive .streak-count {
  color: var(--text-muted);
}

.streak-unit {
  font-size: 1rem;
  color: var(--text-secondary);
  align-self: flex-end;
  padding-bottom: 6px;
}

.streak-dates {
  font-size: 0.82rem;
  color: var(--text-secondary);
}

.streak-longest {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-top: 4px;
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
  width: 100%;
  justify-content: center;
}

.streak-longest-label {
  font-size: 0.82rem;
  color: var(--text-muted);
}

.streak-longest-value {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-primary);
}

.streak-ended {
  font-size: 0.82rem;
  color: var(--text-muted);
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px solid var(--border-color);
  width: 100%;
  text-align: center;
}

/* ── Now Playing Card ────────────────────────────────────── */

.now-playing-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 24px 16px;
  text-align: center;
}

.now-playing-icon--muted {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--bg-input);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
}

.now-playing-title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--text-primary);
}

.now-playing-subtitle {
  font-size: 0.88rem;
  color: var(--text-secondary);
  max-width: 300px;
  line-height: 1.5;
}

.spotify-connect-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 24px;
  background: var(--accent);
  color: var(--color-text-inverse);
  font-weight: 600;
  font-size: 0.95rem;
  border-radius: 24px;
  transition: all var(--transition);
  text-decoration: none;
}

.spotify-connect-btn:hover {
  background: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: 0 4px 16px rgba(29, 185, 84, 0.3);
}

/* ── Responsive ────────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  .dashboard-grid-2 {
    grid-template-columns: 1fr;
  }

  .stats-bar {
    grid-template-columns: repeat(2, 1fr);
  }

  .heatmap-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

@media (max-width: 768px) {
  .sidebar {
    width: var(--sidebar-rail);
  }

  .sidebar-title,
  .sidebar-link span,
  .sidebar-version {
    display: none;
  }

  .sidebar-header {
    justify-content: center;
    padding: var(--space-md) var(--space-xs);
  }

  .sidebar-link {
    justify-content: center;
    padding: var(--space-sm);
  }

  /* The icon rail is only --sidebar-rail wide: keep the nav's own gutters
     small enough that a link is still a full --tap-min hit area, and keep
     the footer's sign-out button the same size as its siblings. */
  .sidebar-nav,
  .sidebar-footer {
    padding-left: var(--space-2xs);
    padding-right: var(--space-2xs);
  }

  .main-content {
    margin-left: var(--sidebar-rail);
    padding: var(--space-lg) var(--space-md) var(--space-xl);
    max-width: calc(100vw - var(--sidebar-rail));
    /* --space-xl is the floor; on a notched phone (viewport-fit=cover, set in
       base.html) the home indicator's inset wins when it is larger. */
    padding-bottom: max(var(--space-xl), env(safe-area-inset-bottom));
  }

  /* The chat page is full-bleed: it cancels the shell's own padding with
     negative margins, so they have to follow this breakpoint's gutters
     (--space-md, not the desktop 32px) or the column hangs past the right
     edge of the viewport. */
  .chat-layout {
    margin: calc(-1 * var(--space-lg)) calc(-1 * var(--space-md)) 0;
    height: calc(100vh - var(--space-2xl));
  }

  /* A page header whose title and action button cannot fit on one line must
     wrap rather than push the button off the right edge. */
  .page-header {
    flex-wrap: wrap;
    gap: var(--space-sm);
  }

  .stats-bar {
    grid-template-columns: 1fr 1fr;
  }

  .chat-messages {
    padding: 16px 16px 8px;
  }

  .chat-msg {
    max-width: 90%;
  }

  .chat-input-bar {
    padding: 10px 16px;
    /* Keep the send button clear of the home indicator. */
    padding-bottom: max(var(--space-sm), env(safe-area-inset-bottom));
  }

  .chat-error {
    margin: 0 16px;
  }

  .stat-value {
    font-size: 1.1rem;
  }

  .page-title {
    font-size: 1.3rem;
  }

  .heatmap-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .trend-summary {
    gap: 12px;
  }
}

@media (max-width: 480px) {
  .stats-bar {
    grid-template-columns: 1fr;
  }

  .chat-msg {
    max-width: 100%;
  }

  .card-header {
    flex-direction: column;
    align-items: flex-start;
  }

  .chat-suggestions {
    flex-direction: column;
    align-items: stretch;
  }
}

/* =========================================================================
   Insights Page — Additional Components
   ========================================================================= */

/* ── Insight Metrics Grid (2×2 in a card body) ────────────────────────── */

.insight-metrics-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 16px;
}

.insight-metric {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: center;
  padding: 10px 8px;
  background: rgba(0, 0, 0, 0.15);
  border-radius: var(--radius-sm);
}

.insight-metric-value {
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--accent);
}

.insight-metric-label {
  font-size: max(11px, 0.78rem);
  color: var(--text-secondary);
  white-space: nowrap;
}

/* ── Insight Subheading ───────────────────────────────────────────────── */

.insight-subheading {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 10px;
  padding-top: 4px;
  border-top: 1px solid var(--border-color);
}

/* ── Skip Rate by Day ─────────────────────────────────────────────────── */

.dow-skip-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.dow-skip-item {
  display: grid;
  grid-template-columns: 32px 1fr 44px;
  align-items: center;
  gap: 8px;
}

.dow-skip-label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-primary);
  text-align: right;
}

.dow-skip-bar-track {
  height: 6px;
  background: var(--bg-input);
  border-radius: 3px;
  overflow: hidden;
}

.dow-skip-bar-fill {
  height: 100%;
  border-radius: 3px;
  transition: width 0.4s ease;
}

.dow-skip-bar-fill.skip-low {
  background: linear-gradient(90deg, var(--accent), #2ecc71);
}

.dow-skip-bar-fill.skip-mid {
  background: linear-gradient(90deg, var(--warning), #f1c40f);
}

.dow-skip-bar-fill.skip-high {
  background: linear-gradient(90deg, var(--danger), #e67e22);
}

.dow-skip-pct {
  font-size: 0.8rem;
  font-weight: 600;
  text-align: right;
}

.dow-skip-pct.skip-low {
  color: var(--accent);
}

.dow-skip-pct.skip-mid {
  color: var(--warning);
}

.dow-skip-pct.skip-high {
  color: var(--danger);
}

/* ── Listening Profile — Derived Stats ────────────────────────────────── */

.insight-profile-stats {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  padding: 12px 0 4px;
  border-top: 1px solid var(--border-color);
}

.profile-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  text-align: center;
  padding: 6px 14px;
  min-width: 100px;
}

.profile-stat-value {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
}

.profile-stat-label {
  font-size: 0.72rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* ── Monthly trend bar chart tweaks ───────────────────────────────────── */

#monthly-trend-card .trend-chart-svg {
  max-height: 220px;
}

/* ── Responsive: insights grid collapses ──────────────────────────────── */

@media (max-width: 600px) {
  .insight-metrics-grid {
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }

  .insight-metric-value {
    font-size: 1.15rem;
  }

  .dow-skip-item {
    grid-template-columns: 28px 1fr 38px;
    gap: 6px;
  }
}

/* =========================================================================
   Recommendations Page — Queue Cards, Seed Selector, Modals, Toasts
   ========================================================================= */

/* ── Seed Track Search ───────────────────────────────────────────────── */

.seed-track-search {
  position: relative;
}

.search-input {
  width: 100%;
  padding: 12px 16px;
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  outline: none;
  transition: border-color var(--transition);
}

.search-input:focus {
  border-color: var(--accent);
}

.search-input::placeholder {
  color: var(--text-muted);
}

.search-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 50;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  margin-top: 4px;
  max-height: 320px;
  overflow-y: auto;
  display: none;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

.search-results.visible {
  display: block;
}

.search-result-item {
  display: flex;
  align-items: center;
  padding: 10px 14px;
  cursor: pointer;
  transition: background var(--transition);
  gap: 12px;
}

.search-result-item:hover {
  background: var(--bg-card-hover);
}

.search-result-item:not(:last-child) {
  border-bottom: 1px solid var(--border-color);
}

.search-result-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.search-result-name {
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-result-artist {
  font-size: 0.78rem;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-result-plays {
  font-size: 0.78rem;
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.search-result-empty {
  padding: 20px 14px;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.9rem;
}

/* ── Seed Track Preview ──────────────────────────────────────────────── */

.seed-track-preview {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 14px;
  padding: 12px 16px;
  background: var(--accent-dim);
  border: 1px solid rgba(29, 185, 84, 0.25);
  border-radius: var(--radius);
  animation: fade-in 0.2s ease-out;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.seed-track-art {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;
}

.seed-track-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.seed-track-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.seed-track-name {
  font-size: 0.95rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.seed-track-artist {
  font-size: 0.82rem;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.seed-track-preview .btn {
  flex-shrink: 0;
}

/* ── Buttons (shared) ────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 18px;
  font-size: 0.88rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--accent);
  color: var(--color-text-inverse);
}

.btn-primary:hover:not(:disabled) {
  background: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(29, 185, 84, 0.3);
}

.btn-secondary {
  background: var(--bg-input);
  color: var(--text-secondary);
  border: 1px solid var(--border-color);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--bg-card-hover);
  color: var(--text-primary);
  border-color: var(--text-muted);
}

.btn-primary svg,
.btn-secondary svg {
  flex-shrink: 0;
}

/* ── Loading Indicator ───────────────────────────────────────────────── */

.recs-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 24px;
  color: var(--text-secondary);
  font-size: 0.95rem;
}

.recs-loading .loading-spinner {
  position: static;
  margin: 0;
}

/* ── Badge ───────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-size: 0.72rem;
  font-weight: 700;
  background: var(--accent);
  color: var(--color-text-inverse);
  border-radius: 10px;
  margin-left: 6px;
}

/* ── Queue List ──────────────────────────────────────────────────────── */

.queue-body {
  padding: 0 !important;
}

.queue-list {
  display: flex;
  flex-direction: column;
}

/* ── Queue Card ──────────────────────────────────────────────────────── */

.queue-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  transition: all 0.2s ease;
  border-bottom: 1px solid var(--border-color);
  user-select: none;
  cursor: default;
}

.queue-card:last-child {
  border-bottom: none;
}

.queue-card:hover {
  background: var(--bg-card-hover);
}

.queue-card.dragging {
  opacity: 0.4;
  background: var(--accent-dim);
}

.queue-card.drag-over {
  border-top: 2px solid var(--accent);
  background: rgba(29, 185, 84, 0.08);
}

.queue-card-drag-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  color: var(--text-muted);
  cursor: grab;
  flex-shrink: 0;
  border-radius: 4px;
  transition: color var(--transition), background var(--transition);
}

.queue-card-drag-handle:hover {
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.05);
}

.queue-card-drag-handle:active {
  cursor: grabbing;
}

.queue-card-art {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;
  background: linear-gradient(135deg, #1a1a2e, #2a2a3e);
}

.queue-card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.album-art-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #1a1a2e, #2a2a3e);
  color: var(--text-muted);
}

.queue-card-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.queue-card-name {
  font-size: 0.92rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.queue-card-artist {
  font-size: 0.8rem;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.queue-card-reason {
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}

.queue-card-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.queue-card-actions .btn-icon {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  transition: all 0.15s ease;
}

.queue-card-actions .btn-icon:hover {
  background: rgba(255, 255, 255, 0.08);
  transform: scale(1.1);
}

.btn-recommend:hover {
  color: #9b59b6 !important;
  background: rgba(155, 89, 182, 0.15) !important;
}

.btn-explain:hover {
  color: #3498db !important;
  background: rgba(52, 152, 219, 0.15) !important;
}

.btn-like {
  color: var(--text-secondary);
}

.btn-like:hover {
  color: var(--accent) !important;
  background: var(--accent-dim) !important;
}

.btn-dislike:hover {
  color: var(--danger) !important;
  background: rgba(231, 76, 60, 0.15) !important;
}

.feedback-done {
  opacity: 0.45;
  cursor: not-allowed;
  transform: scale(0.9) !important;
}

.feedback-done.btn-like {
  color: var(--accent) !important;
}

.feedback-done.btn-dislike {
  color: var(--danger) !important;
}

/* ── Explain Tooltip ─────────────────────────────────────────────────── */

.explain-tooltip {
  position: fixed;
  z-index: 200;
  width: 300px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
  padding: 14px 16px;
  animation: tooltip-fade-in 0.15s ease-out;
}

@keyframes tooltip-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.explain-tooltip-arrow {
  display: none;
}

.explain-section {
  margin-bottom: 8px;
}

.explain-section:last-child {
  margin-bottom: 0;
}

.explain-section strong {
  font-size: 0.95rem;
}

.explain-section p {
  margin: 4px 0 0;
  font-size: 0.85rem;
  color: var(--text-secondary);
  line-height: 1.45;
}

.explain-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  display: block;
  margin-bottom: 2px;
}

/* ── Modal Overlay ───────────────────────────────────────────────────── */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fade-in 0.15s ease-out;
  backdrop-filter: blur(4px);
}

.modal {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  width: 90%;
  max-width: 520px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
  animation: modal-slide-in 0.2s ease-out;
}

@keyframes modal-slide-in {
  from { opacity: 0; transform: translateY(20px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-color);
}

.modal-title {
  font-size: 1.05rem;
  font-weight: 700;
}

.modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  font-size: 1.4rem;
  color: var(--text-secondary);
  transition: all var(--transition);
}

.modal-close:hover {
  background: var(--bg-card-hover);
  color: var(--text-primary);
}

.modal-body {
  padding: 20px;
  overflow-y: auto;
  flex: 1;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--border-color);
}

.modal-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 32px 16px;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.modal-loading .loading-spinner {
  position: static;
  margin: 0;
}

/* ── AI Recs (modal content) ─────────────────────────────────────────── */

.ai-recs-header {
  margin-bottom: 14px;
  font-size: 0.92rem;
  color: var(--text-secondary);
}

.ai-recs-header strong {
  color: var(--text-primary);
}

.ai-recs-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ai-recs-item {
  display: flex;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.15);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.ai-recs-item:hover {
  background: rgba(0, 0, 0, 0.25);
}

.ai-recs-num {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text-muted);
  width: 20px;
  text-align: right;
  flex-shrink: 0;
  padding-top: 1px;
}

.ai-recs-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ai-recs-name {
  font-size: 0.9rem;
  font-weight: 600;
}

.ai-recs-artist {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.ai-recs-reason {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin: 4px 0 0;
  line-height: 1.4;
}

/* ── Toast Notification (CSS transition based) ───────────────────────── */

.toast {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 400;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  border-radius: var(--radius);
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  font-size: 0.9rem;
  font-weight: 500;
  max-width: 400px;
  transform: translateY(120%);
  opacity: 0;
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.25s ease;
  pointer-events: none;
}

.toast-visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}

.toast-success {
  border-color: rgba(29, 185, 84, 0.4);
  background: rgba(29, 185, 84, 0.1);
  color: var(--accent);
}

.toast-error {
  border-color: rgba(231, 76, 60, 0.4);
  background: rgba(231, 76, 60, 0.1);
  color: var(--danger);
}

.toast-warning {
  border-color: rgba(243, 156, 18, 0.4);
  background: rgba(243, 156, 18, 0.1);
  color: var(--warning);
}

.toast-info {
  border-color: rgba(52, 152, 219, 0.4);
  background: rgba(52, 152, 219, 0.1);
  color: #3498db;
}

.toast-icon {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.toast-message {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Responsive: Recommendations ─────────────────────────────────────── */

@media (max-width: 768px) {
  .queue-card {
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 14px;
  }

  .queue-card-actions {
    width: 100%;
    justify-content: flex-end;
    padding-top: 4px;
    border-top: 1px solid var(--border-color);
  }

  .seed-track-preview {
    flex-wrap: wrap;
  }

  .seed-track-preview .btn {
    width: 100%;
    justify-content: center;
  }

  .modal {
    width: 95%;
    max-height: 90vh;
  }

  .explain-tooltip {
    width: 260px;
  }

  .toast {
    left: 16px;
    right: 16px;
    max-width: none;
  }
}

/* =========================================================================
   Explore Page — Interactive Analytics Explorer
   ========================================================================= */

/* ── Explore Layout ───────────────────────────────────────────────────── */

.explore-layout {
  display: flex;
  gap: 20px;
  align-items: flex-start;
}

/* ── Explore Filters Sidebar ──────────────────────────────────────────── */

.explore-filters {
  width: 240px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: sticky;
  top: 28px;
}

.explore-filters-card {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius);
  padding: 14px 16px;
}

.explore-filters-title {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 10px;
}

.explore-filter-group {
  margin-bottom: 10px;
}

.explore-filter-group:last-child {
  margin-bottom: 0;
}

.explore-filter-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--text-primary);
  margin-bottom: 5px;
}

.explore-select {
  width: 100%;
  padding: 7px 10px;
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  outline: none;
  cursor: pointer;
  transition: border-color var(--transition);
  appearance: auto;
}

.explore-select:focus {
  border-color: var(--accent);
}

.explore-select option {
  background: var(--bg-card);
  color: var(--text-primary);
}

.explore-filters-actions {
  display: flex;
  gap: 8px;
}

/* ── Chart Type Toggle ────────────────────────────────────────────────── */

.chart-type-toggle {
  display: flex;
  gap: 4px;
  background: var(--bg-input);
  border-radius: var(--radius-sm);
  padding: 3px;
}

.chart-type-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--text-secondary);
  border-radius: 4px;
  transition: all var(--transition);
  cursor: pointer;
  border: none;
  background: none;
  font-family: inherit;
  flex: 1;
  justify-content: center;
}

.chart-type-btn:hover {
  color: var(--text-primary);
  background: rgba(255, 255, 255, 0.05);
}

.chart-type-btn.active {
  background: var(--accent);
  color: var(--color-text-inverse);
}

.chart-type-btn svg {
  flex-shrink: 0;
}

/* ── Period Picker ────────────────────────────────────────────────────── */

.explore-period-picker {
  margin-bottom: 8px;
}

.explore-date-input {
  width: 100%;
  padding: 7px 10px;
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color var(--transition);
  cursor: pointer;
}

.explore-date-input:focus {
  border-color: var(--accent);
}

.explore-date-input::placeholder {
  color: var(--text-muted);
}

.explore-period-btns {
  flex-wrap: wrap;
}

/* ── Explore Chart Area ───────────────────────────────────────────────── */

.explore-chart-area {
  flex: 1;
  min-width: 0;
}

.explore-chart-card .card-body {
  position: relative;
  min-height: 200px;
}

.explore-chart-svg {
  width: 100%;
  height: auto;
  max-height: 340px;
  display: block;
}

.explore-chart-summary {
  display: flex;
  gap: 20px;
  padding: 8px 0 4px;
  flex-wrap: wrap;
}

/* ── Explore Heatmap ──────────────────────────────────────────────────── */

.explore-heatmap-container {
  padding: 4px 0;
}

.explore-heatmap-grid {
  grid-template-columns: repeat(12, 1fr);
}

/* ── Flatpickr Dark Overrides ──────────────────────────────────────────── */

.flatpickr-calendar {
  background: var(--bg-card) !important;
  border: 1px solid var(--border-color) !important;
  box-shadow: var(--shadow) !important;
}

.flatpickr-months .flatpickr-month,
.flatpickr-current-month .flatpickr-monthDropdown-months,
span.flatpickr-weekday {
  background: transparent !important;
  color: var(--text-primary) !important;
}

.flatpickr-day {
  color: var(--text-secondary) !important;
}

.flatpickr-day.today {
  border-color: var(--accent) !important;
}

.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.inRange {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: var(--color-text-inverse) !important;
}

.flatpickr-day:hover {
  background: var(--bg-card-hover) !important;
}

.flatpickr-day.flatpickr-disabled {
  color: var(--text-muted) !important;
}

.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
  fill: var(--text-secondary) !important;
}

.flatpickr-current-month input.cur-year {
  color: var(--text-primary) !important;
}

/* ── Card subtitle ─────────────────────────────────────────────────────── */

.card-subtitle {
  font-size: 0.82rem;
  color: var(--text-secondary);
}

/* ── Explore Responsive ────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  .explore-layout {
    flex-direction: column;
    /* The base rule's flex-start makes every card shrink-to-fit its widest
       row (the chart's track list), so a narrow viewport got a 448px card in
       a 298px column.  Stretching the column makes the cards fill the width
       and the rows inside them ellipsize/wrap instead. */
    align-items: stretch;
  }

  .explore-filters {
    width: 100%;
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
  }

  .explore-filters-card {
    flex: 1;
    min-width: 200px;
  }

  .explore-heatmap-grid {
    grid-template-columns: repeat(8, 1fr);
  }
}

@media (max-width: 768px) {
  .explore-filters-card {
    min-width: 100%;
  }

  .chart-type-toggle {
    flex-direction: row;
  }

  .explore-heatmap-grid {
    grid-template-columns: repeat(6, 1fr);
  }

  .explore-chart-summary {
    flex-direction: column;
    gap: 6px;
  }
}

@media (max-width: 480px) {
  .explore-heatmap-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ── Login (pre-auth) ─────────────────────────────────────────────────── */
/* The one page outside the app shell: no sidebar, no HTMX, one field.  It is
   served without a session, so its stylesheet must live at /static/ (exempt)
   and it must not depend on any script. */

.login-body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  font-family: var(--font-sans);
  color: var(--text-primary);
  background: var(--bg-primary);
}

.login-card {
  width: 100%;
  max-width: 22rem;
  padding: 2rem 1.75rem;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.login-logo {
  display: block;
  width: 48px;
  height: 48px;
  margin: 0 auto 1rem;
}

.login-title {
  font-size: 1.35rem;
  font-weight: 600;
  text-align: center;
}

.login-subtitle {
  margin: 0.5rem 0 1.5rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
  text-align: center;
}

.login-error {
  margin-bottom: 1rem;
  padding: 0.6rem 0.75rem;
  font-size: 0.85rem;
  color: var(--danger);
  background: rgba(231, 76, 60, 0.12);
  border: 1px solid rgba(231, 76, 60, 0.35);
  border-radius: var(--radius-sm);
}

.login-label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.login-input {
  width: 100%;
  min-height: 44px;
  padding: 0.6rem 0.75rem;
  font-family: inherit;
  font-size: 1rem;
  color: var(--text-primary);
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
}

.login-input:focus {
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.login-submit {
  width: 100%;
  min-height: 44px;
  margin-top: 1rem;
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--bg-sidebar);
  cursor: pointer;
  background: var(--accent);
  border: 0;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.login-submit:hover {
  background: var(--accent-hover);
}

/* =========================================================================
   Mobile layout pass (B-5)
   =========================================================================
   The phone-first rules the A-12 device-profile journey is judged on.  Every
   value comes from design-tokens.css (--tap-min, the spacing scale): nothing
   here states a raw colour or spacing literal, so the B-1 ratchet's ceiling
   still holds.  See tests/test_mobile_layout.py, which measures both at 380px.
   ========================================================================= */

@media (max-width: 768px) {
  /* ── Tap targets: every control is at least --tap-min (44px) ─────────── */
  button,
  select,
  textarea,
  .btn,
  .ui-btn,
  .search-input,
  .explore-select,
  .explore-date-input,
  .chat-input {
    min-height: var(--tap-min);
  }

  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) {
    min-height: var(--tap-min);
    max-width: 100%;
    min-width: 0;
  }

  .chat-send-btn,
  .btn-icon,
  .period-btn,
  .chart-type-btn,
  .suggestion-chip,
  a.sidebar-link,
  a.btn,
  .source-link {
    min-height: var(--tap-min);
    min-width: var(--tap-min);
  }

  /* ── Content that must reflow rather than be clipped ──────────────────
     A <select> is as wide as its widest option, and a segmented control is
     as wide as its buttons: both stay inside their column instead of hanging
     past the card. */
  select {
    max-width: 100%;
    min-width: 0;
  }

  .segmented-control {
    flex-wrap: wrap;
    min-width: 0;
    max-width: 100%;
  }

  /* Platform strings in the insights breakdown are single unbreakable
     tokens ("Partner sonos_ppc Sonos;…"); let them break instead of being
     sliced off by the card's own overflow clip. */
  .platform-name {
    overflow-wrap: anywhere;
  }
}

/* The touch-target platform: a coarse pointer gets the same minimum even if
   the viewport is desktop-wide (tablets, phone landscape). */
@media (pointer: coarse) {
  button,
  select,
  textarea,
  .btn,
  .ui-btn,
  .search-input,
  .explore-select,
  .explore-date-input,
  .chat-input {
    min-height: var(--tap-min);
  }

  .chat-send-btn,
  .btn-icon,
  .period-btn,
  .chart-type-btn,
  .suggestion-chip,
  a.sidebar-link,
  a.btn,
  .source-link {
    min-height: var(--tap-min);
    min-width: var(--tap-min);
  }
}

/* =========================================================================
   Bottom tab navigation (B-2)
   =========================================================================
   Home · Library · Discover · Chat · You as a fixed bottom bar.  Every value
   below comes from design-tokens.css (--tap-comfortable, the spacing scale,
   the surface/accent tokens): the block states no colour or spacing literal,
   so the B-1 ad-hoc-CSS ratchet's ceiling still holds.

   The bar is the phone's navigation.  Below the phone breakpoint the sidebar
   is hidden and the bar takes over, fixed to the bottom edge and clear of the
   home indicator via env(safe-area-inset-bottom); at and above it the sidebar
   stays and the bar is not displayed.  The marking is server-side
   (``is-current`` + ``aria-current`` in base.html), so it needs no script.

   .section-bar is the second half of the information architecture: it names
   the pages inside the tab you are on, so any page is at most "tap a tab, tap
   a page" away.  See tests/test_tab_nav.py.
   ========================================================================= */

.tabbar {
  display: none;
}

.section-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs);
  margin-bottom: var(--space-lg);
}

.section-nav,
.section-signout {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}

.section-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap-min);
  min-height: var(--tap-min);
  padding: var(--space-2xs) var(--space-sm);
  font-family: inherit;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
  background: var(--bg-card);
  border-radius: var(--radius-full);
  transition:
    background var(--transition),
    color var(--transition);
}

.section-link:hover {
  color: var(--text-primary);
  background: var(--bg-card-hover);
}

.section-link.is-current,
.section-link.is-current:hover {
  color: var(--accent);
  background: var(--accent-dim);
}

@media (max-width: 768px) {
  /* The bar replaces the sidebar on a phone: the icon rail is gone, so the
     bottom edge belongs to the navigation and nothing competes with it. */
  .sidebar {
    display: none;
  }

  .main-content {
    margin-left: 0;
    max-width: 100%;
    /* Clear the bar — and the home indicator under it — so the last row of a
       page is never behind the navigation. */
    padding-bottom: calc(
      var(--tap-comfortable) + var(--space-2xl) + env(safe-area-inset-bottom)
    );
  }

  /* The chat column is a fixed-height flex box whose input bar sits at its
     bottom: give the bar its room there too, or the input is covered. */
  .chat-layout {
    height: calc(
      100vh - var(--space-2xl) - var(--tap-comfortable) -
        env(safe-area-inset-bottom)
    );
  }

  .toast {
    bottom: calc(var(--tap-comfortable) + var(--space-lg));
  }

  .tabbar {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: var(--z-sticky);
    display: flex;
    align-items: stretch;
    background: var(--bg-sidebar);
    padding-bottom: env(safe-area-inset-bottom);
  }

  /* The bar's top edge.  Drawn rather than bordered so the rule states no
     width literal: the thickness is the spacing scale's smallest step. */
  .tabbar::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    height: var(--space-3xs);
    background: var(--border-color);
  }

  .tabbar-link {
    flex: 1 1 0;
    min-width: var(--tap-min);
    min-height: var(--tap-comfortable);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3xs);
    padding: var(--space-xs) var(--space-2xs);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--line-height-tight);
  }

  .tabbar-link:hover {
    color: var(--text-primary);
  }

  .tabbar-link.is-current,
  .tabbar-link.is-current:hover {
    color: var(--accent);
  }
}
