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

:root {
  --mono: 'Space Mono', monospace;
  --sans: 'Space Grotesk', sans-serif;
}

/* Design tokens (Stick redesign). --accent/--accent2/--navText/--bg/--header-bg are
   resolved per user scheme choice by layout.js (applyScheme/applyBgTint, both from
   theme.js) and set as inline styles on <html> — the values below are the pre-JS/
   no-JS fallback, always the free-tier default (violet). */
[data-theme="dark"] {
  --bg: #131118;
  --surface: #1e1b24;
  --surface2: #1c1c21;
  --head: #232029;
  --chip: #252230;
  --input: #17151d;
  --border: #2c2833;
  --hair: rgba(255,255,255,.055);
  --text: #f2eef7;
  --muted: #9a93a6;
  --nav-muted: #a0a0b8;
  --faint: #6c6577;
  --tickOff: rgba(255,255,255,.10);
  --gold: #d9a441;
  --berry: #e0699a;
  --danger: #e0655a;
  --mutedBorder: rgba(242,238,247,.28);
  --accent: #7c5cff;
  --accent2: #b18cff;
  --navText: #ffffff;
  --header-bg: var(--surface2);
  --header-border: #44444f;
  --nav-bg-dark: #201452;
  --nav-text-dark: #ffffff;
}

[data-theme="light"] {
  --bg: #faf7f2;
  --surface: #ffffff;
  --surface2: #efefef;
  --head: #f1ede5;
  --chip: #f1ede5;
  --input: #fbfaf7;
  --border: #e6e1d8;
  --hair: rgba(22,17,12,.08);
  --text: #16110c;
  --muted: #857e72;
  --nav-muted: #4f4f78;
  --faint: #b3aa98;
  --tickOff: rgba(22,17,12,.10);
  --gold: #a9781a;
  --berry: #c0497a;
  --danger: #d3453a;
  --mutedBorder: rgba(22,17,12,.22);
  --accent: #7c5cff;
  --accent2: #9b7fff;
  --navText: #ffffff;
  --header-bg: var(--surface2);
  --header-border: #c5c5d6;
}

/* ── Colour schemes ─────────────────────────────────────────────────────────
   The 6 preset accents (+ custom) are applied by layout.js's applyScheme()
   (theme.js), which sets --accent/--accent2/--navText as inline styles
   on <html> (same value in light + dark — the redesign uses one accent hex per
   scheme regardless of theme) and derives --bg/--header-bg via applyBgTint(),
   so no [data-scheme=…] CSS overrides are needed here. */

html { font-size: 16px; scrollbar-gutter: stable; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-weight: 400;
  min-height: 100vh;
  line-height: 1.5;
  display: flex;
  flex-direction: column;
}

/* Grain texture overlay */
.bg-grain {
  position: fixed; inset: 0; pointer-events: none; z-index: 100;
  opacity: 0.03;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
}

/* ── Header ─────────────────────────────────────────── */
header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 2rem;
  height: 54px;
  position: sticky; top: 0;
  background: var(--accent);
  color: var(--navText);
  z-index: 50;
  flex-shrink: 0;
}

/* In dark mode, a full-bleed accent-coloured bar reads too bright — locally
   redefine --accent/--navText within the header (and the mobile search bar,
   which shares its look but lives as a separate fixed element) so every
   existing var(--accent)/var(--navText) consumer already inside them — nav
   links, the Matches badge, the Pro pill, icon buttons, the search box —
   darkens for free. Nothing outside these two elements is affected. */
[data-theme="dark"] header,
[data-theme="dark"] #mobile-search-bar {
  --accent: var(--nav-bg-dark);
  --navText: var(--nav-text-dark);
}

.logo {
  font-family: var(--sans);
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.05em;
  color: var(--navText);
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  justify-self: start;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.logo-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask-image: url(/favicon.svg);
  mask-image: url(/favicon.svg);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

.header-right { display: flex; align-items: center; gap: 0.5rem; justify-content: flex-end; }

.nav-center {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  position: relative;
  align-self: stretch;
}

.search-icon-btn {
  background: none;
  border: 1.5px solid color-mix(in srgb, var(--navText) 40%, transparent);
  cursor: pointer;
  color: var(--navText);
  padding: 0;
  width: 26px; height: 26px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  position: relative;
  transition: background 0.15s;
  z-index: 2;
}
.search-icon-btn:hover { background: color-mix(in srgb, var(--navText) 12%, transparent); }
.search-icon-btn .icon-search,
.search-icon-btn .icon-close {
  position: absolute;
  display: flex;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.search-icon-btn .icon-search {
  opacity: 1;
  transform: scale(1) rotate(0deg);
}
.search-icon-btn .icon-close {
  opacity: 0;
  transform: scale(0.6) rotate(45deg);
  pointer-events: none;
}
.search-icon-btn.open .icon-search {
  opacity: 0;
  transform: scale(0.6) rotate(-45deg);
}
.search-icon-btn.open .icon-close {
  opacity: 1;
  transform: scale(1) rotate(0deg);
  pointer-events: auto;
}

nav { display: flex; align-items: center; gap: 1rem; }

.nav-search {
  position: absolute;
  left: 2.1rem;
  right: 0; top: 0; bottom: 0;
  display: flex; align-items: center; gap: 0.6rem;
  background: var(--accent);
  padding-right: 0.4rem;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
  z-index: 1;
}
.nav-search.open {
  clip-path: inset(0 0% 0 0);
  pointer-events: all;
}

.nav-search-input {
  flex: 1; min-width: 0;
  background: transparent; border: none;
  border-bottom: 2px solid color-mix(in srgb, var(--navText) 70%, transparent);
  outline: none; color: var(--navText);
  font-family: var(--sans); font-weight: 600; font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 0.4rem 0.15rem;
}
.nav-search-input::placeholder { color: var(--navText); opacity: 0.92; text-transform: uppercase; }

.nav-search-btn {
  background: none; border: none; cursor: pointer;
  color: var(--navText); padding: 0.3rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: opacity 0.15s;
}
.nav-search-btn:hover { opacity: 0.8; }

.nav-btn {
  background: none; border: none; cursor: pointer;
  font-family: var(--sans); font-size: 0.74rem; font-weight: 600;
  color: var(--navText);
  opacity: 0.92;
  padding: 0;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: opacity 0.15s;
  text-decoration: none;
  text-underline-offset: 5px;
  text-decoration-thickness: 2px;
  display: inline-flex;
  align-items: center;
  position: relative;
}
.nav-btn:hover { opacity: 1; }
.nav-btn.active { opacity: 1; text-decoration: underline; }

.nav-badge {
  display: inline-block;
  background: var(--navText);
  color: var(--accent);
  border-radius: 10px;
  font-size: .6rem;
  font-weight: 700;
  padding: 0 .4rem;
  margin-left: .35rem;
  vertical-align: middle;
  line-height: 1.6;
  min-width: 1.2rem;
  text-align: center;
}
.nav-badge.hidden { display: none; }

.user-menu { display: flex; align-items: center; gap: 0.4rem; }
.user-menu.hidden { display: none; }

.pro-nav-btn {
  display: flex; align-items: center; gap: 0.3rem;
  height: 26px;
  padding: 0 0.65rem;
  border-radius: 20px;
  background: var(--navText);
  color: var(--accent);
  border: none;
  font-family: var(--sans);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  text-decoration: none;
  transition: filter 0.15s;
}
.pro-nav-btn:hover { filter: brightness(0.95); }
.pro-nav-btn-text { line-height: 1; transform: translateY(1px); }
.pro-nav-btn-divider {
  width: 1px; height: 18px;
  background: color-mix(in srgb, var(--navText) 25%, transparent);
  margin: 0 0.15rem;
}

.header-avatar {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--navText) 22%, transparent);
  color: var(--navText);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 0.65rem; font-weight: 700;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  text-decoration: none;
}
.header-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.header-avatar-wrap { position: relative; }

.header-avatar-menu {
  position: absolute;
  top: 100%;
  /* header has 2rem right padding, so the wrap's own right edge already
     sits 2rem in from the page edge; pull the card back out by the same
     amount minus the 8px gap we actually want, so its right edge lands 8px
     from the page's right edge — matching the 8px gap below the header. */
  right: calc(-2rem + 8px);
  /* Invisible hover bridge, flush against the avatar so hover never drops
     across the gap. 14px clears the header bar itself (the avatar sits
     vertically centered in the 54px header, ~14px of header still remains
     below it), plus an 8px visual gap before the menu card — matching the
     8px gap kept on the right-hand side above. */
  padding-top: calc(14px + 8px);
  z-index: 100;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.12s ease;
}
/* .open is toggled by JS (setupAvatarMenu in header.js) rather than a pure
   CSS :hover rule — a CSS transition-delay-based "stay open" grace period
   flips pointer-events to none the instant the mouse leaves (it can't be
   part of the delayed transition), so re-entering the still-visible menu
   during the grace window doesn't re-register hover and the menu can end up
   visible but unclickable. A JS timer that's cleared on re-entry has no such
   race. */
.header-avatar-menu.open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.header-avatar-menu-inner {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  overflow: hidden;
}

.header-avatar-menu-item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  min-width: 150px;
  text-align: left;
  background: none;
  border: none;
  font-family: var(--sans);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
  padding: 0.55rem 0.9rem;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.1s, color 0.1s;
}
.header-avatar-menu-item svg { flex-shrink: 0; }
.header-avatar-menu-item:hover { background: var(--surface2); color: var(--text); }

/* ── Mobile header left/right groups ──────────────────*/
.mobile-header-left,
.mobile-header-right {
  display: none;
  align-items: center;
  gap: 0.25rem;
}
.mobile-header-right { justify-content: flex-end; }

.hamburger-btn {
  background: none; border: none; cursor: pointer;
  color: var(--navText);
  padding: 0; width: 30px; height: 30px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s;
}
.hamburger-btn:hover,
.hamburger-btn.open { background: color-mix(in srgb, var(--navText) 15%, transparent); }

/* ── Mobile menu drawer ────────────────────────────────
   A left-edge slide-in panel (not a top dropdown): fixed full-height,
   translateX off-screen when closed, backdrop fades independently. */
.mobile-menu {
  display: none;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: 78%; max-width: 300px;
  z-index: 60;
  background: var(--bg);
  color: var(--text);
  border-right: 1px solid var(--border);
  transform: translateX(-103%);
  transition: transform 0.34s cubic-bezier(0.4, 0, 0.1, 1);
  flex-direction: column;
  padding-top: 6px;
  overflow-y: auto;
}
.mobile-menu.open {
  transform: translateX(0);
  /* Only cast the shadow while open — while closed the drawer is translated
     off-screen but a shadow on the base rule still bleeds onto the page
     (a 44px blur reaches past the -103% translateX on narrow viewports). */
  box-shadow: 14px 0 44px -14px rgba(0, 0, 0, 0.55);
}

.mobile-menu-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 22px 18px;
}
.mobile-menu-eyebrow {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted);
}
.mobile-menu-close-btn {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: none;
  color: var(--text);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}

.mobile-menu-nav {
  display: flex; flex-direction: column;
  padding: 4px 14px 0;
}
.mobile-menu-nav .nav-btn {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  text-align: left;
  padding: 14px 12px;
  border-radius: 11px;
  font-family: var(--sans); font-size: 1.05rem; font-weight: 700;
  letter-spacing: -0.02em; text-transform: none;
  color: var(--text);
  opacity: 1;
}
.mobile-menu-nav .nav-btn:hover,
.mobile-menu-nav .nav-btn.active { background: var(--chip); }
.mobile-menu-nav .nav-btn .nav-badge { background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); }

.mobile-menu-divider { margin: 14px 26px; height: 1px; background: var(--hair); }

.mobile-menu-secondary { display: flex; flex-direction: column; padding: 0 14px; }
.mobile-menu-secondary-link {
  padding: 12px;
  border-radius: 11px;
  text-decoration: none;
  color: var(--muted);
  font-family: var(--sans); font-size: 0.85rem; font-weight: 600;
}
.mobile-menu-secondary-link:hover { background: var(--chip); }

.mobile-menu-footer {
  margin-top: auto;
  padding: 16px 20px 22px;
  display: flex; flex-direction: column; gap: 9px;
}
.mobile-menu-import-btn,
.mobile-menu-pro-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px;
  border-radius: 12px;
  text-decoration: none;
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.mobile-menu-import-btn {
  border: 1.5px solid var(--border);
  color: var(--text);
}
.mobile-menu-pro-btn {
  background: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
}
.mobile-menu-pro-btn.hidden { display: none; }

/* ── Mobile backdrop ──────────────────────────────────*/
.mobile-backdrop {
  display: none;
  position: fixed; inset: 0;
  z-index: 59;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}
.mobile-backdrop.open { display: block; opacity: 1; pointer-events: auto; }

/* ── Mobile search bar ────────────────────────────────*/
.mobile-search-bar {
  display: none;
  position: fixed;
  top: 54px; left: 0; right: 0; height: 48px;
  z-index: 49;
  background: var(--accent);
  color: var(--navText);
  align-items: center; gap: 0.6rem;
  padding: 0 1rem;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
.mobile-search-bar.open {
  clip-path: inset(0 0 0% 0);
  pointer-events: all;
}
.mobile-search-bar .nav-search-input {
  font-size: 0.78rem;
}

body.mobile-menu-open { overflow: hidden; }

/* ── Main ───────────────────────────────────────────── */
main {
  max-width: 1240px;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 4rem;
  transition: max-width 0.35s ease;
  position: relative;
  flex: 1 0 auto;
  width: 100%;
  zoom: 1.08;
}

/* Ambient accent glow — follows the active colour scheme */
main::before {
  content: '';
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 80vw;
  max-width: 900px;
  height: 480px;
  background: var(--accent);
  opacity: 0.045;
  filter: blur(90px);
  border-radius: 50%;
  pointer-events: none;
  z-index: -1;
}
body[data-page="dev"] main {
  max-width: min(1400px, 100%);
}

/* ── Settings page ────────────────────────────────────*/
.settings-page {
  max-width: 540px;
  margin: 0 auto;
}
.settings-section {
  margin-bottom: 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem 1.5rem;
}
.settings-section-title {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}
.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.65rem 0;
}
.settings-row + .settings-row {
  border-top: 1px solid var(--border);
}
.settings-label {
  font-size: 0.875rem;
  color: var(--text);
}
.settings-connection-status {
  font-family: var(--mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  background: var(--chip);
  border-radius: 20px;
  padding: 0.15rem 0.6rem;
  align-self: flex-start;
}
.settings-theme-options {
  display: flex;
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow: hidden;
}
.settings-theme-options.saving { opacity: 0.5; pointer-events: none; }
.settings-theme-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.settings-theme-btn:hover { color: var(--text); background: var(--surface2); }
.settings-theme-btn.active { color: var(--accentText, var(--accent)); background: var(--surface2); }
.btn {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 0.4rem 0.8rem;
  border-radius: 20px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.btn:hover { border-color: var(--accent); }
.btn:focus { outline: none; border-color: var(--accent); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn-secondary { /* muted variant — inherits .btn base */ }
.settings-select {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.7rem;
  border-radius: 6px;
  cursor: pointer;
}
.settings-select:focus { outline: none; border-color: var(--accent); }
.settings-pro-badge {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 0.05rem 0.35rem;
  margin-left: 0.4rem;
  vertical-align: middle;
}
/* ── Pro pitch page (/pro) ────────────────────────────────────────────────── */
.pro-page { max-width: 720px; margin: 0 auto; }
.pro-badge-chip {
  display: inline-flex; align-items: center; gap: 0.4rem;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  font-family: var(--mono); font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0.45rem 0.85rem; border-radius: 20px; margin-bottom: 0.9rem;
}
.pro-pitch-title {
  font-family: var(--sans); font-size: 2.1rem; font-weight: 700;
  letter-spacing: -0.05em; max-width: 34ch; margin: 0 0 0.7rem;
}
.pro-pitch-sub {
  font-size: 0.9rem; line-height: 1.65; color: var(--text); opacity: 0.82;
  max-width: 42ch; margin: 0 0 1.8rem;
}
.pro-section-label {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  margin-bottom: 0.75rem;
}
.pro-feature-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.pro-more-to-come {
  font-family: var(--mono); font-size: 0.75rem; color: var(--muted);
  text-align: center; margin: 0.9rem 0 1.9rem;
}
.pro-feature-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 1.25rem 1.35rem; display: flex; gap: 0.85rem; align-items: flex-start;
}
.pro-feature-card-icon {
  width: 40px; height: 40px; flex: none; border-radius: 11px;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.pro-feature-card-title { font-family: var(--sans); font-size: 1rem; font-weight: 700; letter-spacing: -0.02em; }
.pro-feature-card-body { font-family: var(--mono); font-size: 0.75rem; line-height: 1.55; color: var(--muted); margin-top: 0.3rem; }
.pro-plan-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 0.85rem; }
.pro-plan-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 1.35rem 1.5rem; position: relative;
}
.pro-plan-card--best { border-color: var(--accent); border-width: 2px; }
.pro-plan-card-ribbon {
  position: absolute; top: -0.7rem; left: 1.5rem;
  background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText));
  font-family: var(--mono); font-size: 0.58rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.25rem 0.65rem; border-radius: 12px;
}
.pro-plan-card-label { font-family: var(--mono); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.pro-plan-card-price {
  font-family: var(--sans); font-size: 2.1rem; font-weight: 700; letter-spacing: -0.04em;
  display: flex; align-items: baseline; gap: 0.35rem; margin: 0.6rem 0 0.2rem;
}
.pro-plan-card-price span { font-family: var(--mono); font-size: 0.72rem; font-weight: 400; color: var(--muted); }
.pro-plan-card-note { font-family: var(--mono); font-size: 0.68rem; color: var(--muted); margin-bottom: 1rem; }
.pro-plan-card-btn { width: 100%; }
.pro-error { font-size: 0.8rem; color: var(--danger); margin-top: 1rem; }
.pro-already-state { text-align: center; padding: 4rem 1rem; }
.pro-already-icon {
  width: 64px; height: 64px; border-radius: 18px; background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText));
  display: flex; align-items: center; justify-content: center; margin: 0 auto 1.25rem;
}
.pro-already-title { font-family: var(--sans); font-size: 1.9rem; font-weight: 700; letter-spacing: -0.05em; margin: 0 0 0.6rem; }
.pro-already-body { font-size: 0.88rem; line-height: 1.6; color: var(--text); opacity: 0.8; max-width: 400px; margin: 0 auto 1.3rem; }
@media (max-width: 600px) {
  .pro-feature-cards, .pro-plan-cards { grid-template-columns: 1fr; }
}
.settings-tint-slider:disabled { opacity: 0.45; cursor: default; }
#custom-tint-row.locked { cursor: pointer; }
#custom-tint-row.locked .settings-tint-control { pointer-events: none; }
.settings-scheme-options {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
.settings-scheme-options.saving { opacity: 0.5; pointer-events: none; }
.settings-scheme-swatch {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.15s, border-color 0.15s;
  flex-shrink: 0;
  outline: none;
}
.settings-scheme-swatch:hover { transform: scale(1.15); }
.settings-scheme-swatch.active {
  border-color: var(--text);
  transform: scale(1.1);
}
.settings-scheme-swatch.locked { opacity: 0.45; }
.settings-scheme-swatch.locked:hover { opacity: 0.7; }
.settings-scheme-swatch.custom-swatch {
  position: relative;
  overflow: visible;
}
.settings-scheme-swatch.custom-swatch.no-color {
  background: conic-gradient(
    hsl(0,80%,60%), hsl(60,80%,60%), hsl(120,80%,60%),
    hsl(180,80%,60%), hsl(240,80%,60%), hsl(300,80%,60%), hsl(360,80%,60%)
  ) !important;
}
/* Once a custom colour is picked, the custom swatch is otherwise just a plain
   solid circle indistinguishable from any preset — this pencil badge stays on
   it permanently (not just in the .no-color placeholder state above) so it
   always reads as "pick your own colour", not "another preset". Neutral
   surface/border tokens rather than the swatch's own fill, so it stays legible
   against literally any custom colour, including near-white/near-black picks. */
.settings-scheme-swatch.custom-swatch::after {
  content: "\270E";
  position: absolute;
  bottom: -3px;
  right: -3px;
  width: 13px;
  height: 13px;
  line-height: 13px;
  text-align: center;
  font-size: 8px;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
  pointer-events: none;
}

/* In-app custom colour picker popover (issue #514) — replaces the OS's
   native <input type="color"> panel. position:fixed with coordinates set in
   JS on open, same pattern as .na-menu. */
.color-picker-popover {
  display: none;
  position: fixed;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem;
  width: 230px;
  z-index: 100;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
}
.color-picker-popover.open { display: block; }
.color-picker-preview {
  width: 100%;
  height: 28px;
  border-radius: 5px;
  border: 1px solid var(--border);
  margin-bottom: 0.6rem;
}
.color-picker-slider-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}
.color-picker-slider-label {
  font-family: var(--mono);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  color: var(--muted);
  width: 0.9rem;
  flex-shrink: 0;
}
.color-picker-slider {
  flex: 1;
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}
.color-picker-num {
  width: 2.6rem;
  flex-shrink: 0;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.15rem 0.3rem;
  box-sizing: border-box;
  text-align: right;
  /* Hide the native up/down spinner buttons — the slider is the primary
     drag control, this box is for precise typed entry only. */
  -moz-appearance: textfield;
}
.color-picker-num::-webkit-outer-spin-button,
.color-picker-num::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.color-picker-num:focus { outline: none; border-color: var(--accent); }
.color-picker-hex {
  width: 100%;
  margin-top: 0.4rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.75rem;
  padding: 0.3rem 0.5rem;
  box-sizing: border-box;
}
.color-picker-hex:focus { outline: none; border-color: var(--accent); }
.settings-restore-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  padding: 0.2rem 0.5rem;
  border-radius: 14px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
  flex-shrink: 0;
}
.settings-restore-btn:hover { color: var(--text); border-color: var(--muted); }
.settings-tint-control {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.settings-tint-slider {
  width: 120px;
  accent-color: var(--accent);
  cursor: pointer;
}
.settings-tint-value {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  min-width: 1.5rem;
  text-align: right;
}
.settings-row-block {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
}
.settings-plex-webhook {
  display: flex;
  gap: 0.5rem;
  width: 100%;
  align-items: center;
}
.settings-webhook-input {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: 0.72rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.3rem 0.5rem;
  border-radius: 4px;
  outline: none;
}
.settings-action-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.65rem;
  border-radius: 18px;
  cursor: pointer;
  flex-shrink: 0;
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.15s, border-color 0.15s;
}
.settings-action-btn:hover { color: var(--text); border-color: var(--muted); }
.settings-action-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.settings-action-btn:disabled:hover { color: var(--muted); border-color: var(--border); }
.settings-action-btn-danger:hover { color: #cc2244; border-color: #cc2244; }
.settings-row-disabled .settings-label { opacity: 0.5; }
.settings-row-disabled .settings-sublabel a { color: var(--accent); }
.settings-row-disabled .settings-sublabel a:hover { text-decoration: underline; }
.settings-action-btn--primary {
  background: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
  border-color: var(--accentFill, var(--accent));
}
.settings-action-btn--primary:hover { opacity: 0.85; }
.settings-sublabel-inline { font-size: 0.85em; opacity: 0.6; }
/* flex-wrap (not viewport-gated, unlike .settings-row's mobile breakpoint):
   the settings card is a fixed ~492px content width regardless of window
   size (.settings-page's 540px cap), so two full-width buttons here can
   overflow the card on any viewport, not just narrow ones — they need to
   wrap onto their own line rather than push past the card's right edge. */
.settings-btn-group { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; }

/* Import history (issue #167; moved onto its own card on the Import page in issue #523) */
.import-history-panel {
  max-width: 680px;
  margin: 0 auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem 1.4rem;
}
.import-history-list { display: flex; flex-direction: column; margin-bottom: 0.75rem; }
.import-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.65rem 0;
}
.import-row + .import-row { border-top: 1px solid var(--border); }
.import-main { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.import-title { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.import-name {
  font-size: 0.875rem;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.import-source-pill {
  font-family: var(--mono);
  font-size: 0.55rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 3px;
  flex-shrink: 0;
}
.import-approx {
  font-family: var(--mono);
  font-size: 0.6rem;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0 4px;
  flex-shrink: 0;
}
.import-meta { font-size: 0.78rem; color: var(--muted); }
.settings-sublabel {
  font-size: 0.78rem;
  color: var(--muted);
  line-height: 1.4;
}

/* ── Tabs ─────────────────────────────────────────────*/
.tab { display: none; }
.tab.active { display: block; }

.library-view { display: none; }
.library-view.active { display: block; }

/* Pill-shaped filter tabs (design spec: "Pills / buttons: 20px" radius) —
   overrides the shared .dupes-tabs/.dupes-tab underlined-tab-bar look for
   each screen's own row of pill filters, per that screen's mockup spec.
   Each block uses a selector specific enough to win regardless of the two
   rule blocks' order in the file (container id/class + .dupes-tab). */

/* Library: RECENT / ARTISTS / ALBUMS / TRACKS — 20px radius, filled active. */
.dupes-tabs.library-tabs {
  margin-bottom: 1.25rem;
  gap: 0.5rem;
  border-bottom: none;
}
.dupes-tab.library-tab {
  border: 1px solid var(--border);
  border-radius: 20px;
  background: none;
  padding: 0.4rem 1rem;
}
.dupes-tab.library-tab:hover { background: var(--surface2); border-color: var(--border); }
.dupes-tab.library-tab.active {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

/* Matches (/mbid): Unmatched / Paused / Archived — 20px radius, filled active.
   (.na-tab-strip's own display/gap rule lives with the rest of the na-toolbar
   layout further down — see .na-tab-strip { gap: 6px }.) */
.na-tab-strip .dupes-tab {
  border: 1px solid var(--border);
  border-radius: 20px;
  background: none;
  padding: 0.44rem 0.85rem;
  font-size: 0.68rem;
  letter-spacing: 0.05em;
}
.na-tab-strip .dupes-tab:hover { background: var(--surface2); border-color: var(--border); }
.na-tab-strip .dupes-tab.active {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

/* Import: "Review excluded listens" In library / In file / Deleted —
   16px radius, accent-filled active (matches the mockup's use of --accent
   here rather than the neutral --text fill used by Library/Matches/Settings). */
#dupes-tabs {
  gap: 0.4rem;
  border-bottom: none;
}
#dupes-tabs .dupes-tab {
  border: 1px solid var(--border);
  border-radius: 16px;
  background: none;
  padding: 0.44rem 0.7rem;
  font-size: 0.66rem;
  letter-spacing: 0.04em;
}
#dupes-tabs .dupes-tab:hover { background: var(--surface2); border-color: var(--border); }
#dupes-tabs .dupes-tab.active {
  background: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
  border-color: var(--accentFill, var(--accent));
}

/* Settings: Appearance / Connections / Import History / … — 22px radius,
   filled active, thicker 1.5px border on both states. */
.dupes-tabs.settings-tabs {
  gap: 0.4rem;
  border-bottom: none;
}
.dupes-tab.settings-tab {
  border: 1.5px solid var(--mutedBorder);
  border-radius: 22px;
  background: none;
  padding: 0.5rem 0.95rem;
  font-size: 0.69rem;
  letter-spacing: 0.02em;
}
.dupes-tab.settings-tab:hover { background: var(--surface2); }
.dupes-tab.settings-tab.active {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.settings-tab-panel { display: none; }
.settings-tab-panel.active { display: block; }
.settings-tabs { margin-bottom: 1.25rem; justify-content: center; }

/* Search: All / Artists / Albums / Tracks / People — 20px radius, filled active. */
.dupes-tabs.search-filter-tabs {
  margin-bottom: 1.25rem;
  gap: 0.4rem;
  border-bottom: none;
}
.dupes-tab.search-filter-tab {
  border: 1px solid var(--border);
  border-radius: 20px;
  background: none;
  padding: 0.44rem 0.85rem;
  font-size: 0.68rem;
}
.dupes-tab.search-filter-tab:hover { background: var(--surface2); border-color: var(--border); }
.dupes-tab.search-filter-tab.active {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.section-header {
  margin-bottom: 1.25rem;
}
.section-header--eyebrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
.section-eyebrow {
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.recent-header,
.chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* ── Period control ─────────────────────────────────────*/
.chart-header-right {
  display: flex;
  align-items: center;
  gap: 0.65rem;
}
.period-control { position: relative; }

.period-btn {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.3rem 0.6rem;
  border-radius: 4px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.period-btn:hover,
.period-btn[aria-expanded="true"] { color: var(--text); border-color: var(--muted); }

.period-arrow { font-size: 0.6rem; transition: transform 0.15s; }
.period-btn[aria-expanded="true"] .period-arrow { transform: rotate(180deg); }

.period-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0;
  margin: 0;
  min-width: 220px;
  z-index: 30;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  overflow: hidden;
}
.period-dropdown.open { display: block; }

.period-options { list-style: none; padding: 0; margin: 0; }

.period-option {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.period-option:hover { background: var(--surface2); color: var(--text); }
.period-option.selected { color: var(--accent); }

.period-custom-range {
  border-top: 1px solid var(--border);
  padding: 0.6rem 0.9rem 0.5rem;
}
.period-custom-field { margin-bottom: 0.4rem; }
.period-custom-label {
  display: block;
  font-family: var(--mono);
  font-size: 0.6rem;
  color: var(--muted);
  letter-spacing: 0.06em;
  margin-bottom: 0.2rem;
}
.period-custom-input {
  width: 100%;
  box-sizing: border-box;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.3rem 0.5rem;
  border-radius: 4px;
}
.period-custom-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.4rem;
  margin-top: 0.5rem;
}
.period-custom-cancel {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  cursor: pointer;
  padding: 0.3rem 0.5rem;
}
.period-custom-apply {
  background: var(--accentFill, var(--accent));
  border: none;
  color: var(--accentFillText, var(--navText));
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  padding: 0.3rem 0.7rem;
  border-radius: 16px;
}

.date-jump-outer {
  position: relative;
  display: inline-flex;
}
.date-jump-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.15rem 0.25rem;
  transition: border-color 0.15s;
}
.date-jump-wrap:hover { border-color: var(--muted); }
.date-jump-day-arrow {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1;
  padding: 0.25rem 0.3rem;
  border-radius: 4px;
  cursor: pointer;
  transition: color 0.15s;
}
.date-jump-day-arrow:hover { color: var(--text); }
.date-jump-day-arrow:disabled { opacity: 0.25; cursor: default; pointer-events: none; }
.date-jump-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.3rem 0.4rem;
  border-radius: 4px;
  cursor: pointer;
  transition: color 0.15s;
  white-space: nowrap;
}
.date-jump-btn:hover { color: var(--text); }
.date-jump-btn:focus { outline: none; color: var(--text); }
.date-jump-today {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 0.15rem;
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.65rem;
  line-height: 1;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
  white-space: nowrap;
}
.date-jump-today:hover:not(:disabled) { color: var(--text); background: var(--surface2); }
.date-jump-today:disabled { opacity: 0.35; cursor: default; }
.date-jump-picker {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  z-index: 200;
  width: 222px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  transform-origin: top right;
}
.date-jump-nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.date-jump-arrow {
  background: none;
  border: none;
  color: var(--nav-muted);
  cursor: pointer;
  padding: 2px 8px;
  font-size: 0.85rem;
  line-height: 1;
  border-radius: 3px;
  transition: color 0.1s, background 0.1s;
}
.date-jump-arrow:hover { color: var(--text); background: color-mix(in srgb, var(--surface) 60%, var(--border) 40%); }
.date-jump-arrow:disabled { opacity: 0.25; cursor: default; pointer-events: none; }
.date-jump-year-btn {
  background: none;
  border: none;
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 3px;
  letter-spacing: 0.02em;
  transition: color 0.1s, background 0.1s;
}
.date-jump-year-btn:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.date-jump-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  will-change: opacity;
}
.date-jump-grid.day { grid-template-columns: repeat(7, 1fr); }
.date-jump-dow {
  font-family: var(--mono);
  font-size: 0.6rem;
  color: var(--nav-muted);
  text-align: center;
  padding: 0 0 3px;
}
.date-jump-cell {
  background: none;
  border: 1px solid transparent;
  color: var(--nav-muted);
  cursor: pointer;
  padding: 5px 2px;
  font-family: var(--mono);
  font-size: 0.72rem;
  border-radius: 3px;
  text-align: center;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}
.date-jump-cell:hover { color: var(--text); background: var(--surface2); border-color: var(--border); }
.date-jump-cell.today { color: var(--text); border-color: var(--nav-muted); }
.date-jump-cell.active { background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); border-color: var(--accentFill, var(--accent)); }
.date-jump-cell:disabled { opacity: 0.2; cursor: default; pointer-events: none; }

#search-results {
  margin-top: 1.25rem;
}

.search-section-title {
  font-family: var(--mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 2.5rem 0 0.5rem;
}
#search-results > div:first-child .search-section-title { margin-top: 0; }

.search-see-more {
  display: inline-block;
  margin-top: 0.6rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--accent);
  text-decoration: none;
}
.search-see-more:hover { text-decoration: underline; }

.search-echo {
  font-size: 0.95rem;
  color: var(--text);
  margin-bottom: 1rem;
}
.search-echo-count {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
  margin-left: 0.4rem;
}

.search-filter-tabs { margin-bottom: 1.25rem; }

.search-filter-section.hidden { display: none; }

.search-clear-btn {
  font-family: var(--sans);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
  background: var(--chip);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
}
.search-clear-btn:hover { border-color: var(--mutedBorder, var(--border)); }
.search-mb-link {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--accent);
  text-decoration: none;
}
.search-mb-link:hover { text-decoration: underline; }

.section-header h2 {
  font-family: var(--sans);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.035em;
}

/* ── Track list ───────────────────────────────────────*/
.track-list {
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

.track-day-header {
  padding: 1.1rem 1rem 0.55rem 0;
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
}
.track-day-name {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text);
}
.track-day-date {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--muted);
}

.track-row {
  display: grid;
  grid-template-columns: 44px 1fr auto auto;
  align-items: center;
  gap: 1rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  transition: background 0.12s, box-shadow 0.12s;
  position: relative;
}
#recent-list .track-row, #timeline .track-row { cursor: pointer; }
.track-row:last-child { border-bottom: none; }
.track-row:hover {
  background: var(--surface2);
}

.track-info { min-width: 0; }
.track-name {
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.track-meta {
  font-size: 0.78rem;
  color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  margin-top: 2px;
}
.track-date {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  white-space: nowrap;
  text-align: right;
}
.date-short { display: none; flex-direction: column; align-items: flex-end; line-height: 1.3; }

.empty-state {
  padding: 3rem 1.5rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.875rem;
}

/* ── Shared icon+headline+body+CTA "nothing here" pattern (item 7) ────────
   Opt-in richer structure inside the plain .empty-state above — built by
   public/js/empty-state.js, used for no-results/no-matches/empty-library/
   error/404 screens per the mockup's "Stick States" reference. */
.empty-state--rich {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3.1rem 1.5rem 3.4rem;
}
.empty-state-icon {
  width: 64px; height: 64px; flex: none; border-radius: 17px;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 1.1rem;
}
.empty-state-icon--neutral { background: var(--chip); color: var(--faint); }
.empty-state-icon--accent  { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); }
.empty-state-icon--danger  { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.empty-state-title {
  font-family: var(--sans); font-size: 1.35rem; font-weight: 700;
  letter-spacing: -0.03em; color: var(--text); margin: 0 0 0.55rem;
}
.empty-state-body {
  font-size: 0.8rem; line-height: 1.6; color: var(--muted);
  max-width: 420px; margin: 0 auto 1.1rem;
}
.empty-state-actions { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
.empty-state-btn {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  padding: 0.68rem 1.1rem; border-radius: 22px;
  cursor: pointer; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--text); border: 1px solid var(--border);
}
.empty-state-btn--primary { background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); border: none; }

/* ── Skeleton loading rows (item 7) — reuses the existing art-shimmer
   gradient technique rather than introducing a second shimmer mechanism. */
.skeleton-row-list { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; padding: 0 1.1rem; }
.skeleton-row {
  display: grid; grid-template-columns: 48px 1fr 60px; gap: 0.9rem;
  align-items: center; padding: 0.75rem 0;
  border-top: 1px solid var(--hair);
}
.skeleton-row:first-child { border-top: none; }
.skeleton-thumb, .skeleton-line {
  background: linear-gradient(90deg, var(--surface2) 25%, var(--border) 50%, var(--surface2) 75%);
  background-size: 200% 100%;
  animation: art-shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
}
.skeleton-thumb { width: 48px; height: 48px; border-radius: 8px; }
.skeleton-lines { display: flex; flex-direction: column; gap: 0.45rem; }
.skeleton-line--title { height: 12px; width: 52%; }
.skeleton-line--sub   { height: 10px; width: 32%; }
.skeleton-line--trail { height: 12px; }

/* ── Pagination ───────────────────────────────────────*/
.pagination {
  display: flex;
  gap: 0.35rem;
  margin-top: 1rem;
  justify-content: center;
  flex-wrap: wrap;
  align-items: center;
}
.page-btn {
  background: var(--surface); border: 1px solid var(--border);
  color: var(--muted); cursor: pointer;
  font-family: var(--mono); font-size: 0.75rem;
  padding: 0.4rem 0.7rem; border-radius: 8px;
  transition: all 0.15s;
  white-space: nowrap;
}
.page-btn:hover:not([disabled]) { color: var(--text); border-color: var(--muted); }
.page-btn.active { color: var(--text); border-color: var(--accent); }
.page-btn[disabled] { opacity: 0.3; cursor: default; }
.page-edge { font-size: 0.7rem; }
.page-ellipsis {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  padding: 0 0.1rem;
  user-select: none;
}

/* ── Chart list ───────────────────────────────────────*/
.chart-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.chart-row {
  display: grid;
  grid-template-columns: 2.5rem 52px 1fr 80px auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.85rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  transition: border-color 0.15s, box-shadow 0.15s;
  animation: fadeUp 0.3s ease both;
}
.chart-row:hover { border-color: var(--border); }

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

.chart-rank {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--muted);
  text-align: right;
}
.chart-rank.top {
  color: var(--accent);
  font-size: 0.88rem;
  font-weight: 500;
}

.chart-info { min-width: 0; }
.chart-name {
  font-size: 0.96rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chart-sub {
  font-size: 0.75rem;
  color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  margin-top: 2px;
}

.chart-plays {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  white-space: nowrap;
  background: var(--surface2);
  border: 1px solid var(--border);
  padding: 0.2rem 0.65rem;
  border-radius: 20px;
}
.chart-bar {
  height: 6px;
  background: var(--tickOff, var(--surface2));
  border-radius: 3px;
  overflow: hidden;
}
.chart-bar-fill {
  height: 100%;
  /* --accentFill (theme.js) is --accent itself, unless the accent is too
     close in tone to the track/page surfaces to read as a fill (e.g. white
     in light mode, black in dark mode) — then it's the theme's own
     high-contrast neutral instead, same swap computeNavText already does
     for text-on-accent. */
  background: var(--accentFill, var(--accent));
  border-radius: 3px;
  transition: width 0.4s ease;
}
@media (max-width: 540px) {
  .chart-row .chart-bar { display: none; }
  .chart-row { grid-template-columns: 2.5rem 52px 1fr auto; }
}

/* ── Insights bar rows (years / sources / genres) ──────*/
.insights-bar-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.insights-bar-row {
  display: grid;
  grid-template-columns: 4.5rem 1fr auto;
  align-items: center;
  gap: 0.75rem;
}
.insights-bar-label {
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Auto-sizing variant: label column grows to fit its widest label,
   capped so the bar/value columns never get crowded out. */
.insights-bar-grid {
  display: grid;
  grid-template-columns: minmax(4.5rem, max-content) 1fr auto;
  align-items: center;
  row-gap: 0.6rem;
  column-gap: 0.75rem;
}
.insights-bar-grid .insights-bar-row {
  display: contents;
}
.insights-bar-grid .insights-bar-label {
  max-width: 9rem;
}
@media (max-width: 540px) {
  .insights-bar-grid {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    row-gap: 0.6rem;
  }
  .insights-bar-grid .insights-bar-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    column-gap: 0.75rem;
  }
  .insights-bar-grid .insights-bar-label {
    max-width: none;
    flex: 0 1 auto;
    min-width: 0;
  }
  .insights-bar-grid .chart-bar {
    flex: 1 1 auto;
  }
  .insights-bar-grid .insights-bar-value {
    flex: 0 0 auto;
  }
}
.insights-bar-value {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  white-space: nowrap;
}

/* ── Dev Metrics column charts ──────────────────────────────────────────── */
.dev-metrics-colchart {
  position: relative; /* anchors Server Metrics' threshold/cursor/restart overlays (below) */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
  height: 140px;
}
.dev-metrics-colchart.dev-srv-spark { height: 40px; gap: 1px; }
.dev-metrics-col {
  position: relative;
  flex: 1 1 0;
  max-width: 28px;
  display: flex;
  align-items: flex-end;
  height: 100%;
  min-width: 2px;
}
.dev-metrics-col-bar {
  width: 100%;
  min-height: 2px;
  background: var(--accentFill, var(--accent));
  border-radius: 2px 2px 0 0;
  transition: height 0.3s ease;
}

/* Styled tooltip on hover, matching .insights-clock-cell's data-tooltip pattern. */
.dev-metrics-col::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.35rem 0.6rem;
  font-size: 0.75rem;
  white-space: nowrap;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s ease;
}
.dev-metrics-col:hover::after {
  opacity: 1;
}
.dev-metrics-col-start::after {
  left: 0;
  transform: none;
}
.dev-metrics-col-end::after {
  left: auto;
  right: 0;
  transform: none;
}
.dev-metrics-colchart-labels {
  display: flex;
  justify-content: center;
  gap: 2px;
  margin-top: 0.4rem;
}
.dev-metrics-col-label {
  flex: 1 1 0;
  max-width: 28px;
  min-width: 2px;
  font-family: var(--mono);
  font-size: 0.65rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: visible;
  text-align: center;
}

/* ── Server Metrics dashboard ──────────────────────────────────────────── */
.dev-srv-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1rem;
}
.dev-srv-card {
  position: relative;
  overflow: hidden; /* a mini spark chart with many points (24h = 288 cols at min-width 2px) needs more width than this card has — clip it here rather than let it bleed across the page */
  flex: 1 1 200px;
  min-width: 180px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1rem;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.dev-srv-card:hover { border-color: var(--accent); }
.dev-srv-card--expanded { border-color: var(--accent); }
.dev-srv-card--warn  { border-color: var(--warning, #d4a017); }
.dev-srv-card--alarm { border-color: var(--danger); }
.dev-srv-card--na     { cursor: default; opacity: 0.6; }
.dev-srv-card--na:hover { border-color: var(--border); }
.dev-srv-card-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.dev-srv-card-chip {
  font-family: var(--mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  border: 1px solid var(--border);
  color: var(--muted);
}
.dev-srv-card-chip--warn  { border-color: var(--warning, #d4a017); color: var(--warning, #d4a017); }
.dev-srv-card-chip--alarm { border-color: var(--danger); color: var(--danger); }
.dev-srv-card-value {
  font-family: var(--sans);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0.15rem 0 0.5rem;
}
.dev-srv-card-spark { height: 40px; }
.dev-srv-card-status {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--muted);
}

.dev-srv-detail-panel {
  margin-top: 1rem;
  padding: 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}
/* A non-mini column chart's columns refuse to shrink below their 2px
   min-width (see .dev-metrics-col above) — with 288+ columns (e.g. the 24h
   range), that floor adds up to more width than a phone viewport has, so
   without a scroll container of its own the chart bled past the page edge
   instead of clipping or scrolling. These ids wrap both the bar chart and
   its label row (rendered as siblings by renderTimeChart), so they scroll
   together as one unit rather than drifting out of alignment. */
#dev-srv-detail-chart, #dev-srv-phase-chart {
  overflow-x: auto;
}
#dev-srv-phases {
  overflow-x: auto;
}
.dev-srv-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.dev-srv-detail-stats {
  display: flex;
  gap: 0.9rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}
.dev-srv-detail-fields {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}

/* Dashed threshold line, matching whichever alarm threshold the card mirrors
   (see thresholds in the GET /api/dev/server-metrics response). */
.dev-srv-threshold {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px dashed var(--danger);
  opacity: 0.6;
}

/* The shared hover cursor — a vertical guide drawn at the same fractional X
   across every chart wrapper carrying [data-cursor-chart], so hovering any
   one chart shows "this is the same moment" on all the others at once. */
.dev-srv-cursor {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--accent);
  opacity: 0.5;
  pointer-events: none;
}

.dev-srv-phase-row { cursor: pointer; }
.dev-srv-phase-row:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.dev-srv-phase-row.active { background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* A process-restart marker on a process-sourced chart (an uptime reset
   detected inside the range) — without this, a real restart's memory drop
   reads as an unexplained cliff rather than what it actually was. */
.dev-srv-restart {
  position: absolute;
  top: 0;
  bottom: -0.4rem;
  width: 2px;
  background: var(--muted);
  opacity: 0.5;
}

.insights-bar-row-clickable {
  cursor: pointer;
  border-radius: 6px;
  margin: -0.2rem -0.4rem;
  padding: 0.2rem 0.4rem;
  transition: background 0.15s ease;
}
.insights-bar-row-clickable:hover,
.insights-bar-row-clickable:focus-visible {
  background: var(--surface2);
  outline: none;
}
.insights-bar-row-clickable .insights-bar-label {
  color: var(--text);
  font-weight: 500;
}
.insights-year-months {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0 0 0 1rem;
  margin-top: 0.45rem;
}
.insights-year-months:empty { display: none; }
/* Top Genres reuses this exact year→month drill-down structure (real per-row
   grid boxes, no display:contents trick — that trick is what .insights-bar-grid
   uses for Sources/the old flat Genres row, and fighting it to also support
   clickable/nested rows caused both a lost hover highlight (contents rows have
   no box to paint a background onto) and stray empty drill-down rows (a
   display override with equal specificity to `:empty { display: none }` won
   by source order). Reusing .insights-bar-list's real-box rows sidesteps both;
   this just widens the shared label column so a genre/artist name isn't
   truncated at the default 4.5rem sized for "Jan"/"31st". */
#tile-genres .insights-bar-row { grid-template-columns: 9rem 1fr auto; }
/* Artist rows (nested under a genre) share ONE label column across the whole
   drill-down instead of each row sizing independently — otherwise a short
   name like "SWMRS" leaves its own row way more bar-track width than a row
   with a long name, so the grey tracks don't line up between rows. subgrid
   is what makes that possible while keeping each row a real box (so hover/
   padding still work, unlike the display:contents trick used elsewhere in
   this file): the container defines the 3 shared tracks — a fit-content(40%)
   label column sized to the WIDEST artist name present, capped at 40% — and
   each row subgrids into them instead of computing its own. */
#tile-genres .insights-year-months {
  display: grid;
  grid-template-columns: fit-content(40%) 1fr auto;
  row-gap: 0.45rem;
  column-gap: 0.75rem;
}
#tile-genres .insights-year-months:empty { display: none; }
#tile-genres .insights-year-months .insights-bar-row {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
}
/* The "View all →" link at the foot of a genre's artist drill-down (reuses
   .tile-view-all's link styling — see home.js's tile links). Spans all 3
   subgrid columns like the rows above it, rather than being squeezed into
   just the label column. */
.insights-genre-viewall-row {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  margin-top: 0.3rem;
}
.insights-bar-row-month .insights-bar-label { font-size: 0.75rem; }
.insights-bar-row-month .chart-bar-fill { opacity: 0.25; }
.insights-bar-row-day .insights-bar-label { font-size: 0.7rem; }
.insights-bar-row-day .chart-bar-fill { opacity: 0.18; }
.chart-loading-inline {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.75rem 0;
}
.chart-loading-inline .spinner { width: 18px; height: 18px; }

/* ── Art thumbnails ───────────────────────────────────*/
.art-thumb {
  position: relative;
  background: var(--surface2);
  border-radius: 7px;
  overflow: hidden;
  flex-shrink: 0;
}
.track-row .art-thumb { width: 44px; height: 44px; }
.chart-row .art-thumb { width: 52px; height: 52px; }

.art-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 7px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.art-img.art-loaded { opacity: 1; }

@keyframes art-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.art-thumb.art-loading {
  background: linear-gradient(90deg, var(--surface2) 25%, var(--border) 50%, var(--surface2) 75%);
  background-size: 200% 100%;
  animation: art-shimmer 1.4s ease-in-out infinite;
}

.art-thumb.art-no-art::after {
  content: "?";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.875rem;
  font-family: var(--sans);
  color: var(--muted);
  pointer-events: none;
}

/* ── Upload ───────────────────────────────────────────*/
/* .upload-area is the shared box for every upload-flow panel (drop zone,
   column-mapping preview, scan progress, confirm screen, …) — most of them
   want the mockup's solid card border; only the empty drop zone itself
   wants the dashed treatment, added via .upload-area--drop (toggled in
   showOnly(), public/js/utils.js) so the other panels are unaffected. */
.upload-area {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  margin-bottom: 2rem;
}
.upload-area--drop {
  border-style: dashed;
  border-width: 1.5px;
}

.upload-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2.4rem 2rem;
  gap: 0.6rem;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s;
}
.upload-inner:hover, .upload-inner.drag-over {
  background: var(--surface2);
}

.upload-icon {
  width: 46px;
  height: 46px;
  border-radius: 12px;
  background: var(--chip);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.3rem;
}

.upload-title { font-family: var(--sans); font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em; }
.upload-sub { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); }
.upload-format {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: center;
  margin-top: 0.4rem;
}
.upload-format-chip {
  font-family: var(--mono);
  font-size: 0.62rem;
  color: var(--muted);
  background: var(--chip);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 0.3rem 0.55rem;
}

.upload-progress {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 3rem;
  color: var(--muted);
  font-size: 0.875rem;
}

.spinner {
  width: 28px; height: 28px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.chart-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4rem 0;
}

.progress-bar-wrap {
  width: 100%;
  max-width: 320px;
  height: 4px;
  background: var(--surface2);
  border-radius: 2px;
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  /* Same rationale as .chart-bar-fill — see --accentFill in theme.js. */
  background: var(--accentFill, var(--accent, #e87d3e));
  border-radius: 2px;
  width: 0%;
  transition: width 0.3s ease;
}

.upload-result {
  padding: 1.5rem;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.85rem;
}
.upload-result.success { color: #4caf7d; }
.upload-result.error   { color: var(--danger); }
.upload-result-note {
  margin-top: 0.75rem;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.5;
}

.hidden { display: none !important; }

.link-btn {
  background: none; border: none; cursor: pointer;
  color: var(--accent); font-family: inherit; font-size: inherit;
  text-decoration: underline; text-underline-offset: 2px;
}

.export-guide-link-row {
  text-align: center;
  font-size: 0.82rem;
  margin: 2rem 0;
}

/* ── Danger zone ──────────────────────────────────────*/
.btn-export {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  padding: 0.4rem 0.9rem;
  border-radius: 18px;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.15s;
}
.btn-export:hover { color: var(--text); border-color: var(--muted); }

/* ── Upload preview ───────────────────────────────────────*/
.upload-preview {
  padding: 1.5rem;
}

.preview-header {
  margin-bottom: 1rem;
}

.preview-title {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--text);
  margin-bottom: 0.25rem;
}

.preview-sub {
  font-size: 0.77rem;
  color: var(--muted);
}

.preview-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 0.75rem;
}

.auto-preview-scroll {
  max-height: 200px;
  overflow-y: auto;
}

.preview-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.77rem;
}

.preview-table thead th {
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
  white-space: nowrap;
}

.preview-table tbody td {
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  white-space: nowrap;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.preview-table tbody tr:last-child td { border-bottom: none; }

.col-select {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.25rem 0.4rem;
  border-radius: 4px;
  cursor: pointer;
  width: 100%;
  min-width: 80px;
}

.col-select:focus { outline: none; border-color: var(--accent); }

.preview-error {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--danger);
  margin-bottom: 0.75rem;
  min-height: 1rem;
}

.preview-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
}

.btn-preview-cancel {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.77rem;
  padding: 0.45rem 1rem;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.15s;
}

.btn-preview-cancel:hover { color: var(--text); border-color: var(--muted); }

.btn-preview-import {
  background: var(--accentFill, var(--accent));
  border: 1px solid var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
  font-family: var(--mono);
  font-size: 0.77rem;
  padding: 0.45rem 1.25rem;
  border-radius: 22px;
  cursor: pointer;
  transition: opacity 0.15s;
}

.btn-preview-import:hover:not(:disabled) { opacity: 0.85; }
.btn-preview-import:disabled { opacity: 0.4; cursor: not-allowed; }

.btn-preview-import--danger {
  background: var(--danger);
  border-color: var(--danger);
}
.btn-preview-import--danger:hover:not(:disabled) { opacity: 0.85; }

/* ── Format badge ─────────────────────────────────────*/
.format-badge {
  font-family: var(--mono);
  font-size: 0.7rem;
  background: var(--surface2);
  color: var(--accent2);
  padding: 0.15rem 0.45rem;
  border-radius: 3px;
  white-space: nowrap;
}

/* ── Confirm stats (duplicate check result) ───────────*/
.confirm-stats {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.6rem;
  padding: 0.75rem 0 1rem;
}
@media (max-width: 700px) {
  .confirm-stats { grid-template-columns: repeat(2, 1fr); }
}

.confirm-stat {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  align-items: center;
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 0.9rem 1rem;
}

/* Data, not chrome — Space Grotesk per docs/design-language.md, same fix as
   .home-stat-n/.mbid-stat-n. Per-variant colors match the mockup exactly:
   found/in-library/in-file stay neutral, new is accent, deleted is berry. */
.confirm-n {
  font-family: var(--sans);
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
}

.confirm-l {
  font-size: 0.72rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.confirm-stat-new .confirm-n     { color: var(--accent); }
.confirm-stat-deleted .confirm-n { color: var(--berry); }

.confirm-enrich {
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 0.75rem;
}

.confirm-preview-scroll {
  max-height: 200px;
  overflow-y: auto;
  margin-bottom: 0.75rem;
}

/* ── Duplicate review section ─────────────────────────*/
.dupes-details {
  margin: 0.75rem 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}

.dupes-summary {
  list-style: none;
  cursor: pointer;
  padding: 0.55rem 0.85rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
  background: var(--surface2);
  user-select: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.dupes-summary::-webkit-details-marker { display: none; }
.dupes-summary::before {
  content: "▶";
  font-size: 0.6rem;
  transition: transform 0.15s;
}
.dupes-details[open] > .dupes-summary::before { transform: rotate(90deg); }
.dupes-summary:hover { color: var(--text); }

.dupes-count-badge {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0.05rem 0.35rem;
  font-size: 0.7rem;
}

.dupes-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border);
}

.dupes-tab {
  background: none;
  border: none;
  border-right: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.4rem 0.85rem;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.12s, background 0.12s;
}
.dupes-tab:hover { color: var(--text); background: var(--surface2); }
.dupes-tab.active { color: var(--text); background: var(--surface); }
a.dupes-tab { text-decoration: none; }

.dupes-scroll {
  max-height: 320px;
  overflow-y: auto;
}

.dupes-scroll .track-list {
  border-radius: 0;
  border-left: none;
  border-right: none;
  border-top: none;
}

/* These track-rows have no art thumbnail, so override to 2-column layout */
.dupes-scroll .track-row,
.confirm-preview-scroll .track-row {
  grid-template-columns: 1fr auto;
}

.dupes-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
  table-layout: fixed;
}

.dupes-table th:nth-child(1) { width: 2rem; }   /* checkbox */
.dupes-table th:nth-child(3) { width: 2rem; }   /* ↔ sep */

.dupes-table thead th {
  padding: 0.35rem 0.65rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: left;
}

.dupes-table tbody td {
  padding: 0.45rem 0.65rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.dupes-table tbody tr:last-child td { border-bottom: none; }
.dupes-table tbody tr:hover td { background: var(--surface2); }

.dupe-col-check { width: 1.75rem; text-align: center; }

.dupe-track-name {
  display: block;
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dupe-meta {
  display: block;
  color: var(--muted);
  font-size: 0.72rem;
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dupe-sep {
  width: 1.5rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.8rem;
  vertical-align: middle;
}

.dupe-existing .dupe-track-name { color: var(--muted); }

.dupes-more {
  text-align: center;
  color: var(--muted);
  font-size: 0.72rem;
  font-family: var(--mono);
  padding: 0.5rem;
}

.dupes-footer {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.5rem 0.75rem;
  border-top: 1px solid var(--border);
  background: var(--surface2);
  font-size: 0.75rem;
}

.dupes-check-all-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
}
.dupes-check-all-label:hover { color: var(--text); }

.dupes-selected-count {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: #4caf7d;
}

/* ── Modal ─────────────────────────────────────────────*/
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
}

/* Confirm dialog uses a native <dialog> so it joins the browser top layer and
   always paints above any other open dialog (e.g. the Recently Matched modal).
   It fills the viewport and dims via its own background so a click on the empty
   area still cancels — matching the old .modal-overlay behaviour. */
.confirm-dialog,
.kbd-modal {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  border: none;
  padding: 22px;
  background: rgba(8, 7, 10, 0.5);
}
.confirm-dialog[open],
.kbd-modal[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}
.confirm-dialog::backdrop,
.kbd-modal::backdrop { background: transparent; }

.kbd-modal-inner {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 14px;
  width: 468px;
  max-width: 100%;
  max-height: 100%;
  overflow-y: auto;
  padding: 22px 24px;
}
.kbd-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}
.kbd-modal-head h3 {
  font-family: var(--sans); font-size: 1.2rem; font-weight: 700;
  letter-spacing: -0.02em;
}
.kbd-modal-groups {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 28px;
}
.kbd-group-title {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.kbd-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  font-family: var(--sans); font-size: 0.82rem;
}
.kbd-keys { display: flex; gap: 4px; }
.kbd-key {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  background: var(--head);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 8px;
  color: var(--text);
  min-width: 24px;
  text-align: center;
  display: inline-block;
  box-shadow: 0 1px 0 var(--border);
}
.kbd-modal-foot {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--hair);
  font-family: var(--mono); font-size: 0.68rem;
  color: var(--faint);
}
@media (max-width: 600px) {
  .kbd-modal-groups { grid-template-columns: 1fr; }
}

/* Shared mobile bottom-sheet treatment — every dialog built on .kbd-modal's
   or .confirm-dialog's overlay mechanics (keyboard shortcuts, Pro-upgrade,
   Export & Share, the destructive confirm dialog) slides in from the bottom
   edge-to-edge on narrow viewports instead of sitting as a centered
   desktop-style box. */
@media (max-width: 600px) {
  .kbd-modal[open],
  .confirm-dialog[open] { align-items: flex-end; padding: 0; }
  .kbd-modal-inner,
  .confirm-dialog .modal {
    width: 100%;
    max-width: 100%;
    border-radius: 16px 16px 0 0;
    max-height: 85vh;
    padding: 18px 18px calc(18px + env(safe-area-inset-bottom, 0px));
  }
}

/* ── Pro-upgrade modal (reuses .kbd-modal's overlay/dialog mechanics) ──────── */
/* Desktop-only fixed width — scoped above the mobile breakpoint so it can't
   win (equal specificity, later in file) over the mobile bottom-sheet's
   width:100% and re-break full-width edge-to-edge on narrow viewports. */
@media (min-width: 601px) {
  .pro-modal-inner { width: 420px; }
}
.pro-modal-features {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.pro-modal-features li {
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text);
  padding-left: 1.3rem;
  position: relative;
}
.pro-modal-features li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--accent);
  font-weight: 700;
}
.pro-modal-plans {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
}
.pro-modal-plan {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1rem 0.9rem 0.9rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.pro-modal-plan--best { border-color: var(--accent); border-width: 2px; }
.pro-modal-plan-ribbon {
  position: absolute;
  top: -0.6rem;
  left: 0.75rem;
  font-family: var(--mono);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--accentFillText, var(--navText, #fff));
  background: var(--accentFill, var(--accent));
  border-radius: 12px;
  padding: 0.15rem 0.5rem;
  white-space: nowrap;
}
.pro-modal-plan-head { display: flex; flex-direction: column; gap: 0.15rem; }
.pro-modal-plan-name { font-weight: 700; font-size: 0.85rem; }
/* Price is data, not chrome — Space Grotesk per docs/design-language.md,
   not the mono "machine voice" register. */
.pro-modal-plan-price { font-family: var(--sans); font-size: 1.3rem; font-weight: 700; }
.pro-modal-plan-period { font-size: 0.68rem; font-weight: 400; color: var(--muted); }
.pro-modal-plan-btn { width: 100%; text-align: center; }
.pro-modal-error { font-size: 0.78rem; color: var(--danger); margin: 0.75rem 0 0; }
.pro-modal-more-link { color: var(--accent); text-decoration: none; }
.pro-modal-more-link:hover { text-decoration: underline; }
@media (max-width: 500px) {
  .pro-modal-plans { grid-template-columns: 1fr; }
}

/* ── Export & Share modal ─────────────────────────────────────────────────── */
/* Desktop-only, same reasoning as .pro-modal-inner above. */
@media (min-width: 601px) {
  .export-share-modal-inner { width: 440px; }
}
.es-section { margin-bottom: 1.5rem; }
.es-section:last-child { margin-bottom: 0; }
.es-section-label {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.6rem;
}
.es-share-row { display: flex; gap: 0.5rem; align-items: center; }
.es-visibility-row { padding: 0.75rem 0 0; }
.es-hint { font-size: 0.78rem; color: var(--muted); line-height: 1.4; margin: 0.4rem 0 0; }

/* ── Listening clock: expand-in-place tile ───────────────────────────────────
   Tapping the tile expands its *own* grid cells to a larger, scrollable
   fixed-position overlay via CSS classes alone — no cloned/duplicate DOM and
   no <dialog>. An earlier version rebuilt a second 168-cell grid inside a
   dialog on open; that was cheap on desktop but measurably laggy on real
   mobile hardware (desktop "mobile view" emulation never showed it, since
   it isn't CPU-bound there). Reusing the same nodes avoids that entirely. */
.insights-clock-tile-clickable {
  cursor: pointer;
  touch-action: manipulation;
  border-radius: 10px;
  transition: background 0.15s ease;
}
.insights-clock-tile-clickable:hover,
.insights-clock-tile-clickable:focus-visible {
  background: var(--surface2);
  outline: none;
}

.clock-expand-close,
.clock-expand-daylabels,
.clock-expand-hourlabels,
.clock-expand-readout {
  display: none;
}
.clock-expand-body,
.clock-expand-scroll {
  display: contents;
}

.tile-insights-clock.clock-expanded {
  position: fixed;
  inset: 0;
  z-index: 1001;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: 0;
  padding: 20px 20px calc(20px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  cursor: default;
}
.tile-insights-clock.clock-expanded .clock-expand-close {
  display: flex;
  margin-left: auto;
  margin-bottom: 14px;
}
.tile-insights-clock.clock-expanded .clock-expand-body {
  display: flex;
  gap: 6px;
}
.tile-insights-clock.clock-expanded .clock-expand-scroll {
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  flex: 1;
}
.tile-insights-clock.clock-expanded .clock-expand-daylabels {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 0 0 auto;
  padding-top: 24px;
}
.tile-insights-clock.clock-expanded .clock-expand-daylabels span {
  height: 30px;
  display: flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.65rem;
  color: var(--muted);
}
.tile-insights-clock.clock-expanded .clock-expand-hourlabels {
  display: grid;
  grid-template-columns: repeat(24, 30px);
  gap: 2px;
  margin-bottom: 2px;
  width: max-content;
}
.tile-insights-clock.clock-expanded .clock-expand-hourlabels span {
  font-family: var(--mono);
  font-size: 0.6rem;
  color: var(--muted);
  text-align: center;
}
.tile-insights-clock.clock-expanded .insights-clock-grid {
  grid-template-columns: repeat(24, 30px);
  grid-template-rows: repeat(7, 30px);
  aspect-ratio: unset;
  width: max-content;
}
.tile-insights-clock.clock-expanded .clock-expand-readout {
  display: block;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--hair);
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}

.clock-expand-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(8, 7, 10, 0.5);
}
.clock-expand-backdrop.visible { display: block; }
body.clock-expand-open { overflow: hidden; }

.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.5rem;
  max-width: 380px;
  width: 90%;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}

.modal-icon {
  width: 40px;
  height: 40px;
  border-radius: 11px;
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  color: var(--danger);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.9rem;
}
.modal-icon.hidden { display: none; }

.modal-title {
  font-family: var(--sans);
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 0.5rem;
}
.modal-title.hidden { display: none; }

.modal-message {
  font-size: 0.875rem;
  line-height: 1.5;
  margin-bottom: 1.25rem;
  color: var(--text);
}

.modal-loading {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  margin-right: 0.5rem;
}
.modal-loading .spinner { width: 16px; height: 16px; }

.modal-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
}

.btn-modal-cancel {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.77rem;
  padding: 0.45rem 1rem;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.15s;
}

.btn-modal-cancel:hover { color: var(--text); border-color: var(--muted); }

.btn-modal-confirm {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.77rem;
  padding: 0.45rem 1.25rem;
  border-radius: 20px;
  cursor: pointer;
  transition: all 0.15s;
}

/* Destructive confirms (Clear all plays, Delete all, etc.) must read as
   dangerous, not brand-colored — was mistakenly using --accent, which put a
   "Clear all plays" button in the same purple as an ordinary confirm. */
.btn-modal-confirm.btn-modal-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

.btn-modal-confirm:hover { opacity: 0.85; }

.modal-source-picker { margin-bottom: 1.25rem; }
.modal-source-picker.hidden { display: none; }
.modal-source-row {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.7rem 0.75rem;
  border-radius: 10px;
  border: 1.5px solid var(--border);
  margin-bottom: 0.5rem;
  cursor: pointer;
  background: none;
  width: 100%;
  text-align: left;
  color: var(--text);
  font-family: var(--sans);
}
.modal-source-row:last-child { margin-bottom: 0; }
.modal-source-row.selected { border-color: var(--danger); }
.modal-source-radio {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1.5px solid var(--mutedBorder);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.modal-source-row.selected .modal-source-radio { border-color: var(--danger); }
.modal-source-radio-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  display: none;
}
.modal-source-row.selected .modal-source-radio-dot { display: block; }
.modal-source-name { font-size: 0.85rem; font-weight: 700; }
.modal-source-count { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); white-space: nowrap; }

/* ── Global banner (toasts + failure/decision cards) ─────────────────────── */
.stick-banner {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 210;            /* above header (50), below confirm modal (1100) */
  display: flex;
  flex-direction: column-reverse; /* newest on top */
  gap: 0.5rem;
  max-width: min(360px, calc(100vw - 32px));
  pointer-events: none;   /* never blocks the page; cards re-enable below */
}
.stick-banner-card {
  pointer-events: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.7rem 1.9rem 0.7rem 0.85rem;
  box-shadow: 0 8px 24px rgba(0,0,0,0.28);
  position: relative;
  font-size: 0.8rem;
  color: var(--text);
  animation: stick-banner-in 0.22s ease;
}
.stick-banner-title {
  font-weight: 600;
  margin-bottom: 0.2rem;
  line-height: 1.35;
}
.stick-banner-text {
  color: var(--muted);
  line-height: 1.4;
  word-break: break-word;
}
.stick-banner-card .stick-banner-title + .stick-banner-text { color: var(--muted); }
.stick-banner-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.6rem;
}
.stick-banner-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.3rem 0.7rem;
  border-radius: 16px;
  cursor: pointer;
  transition: all 0.15s;
}
.stick-banner-btn:hover { color: var(--text); border-color: var(--muted); }
.stick-banner-btn.primary {
  background: var(--accentFill, var(--accent));
  border-color: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
}
.stick-banner-btn.primary:hover { opacity: 0.85; color: var(--accentFillText, var(--navText)); }
.stick-banner-close {
  position: absolute;
  top: 0.35rem;
  right: 0.45rem;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.15rem;
}
.stick-banner-close:hover { color: var(--text); }
@keyframes stick-banner-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .stick-banner-card { animation: none; }
}

/* ── Cookie notice (AUDIT.md NEW-1) — plain, non-blocking, ad-eligible pages only */
.cookie-notice {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 220;            /* above the toast stack (210), below confirm modal (1100) */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem 1.5rem;
  padding: 0.85rem 1.25rem;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 16px rgba(0,0,0,0.16);
}
.cookie-notice-text {
  margin: 0;
  color: var(--text);
  font-size: 0.85rem;
  line-height: 1.4;
  max-width: 60ch;
}
.cookie-notice-text a { color: var(--accent); }
.cookie-notice-btn {
  background: var(--accentFill, var(--accent));
  border: 1px solid var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.4rem 1rem;
  border-radius: 16px;
  cursor: pointer;
  transition: opacity 0.15s;
  flex-shrink: 0;
}
.cookie-notice-btn:hover { opacity: 0.85; }

/* ── Duplicate review overlay ────────────────────────*/
.dedup-modal {
  max-width: 620px;
  display: flex;
  flex-direction: column;
  max-height: 80vh;
}

.dedup-scroll {
  overflow-y: auto;
  flex: 1;
  margin: 0.75rem 0;
  border: 1px solid var(--border);
  border-radius: 6px;
}

.dedup-group {
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.25rem;
  margin-bottom: 0.25rem;
}
.dedup-group:last-child { border-bottom: none; margin-bottom: 0; }

.dedup-group-mbid {
  font-family: var(--mono);
  font-size: 0.65rem;
  color: var(--muted);
  padding: 0.4rem 0.75rem 0.2rem;
  word-break: break-all;
}

.dedup-row {
  grid-template-columns: 40px 1fr auto auto;
}

.dedup-remove {
  opacity: 0.45;
  text-decoration: line-through;
  text-decoration-color: var(--accent);
}

.dedup-tag {
  font-family: var(--mono);
  font-size: 0.65rem;
  padding: 0.15rem 0.45rem;
  border-radius: 3px;
  align-self: center;
  white-space: nowrap;
}
.dedup-row:not(.dedup-remove) .dedup-tag {
  background: #0d2d0d;
  color: #4caf50;
  border: 1px solid #1a4d1a;
}
.dedup-remove .dedup-tag {
  background: #2d0d0d;
  color: var(--accent);
  border: 1px solid #4d1a1a;
}
[data-theme="light"] .dedup-row:not(.dedup-remove) .dedup-tag {
  background: #e8f5e9;
  color: #2e7d32;
  border: 1px solid #a5d6a7;
}
[data-theme="light"] .dedup-remove .dedup-tag {
  background: #ffebee;
  color: var(--accent);
  border: 1px solid #ffcdd2;
}

/* Source badges always visible inside the dedup review overlay */
.dedup-scroll .source-badge { opacity: 1; }

.dedup-progress {
  position: sticky;
  top: 0;
  background: var(--bg);
  padding-bottom: 0.75rem;
  margin-bottom: 0.25rem;
  z-index: 1;
}
.dedup-progress-label {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 0 0 0.5rem;
}
.dedup-deleting .dedup-scroll {
  opacity: 0.25;
  pointer-events: none;
}
.dedup-deleting .modal-actions button {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}
.btn-scan-cancel {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.82rem;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  text-decoration: underline;
}
.btn-scan-cancel:hover { color: var(--text); }

/* ── Version footer ──────────────────────────────────*/
.version-footer {
  text-align: center;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--faint);
  padding: 1rem 0 2rem;
  flex-shrink: 0;
}
.version-footer a { color: inherit; text-decoration: underline; }
.footer-kbd-link {
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; color: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.footer-kbd-wrap { white-space: nowrap; }
@media (max-width: 600px) {
  .footer-kbd-wrap { display: none; }
}

/* ── MusicBrainz tab ─────────────────────────────────*/
.mbid-status-bar {
  display: flex;
  gap: 1.5rem;
  justify-content: center;
  margin-bottom: 1.5rem;
  padding: 1rem 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  flex-wrap: wrap;
}

.mbid-stat { display: flex; flex-direction: column; }
/* Data, not chrome — Space Grotesk per docs/design-language.md, same fix as
   the Home page's stat numbers (.home-stat-n). */
.mbid-stat-n {
  font-family: var(--sans);
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
}
.mbid-stat-l {
  font-size: 0.7rem;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 2px;
}

.mbid-progress {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0;
  color: var(--muted);
  font-size: 0.82rem;
}

.mbid-activity {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  padding: 0.4rem 0;
  margin-bottom: 1rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  /* Fixed height = 5 rows × ~1.6rem each + 0.8rem padding. Prevents
     layout shift when the activity panel repaints between polls. */
  height: 9rem;
  overflow: hidden;
}
.mbid-activity-row {
  display: grid;
  grid-template-columns: 5rem 1fr auto;
  gap: 0.6rem;
  padding: 0.25rem 0.75rem;
  align-items: center;
  color: var(--muted);
}
.mbid-activity-row.mbid-activity-current {
  color: var(--text);
}
.mbid-activity-kind {
  text-transform: uppercase;
  font-size: 0.62rem;
  color: var(--muted);
  letter-spacing: 0.05em;
}
.mbid-activity-track { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbid-activity-source {
  display: inline-block;
  font-size: 0.62rem;
  color: var(--muted);
  opacity: 0.8;
  margin-left: 0.4rem;
  font-style: italic;
}
.mbid-activity-status {
  font-size: 0.65rem;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  white-space: nowrap;
}
.mbid-activity-now       { background: var(--accent2); color: var(--bg); }
.mbid-activity-matched      { background: rgba(80, 200, 120, 0.15); color: rgb(80, 200, 120); }
.mbid-activity-cached       { background: rgba(80, 200, 120, 0.15); color: rgb(80, 200, 120); }
.mbid-activity-near_miss    { background: rgba(230, 180, 60, 0.18); color: rgb(230, 180, 60); }
.mbid-activity-not_found    { background: rgba(220, 90, 90, 0.18);  color: rgb(220, 90, 90); }
.mbid-activity-cascade-hit  { background: rgba(80, 200, 120, 0.15); color: rgb(80, 200, 120); }
.mbid-activity-cascade-miss { background: rgba(150, 150, 150, 0.15); color: var(--muted); }

.mbid-unmatched-hint {
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 1rem;
  line-height: 1.5;
}

.mbid-dedup-section {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}
.mbid-dedup-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.5rem;
}
.mbid-dedup-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

/* Needs-attention toolbar: tab strip + filter box + per-tab bulk-action button group */
.na-toolbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-bottom: 1px solid var(--border);
  margin: 0.5rem 0 0;
  padding-bottom: 0.65rem;
}
.na-tab-strip { display: flex; gap: 6px; }
.na-search-input {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.78rem;
  padding: 0.35rem 0.7rem;
  border-radius: 4px;
  width: 300px;
  min-width: 200px;
  max-width: 340px;
}
.na-search-input:focus { outline: none; border-color: var(--muted); }
.na-actions {
  display: flex;
  gap: 0.5rem;
  padding: 0.2rem 0;
  margin-left: auto;
}
.na-actions > .btn-preview-cancel {
  font-size: 0.72rem;
  padding: 0.3rem 0.75rem;
}

.mbid-table-wrap {
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow-x: auto;
  margin-bottom: 0.75rem;
}

.mbid-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
  table-layout: fixed;
}

.mbid-table thead th {
  padding: 0.45rem 0.75rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}

.mbid-table tbody td {
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.mbid-table tbody tr:last-child td { border-bottom: none; }
.mbid-table tbody tr:hover td { background: var(--surface); }

/* Needs-attention: 7 cols — Source, Artist, Track, Album, Plays, MBID input, Actions.
   The MBID column holds a paste-in identifier, not user-readable text — kept
   just wide enough for the input to be usable, with the freed width going to
   Track/Album so the actual song/album names have room to breathe. */
.pa-table thead th:nth-child(1),
.pa-table tbody td:nth-child(1) { width: 8%; white-space: nowrap; }
.pa-table thead th:nth-child(2),
.pa-table tbody td:nth-child(2) { width: 16%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-table thead th:nth-child(3),
.pa-table tbody td:nth-child(3) { width: 27%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-table thead th:nth-child(4),
.pa-table tbody td:nth-child(4) { width: 20%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-table thead th:nth-child(5),
.pa-table tbody td:nth-child(5) { width: 5%; }
.pa-table thead th:nth-child(6),
.pa-table tbody td:nth-child(6) { width: 10%; }
.pa-table thead th:nth-child(7),
.pa-table tbody td:nth-child(7) { width: 14%; white-space: nowrap; }

/* Paused tab: 6 cols — Source, Artist, Track, Album, Plays, Actions */
.pa-paused-table thead th:nth-child(1),
.pa-paused-table tbody td:nth-child(1) { width: 8%; }
.pa-paused-table thead th:nth-child(2),
.pa-paused-table tbody td:nth-child(2) { width: 18%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-paused-table thead th:nth-child(3),
.pa-paused-table tbody td:nth-child(3) { width: 26%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-paused-table thead th:nth-child(4),
.pa-paused-table tbody td:nth-child(4) { width: 26%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pa-paused-table thead th:nth-child(5),
.pa-paused-table tbody td:nth-child(5) { width: 7%; }
.pa-paused-table thead th:nth-child(6),
.pa-paused-table tbody td:nth-child(6) { width: 15%; white-space: nowrap; }

/* Review: 6 cols — Artist, Yours, MusicBrainz, Score, Plays, Actions
   (Actions holds up to 4 buttons — Use MB title / Keep as-is / Context / Fix —
   sized to the buttons' actual content rather than left with empty space.
   Artist/Yours/MusicBrainz wrap instead of truncating — the full title matters
   here for telling a near-miss apart from the real recording.) */
.review-table thead th:nth-child(1),
.review-table tbody td:nth-child(1) { width: 13%; overflow-wrap: break-word; white-space: normal; }
.review-table thead th:nth-child(2),
.review-table tbody td:nth-child(2) { width: 26%; overflow-wrap: break-word; white-space: normal; }
.review-table thead th:nth-child(3),
.review-table tbody td:nth-child(3) { width: 27%; overflow-wrap: break-word; white-space: normal; }
.review-table thead th:nth-child(4),
.review-table tbody td:nth-child(4) { width: 6%; }
.review-table thead th:nth-child(5),
.review-table tbody td:nth-child(5) { width: 6%; }
.review-table thead th:nth-child(6),
.review-table tbody td:nth-child(6) { width: 22%; }

/* Cleanup artist: 5 cols — Current spelling, Merge into, Plays (variant), Total plays, Actions */
.cleanup-table-artist thead th:nth-child(1),
.cleanup-table-artist tbody td:nth-child(1) { width: 28%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table-artist thead th:nth-child(2),
.cleanup-table-artist tbody td:nth-child(2) { width: 28%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table-artist thead th:nth-child(3),
.cleanup-table-artist tbody td:nth-child(3) { width: 10%; text-align: right; }
.cleanup-table-artist thead th:nth-child(4),
.cleanup-table-artist tbody td:nth-child(4) { width: 10%; text-align: right; }
.cleanup-table-artist thead th:nth-child(5),
.cleanup-table-artist tbody td:nth-child(5) { width: 24%; }

/* Cleanup track: 7 cols — Type, Artist, Current, Suggested, Score, Plays, Actions */
.cleanup-table thead th:nth-child(1),
.cleanup-table tbody td:nth-child(1) { width: 7%; white-space: nowrap; }
.cleanup-table thead th:nth-child(2),
.cleanup-table tbody td:nth-child(2) { width: 14%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table thead th:nth-child(3),
.cleanup-table tbody td:nth-child(3) { width: 26%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table thead th:nth-child(4),
.cleanup-table tbody td:nth-child(4) { width: 26%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table thead th:nth-child(5),
.cleanup-table tbody td:nth-child(5) { width: 6%; text-align: right; }
.cleanup-table thead th:nth-child(6),
.cleanup-table tbody td:nth-child(6) { width: 6%; text-align: right; }
.cleanup-table thead th:nth-child(7),
.cleanup-table tbody td:nth-child(7) { width: 15%; }

/* Cleanup album: 5 cols — Artist, Current, Suggested, Plays, Actions */
.cleanup-table-album thead th:nth-child(1),
.cleanup-table-album tbody td:nth-child(1) { width: 18%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table-album thead th:nth-child(2),
.cleanup-table-album tbody td:nth-child(2) { width: 30%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table-album thead th:nth-child(3),
.cleanup-table-album tbody td:nth-child(3) { width: 30%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cleanup-table-album thead th:nth-child(4),
.cleanup-table-album tbody td:nth-child(4) { width: 7%; }
.cleanup-table-album thead th:nth-child(5),
.cleanup-table-album tbody td:nth-child(5) { width: 15%; }

/* Global Matches (dev, issue #495): 7 cols — User, Artist, Track, Album,
   Plays, MBID, Actions. No separate "Source"/"Import" column — the row's
   source is a small badge folded inline into the User cell's own text
   (below) rather than its own column. Track/Album get the most room since
   they're the identifying data; User/Artist truncate rather than wrap so
   rows stay a consistent height in a cross-user list that can run long.
   Artist and MBID are editable inputs for every row (unmatched rows
   pre-filled with the known artist, pending-artist rows blank) — this
   mirrors the per-user Needs Attention page: pasting a valid MBID is what
   confirms a row, for both unmatched and pending-artist alike, so it gets
   its own column and a Save button that's disabled until one is present. */
.dev-matches-table thead th:nth-child(1),
.dev-matches-table tbody td:nth-child(1) { width: 16%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-matches-table thead th:nth-child(2),
.dev-matches-table tbody td:nth-child(2) { width: 14%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-matches-table thead th:nth-child(3),
.dev-matches-table tbody td:nth-child(3) { width: 21%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-matches-table thead th:nth-child(4),
.dev-matches-table tbody td:nth-child(4) { width: 17%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-matches-table thead th:nth-child(5),
.dev-matches-table tbody td:nth-child(5) { width: 6%; text-align: right; }
.dev-matches-table thead th:nth-child(6),
.dev-matches-table tbody td:nth-child(6) { width: 14%; max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-matches-table thead th:nth-child(7),
.dev-matches-table tbody td:nth-child(7) { width: 12%; white-space: nowrap; text-align: right; }
/* pending_artist rows put a plain text input in the Artist/MBID cells instead
   of plain text — the ellipsis-truncation trick above would clip an
   <input>, so opt out. Specificity here must match the nth-child rules above
   (both .dev-matches-table + one more class, both tbody+td) so these win on
   source order instead of losing outright — a lower-specificity version of
   this previously lost silently, leaving the input clipped to nothing. */
.dev-matches-table tbody td.mv-artist-cell-editable,
.dev-matches-table tbody td.mv-mbid-cell-editable {
  max-width: none; overflow: visible; white-space: nowrap;
}
.dev-matches-table tbody td.mv-artist-cell-editable .pa-artist-input,
.dev-matches-table tbody td.mv-mbid-cell-editable .pa-mbid-input { width: 100%; }
.dev-matches-table tbody td.mv-mbid-cell-editable { position: relative; }

/* Source badge, inline after the username inside the User cell's own text
   (see matches-view.js) — reuses only the per-source color modifier classes
   from the Recent Plays badge (.source-lastfm/-spotify/-applemusic/...,
   pure background/color, no layout properties of their own), not
   `.source-badge` itself: that class's position:absolute is built for
   overlaying an art thumbnail, and reusing it verbatim here (appended to
   the <tr>, then inside the actions cell) broke the table's layout twice in
   ways that only showed up in a real browser. As plain inline content this
   needs no layout mechanism of its own — it rides the exact same
   white-space:nowrap + text-overflow:ellipsis truncation column 1 already
   has above, unchanged, the same way Track/Album do. */
.mv-source-badge {
  display: inline-block;
  font-family: var(--mono); font-size: 0.5rem; font-weight: 500;
  letter-spacing: 0.03em; padding: 1px 3px; border-radius: 3px;
  margin-left: 0.35rem; vertical-align: middle;
}

/* Inline error shown next to a cleanup action button when an apply fails. */
.cleanup-error {
  display: inline-block;
  margin-left: 0.5rem;
  font-size: 0.72rem;
  color: #c0392b;
  vertical-align: middle;
}

.cleanup-badge {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0.15rem 0.45rem;
  border-radius: 3px;
  text-transform: uppercase;
}
.cleanup-badge-clean {
  background: rgba(var(--accent2-rgb, 255,140,66), 0.15);
  color: var(--accent2);
}
.cleanup-badge-near {
  background: rgba(232, 69, 69, 0.15);
  color: var(--accentText, var(--accent));
}
.cleanup-badge-mb {
  background: rgba(59, 130, 246, 0.15);
  color: #3b82f6;
}
.cleanup-suggested {
  color: var(--accent2);
}
.cleanup-wrong {
  color: var(--accentText, var(--accent));
  border-color: var(--accent);
}
.cleanup-status {
  font-size: 0.75rem;
  color: var(--muted);
}
.cleanup-section {
  margin-bottom: 2rem;
}
.cleanup-legend {
  font-size: 0.75rem;
  color: var(--muted);
  margin: 0 0 0.75rem;
  line-height: 1.6;
}
.cleanup-legend strong {
  color: var(--text);
}
.cleanup-legend-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  margin-top: 0.25rem;
}
.cleanup-legend-actions span {
  white-space: nowrap;
}
.cleanup-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.cleanup-subheader {
  margin: 0;
  font-size: 1rem;
}
.cleanup-count {
  font-size: 0.75rem;
  color: var(--muted);
  font-weight: normal;
}

.mbid-plays {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--accent2);
  text-align: right;
}

.mbid-input {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.3rem 0.5rem;
  border-radius: 4px;
  width: 100%;
}
.mbid-input:focus { outline: none; border-color: var(--accent); }
.mbid-input.mbid-invalid { border-color: var(--error, #e05252); }
.mbid-input.na-auto-filled { border-color: var(--accent2); background: color-mix(in srgb, var(--accent2) 8%, transparent); }

.mbid-error {
  display: block;
  font-size: 0.68rem;
  color: var(--error, #e05252);
  font-family: var(--mono);
  margin-top: 0.2rem;
}
.mbid-error.hidden { display: none; }

.mbid-preview {
  display: block;
  font-size: 0.68rem;
  color: var(--muted);
  font-family: var(--mono);
  margin-top: 0.2rem;
}
.mbid-preview.hidden { display: none; }
.mbid-preview.mbid-preview-mismatch { color: var(--warning, #d4a017); }

.mbid-actions {
  text-align: left;
}
.mbid-actions > * {
  vertical-align: middle;
}
.mbid-actions > * + * {
  margin-left: 0.4rem;
}

/* Multi-button action cells (Needs review, cleanup tables) lay out as a fixed
   2-column grid instead of relying on natural inline wrap — the buttons'
   varying label lengths otherwise wrap unevenly (e.g. 3-then-1) depending on
   how much happens to fit per line. */
.mbid-actions-grid {
  display: grid;
  grid-template-columns: repeat(2, max-content);
  gap: 0.4rem;
}
.mbid-actions-grid > * { margin-left: 0 !important; }

.btn-mb-search {
  flex-shrink: 0;
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.28rem 0.45rem;
  background: none;
  border: 1px solid var(--border);
  border-radius: 18px;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
}
.btn-mb-search:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.btn-mb-search:disabled { opacity: 0.5; cursor: default; }

.mbid-search-link {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  text-decoration: none;
  padding: 0.28rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 18px;
  white-space: nowrap;
  transition: all 0.15s;
  flex-shrink: 0;
  background: none;
  cursor: pointer;
}
.mbid-search-link:hover { color: var(--text); border-color: var(--muted); }

.btn-mbid-save {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.28rem 0.55rem;
  border-radius: 18px;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
  flex-shrink: 0;
}
.btn-mbid-save:not(:disabled):hover { color: var(--text); border-color: var(--accent); }
.btn-mbid-save:disabled { opacity: 0.35; cursor: default; }

.btn-na-pause, .btn-na-resume {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.28rem 0.55rem;
  border-radius: 18px;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
  flex-shrink: 0;
}
.btn-na-pause:hover  { color: var(--text); border-color: var(--muted); }
.btn-na-resume:hover { color: var(--text); border-color: var(--accent); }

.btn-na-mb-submit {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.28rem 0.45rem;
  border-radius: 18px;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
  flex-shrink: 0;
}
.btn-na-mb-submit:hover { color: var(--link); border-color: var(--link); }

/* ── Per-row "⋮" actions menu (issue #153) ────────────*/
.na-menu-wrap {
  position: relative;
  display: inline-block;
  vertical-align: middle;
}

.na-menu-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1;
  padding: 0.28rem 0.5rem;
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.15s;
}
.na-menu-btn:hover,
.na-menu-btn[aria-expanded="true"] { color: var(--text); border-color: var(--muted); }

/* position:fixed (coordinates set in JS on open) so the popover escapes the
   overflow:hidden on .mbid-table-wrap regardless of which row it's anchored to */
.na-menu {
  display: none;
  position: fixed;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0;
  margin: 0;
  min-width: 150px;
  z-index: 100;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  overflow: hidden;
}
.na-menu.open { display: block; }

.na-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.na-menu-item:hover { background: var(--surface2); color: var(--text); }
.na-menu-item.na-danger:hover { color: var(--accent); }

/* Buttons inside mbid tables should match btn-mbid-save sizing, not the larger upload-flow size */
.mbid-table .btn-preview-cancel {
  font-size: 0.7rem;
  padding: 0.28rem 0.55rem;
}

/* ── Pending-artist suggest ───────────────────────────*/
.pa-artist-cell { position: relative; }

.pa-artist-row {
  display: flex;
  gap: 0.3rem;
  align-items: center;
}

.btn-pa-suggest {
  flex-shrink: 0;
  background: none;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.25rem 0.45rem;
  cursor: pointer;
  transition: opacity 0.18s ease, color 0.15s, border-color 0.15s;
}
.btn-pa-suggest:hover:not(:disabled) { color: var(--text); border-color: var(--muted); }
.btn-pa-suggest:disabled { opacity: 0.4; cursor: default; }
.btn-pa-suggest.pa-suggest-open { color: var(--text); border-color: var(--muted); }

.pa-suggestion-cell {
  padding: 0 !important;
}
.pa-suggestion-inner {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
}
.pa-suggestion-row.open .pa-suggestion-inner {
  max-height: 600px;
}
.pa-suggestion-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.35rem 0.75rem;
  font-size: 0.65rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}


/* 3 grid items — artist, the title+album detail block, score — was defining
   7 column-tracks left over from an older markup shape; with only 3 actual
   children the row auto-placed into the first 3 (narrow) tracks and left
   the rest of the row empty (the "squashed left" bug). background was also
   a hardcoded #fff, breaking dark mode. */
.pa-suggestion-item {
  display: grid;
  grid-template-columns: 22% 1fr auto;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.72rem;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  transition: background 0.1s;
}
.pa-suggestion-item > * {
  padding: 0.45rem 0.75rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pa-suggestion-item:last-child { border-bottom: none; }
.pa-suggestion-item:hover { background: var(--surface2); }
.pa-suggestion-item.pa-suggestion-empty {
  color: var(--muted);
  cursor: default;
  grid-template-columns: 1fr;
}
.pa-suggestion-score  { color: var(--accent2); font-size: 0.65rem; }
.pa-suggestion-artist { color: var(--text); }
.pa-suggestion-detail { display: flex; align-items: baseline; gap: 0.4rem; min-width: 0; overflow: hidden; }
.pa-suggestion-title  { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.pa-suggestion-album  { color: var(--muted); font-style: italic; opacity: 0.8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0; }

/* Needs-attention candidate rows: 5 fields (score, artist, track, album, trailing
   meta+year) laid out to align under the real .pa-table's Source/Artist/Track/Album
   columns above, plus a trailing column absorbing the table's Plays+MBID+Actions width
   (candidates have no per-candidate value for those). See issue #528 — this modifier
   used to be missing, so these items fell back to the 3-column .pa-suggestion-item grid
   above (sized for match-editor.js's unrelated 3-child markup), scattering 7 flat
   children across 3 tracks. */
.pa-suggestion-item--na {
  grid-template-columns: 8% 16% 27% 20% 1fr;
}
.pa-suggestion-item--na .pa-suggestion-trailing {
  color: var(--muted);
  font-size: 0.63rem;
  opacity: 0.7;
  text-align: right;
}

/* ── Source badge toggle ──────────────────────────────*/
.recent-header-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.recent-title-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.recent-select-actions { display: flex; align-items: center; gap: 0.5rem; }
.recent-select-actions > .btn-preview-cancel { font-size: 0.72rem; padding: 0.3rem 0.75rem; }
.recent-sel-count { font-family: var(--mono); font-size: 0.7rem; color: var(--muted); }
#recent-list .track-row .play-check { display: none; width: 16px; height: 16px; }
#recent-list.select-mode .track-row { grid-template-columns: auto 44px 1fr auto auto; cursor: default; }
#recent-list.select-mode .track-row .play-check { display: block; cursor: pointer; }
#recent-list.select-mode .track-row:hover { box-shadow: none; }
#recent-list.select-mode .entity-link:hover { text-decoration: none; color: inherit; }

.source-badge-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  user-select: none;
}
.source-badge-toggle input { display: none; }
.toggle-track {
  width: 28px;
  height: 16px;
  background: var(--border);
  border-radius: 8px;
  position: relative;
  flex-shrink: 0;
  transition: background 0.2s;
}
.source-badge-toggle input:checked + .toggle-track { background: var(--accentFill, var(--accent)); }
.toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  background: #fff;
  border-radius: 50%;
  transition: left 0.2s;
}
.source-badge-toggle input:checked + .toggle-track .toggle-thumb { left: 14px; }
.toggle-label {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

#recent-list.source-badges-hidden .source-badge { display: none; }

/* ── Source badges (Recents hover) ────────────────────*/
.source-badge {
  position: absolute;
  bottom: 0;
  right: 0;
  font-family: var(--mono);
  font-size: 0.5rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  padding: 1px 3px;
  border-radius: 3px 0 0 0;
  opacity: 0;
  transition: opacity 0.15s;
  pointer-events: none;
  line-height: 1.4;
}
.track-row:hover .source-badge { opacity: 1; }

.source-lastfm    { background: #d51007; color: #fff; }
.source-spotify   { background: #1db954; color: #fff; }
.source-applemusic { background: #e8e8e8; color: #333; }
.source-manual    { background: #6366f1; color: #fff; }
.source-plex      { background: #e5a00d; color: #fff; }

[data-theme="light"] .source-lastfm    { background: #d51007; }
[data-theme="light"] .source-spotify   { background: #1db954; }
[data-theme="light"] .source-applemusic { background: #d1d5db; color: #111; }
[data-theme="light"] .source-manual    { background: #6366f1; }
[data-theme="light"] .source-plex      { background: #e5a00d; }

/* ── MBID unmatched dot ───────────────────────────────*/
.mbid-unmatched-dot {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accentFill, var(--accent));
  border: 1.5px solid var(--bg);
  pointer-events: none;
  z-index: 1;
}
.track-row .mbid-unmatched-dot {
  opacity: 0;
  transition: opacity 0.15s;
}
.track-row:hover .mbid-unmatched-dot { opacity: 1; }

/* Grid cards have border-radius:14px + overflow:hidden on .chart-row;
   move the dot inward so it isn't clipped at the corner. */
.chart-list.grid-view .mbid-unmatched-dot {
  top: 8px;
  right: 8px;
}

/* ── Detail view ──────────────────────────────────────*/
.chart-row-clickable { cursor: pointer; }
.chart-row-clickable:hover {
  background: var(--surface2);
}

.detail-header-wrap {
  margin-top: 0.5rem;
}

.detail-section-label {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 1.5rem 0 0.6rem;
}
/* ── Album detail tracklist toggle header ─────────────*/
.detail-tracklist-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 1.5rem 0 0.6rem;
}
.detail-tracklist-header .detail-section-label {
  margin: 0;
}
.detail-tracklist-toggle {
  display: flex;
  gap: 0.4rem;
}

/* ── Frosted glass detail banner ──────────────────────*/
.detail-header { margin-bottom: 1.5rem; }

.detail-art-banner {
  position: relative;
  width: 100%;
  height: 210px;
  border-radius: 20px;
  overflow: hidden;
  background: var(--surface2);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.06), 0 8px 32px rgba(0,0,0,0.35);
  transform: translateZ(0);
  -webkit-mask-image: -webkit-radial-gradient(white, black);
}

.art-img-banner {
  position: absolute;
  inset: -10%;
  width: 120%;
  height: 120%;
  object-fit: cover;
  filter: blur(16px) saturate(1.2);
  opacity: 0;
  transition: opacity 0.5s ease;
}
.art-img-banner.art-loaded { opacity: 1; }

.art-img-banner-thumb {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  height: calc(100% - 2.2rem);
  width: auto;
  object-fit: cover;
  border-radius: 10px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.5);
  z-index: 2;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.art-img-banner-thumb.art-loaded { opacity: 1; }

.detail-banner-gradient {
  position: absolute;
  inset: 0;
}

.detail-banner-content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  padding: 1rem calc(175px + 2.5rem) 1rem 1.1rem;
  gap: 0.4rem;
}

.detail-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-size: 1.4rem;
  font-weight: 700;
  color: #fff;
  background: rgba(0,0,0,0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 10px;
  padding: 0.25rem 0.65rem;
  overflow: hidden;
  max-width: 100%;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.detail-sub {
  display: inline-block;
  font-size: 0.82rem;
  color: rgba(255,255,255,0.85);
  background: rgba(0,0,0,0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 7px;
  padding: 0.15rem 0.55rem;
  margin-bottom: 0.1rem;
}
.detail-sub .entity-link { color: rgba(255,255,255,0.85); }
.detail-sub .entity-link:hover { color: #fff; }

.detail-stats {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  background: rgba(0,0,0,0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 8px;
  padding: 0.3rem 0.65rem;
}
.detail-stat-item { display: flex; flex-direction: column; }
.detail-stat-n {
  font-family: var(--mono);
  font-size: 0.82rem;
  font-weight: 500;
  color: rgba(255,255,255,0.95);
  line-height: 1;
}
.detail-stat-l {
  font-size: 0.56rem;
  color: rgba(255,255,255,0.55);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-top: 2px;
}

.detail-pagination { margin-top: 0.75rem; }

/* Slide-in entrance for detail panels */
#artists-detail:not(.hidden),
#albums-detail:not(.hidden),
#tracks-detail:not(.hidden) {
  animation: fadeUp 0.28s ease both;
}

/* ── Reject MBID match button (track / album detail) ─*/
.detail-reject-bar {
  padding: 0 0 0.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.detail-reject-bar-buttons { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.detail-reject-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.25rem 0.6rem;
  border-radius: 20px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.detail-reject-btn:hover { color: var(--accent); border-color: var(--accent); }

.detail-see-more {
  display: block;
  width: 100%;
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.45rem 0.6rem;
  border-radius: 20px;
  cursor: pointer;
  text-align: center;
  transition: color 0.15s, border-color 0.15s;
  margin-top: 0.5rem;
}
.detail-see-more:hover { color: var(--text); border-color: var(--muted); }

/* ── Section header row (label + "All N →" / see-all link) ─*/
.detail-section-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 1.5rem 0 0.6rem;
}
.detail-section-header-row .detail-section-label { margin: 0; }
.detail-see-all {
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s;
}
.detail-see-all:hover { color: var(--text); }

/* .detail-recent-viewall is genuine navigation (to the filtered Recent Plays
   view), unlike the sibling "All N →" expand-in-place toggles that share
   .detail-see-all above — so it gets the accent color reserved for
   interactive/action affordances (see .tile-view-all on the home page). */
.detail-see-all.detail-recent-viewall { color: var(--accent); }
.detail-see-all.detail-recent-viewall:hover { color: var(--accent); text-decoration: underline; }

/* ── Artist genre chips ────────────────────────────────*/
.detail-genre-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}
.detail-genre-chip {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: rgba(255,255,255,0.85);
  background: rgba(255,255,255,0.12);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-radius: 16px;
  padding: 0.25rem 0.6rem;
}

/* ── Artist/album "history" panels (plays by year / recent plays) ─*/
.detail-history-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
@media (max-width: 700px) {
  .detail-history-grid { grid-template-columns: 1fr; }
}
.detail-history-panel {
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1rem 1.1rem;
}
.detail-history-panel-title {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.8rem;
}
.detail-history-panel-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.8rem;
}
.detail-history-panel-title-row .detail-history-panel-title { margin-bottom: 0; }
.detail-recent-list { display: flex; flex-direction: column; }
.detail-recent-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.45rem 0;
  border-top: 1px solid var(--hair);
}
.detail-recent-row:first-child { border-top: none; }
.detail-recent-art { width: 36px; height: 36px; }
.detail-recent-info { min-width: 0; flex: 1; }
.detail-recent-track {
  font-family: var(--sans);
  font-size: 0.83rem;
  font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.detail-recent-album {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  margin-top: 1px;
}
.detail-recent-when {
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--faint);
  white-space: nowrap;
}

/* ── MusicBrainz match panel (track detail) ─────────*/
.detail-match-panel {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.75rem;
  margin-bottom: 1rem;
  background: var(--surface);
}
.detail-match-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: 0.72rem;
}
.detail-match-label { color: var(--text); font-weight: 600; }
.detail-match-meta  { color: var(--muted); }
.detail-match-editor { margin-top: 0.6rem; }

/* ── Shared match editor (track detail + recently matched) ─*/
.match-editor-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.me-panel { margin-top: 0.6rem; }
.me-panel.hidden { display: none; }
.me-candidates {
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  margin-bottom: 0.5rem;
  max-height: 320px;
  overflow-y: auto;
}
.me-candidates:empty { display: none; }
.me-current { background: var(--surface2); }
.me-manual { display: flex; gap: 0.5rem; align-items: center; }
.me-manual .me-mbid { flex: 1; min-width: 0; }

/* ── Recently matched table ─────────────────────────*/
.rm-table .rm-date   { color: var(--muted); white-space: nowrap; }
.rm-table .rm-method { color: var(--accent2); white-space: nowrap; }
.rm-resolved { color: var(--text); }
.rm-muted    { color: var(--muted); }
.rm-editor-row.hidden { display: none; }
.rm-editor { padding: 0.5rem 0; }
.review-editor-row.hidden { display: none; }
.review-editor { padding: 0.5rem 0; }

/* ── Recently matched modal ──────────────────────────*/
/* Explicit fixed positioning + height so flex children fill correctly.
   <dialog> auto-centering via margin:auto doesn't apply when display is
   overridden, and flex:1 on the body requires a fixed container height. */
.rm-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  padding: 0;
  width: 92vw;
  max-width: 1400px;
  height: 82vh;
  box-shadow: 0 8px 32px rgba(0,0,0,0.4);
  outline: none;
  color: var(--text);
}
.rm-modal[open] {
  display: flex;
  flex-direction: column;
}
.rm-modal::backdrop { background: rgba(0,0,0,0.55); }
.rm-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.875rem 1.5rem;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.rm-modal-header h2 { font-size: 0.95rem; font-weight: 500; margin: 0; }
.rm-modal-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  font-size: 0.9rem;
  padding: 0.2rem 0.5rem;
  border-radius: 50%;
  line-height: 1;
}
.rm-modal-close:hover { color: var(--text); }
.rm-modal-body {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}
.rm-modal-table-wrap {
  border: none;
  border-radius: 0;
  margin-bottom: 0;
}
.rm-modal-footer {
  display: flex;
  justify-content: center;
  padding: 0.75rem;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.rm-modal-footer.hidden { display: none; }

/* ── Recently matched fallback bar (no spinner) ──────*/
.mbid-rm-bar {
  padding: 0.25rem 0 0.5rem;
}
.mbid-rm-bar.hidden { display: none; }

/* ── Delete play button (track history rows) ─────*/
.detail-delete-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.4rem;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
  flex-shrink: 0;
  align-self: center;
}
.track-row:hover .detail-delete-btn { opacity: 1; }
.pa-table tr:hover .detail-delete-btn { opacity: 1; }
.detail-delete-btn:hover { color: var(--accent); background: var(--surface2); }

/* ── Chart row delete button ──────────────────────────*/
.chart-row-deletable {
  grid-template-columns: 2.5rem 52px 1fr auto auto;
}
.chart-delete-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.9rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
  padding: 0.25rem 0.5rem;
  border-radius: 50%;
}
.chart-row:hover .chart-delete-btn { opacity: 1; }
.chart-delete-btn:hover { color: var(--accent); background: var(--surface2); }

/* ── Entity links in recent list ─────────────────────*/
.entity-link { cursor: pointer; transition: color 0.12s; }
.entity-link:hover { color: var(--text); text-decoration: underline; text-underline-offset: 2px; }

/* ── Art card grid — Artists + Albums + Tracks pages ──*/
.chart-list.grid-view {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
  gap: 1rem;
}

.chart-list.grid-view .chart-row {
  display: block;
  position: relative;
  aspect-ratio: 1;
  padding: 0;
  overflow: hidden;
  background: var(--surface2);
  border-radius: 14px;
  border: 1px solid var(--border);
  animation: fadeUp 0.3s ease both;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.chart-list.grid-view .chart-row:hover {
  transform: scale(1.03);
  box-shadow: 0 8px 28px rgba(0,0,0,0.28);
  border-color: var(--accent);
}

.chart-list.grid-view .chart-row .art-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
}

.chart-list.grid-view .chart-row .art-img {
  border-radius: 0;
}

.chart-list.grid-view .chart-row .chart-rank {
  position: absolute;
  top: 0.6rem;
  left: 0.6rem;
  z-index: 3;
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 500;
  background: rgba(0,0,0,0.52);
  color: rgba(255,255,255,0.9);
  padding: 0.18rem 0.45rem;
  border-radius: 5px;
  line-height: 1.2;
}

.chart-list.grid-view .chart-row .chart-rank.top {
  background: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
}

.chart-list.grid-view .chart-row .chart-info {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  z-index: 2;
  padding: 2.25rem 0.7rem 0.7rem;
  background: linear-gradient(to top, rgba(0,0,0,0.88) 0%, transparent 100%);
}

.chart-list.grid-view .chart-row .chart-name {
  color: #fff;
  font-size: 0.83rem;
  font-weight: 600;
  white-space: normal;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chart-list.grid-view .chart-row .chart-sub {
  color: rgba(255,255,255,0.6);
  margin-top: 1px;
}

.chart-list.grid-view .chart-row .chart-plays {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 3;
  background: rgba(0,0,0,0.52);
  border: none;
  color: rgba(255,255,255,0.85);
  font-size: 0.63rem;
  padding: 0.18rem 0.45rem;
}

.chart-list.grid-view .chart-row-deletable {
  display: block;
  grid-template-columns: unset;
}

.chart-list.grid-view .chart-delete-btn {
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  z-index: 4;
  opacity: 0;
  background: rgba(0,0,0,0.6);
  color: #fff;
  border: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: opacity 0.15s, background 0.15s;
}

.chart-list.grid-view .chart-row:hover .chart-delete-btn {
  opacity: 1;
}

.chart-list.grid-view .chart-row-deletable .chart-plays {
  right: 2.2rem;
}

/* ── View toggle button ───────────────────────────────*/
.view-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.38rem 0.7rem;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
  white-space: nowrap;
}
.view-toggle-btn:hover {
  color: var(--text);
  border-color: var(--accent);
}
.view-toggle-btn.active {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

/* Three-way List/Dense/Grid segmented control (view-toggle.js). */
.view-toggle-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 2px;
}
.view-toggle-seg {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 24px;
  background: none;
  border: none;
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.view-toggle-seg:hover { color: var(--text); }
.view-toggle-seg.active {
  color: var(--accentFillText, var(--navText, #fff));
  background: var(--accentFill, var(--accent));
}

/* Dense view — a tighter row for Artists/Albums/Tracks charts and Recent. */
.chart-list.dense-view { gap: 0.15rem; }
.chart-list.dense-view .chart-row {
  /* Only 4 tracks — .chart-bar is display:none in dense view, so the grid
     template must drop its column too, or chart-plays inherits the bar's
     narrower track instead of sizing to its own content. */
  grid-template-columns: 1.6rem 34px 1fr auto;
  gap: 0.65rem;
  padding: 0.4rem 0.7rem;
  border-radius: 8px;
}
.chart-list.dense-view .chart-row .art-thumb { width: 34px; height: 34px; }
.chart-list.dense-view .chart-name { font-size: 0.85rem; }
.chart-list.dense-view .chart-sub { display: none; }
.chart-list.dense-view .chart-bar { display: none; }
.chart-list.dense-view .chart-plays { padding: 0.1rem 0.5rem; }

#recent-list.dense-view .track-row {
  grid-template-columns: 34px 1fr auto auto;
  gap: 0.65rem;
  padding: 0.4rem 1rem;
}
#recent-list.dense-view .track-row .art-thumb { width: 34px; height: 34px; }
#recent-list.dense-view .track-name { font-size: 0.85rem; }
#recent-list.dense-view .track-meta { font-size: 0.7rem; }
#recent-list.dense-view .track-day-header { padding: 0.5rem 0 0.25rem; }
/* Select mode always wins the grid layout over dense sizing, so checkboxes stay visible. */
#recent-list.dense-view.select-mode .track-row { grid-template-columns: auto 34px 1fr auto auto; padding: 0.4rem 0.7rem; }

/* ── Responsive ───────────────────────────────────────*/
@media (max-width: 600px) {
  header {
    padding: 0 1rem;
    grid-template-columns: 1fr auto 1fr;
  }

  .mobile-header-left  { display: flex; }
  .mobile-header-right { display: flex; }
  .mobile-menu         { display: flex; }
  .mobile-search-bar   { display: flex; }

  .nav-center   { display: none; }
  .header-right { display: none; }

  main { padding: 1.25rem 1rem 3rem; }
  /* The search page keeps .mobile-search-bar permanently open (see
     setupMobileSearch() in layout.js), and that bar is a fixed overlay
     (top: 54px, height: 48px) rather than something that pushes layout —
     so without this, the search page's back button sits directly under it. */
  body[data-page="search"] main { padding-top: calc(1.25rem + 48px); }
  .track-row { grid-template-columns: 44px 1fr auto auto; }
  .track-date { text-align: right; }
  .date-long  { display: none; }
  .date-short { display: flex; }
  .chart-header { flex-wrap: wrap; gap: 0.5rem; }
  .settings-tabs {
    justify-content: flex-start;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .settings-tabs::-webkit-scrollbar { display: none; }
  .settings-tabs .dupes-tab { flex: 0 0 auto; }
  .settings-row { flex-wrap: wrap; row-gap: 0.5rem; }
  .settings-scheme-options { flex-wrap: wrap; }
  .recent-header { flex-wrap: wrap; gap: 0.5rem; }
  .recent-header-right { display: grid; grid-template-columns: 1fr auto; align-items: start; row-gap: 0.5rem; column-gap: 0.5rem; width: 100%; }
  .view-toggle-group { grid-column: 1; grid-row: 1; justify-self: start; }
  .date-jump-outer { grid-column: 2; grid-row: 1; justify-self: end; flex-direction: column; align-items: center; }
  .recent-select-actions { grid-column: 1 / -1; grid-row: 2; justify-self: start; flex-wrap: nowrap; }
  .date-jump-today { position: static; transform: none; margin-top: 0.15rem; }
  .recent-select-actions > .btn-preview-cancel { font-size: 0.68rem; padding: 0.3rem 0.55rem; white-space: nowrap; }
  .chart-row { grid-template-columns: 2rem 44px 1fr auto; }
  .chart-row .art-thumb { width: 44px; height: 44px; }
  .chart-row-deletable { grid-template-columns: 2rem 44px 1fr auto auto; }
  #artists-list.chart-list.grid-view,
  #albums-list.chart-list.grid-view,
  #tracks-list.chart-list.grid-view { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 0.65rem; }
  .section-header h2 { font-size: 1.35rem; }
  .page-edge { display: none; }
  /* Track/album hero: grow to fit its title instead of clipping it. Excludes
     .hero-banner (home) and .reco-hero (recommendations), which have their
     own sizing rules below. */
  .detail-art-banner:not(.hero-banner):not(.reco-hero) {
    height: auto;
    min-height: 200px;
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }
  .detail-art-banner:not(.hero-banner):not(.reco-hero) .detail-banner-content {
    position: relative;
    inset: auto;
    padding: 1rem calc(120px + 2.2rem) 1rem 1.1rem;
  }
  .detail-art-banner:not(.hero-banner):not(.reco-hero) .art-img-banner-thumb {
    height: 120px;
    top: 50%;
    transform: translateY(-50%);
  }
  .detail-title { font-size: 1.25rem; }
  .detail-art-banner:not(.hero-banner):not(.reco-hero) .detail-title {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
  }
  .detail-stats { gap: 1rem; }
}

/* ── Matches page (/mbid) mobile overhaul ─────────────────────────────────
   The MBID dashboard's data views are fixed-layout tables far too wide for a
   phone. On narrow screens collapse each table into stacked, labelled cards
   (one card per row), and let the status bar / toolbars / modals reflow. */
@media (max-width: 600px) {
  /* Status bar: compact wrapping grid instead of a wide centered flex row */
  .mbid-status-bar {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.75rem 0.5rem;
    padding: 0.85rem 1rem;
  }
  .mbid-stat-n { font-size: 1.2rem; }

  /* Toolbar: tab strip, filter box, and bulk-action buttons each wrap onto their own line */
  .na-toolbar { flex-wrap: wrap; gap: 0.5rem; }
  .na-tab-strip { flex: 1 1 100%; }
  .na-search-input { flex: 1 1 100%; width: 100%; max-width: none; }
  .na-actions { flex: 1 1 100%; flex-wrap: wrap; margin-left: 0; }
  .na-actions > .btn-preview-cancel {
    flex: 1 1 auto;
    min-height: 40px;
    font-size: 0.78rem;
  }

  /* Card conversion — applies to every .mbid-table (needs-attention, cleanup,
     recently-matched). The wrapper no longer clips since rows now stack. */
  .mbid-table-wrap { overflow: visible; border: none; border-radius: 0; }
  .mbid-table { display: block; font-size: 0.85rem; }
  .mbid-table thead { display: none; }
  .mbid-table tbody { display: block; }
  .mbid-table tbody tr {
    display: block;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    padding: 0.75rem;
    margin-bottom: 0.6rem;
  }
  .mbid-table tbody tr:hover td { background: none; }
  .mbid-table tbody td {
    display: block;
    width: auto !important;
    max-width: none !important;
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    border-bottom: none;
    padding: 0.2rem 0;
    text-align: left !important;
  }
  /* Field label above each value (cells without data-label render nothing) */
  .mbid-table tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-family: var(--mono);
    font-size: 0.6rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 0.15rem;
  }
  .mbid-table tbody td.mbid-plays { color: var(--accent2); }
  /* Play counts aren't actionable on a phone — hide them (keep Score) */
  .mbid-table tbody td[data-label="Plays"],
  .mbid-table tbody td[data-label="Plays (variant)"],
  .mbid-table tbody td[data-label="Total plays"] { display: none; }

  /* Actions row: wrap, full-bleed, touch-friendly */
  .mbid-table tbody td.mbid-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding-top: 0.6rem;
  }
  .mbid-table tbody td.mbid-actions > * + * { margin-left: 0; }
  .mbid-table tbody td.mbid-actions .btn-mbid-save,
  .mbid-table tbody td.mbid-actions .btn-preview-cancel,
  .mbid-table tbody td.mbid-actions .mbid-search-link {
    flex: 1 1 auto;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .na-menu-btn { min-height: 40px; min-width: 40px; }

  /* Recently Matched modal: go full-screen so the cards have room */
  .rm-modal {
    width: 100vw;
    height: 100dvh;
    max-width: none;
    border-radius: 0;
    border: none;
    top: 0;
    left: 0;
    transform: none;
  }
  /* Inline match-editor (the "Fix…" candidate picker) stacks full width */
  .me-manual { flex-wrap: wrap; }
  .me-manual .me-mbid { flex: 1 1 100%; }
  .me-manual .me-apply { flex: 1 1 auto; min-height: 40px; }

  /* Duplicate scan modal: use the full viewport width */
  .dedup-modal,
  .modal { width: 94vw; max-width: none; }
}

/* Needs-attention source badges + review/cleanup panels */
.na-source {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 0.25rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.na-src-unmatched { background: rgba(212, 160, 23, 0.15); color: var(--warning, #d4a017); }
.na-src-pa        { background: rgba(59, 130, 246, 0.15); color: #3b82f6; }
.na-import-source {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.65rem;
  color: var(--muted);
  white-space: nowrap;
}
.na-artist-known  { color: var(--text); }
.review-mismatch  { color: var(--warning, #d4a017); font-weight: 600; }
.review-variant-badge {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 500;
  color: var(--accent2);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0.05rem 0.35rem;
  margin-left: 0.35rem;
  white-space: nowrap;
}
.review-context-list { padding: 0.25rem 0; }
.review-context-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.4rem 0.75rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  border-bottom: 1px solid var(--border);
}
.review-context-item:last-child { border-bottom: none; }
.review-context-track { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.review-context-plays { color: var(--muted); white-space: nowrap; }
.review-context-empty { padding: 0.6rem 0.75rem; color: var(--muted); font-size: 0.8rem; }
.review-context-group-label {
  padding: 0.4rem 0.75rem 0.2rem;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
}
.cleanup-subheader {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}
.cleanup-count {
  font-size: 0.72rem;
  color: var(--muted);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}
.cleanup-section { margin-top: 1.75rem; padding-left: 0.75rem; border-left: 3px solid var(--border); }
.cleanup-section:first-child { margin-top: 0; }
.cleanup-section[data-kind="artist"] { border-left-color: #8b5cf6; }
.cleanup-section[data-kind="track"]  { border-left-color: #3b82f6; }
.cleanup-section[data-kind="album"]  { border-left-color: #f59e0b; }
.cleanup-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 0.5rem;
  padding: 0 0.25rem;
}
.cleanup-apply-all-artist { border-color: #8b5cf6; color: #8b5cf6; }
.cleanup-apply-all-track  { border-color: #3b82f6; color: #3b82f6; }
.cleanup-apply-all-album  { border-color: #f59e0b; color: #f59e0b; }
.cleanup-apply-all-artist:hover:not(:disabled) { background: rgba(139, 92, 246, 0.12); color: #8b5cf6; border-color: #8b5cf6; }
.cleanup-apply-all-track:hover:not(:disabled)  { background: rgba(59, 130, 246, 0.12); color: #3b82f6; border-color: #3b82f6; }
.cleanup-apply-all-album:hover:not(:disabled)  { background: rgba(245, 158, 11, 0.12); color: #f59e0b; border-color: #f59e0b; }
.cleanup-status {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}

/* ── Auth overlay ─────────────────────────────────────────────────────────── */

.auth-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
}
.auth-overlay.hidden { display: none; }

.auth-box {
  width: 100%; max-width: 360px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 2rem 2rem 2.25rem;
  display: flex; flex-direction: column; gap: 1.25rem;
}

.auth-logo {
  font-family: var(--mono);
  font-size: 1.1rem;
  color: var(--accent);
  text-align: center;
  letter-spacing: 0.05em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}

#auth-form, #auth-methods, #auth-bootstrap, #auth-code-form,
#auth-register, #auth-register-form, #auth-register-code-form,
#auth-passkey-prompt {
  display: flex; flex-direction: column; gap: 0.75rem; width: 100%;
}
.auth-box input {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-family: var(--sans); font-size: 0.85rem;
  padding: 0.6rem 0.8rem;
  outline: none;
  transition: border-color 0.15s;
  width: 100%; box-sizing: border-box;
}
.auth-box input:focus { border-color: var(--accent); }
.auth-box input::placeholder { color: var(--muted); }
/* iOS Safari auto-zooms the viewport on focusing any input under 16px font-size;
   bump to 16px only on small screens so desktop keeps its smaller auth styling. */
@media (max-width: 600px) {
  .auth-box input { font-size: 16px; }
}
/* Primary buttons: passkey sign-in is the prioritized action, alongside every
   other step's own primary submit (Verify code, Create account, passkey setup). */
.auth-box button[type="submit"], #auth-passkey, #auth-reg-passkey {
  background: var(--accentFill, var(--accent));
  border: none; border-radius: 22px;
  color: var(--accentFillText, var(--navText));
  font-family: var(--sans); font-size: 0.85rem; font-weight: 500;
  padding: 0.65rem 1rem;
  cursor: pointer;
  transition: opacity 0.15s;
}
.auth-box button[type="submit"]:hover, #auth-passkey:hover, #auth-reg-passkey:hover { opacity: 0.85; }
.auth-box button:disabled { opacity: 0.5; cursor: not-allowed; }
/* Continue (email path) is the secondary, always-available fallback alongside
   the prioritized passkey shortcut on Step 1. */
#auth-continue {
  background: var(--surface2);
  border: 1px solid var(--border); border-radius: 22px;
  color: var(--text);
  font-family: var(--sans); font-size: 0.85rem; font-weight: 500;
  padding: 0.65rem 1rem;
  cursor: pointer;
  transition: opacity 0.15s;
}
#auth-continue:hover { opacity: 0.85; }
/* Quiet divider between the email path and the passkey shortcut on Step 1 —
   chrome, not data, so it stays minimal (a hairline + mono "or"). */
.auth-divider {
  display: flex; align-items: center; gap: 0.75rem;
  color: var(--muted);
  font-family: var(--mono); font-size: 0.7rem;
  text-transform: uppercase; letter-spacing: 0.05em;
}
.auth-divider::before, .auth-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}

.auth-ident-label {
  font-family: var(--mono); font-size: 0.8rem;
  color: var(--muted); text-align: center;
}
/* white-space: pre-line renders the \n the JS puts before the email as a real
   line break; overflow-wrap only breaks the email itself as a last resort
   (an unrealistically long address), never mid-character like word-break did. */
#auth-ident-label { white-space: pre-line; overflow-wrap: break-word; }
.auth-passkey-hint {
  font-family: var(--sans); font-size: 0.78rem;
  color: var(--muted); text-align: center; margin: 0;
}
/* Invite-only signup notice: a requirement to act on, not a passive tip like the
   passkey hint above — so it gets the same accent-tinted callout treatment as
   .auth-error below instead of plain muted text. */
.auth-invite-hint {
  font-family: var(--sans); font-size: 0.78rem; line-height: 1.4;
  color: var(--accent); text-align: center; margin: 0;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 4px;
  padding: 0.55rem 0.7rem;
}
.auth-link {
  font-family: var(--sans); font-size: 0.75rem;
  color: var(--muted); text-align: center;
  text-decoration: none; cursor: pointer;
}
.auth-link:hover { color: var(--text); text-decoration: underline; }

.auth-error {
  font-size: 0.78rem;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 4px;
  padding: 0.45rem 0.7rem;
}
.auth-error.hidden { display: none; }

/* ── User menu (header) ───────────────────────────────────────────────────── */

.user-menu {
  display: flex; align-items: center; gap: 0.6rem;
  margin-left: auto;
}
.user-menu.hidden { display: none; }

.user-name {
  font-family: var(--mono); font-size: 0.72rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s;
  width: max-content;
}
.user-name:hover { color: var(--text); }

/* ── Settings account section ─────────────────────────────────────────────── */
.settings-subsection-label {
  font-size: 0.7rem;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 1rem 0 0.5rem;
}

.settings-pw-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 360px;
  margin-bottom: 0.25rem;
}

.settings-input {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-family: var(--mono); font-size: 0.78rem;
  padding: 0.4rem 0.6rem;
  outline: none;
  transition: border-color 0.15s;
}
.settings-input:focus { border-color: var(--accent); }
.settings-input::placeholder { color: var(--muted); }

.settings-error {
  font-size: 0.78rem;
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
  border-radius: 4px;
  padding: 0.35rem 0.6rem;
  display: block;
}
.settings-error.hidden { display: none; }

.dev-forbidden {
  font-size: 0.85rem;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 4px;
  padding: 0.8rem 1rem;
  margin: 1rem 0;
}

.settings-success {
  font-size: 0.78rem;
  color: var(--text);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 4px;
  padding: 0.35rem 0.6rem;
  display: block;
}
.settings-success.hidden { display: none; }

.settings-signout-row { margin-top: 1rem; }

.settings-value {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text);
}

.settings-danger-title { color: var(--danger); border-bottom-color: var(--danger); opacity: 0.85; }
.settings-danger-section { border-color: var(--danger); }

/* ── Settings feedback section ───────────────────────────────────────────── */
.settings-feedback-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 480px;
  margin-top: 1.2rem;
}
.settings-feedback-actions {
  display: flex;
  justify-content: flex-end;
  padding-top: 0.25rem;
}
/* Segmented choice control — same visual language as the Theme picker
   (.settings-theme-options/.settings-theme-btn), kept as its own class so the
   two features don't share class names for unrelated concepts. */
.settings-segment {
  display: flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  width: max-content;
}
.settings-segment-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 0.4rem 0.85rem;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.settings-segment-btn + .settings-segment-btn { border-left: 1px solid var(--border); }
.settings-segment-btn:hover { color: var(--text); background: var(--surface2); }
.settings-segment-btn.active { color: var(--accentText, var(--accent)); background: var(--surface2); }

/* ── Log Albums tab ─────────────────────────────────────────────────── */
.logalbum-panel {
  max-width: 680px;
  margin: 0 auto 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem 1.4rem;
}

.logalbum-search-form {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.logalbum-input {
  flex: 1;
  min-width: 160px;
  padding: 0.75rem 0.85rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  font-size: 0.8rem;
  font-family: var(--mono);
}
.logalbum-input:focus { outline: none; border-color: var(--accent); }
.logalbum-input::placeholder { color: var(--muted); }
.logalbum-search-btn {
  padding: 0.68rem 1.25rem;
  background: var(--accentFill, var(--accent));
  border: none;
  border-radius: 22px;
  color: var(--accentFillText, var(--navText));
  font-size: 0.68rem;
  font-weight: 700;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
  white-space: nowrap;
  transition: filter 0.15s;
}
.logalbum-search-btn:hover { color: var(--text); border-color: var(--muted); }

.logalbum-status { font-size: 0.8rem; color: var(--muted); margin: 0.5rem 0; }

.logalbum-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 0.75rem;
  margin-top: 0.5rem;
}
.logalbum-no-results { font-size: 0.875rem; color: var(--muted); }

.logalbum-card {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.logalbum-card:hover,
.logalbum-card:focus { border-color: var(--accent); outline: none; }

.logalbum-art {
  width: 52px;
  height: 52px;
  object-fit: cover;
  border-radius: 3px;
  flex-shrink: 0;
  background: var(--border);
}
.logalbum-info { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.logalbum-title  { font-size: 0.875rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.logalbum-artist { font-size: 0.8rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.logalbum-meta   { font-size: 0.72rem; color: var(--muted); font-family: var(--mono); }

.logalbum-back-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.8rem;
  font-family: var(--mono);
  cursor: pointer;
  padding: 0;
  margin-bottom: 1rem;
  display: inline-block;
}
.logalbum-back-btn:hover { color: var(--text); }

.logalbum-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.logalbum-header-art {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
  background: var(--border);
}
.logalbum-header-info { display: flex; flex-direction: column; gap: 0.2rem; }
.logalbum-header-title  { font-size: 1rem; font-weight: 700; }
.logalbum-header-artist { font-size: 0.875rem; color: var(--muted); }
.logalbum-header-year   { font-size: 0.75rem; color: var(--muted); font-family: var(--mono); }

.logalbum-time-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.logalbum-time-label { font-size: 0.8rem; color: var(--muted); font-family: var(--mono); }
.logalbum-time-mode {
  padding: 0.35rem 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 0.8rem;
  font-family: var(--mono);
  cursor: pointer;
}
.logalbum-time-mode:focus { outline: none; border-color: var(--accent); }
.logalbum-date-input,
.logalbum-time-input {
  padding: 0.35rem 0.6rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 0.8rem;
  font-family: var(--mono);
}
.logalbum-date-input:focus,
.logalbum-time-input:focus { outline: none; border-color: var(--accent); }

.logalbum-track-controls {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
}
.logalbum-sep { color: var(--muted); }
.logalbum-track-count { margin-left: auto; color: var(--muted); font-family: var(--mono); font-size: 0.75rem; }

.logalbum-track-list {
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 1.25rem;
}
.logalbum-track-row {
  display: grid;
  grid-template-columns: 1rem 2rem 1fr auto;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.75rem;
  cursor: pointer;
  transition: background 0.1s;
}
.logalbum-track-row:not(:last-child) { border-bottom: 1px solid var(--border); }
.logalbum-track-row:hover { background: var(--border); }
.logalbum-track-pos  { font-size: 0.72rem; color: var(--muted); font-family: var(--mono); text-align: right; }
.logalbum-track-title { font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.logalbum-track-dur  { font-size: 0.72rem; color: var(--muted); font-family: var(--mono); white-space: nowrap; }

.logalbum-submit-row { display: flex; justify-content: flex-end; }
.logalbum-another-row { margin-top: 1rem; display: flex; justify-content: center; }

.upload-result-warn  { background: color-mix(in srgb, var(--accent2) 15%, var(--surface)); border-color: var(--accent2); }
.upload-result-error { background: color-mix(in srgb, #e53e3e 15%, var(--surface)); border-color: #e53e3e; }

/* ── Account overlay ─────────────────────────────────────────────────────── */

.auth-box { position: relative; }

.btn-account {
  background: none; border: none; cursor: pointer; padding: 0;
}
.btn-account:hover { color: var(--text); }

.account-close {
  position: absolute; top: 0.75rem; right: 0.75rem;
  background: none; border: none; color: var(--muted);
  font-size: 0.9rem; cursor: pointer;
  padding: 0.2rem 0.4rem; border-radius: 50%; line-height: 1;
  transition: color 0.15s, background 0.15s;
}
.account-close:hover { color: var(--text); background: var(--surface2); }

.account-info {
  display: flex; flex-direction: column; gap: 0.2rem;
  padding-bottom: 0.25rem; border-bottom: 1px solid var(--border);
}
.account-username { font-family: var(--mono); font-size: 1rem; font-weight: 500; color: var(--text); }
.account-member-since { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); }

.account-section-label {
  font-family: var(--mono); font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
}

#account-pw-form { display: flex; flex-direction: column; gap: 0.75rem; }
#account-pw-form input {
  background: var(--surface2); border: 1px solid var(--border);
  border-radius: 5px; color: var(--text);
  font-family: var(--sans); font-size: 0.85rem;
  padding: 0.6rem 0.8rem; outline: none; transition: border-color 0.15s;
}
#account-pw-form input:focus { border-color: var(--accent); }
#account-pw-form input::placeholder { color: var(--muted); }
#account-pw-submit {
  background: var(--accentFill, var(--accent)); border: none; border-radius: 20px; color: var(--accentFillText, var(--navText));
  font-family: var(--sans); font-size: 0.85rem; font-weight: 500;
  padding: 0.65rem 1rem; cursor: pointer; transition: opacity 0.15s; margin-top: 0.25rem;
}
#account-pw-submit:hover { opacity: 0.85; }
#account-pw-submit:disabled { opacity: 0.5; cursor: not-allowed; }

.account-success {
  font-size: 0.78rem; color: #4caf7d;
  background: color-mix(in srgb, #4caf7d 10%, transparent);
  border: 1px solid color-mix(in srgb, #4caf7d 30%, transparent);
  border-radius: 4px; padding: 0.45rem 0.7rem;
}
.account-success.hidden { display: none; }

.account-danger-zone {
  display: flex; flex-direction: column; gap: 0.75rem;
  padding-top: 0.25rem; border-top: 1px solid var(--border);
}

.btn-delete-account {
  background: none;
  border: 1px solid color-mix(in srgb, var(--danger) 50%, var(--border));
  border-radius: 20px;
  color: var(--danger);
  font-family: var(--sans); font-size: 0.85rem; font-weight: 500;
  padding: 0.65rem 1rem;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn-delete-account:hover {
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border-color: var(--danger);
}

/* ── Dev Login (auth overlay) ─────────────────────────────────────────────── */

.auth-dev-divider {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 1rem 0 0.75rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.auth-dev-divider::before,
.auth-dev-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.btn-dev-login {
  width: 100%;
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.8rem;
  padding: 0.6rem 1rem;
  border-radius: 20px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
  letter-spacing: 0.03em;
}
.btn-dev-login:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}

/* ── Dev Tools ────────────────────────────────────────────────────────────── */

#devtools-btn {
  position: fixed;
  bottom: 16px;
  left: 16px;
  z-index: 900;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--faint);
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 700;
  padding: 0.35rem 0.65rem;
  border-radius: 16px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
  letter-spacing: 0.02em;
  text-decoration: none;
  display: inline-block;
}
@media (max-width: 700px) {
  #devtools-btn { display: none; }
}
#devtools-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}

.devtools-system-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.25rem 0.5rem;
}
.devtools-sys-key {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}
.devtools-sys-val {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--text);
}

/* ── Dev console (unified /dev page) ─────────────────────────────────────── */

.dev-console {
  display: flex;
  align-items: stretch;
  gap: 20px;
  /* Both panes get a fixed, viewport-bound height and scroll independently
     within it, instead of a position:sticky sidebar riding alongside a
     page-scrolling content pane. That approach had persistent Safari-only
     mouse-wheel bugs — a position:sticky element that is ALSO its own (or
     even its child's) overflow-y:auto scroll container recomputes the
     sticky offset against the ancestor's scroll on every wheel tick, which
     can reset or altogether block the element's own scroll in WebKit; two
     separate attempts at keeping the sticky sidebar (moving the overflow
     onto an inner box, adding overscroll-behavior) both still hit it. A
     plain fixed-height flex row with two ordinary overflow-y:auto children —
     neither sticky nor fixed — has none of those quirks in any browser.
     160px is a deliberately conservative (not pixel-perfect) budget for the
     sticky header + main's top/bottom padding — main also has `zoom: 1.08`
     (see its rule above), which inflates rendered vs. declared CSS pixels
     inside it in a way that's impractical to account for exactly; erring
     smaller here just leaves a little empty space below the console rather
     than risking it overflowing past the fold again. */
  height: calc(100vh - 160px);
}

.dev-sidebar {
  flex: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px;
  width: 290px;
  transition: width 0.38s cubic-bezier(0.4, 0, 0.2, 1);
  overflow-y: auto;
  /* Without this, once the sidebar's own (often short) scroll range is
     exhausted, the browser's default scroll-chaining hands the rest of the
     wheel gesture to the page underneath — so hovering the sidebar and
     scrolling mostly moves the main content pane's long list instead. */
  overscroll-behavior-y: contain;
}
.dev-sidebar.collapsed { width: 58px; padding: 18px 11px; }

.dev-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.dev-sidebar-title { font-weight: 700; font-size: 1rem; letter-spacing: -0.02em; }
.dev-sidebar-collapse-btn {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 700 15px var(--mono);
}
.dev-sidebar-collapse-btn:hover { color: var(--text); border-color: var(--muted); }

.dev-sidebar-section { margin-bottom: 16px; }
.dev-sidebar-section:last-child { margin-bottom: 0; }
.dev-sidebar-label {
  font: 700 10px var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}

.dev-sidebar-btn, .dev-sidebar-nav-btn {
  display: block;
  width: 100%;
  text-align: left;
  font: 600 12px var(--sans);
  padding: 9px 12px;
  border-radius: 9px;
  margin-bottom: 5px;
  cursor: pointer;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  text-decoration: none;
  box-sizing: border-box;
}
.dev-sidebar-btn:last-child, .dev-sidebar-nav-btn:last-child { margin-bottom: 0; }
.dev-sidebar-btn:hover, .dev-sidebar-nav-btn:hover { border-color: var(--muted); }
.dev-sidebar-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.dev-sidebar-btn:disabled:hover { border-color: var(--border); }
/* Fixed --berry danger hue, not the user's chosen accent scheme; a
   theme-aware color-mix hover instead of a hardcoded dark-mode-only hex. */
.dev-sidebar-btn-danger { border-color: var(--berry); color: var(--berry); }
.dev-sidebar-btn-danger:hover { background: color-mix(in srgb, var(--berry) 12%, transparent); border-color: var(--berry); }
.dev-sidebar-btn-warn { border-color: var(--warning, #d4a017); color: var(--warning, #d4a017); }
.dev-sidebar-btn-warn:hover { border-color: var(--warning, #d4a017); color: var(--warning, #d4a017); }
.dev-sidebar-nav-btn.active { border-color: var(--accentFill, var(--accent)); background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); }

.dev-sidebar-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding: 2px 0;
}
/* dev.js toggles the `hidden` attribute to switch between the full sidebar
   and this collapsed icon rail — but the unconditional display:flex above
   is an author rule, so it always beats the browser's default [hidden]
   { display:none }, leaving the rail visible (stacked below the full
   sidebar) even when collapsed=false. */
.dev-sidebar-rail[hidden] { display: none; }
.dev-rail-btn, .dev-rail-nav-btn {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 700 15px var(--mono);
}
.dev-rail-nav-btn { font-size: 9px; letter-spacing: 0.02em; }
.dev-rail-btn:hover, .dev-rail-nav-btn:hover { color: var(--text); border-color: var(--muted); }
.dev-rail-nav-btn.active { border-color: var(--accentFill, var(--accent)); background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); }
.dev-rail-sep { width: 22px; height: 1px; background: var(--border); margin: 3px 0; }

.dev-content { flex: 1; min-width: 0; overflow-y: auto; }

@media (max-width: 860px) {
  /* Stacked mobile layout reverts to plain page scrolling — the fixed
     height + independent-scroll-panes above are a desktop-only affordance. */
  .dev-console { flex-direction: column; height: auto; }
  .dev-sidebar, .dev-sidebar.collapsed { width: 100%; max-height: none; overflow-y: visible; }
  .dev-sidebar-rail { flex-direction: row; flex-wrap: wrap; }
  .dev-content { width: 100%; overflow-y: visible; }
}

/* ── Dev MBID full-page viewer ───────────────────────────────────────────── */

.dev-mbid-header {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: flex-start;
}
.dev-mbid-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}
.dev-mbid-legend {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
}
.dev-mbid-legend-item {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
}
.dev-mbid-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  width: 100%;
}
.dev-mbid-tabs {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}
.dev-mbid-tab {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  padding: 0.3rem 0.7rem;
  border-radius: 16px;
  cursor: pointer;
  transition: all 0.12s;
}
.dev-mbid-tab:hover { color: var(--text); border-color: var(--muted); }
.dev-mbid-tab.active { color: var(--accentFillText, var(--navText)); border-color: var(--accentFill, var(--accent)); background: var(--accentFill, var(--accent)); }

.dev-mbid-search {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.78rem;
  padding: 0.35rem 0.7rem;
  border-radius: 4px;
  width: 300px;
  min-width: 220px;
  max-width: 300px;
  flex: 0 1 300px;
}
.dev-mbid-search:focus { outline: none; border-color: var(--muted); }

/* Global Matches user filter (issue #495): a <select>, not free text, so it
   doesn't need the full 300px search-box width. */
.dev-matches-user-select { width: auto; min-width: 160px; max-width: 200px; flex: 0 0 auto; }

.dev-mbid-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin: 1rem 0 0.75rem;
}
.dev-mbid-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 0.78rem;
}
.dev-mbid-table th {
  text-align: left;
  padding: 0.5rem 0.75rem;
  color: var(--muted);
  font-weight: 400;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 1;
}
.dev-mbid-table td {
  padding: 0.45rem 0.75rem;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  vertical-align: middle;
}
.dev-mbid-table tr:last-child td { border-bottom: none; }
.dev-mbid-table tr:hover td { background: color-mix(in srgb, var(--surface2) 50%, transparent); }
.dev-mbid-cell-wrap { max-width: 220px; word-break: break-word; }
.dev-mbid-muted { color: var(--muted); }
.dev-mbid-mbid { font-size: 0.68rem; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dev-mbid-empty { color: var(--muted); padding: 1.5rem 0.75rem; }

.dev-mbid-badge {
  display: inline-block;
  font-size: 0.7rem;
  padding: 0.2rem 0.5rem;
  border-radius: 6px;
  white-space: nowrap;
}
/* Fixed semantic hues, not tied to the user's chosen accent scheme — a
   not-found badge previously reused var(--accent), so it could visually
   collide with the matched badge for a user on a teal/green scheme. */
.dev-mbid-status-matched   { background: color-mix(in srgb, #22b3ac 15%, transparent); color: #22b3ac; }
.dev-mbid-status-not_found { background: color-mix(in srgb, var(--berry) 15%, transparent); color: var(--berry); }
.dev-mbid-status-pending   { background: color-mix(in srgb, #e0a015 15%, transparent); color: #e0a015; }
.dev-mbid-status-manual    { background: color-mix(in srgb, #7c5cff 15%, transparent); color: #7c5cff; }

/* Solid-fill status dots (MBID Cache viewer only) — same semantic hues as the
   pill badges above, used as a compact legend-keyed indicator instead of text. */
.dev-mbid-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  flex-shrink: 0;
}
.dev-mbid-dot-matched   { background: #22b3ac; }
.dev-mbid-dot-not_found { background: var(--berry); }
.dev-mbid-dot-pending   { background: #e0a015; }
.dev-mbid-dot-manual    { background: #7c5cff; }

.dev-mbid-actions { text-align: right; }

.dev-mbid-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 0.1rem;
  margin-bottom: 1.5rem;
}
.dev-mbid-info {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
}
.dev-mbid-pagination { display: flex; gap: 0.5rem; }
.dev-mbid-page-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  padding: 0.3rem 0.7rem;
  border-radius: 16px;
  cursor: pointer;
  transition: all 0.12s;
}
.dev-mbid-page-btn:hover:not(:disabled) { color: var(--text); border-color: var(--muted); }
.dev-mbid-page-btn:disabled { opacity: 0.35; cursor: not-allowed; }

/* ── Dev Worker Logs page ────────────────────────────────────────────────── */

body[data-page="dev-worker"] main {
  max-width: min(1400px, 95vw);
}

.dev-worker-header { display: flex; flex-direction: column; gap: 0.6rem; }

.dev-worker-title-row {
  display: flex;
  align-items: center;
  gap: 1rem;
}

/* Range pills on the left, the "show 404 hits" toggle on the right; wraps to
   two lines rather than squeezing the pills on a narrow viewport. */
.dev-metrics-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1rem;
}

.dev-metrics-range {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.dev-metrics-range-btn {
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 0.3rem 0.8rem;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.dev-metrics-range-btn:hover {
  color: var(--text);
}
.dev-metrics-range-btn.active {
  background: var(--accentFill, var(--accent));
  border-color: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
}
.dev-worker-live {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}
.dev-worker-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--muted);
  transition: background 0.3s;
}
.dev-worker-dot.active {
  background: #4caf7d;
  box-shadow: 0 0 0 2px color-mix(in srgb, #4caf7d 25%, transparent);
  animation: dev-worker-pulse 1.5s ease-in-out infinite;
}
@keyframes dev-worker-pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.5; }
}

.dev-worker-last {
  color: var(--muted);
  opacity: 0.7;
}

.dev-worker-stats {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.dev-worker-stat {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
}
.dev-worker-stat-n {
  color: var(--text);
  font-weight: 500;
  margin-right: 0.2rem;
}

/* One row per worker role (musicbrainz / art / artistimage), shown side by side
   so concurrent progress across the three threads is visible at a glance. */
.dev-worker-roles {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.75rem 0 0;
}
.dev-worker-role {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
  background: color-mix(in srgb, #4caf7d 8%, transparent);
  border: 1px solid color-mix(in srgb, #4caf7d 25%, transparent);
  border-radius: 5px;
  font-family: var(--mono);
  font-size: 0.75rem;
}
.dev-worker-role.idle {
  background: color-mix(in srgb, var(--muted) 6%, transparent);
  border-color: color-mix(in srgb, var(--muted) 18%, transparent);
}
.dev-worker-role-name {
  color: #4caf7d;
  font-weight: 500;
  text-transform: uppercase;
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  min-width: 7.5rem;
}
.dev-worker-role.idle .dev-worker-role-name { color: var(--muted); }
.dev-worker-role-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dev-worker-current-phase {
  font-family: var(--mono);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: color-mix(in srgb, #4caf7d 15%, transparent);
  color: #4caf7d;
  border-radius: 3px;
  padding: 0.1rem 0.35rem;
  white-space: nowrap;
}
.dev-worker-current-phase.hidden { display: none; }

.dev-worker-current-elapsed {
  margin-left: auto;
  color: var(--muted);
  font-size: 0.7rem;
  white-space: nowrap;
}

.dev-worker-throttle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.75rem;
  margin: 0.75rem 0 0;
  background: color-mix(in srgb, #f0a500 10%, transparent);
  border: 1px solid color-mix(in srgb, #f0a500 30%, transparent);
  border-radius: 5px;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: #f0a500;
}
.dev-worker-throttle.hidden { display: none; }

.dev-worker-kind {
  font-family: var(--mono);
  font-size: 0.7rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0.1rem 0.35rem;
  color: var(--muted);
}

.dev-worker-detail { font-size: 0.72rem; max-width: 280px; }
.dev-mbid-status-info { background: none; color: var(--muted); font-style: italic; }

.dev-worker-hint {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
  padding: 1.5rem 0;
}
.dev-worker-hint.hidden { display: none; }

/* ── MB Worker Queue (/dev/queue) ────────────────────────────────────────── */

body[data-page="dev-queue"] main {
  max-width: min(1400px, 95vw);
}

.dev-queue-toolbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.25rem;
}

.dev-queue-btn {
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.25rem 0.65rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 16px;
  color: var(--text);
  cursor: pointer;
}
.dev-queue-btn:hover:not(:disabled) { border-color: var(--muted); }
.dev-queue-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* Shared by the queue view's auto-refresh checkbox and the metrics view's
   "show 404 hits" checkbox — same chrome micro-copy role, same treatment. */
.dev-queue-autorefresh,
.dev-metrics-toggle {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 0.35rem;
  cursor: pointer;
  user-select: none;
}

/* One column per worker thread (musicbrainz / art / artistimage), side by side. */
#dev-queue-phases {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1.25rem;
}

.dev-queue-worker-col {
  flex: 1 1 320px;
  min-width: 280px;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.dev-queue-worker-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-bottom: 0.35rem;
  margin-bottom: 0.2rem;
  background: var(--header-bg);
  border-bottom: 2px solid var(--border);
}

.dev-queue-worker-name {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
}

.dev-queue-worker-total {
  margin-left: auto;
  font-size: 0.68rem;
}

.dev-queue-api-dot {
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.15rem 0.45rem;
  border-radius: 3px;
  white-space: nowrap;
}
.dev-queue-api-green { background: color-mix(in srgb, #4caf7d 15%, transparent); color: #4caf7d; }
.dev-queue-api-amber { background: color-mix(in srgb, #f0a500 15%, transparent); color: #f0a500; }
.dev-queue-api-red   { background: color-mix(in srgb, #e05252 15%, transparent); color: #e05252; }

.dev-queue-phase {
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--surface);
  overflow: hidden;
}

.dev-queue-phase-summary {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  user-select: none;
  list-style: none;
}
.dev-queue-phase-summary::-webkit-details-marker { display: none; }
.dev-queue-phase-summary::before {
  content: "▶";
  font-size: 0.55rem;
  color: var(--muted);
  transition: transform 0.15s;
  flex-shrink: 0;
}
details[open].dev-queue-phase > .dev-queue-phase-summary::before {
  transform: rotate(90deg);
}

.dev-queue-phase-name {
  flex: 1;
  font-size: 0.82rem;
  font-weight: 500;
}

.dev-queue-count {
  margin-left: auto;
  font-size: 0.68rem;
  min-width: 1.8rem;
  text-align: center;
}

.dev-queue-subcount {
  font-size: 0.68rem;
  color: var(--muted);
  white-space: nowrap;
}

.dev-queue-phase-empty { opacity: 0.45; }
.dev-queue-phase-empty .dev-queue-phase-name { color: var(--muted); }

.dev-queue-phase-body {
  border-top: 1px solid var(--border);
}

.dev-queue-more {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  padding: 0.4rem 0.75rem;
  margin: 0;
  border-top: 1px solid var(--border);
}

/* ── Home Dashboard ──────────────────────────────────────────────────────────── */

.home-heading-row {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  max-width: 1400px;
  margin: 0 auto;
  padding: 1.5rem 1.5rem 0;
}
.home-heading {
  font-family: var(--sans);
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.05em;
}
.home-heading-date {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.home-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
  padding: 1.5rem;
  max-width: 1400px;
  margin: 0 auto;
}

.home-tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem;
  overflow: hidden;
  min-height: 0;
  animation: tile-in 0.3s ease both;
}

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

.tile-hero       { grid-column: span 8;  animation-delay: 0ms; }
.tile-stats      { grid-column: span 4;  animation-delay: 40ms; }
.tile-top-tracks { grid-column: span 4;  animation-delay: 80ms; }
.tile-albums     { grid-column: span 4;  animation-delay: 120ms; }
.tile-artists    { grid-column: span 4;  animation-delay: 160ms; }
.tile-recent     { grid-column: span 12; animation-delay: 200ms; }

@media (max-width: 1100px) {
  .tile-hero     { grid-column: span 7; }
  .tile-stats    { grid-column: span 5; }
}

@media (max-width: 900px) {
  .home-grid { padding: 1rem; gap: 0.75rem; }
  .home-tile { grid-column: 1 / -1 !important; }
}

body[data-page="stats"] main > .section-header,
body[data-page="recommendations"] main > .section-header {
  padding-left: 1.5rem;
}
@media (max-width: 900px) {
  body[data-page="stats"] main > .section-header,
  body[data-page="recommendations"] main > .section-header {
    padding-left: 1rem;
  }
}

/* ── Statistics page tiles ────────────────────────────────────────────────────*/
/* flex column so .home-stats-grid's flex:1 + align-content:center (below)
   actually has a sized container to center within, instead of the stats
   band sitting pinned at the top with empty space below it. */
.tile-insights-overview { grid-column: span 6; display: flex; flex-direction: column; }
.tile-insights-streaks  { grid-column: span 6; }
.tile-insights-years    { grid-column: span 6; }
.tile-insights-clock    { grid-column: span 12; }
.tile-insights-sources  { grid-column: span 6; }
.tile-insights-genres   { grid-column: span 6; }
.tile-insights-trend    { grid-column: span 6; }

/* ── Doc page (privacy policy, export guide, …) ────────────────────────────────*/
.doc-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 3rem 1.5rem 2rem;
  color: var(--text);
}
.doc-page h1 { font-family: var(--sans); margin-bottom: 0.25rem; }
.doc-updated { color: var(--muted); font-size: 0.85rem; margin-bottom: 2rem; }
.doc-page section { margin-bottom: 1.75rem; }
.doc-page h2 { font-family: var(--sans); font-size: 1.05rem; margin-bottom: 0.5rem; }
.doc-page p, .doc-page li { color: var(--text); line-height: 1.6; }
.doc-page ul, .doc-page ol { padding-left: 1.25rem; }
.doc-page ol li { margin-bottom: 0.4rem; }
.doc-page a { color: var(--accent); }
.doc-page code { background: var(--hair); border-radius: 4px; padding: 0.1rem 0.35rem; }
.doc-back { margin-top: 2rem; }
.doc-back a {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
}
.doc-back a:hover { text-decoration: underline; }

.notfound-page {
  max-width: 480px;
  margin: 0 auto;
  padding: 3rem 1.5rem;
  text-align: center;
}

/* Overview tile: 2-column grid; the 5th stat (days tracked) has no partner
   to sit beside, so it spans the full row and centers below the other four
   instead of leaving a dangling empty cell.
   align-content is flex-start, NOT the base .home-stats-grid's center: this
   tile sits in the same .home-grid row as Top Genres (both grid-column:
   span 6), and default grid stretch makes this tile match Top Genres'
   height — which grows when a genre drill-down opens. Centering here would
   make the stat numbers visibly drift downward every time a sibling tile
   changes height; anchoring to the top means that extra height just becomes
   blank space below instead of moving the numbers. */
.home-stats-grid.insights-overview-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem 1rem;
  align-content: flex-start;
}

.insights-overview-grid .home-stat-item {
  align-items: center;
  text-align: center;
}

.insights-overview-grid .home-stat-item:last-child {
  grid-column: 1 / -1;
  justify-self: center;
}

.insights-overview-grid .home-stat-n { font-size: 2.1rem; }

.insights-footnote {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.75rem;
}

.insights-record {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 0.35rem;
}
.insights-record strong { color: var(--text); font-weight: 600; }

.insights-streak-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.6rem;
}
.insights-streak-badge {
  font-family: var(--mono);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.3rem 0.7rem;
  border-radius: 20px;
  border: 1px solid var(--border);
  white-space: nowrap;
}
.insights-streak-current  { color: var(--accent); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.insights-streak-longest  { color: var(--text); background: var(--surface2); }
.insights-streak-inactive { color: var(--muted); background: var(--surface2); }
.insights-streak-label {
  font-size: 0.8rem;
  color: var(--muted);
}

.insights-clock-grid {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  grid-template-rows: repeat(7, 1fr);
  gap: 2px;
  aspect-ratio: 24 / 7;
}
.insights-clock-cell {
  position: relative;
  border-radius: 2px;
  /* --accentFill, not --accent — a near-white/near-black accent would
     otherwise blend into --surface2 at any intensity, flattening the whole
     heatmap to one indistinguishable tone. See --accentFill in theme.js. */
  background: color-mix(in srgb, var(--accentFill, var(--accent)) calc(var(--intensity) * 100%), var(--surface2));
}
.insights-clock-cell.clock-cell-busiest {
  box-shadow: inset 0 0 0 2px var(--text);
  z-index: 1;
}
@media (max-width: 700px) {
  .insights-clock-grid { aspect-ratio: 24 / 10; }
}

.insights-clock-cell::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.35rem 0.6rem;
  font-size: 0.75rem;
  white-space: nowrap;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.1s ease;
}
.insights-clock-cell:hover::after {
  opacity: 1;
}
.insights-clock-cell.clock-cell-flip::after {
  bottom: auto;
  top: calc(100% + 6px);
}
.insights-clock-cell.clock-cell-start::after {
  left: 0;
  transform: none;
}
.insights-clock-cell.clock-cell-end::after {
  left: auto;
  right: 0;
  transform: none;
}

.tile-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.9rem;
}

.tile-subsection-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 1.1rem 0 0.9rem;
}

.tile-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.9rem;
}

.tile-label-row .tile-label {
  margin-bottom: 0;
}

.tile-view-all {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
}

.tile-view-all:hover {
  text-decoration: underline;
}

.tile-sublabel {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  opacity: 0.7;
  margin-left: 0.3rem;
}

.home-empty {
  font-size: 0.85rem;
  color: var(--muted);
  padding: 1rem 0;
}

/* ── Hero tile (reuses .detail-art-banner from the detail pages) ───────────────*/

.tile-hero { padding: 0; position: relative; }

.tile-hero .hero-banner {
  height: 200px;
  border-radius: 14px;
  cursor: pointer;
  transition: box-shadow 0.15s;
}

.tile-hero .hero-banner:hover {
  box-shadow: 0 0 0 1px rgba(255,255,255,0.06), 0 8px 32px rgba(0,0,0,0.45);
}

.hero-empty {
  height: 200px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1.25rem;
}

.hero-empty .tile-label,
.hero-empty .home-empty {
  margin: 0;
}

.hero-banner-eyebrow {
  position: absolute;
  top: 1.1rem;
  left: 1.1rem;
  z-index: 2;
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
  background: rgba(0,0,0,0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 10px;
  padding: 0.35rem 0.75rem;
}

.hero-eyebrow-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}

/* Corner stat badge — the eyebrow's top-right counterpart (category top-left,
   stat top-right, matching the mockup's paired corner-pill treatment). */
.reco-stat-badge {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  z-index: 2;
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: rgba(255,255,255,0.86);
  background: rgba(0,0,0,0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 20px;
  padding: 0.35rem 0.7rem;
  white-space: nowrap;
}

/* Giant translucent initials watermark — decorative, shown regardless of
   whether real art is loaded (an honest flourish, not a placeholder for
   missing data — see docs/design-language.md). */
.reco-watermark {
  position: absolute;
  bottom: -0.6rem;
  right: 0;
  font-family: var(--sans);
  font-size: 6.5rem;
  font-weight: 700;
  line-height: 0.75;
  letter-spacing: -0.05em;
  color: rgba(255,255,255,0.1);
  z-index: 1;
  pointer-events: none;
  user-select: none;
}

.tile-hero .hero-banner .detail-banner-content {
  padding: 1rem calc(165px + 2.5rem) 1rem 1.1rem;
}

.hero-time {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: rgba(255,255,255,0.7);
  background: rgba(0,0,0,0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 7px;
  padding: 0.15rem 0.55rem;
}

@media (max-width: 600px) {
  .tile-hero .hero-banner {
    height: auto;
    min-height: 190px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }
  .tile-hero .hero-banner .detail-banner-content {
    position: relative;
    inset: auto;
    /* top padding clears the absolutely-positioned "Last played" eyebrow badge,
       which doesn't otherwise contribute to this box's auto height */
    padding: 3.25rem calc(120px + 2.2rem) 1rem 1.1rem;
  }
  .tile-hero .hero-banner .art-img-banner-thumb {
    height: 120px;
    top: 50%;
    transform: translateY(-50%);
  }
  .tile-hero .hero-banner .detail-title {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
  }
}

/* ── Library Stats tile ───────────────────────────────────────────────────────*/

.tile-stats { display: flex; flex-direction: column; }

.home-stats-grid {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 0.5rem;
  align-content: center;
}

.home-stat-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-decoration: none;
  border-radius: 8px;
  padding: 0.25rem 0.4rem;
  margin: -0.25rem -0.4rem;
  transition: background 0.15s;
}

.home-stat-item:hover { background: var(--surface2); }

/* Big stat numbers are data, not chrome — Space Grotesk + neutral colour
   per docs/design-language.md ("accent is not used to colour data itself...
   stat tiles stay neutral"), not the mono/accent treatment reserved for
   machine-voice labels. */
.home-stat-n {
  font-family: var(--sans);
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
  letter-spacing: -0.02em;
}

.home-stat-l {
  font-size: 0.7rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ── Recently Played ──────────────────────────────────────────────────────────*/

.home-recent-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.4rem 1rem;
}

.home-recent-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-width: 0;
  cursor: pointer;
  border-radius: 8px;
  padding: 0.25rem 0.4rem;
  margin: 0 -0.4rem;
  transition: background 0.15s;
}

.home-recent-row:hover { background: var(--surface2); }

.home-recent-img {
  width: 38px;
  height: 38px;
  border-radius: 7px;
  flex-shrink: 0;
}

.home-recent-info {
  flex: 1;
  min-width: 0;
}

.home-recent-name {
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home-recent-meta {
  font-size: 0.74rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

.home-recent-time {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: 0.35rem;
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.home-recent-clock {
  font-size: 0.62rem;
  opacity: 0.65;
}

@media (max-width: 700px) {
  .home-recent-list { grid-template-columns: 1fr; }
  .home-recent-time {
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
  }
  .home-recent-clock { margin-top: 1px; }
}

/* ── Top Tracks / Top Albums ──────────────────────────────────────────────────*/

.home-list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.home-list-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  cursor: pointer;
  border-radius: 8px;
  padding: 0.25rem 0.4rem;
  margin: 0 -0.4rem;
  min-height: 3.42rem;
  transition: background 0.15s;
}

.home-list-row:hover { background: var(--surface2); }

.home-list-img {
  width: 38px;
  height: 38px;
  border-radius: 7px;
  flex-shrink: 0;
}

.home-list-img-round { border-radius: 50%; }

.home-list-info {
  flex: 1;
  min-width: 0;
}

.home-list-name {
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home-list-sub {
  font-size: 0.74rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 1px 0 2px;
}

.home-list-sub-empty { visibility: hidden; }

.home-list-bar-wrap {
  height: 6px;
  background: var(--tickOff, var(--border));
  border-radius: 3px;
  overflow: hidden;
  margin-top: 4px;
}

.home-list-bar {
  height: 100%;
  /* See --accentFill in theme.js — same rationale as .chart-bar-fill. */
  background: var(--accentFill, var(--accent));
  border-radius: 3px;
}

.home-list-plays {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  flex-shrink: 0;
}

/* ── Recommendations refresh countdown ────────────────────────────────────────*/
.reco-refresh-bar {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0.75rem 1.5rem 0;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  letter-spacing: 0.02em;
  min-height: 1.5rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
/* Dev-only manual refresh — there is no user-facing recompute endpoint,
   recommendations are otherwise computed once a week by the worker. */
.reco-refresh-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 0.35rem 0.75rem;
  cursor: pointer;
}
.reco-refresh-btn:hover { border-color: var(--accent); color: var(--text); }
.reco-refresh-btn:disabled { opacity: 0.5; cursor: default; }

/* ── Recommendations page tiles ───────────────────────────────────────────────*/
.tile-reco-forgotten  { grid-column: span 8; animation-delay: 0ms;   padding: 0; }
.tile-reco-new-artist { grid-column: span 4; animation-delay: 40ms;  padding: 0; }
.tile-reco-wildcard   { grid-column: span 4; animation-delay: 80ms;  padding: 0; order: 3; display: flex; flex-direction: column; }
.tile-reco-new-album  { grid-column: span 8; animation-delay: 120ms; padding: 0; order: 4; }

.reco-hero {
  height: 200px;
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow 0.15s;
}
.reco-hero:hover {
  box-shadow: 0 0 0 1px rgba(255,255,255,0.06), 0 8px 32px rgba(0,0,0,0.45);
}
.tile-reco-forgotten .reco-hero,
.tile-reco-new-artist .reco-hero {
  height: 230px;
}
.tile-reco-wildcard .reco-hero {
  flex: 1;
  height: auto;
  min-height: 230px;
}
.tile-reco-forgotten  .reco-hero.reco-has-bio,
.tile-reco-new-artist .reco-hero.reco-has-bio,
.tile-reco-new-album  .reco-hero.reco-has-bio {
  height: 310px;
}

/* Content padding: leave room for the art thumb on the right */
.reco-hero .detail-banner-content {
  padding: 1rem calc(155px + 2.5rem) 1rem 1.1rem;
  z-index: 3;
}
.tile-reco-forgotten .reco-hero .detail-banner-content,
.tile-reco-new-artist .reco-hero .detail-banner-content {
  padding: 1rem calc(185px + 2.5rem) 1rem 1.1rem;
}
/* New Artist: circular portrait centered vertically; text allowed to slide under it */
.tile-reco-new-artist .reco-hero .art-img-banner-thumb {
  width: 150px;
  height: 150px;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 50%;
  object-fit: cover;
}
.tile-reco-new-artist .reco-hero .detail-banner-content,
.tile-reco-wildcard .reco-hero .detail-banner-content {
  padding: 1rem 1.1rem;
  z-index: 3;
}
/* Forgotten/New Album keep the default right-side vertical thumb (no
   centered-portrait override below), so their stat badge must clear it
   instead of sitting in the same top-right corner. */
.tile-reco-forgotten .reco-stat-badge { right: calc(185px + 1.1rem); }
.tile-reco-new-album .reco-stat-badge { right: calc(155px + 1.1rem); }

.tile-reco-wildcard .reco-hero .art-img-banner-thumb {
  top: 50%;
  left: 50%;
  right: auto;
  transform: translate(-50%, -50%);
  height: 190px;
  width: 190px;
  border-radius: 12px;
}

.reco-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1.25rem;
  height: 200px;
  gap: 0.4rem;
}
.tile-reco-forgotten .reco-empty,
.tile-reco-new-artist .reco-empty {
  height: 230px;
}

.hero-bio {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0.5rem 0 0;
  padding: 0.4rem 0.65rem;
  font-size: 0.75rem;
  line-height: 1.55;
  color: rgba(255,255,255,0.82);
  /* No backdrop-filter here (unlike the other pills on this card): WebKit has
     a known bug where `backdrop-filter` + `overflow: hidden` on the same
     element fails to clip overflowing text once `-webkit-line-clamp` cuts a
     line — the blurred background pill renders at the clamped height, but
     the clamped-away line still paints past it with no backing. A plain,
     more opaque solid background avoids the bug entirely (no blur to fight
     the clip) while keeping the pill legible over busy album art. */
  background: rgba(0,0,0,0.62);
  border-radius: 8px;
}

.reco-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
}

.reco-chip {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: rgba(255,255,255,0.85);
  background: rgba(0,0,0,0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 7px;
  padding: 0.2rem 0.55rem;
}

.reco-hero-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-top: 0.5rem;
}

.reco-action-btn {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--accentFillText, var(--navText, #fff));
  background: var(--accentFill, var(--accent));
  border: none;
  border-radius: 20px;
  padding: 0.35rem 0.85rem;
  cursor: pointer;
  white-space: nowrap;
}

.reco-action-btn:hover { filter: brightness(1.08); }

@media (max-width: 900px) {
  .tile-reco-forgotten .reco-hero,
  .tile-reco-new-artist .reco-hero,
  .tile-reco-new-album .reco-hero {
    height: auto;
    min-height: 180px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }
  .tile-reco-forgotten  .reco-hero.reco-has-bio,
  .tile-reco-new-artist .reco-hero.reco-has-bio,
  .tile-reco-new-album  .reco-hero.reco-has-bio {
    /* override the base (non-media) fixed `height: 310px` — without this,
       that more-specific rule still wins and clips normal-flow content
       (the bio paragraph) once it's taller than 310px on a narrow card */
    height: auto;
    min-height: 220px;
  }

  /* Forgotten/New Album pair a long fixed eyebrow label ("Forgotten
     Favourite") with a variable-length stat badge ("Last played 1y ago") —
     side-by-side corners (even reset to the default 1.1rem offset) can
     still be wider than a narrow mobile card, causing the two pills to
     visually overlap. Stack the stat badge under the eyebrow instead so
     they never share a row regardless of text length. */
  .tile-reco-forgotten .reco-stat-badge,
  .tile-reco-new-album .reco-stat-badge {
    top: 3rem;
    left: 1.1rem;
    right: auto;
  }

  /* Forgotten/New Album: shrink the right-pinned thumb from a full-height
     strip to a small centered rectangle so it never shares space with text. */
  .tile-reco-forgotten .reco-hero .art-img-banner-thumb,
  .tile-reco-new-album .reco-hero .art-img-banner-thumb {
    height: 110px;
    width: auto;
    top: 50%;
    transform: translateY(-50%);
  }
  /* New Artist: move the circular portrait above the text instead of behind
     it — "text slides under it" only works at desktop card heights. */
  .tile-reco-new-artist .reco-hero .art-img-banner-thumb {
    width: 84px;
    height: 84px;
    top: 3rem;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }

  /* Wildcard/no-thumb cards: no thumb to reserve space for. */
  .reco-hero.reco-no-thumb .detail-banner-content { padding: 1rem 1.1rem; }
  .tile-reco-forgotten .reco-hero .detail-banner-content,
  .tile-reco-new-album .reco-hero .detail-banner-content {
    position: relative;
    inset: auto;
    /* top padding clears both stacked badge rows (eyebrow + stat badge,
       see above); right padding reserves room for the shrunk thumb above */
    padding: 5rem calc(130px + 1.5rem) 1rem 1.1rem;
  }
  .tile-reco-new-artist .reco-hero .detail-banner-content {
    position: relative;
    inset: auto;
    /* portrait now sits above the text (top: 3rem, 84px tall), so
       padding-top must clear the eyebrow row + portrait + gap */
    padding: calc(3rem + 84px + 0.75rem) 1.1rem 1rem 1.1rem;
  }

  .reco-empty,
  .tile-reco-forgotten .reco-empty,
  .tile-reco-new-artist .reco-empty { height: 180px; }
  /* Don't multi-line-clamp the bio on mobile: `-webkit-line-clamp` +
     `overflow: hidden` on this element doesn't reliably clip in every
     mobile rendering engine — it can compute the correct clamped box
     height for layout while still painting part of the next line past it
     (confirmed via a local repro: the same partial-line leak happened with
     or without -webkit-line-clamp, and with or without backdrop-filter).
     Since the card is already auto-height and grows to fit its content
     (see the .reco-hero rules above), there's no need to clamp at all —
     just let the full bio wrap across as many lines as it needs. */
  .hero-bio {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
  }
}

/* ── Community tools (issue #207) ──────────────────────────────────────────── */
.btn-primary { background: var(--accentFill, var(--accent)); border-color: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); }
.btn-primary:hover { filter: brightness(1.08); }

.community-find, .community-timeline { max-width: 720px; margin: 0 auto 2rem; }
.community-search { margin: 0.6rem 0 1rem; }
.community-search input {
  width: 100%; box-sizing: border-box;
  background: var(--surface2); border: 1px solid var(--border); color: var(--text);
  font-family: var(--sans); font-size: 0.9rem; padding: 0.6rem 0.85rem; border-radius: 8px;
}
.community-search input:focus { outline: none; border-color: var(--accent); }

/* ── Search — People results (item 6: avatars + working Follow button) ──── */
.search-people-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.9rem;
}
.search-people-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: pointer;
}
.search-people-avatar {
  width: 52px; height: 52px; flex: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 1.1rem; font-weight: 700;
  position: relative; overflow: hidden;
}
.search-people-avatar-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.search-people-name { font-family: var(--sans); font-size: 0.94rem; font-weight: 700; letter-spacing: -0.02em; margin-top: 0.65rem; }
.search-people-handle { font-family: var(--mono); font-size: 0.65rem; color: var(--muted); margin-top: 0.15rem; }
.search-people-bio { font-family: var(--sans); font-size: 0.72rem; line-height: 1.4; color: var(--muted); margin-top: 0.5rem; min-height: 1.9em; }
.search-people-follow-btn {
  font-family: var(--mono); font-size: 0.58rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  padding: 0.5rem 1rem; border-radius: 18px; margin-top: 0.65rem;
  background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); border: none;
  cursor: pointer;
}
.search-people-follow-btn.following {
  background: transparent; color: var(--muted); border: 1px solid var(--border);
}

.page-title { max-width: 720px; margin: 0 auto 1.2rem; font-size: 1.6rem; font-weight: 700; }
.following-who { max-width: 720px; margin: 0 auto 1.8rem; }
.following-who-chips { display: flex; flex-wrap: wrap; gap: 0.65rem; }
.following-chip {
  display: flex; flex-direction: column; align-items: center; gap: 0.35rem;
  width: 88px; padding: 0.75rem 0.4rem 0.6rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  text-decoration: none; color: var(--text); transition: border-color 0.12s, background 0.12s;
  text-align: center; overflow: hidden;
  font-family: inherit; cursor: pointer;
}
.following-chip--friend { border-color: var(--accent); }
.following-chip:hover { border-color: var(--accent); background: var(--surface2); }
.following-chip.active {
  border-color: var(--accent); border-width: 2px;
  background: var(--surface2);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
.following-chip--all { justify-content: center; }
.following-chip--all-icon {
  width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
  background: var(--chip); color: var(--muted); border: 2px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 0.7rem; font-weight: 600;
}
.following-chip--all.active .following-chip--all-icon {
  background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText, #fff)); border-color: var(--accentFill, var(--accent));
}
.following-chip-avatar {
  /* background/color are set inline per-person via hashColor() (avatar.js) */
  width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
  position: relative;
  display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 1.1rem; overflow: hidden;
  border: 2px solid var(--border);
}
.following-chip--friend .following-chip-avatar { border-color: var(--accent); }
.following-chip-avatar-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 50%;
}
.following-chip-name {
  font-size: 0.72rem; font-weight: 500; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%;
}
.following-chip-handle { font-family: var(--mono); font-size: 0.6rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%; }
.following-who-more {
  margin-top: 0.6rem;
  font-family: var(--mono); font-size: 0.72rem; color: var(--muted);
  background: none; border: none; padding: 0; cursor: pointer;
}
.following-who-more:hover { color: var(--accent); }

.community-more { text-align: center; padding: 1rem 0; }
.track-owner { font-size: 0.72rem; margin-top: 3px; }
.track-owner a { color: var(--accent); text-decoration: none; }
.track-owner a:hover { text-decoration: underline; }

/* Profile page */
.profile-header {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem;
  max-width: 1240px; margin: 2rem auto 1.5rem; padding-bottom: 1.2rem; border-bottom: 1px solid var(--border);
}
.profile-header-left { display: flex; align-items: flex-start; gap: 1rem; }
.profile-name-row { display: flex; align-items: center; gap: 0.55rem; }
.profile-name { font-size: 1.6rem; margin: 0; }
.profile-pro-pill {
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--accentFillText, var(--navText, #fff));
  background: var(--accentFill, var(--accent));
  border-radius: 20px;
  padding: 0.15rem 0.55rem;
}
.profile-handle { font-family: var(--mono); font-size: 0.78rem; color: var(--muted); margin-top: 2px; }
.profile-summary-line { margin: 0.4rem 0 0; font-size: 0.85rem; color: var(--muted); max-width: 48ch; }
.profile-bio { margin: 0.7rem 0 0; font-size: 0.9rem; color: var(--text); max-width: 48ch; }
.profile-actions { flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 0.5rem; }
/* Avatar circles */
.ep-avatar-circle {
  flex-shrink: 0; width: 52px; height: 52px; border-radius: 50%;
  background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText));
  display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 1.2rem; overflow: hidden;
  border: 2px solid var(--border);
}
.ep-avatar-circle--lg { width: 80px; height: 80px; font-size: 1.8rem; }
.ep-avatar-circle.profile-avatar { width: 80px; height: 80px; font-size: 1.8rem; }
.ep-avatar-circle img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ep-avatar-loading { display: inline-block; width: 24px; height: 24px; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; border-radius: 50%; animation: spin .7s linear infinite; }
.ep-avatar-preview-row { display: flex; align-items: center; gap: 1rem; }
.ep-avatar-btns { display: flex; flex-direction: column; gap: 0.4rem; }
.ep-avatar-upload-label { cursor: pointer; position: relative; overflow: hidden; }
.ep-avatar-upload-label input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
.profile-follow-stats { display: flex; gap: 0.5rem; }
.profile-follow-stat-tile {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.5rem 0.8rem;
  cursor: pointer;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.profile-follow-stat-tile:hover { border-color: var(--accent); }
/* Logged-out public profile: same pill look as the signed-in follow stat
   tiles, but not clickable (no follow list to open when signed out). */
.profile-follow-stat-static {
  display: inline-block;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.77rem;
  padding: 0.45rem 1rem;
  border-radius: 20px;
}
.profile-follow-stat-n {
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
  position: relative;
}
.profile-follow-stat-n .nav-badge { position: absolute; top: -0.6rem; right: -0.9rem; }
.profile-follow-stat-label {
  font-family: var(--mono);
  font-size: 0.58rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 1px;
}

#profile-body { max-width: 1240px; margin: 0 auto; }
.profile-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.6rem; margin-bottom: 1.8rem; }
.profile-stat { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 0.9rem 0.6rem; text-align: center; }
.profile-stat-n { font-size: 1.3rem; font-weight: 600; }
.profile-stat-l { font-family: var(--mono); font-size: 0.66rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 3px; }

.profile-top-stats { margin-bottom: 1.8rem; }
.profile-top-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.profile-top-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 1rem; min-width: 0; }

.profile-plays-head { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.profile-copy-actions { display: flex; align-items: center; gap: 0.5rem; }
.profile-sel-count { font-family: var(--mono); font-size: 0.7rem; color: var(--muted); }

.track-row-profile { cursor: pointer; }
.track-row-profile .play-check { display: none; width: 16px; height: 16px; }

#profile-plays.select-mode .track-row-profile { grid-template-columns: auto 44px 1fr auto auto; cursor: default; }
#profile-plays.select-mode .track-row-profile .play-check { display: block; cursor: pointer; }
#profile-plays.select-mode .entity-link:hover { text-decoration: none; color: inherit; }

.settings-section-note { font-size: 0.8rem; color: var(--muted); margin: 0 0 0.8rem; }
.settings-row-stacked { flex-direction: column; align-items: stretch; gap: 0.4rem; }
.settings-textarea { resize: vertical; font-family: var(--sans); min-height: 3.2rem; }
.settings-link { display: inline-block; margin-top: 0.6rem; color: var(--accent); text-decoration: none; font-size: 0.82rem; }
.settings-link:hover { text-decoration: underline; }

/* ── Edit Profile dialog ────────────────────────────────────────────────── */
.ep-dialog {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  padding: 0;
  max-width: 420px;
  width: calc(100% - 2rem);
  box-shadow: 0 8px 32px rgba(0,0,0,0.25);
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
}
.ep-dialog::backdrop { background: rgba(0,0,0,0.5); }
.ep-dialog-inner { padding: 1.5rem; display: flex; flex-direction: column; gap: 1rem; }
.ep-dialog-title { font-size: 1.05rem; font-weight: 600; margin: 0 0 0.2rem; }
.ep-field { display: flex; flex-direction: column; gap: 0.35rem; }
.ep-label { font-size: 0.82rem; color: var(--muted); }
.ep-hint { font-size: 0.75rem; line-height: 1.45; color: var(--muted); margin: 0; }
.ep-error { font-size: 0.82rem; color: var(--danger, #e84545); margin: 0; }
.ep-dialog-actions { display: flex; justify-content: flex-end; gap: 0.5rem; padding-top: 0.25rem; }

/* ── User list dialog (followers / following) ───────────────────────────── */
.ul-dialog {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  padding: 0;
  max-width: 420px;
  width: calc(100% - 2rem);
  max-height: min(520px, 85vh);
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0,0,0,0.25);
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
}
.ul-dialog::backdrop { background: rgba(0,0,0,0.5); }
.ul-dialog-inner { display: flex; flex-direction: column; max-height: min(520px, 85vh); }
.ul-dialog-head { display: flex; align-items: center; justify-content: space-between; padding: 1.1rem 1.2rem 0.8rem; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.ul-dialog-title { font-size: 0.95rem; font-weight: 600; margin: 0; }
.ul-close-btn { background: none; border: none; cursor: pointer; color: var(--muted); font-size: 1.1rem; padding: 0.2rem 0.4rem; line-height: 1; border-radius: 50%; }
.ul-close-btn:hover { color: var(--text); background: var(--surface); }
.ul-dialog-list { overflow-y: auto; flex: 1; min-height: 0; padding: 0.5rem 0; }

/* .ep-dialog/.ul-dialog centre via fixed top/left/translate
   rather than native <dialog> flex centering, so they need their own mobile
   bottom-sheet override: swap the translate-centered box for a bottom-
   anchored, full-width, top-rounded sheet — same treatment as the
   .kbd-modal/.confirm-dialog family above. */
@media (max-width: 600px) {
  .ep-dialog,
  .ul-dialog {
    top: auto;
    bottom: 0;
    left: 0;
    transform: none;
    width: 100%;
    max-width: 100%;
    border-radius: 16px 16px 0 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .ul-dialog { max-height: 85vh; }
}

.ul-user-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1.2rem; transition: background 0.1s; }
.ul-user-row:hover { background: var(--surface); }
.ul-user-link { display: flex; align-items: center; gap: 0.5rem; flex: 1; min-width: 0; text-decoration: none; color: var(--text); padding: 0.15rem 0; }
.ul-user-avatar { width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; background: var(--accentFill, var(--accent)); color: var(--accentFillText, var(--navText)); position: relative; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 0.85rem; overflow: hidden; border: 1px solid var(--border); }
.ul-user-avatar-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.ul-user-name { font-weight: 500; font-size: 0.88rem; }
.ul-user-handle { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); }
.ul-user-badge { font-family: var(--mono); font-size: 0.65rem; color: var(--accent); border: 1px solid var(--accent); border-radius: 4px; padding: 1px 5px; flex-shrink: 0; }
.ul-follow-btn { flex-shrink: 0; padding: 0.3rem 0.65rem; font-size: 0.66rem; }
.ul-section-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); padding: 0.5rem 1.2rem 0.25rem; }

/* ── "Merge into album…" picker (issue #543) — built on .ul-dialog's chrome */
.amp-row { display: flex; align-items: center; gap: 0.7rem; padding: 0.5rem 1.2rem; cursor: pointer; transition: background 0.1s; }
.amp-row:hover { background: var(--surface); }
.amp-art-thumb { width: 40px; height: 40px; }
.amp-row-info { min-width: 0; flex: 1; }
.amp-row-name { font-family: var(--sans); font-size: 0.88rem; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.amp-row-meta { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); margin-top: 0.1rem; }

@media (max-width: 600px) {
  .profile-stats { grid-template-columns: repeat(2, 1fr); }
  .profile-top-grid { grid-template-columns: 1fr; }
  .profile-header { flex-wrap: wrap; row-gap: 1rem; }
  .profile-actions { flex-shrink: 1; width: 100%; align-items: flex-start; }
  .profile-follow-stats { flex-wrap: wrap; }
}

/* ── Dev: user management table ───────────────────────────────────────────── */
.dev-users-grid {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}
.dev-users-grid th, .dev-users-grid td {
  text-align: left;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.dev-users-grid th {
  font-family: var(--sans);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.dev-users-grid td { font-family: var(--mono); color: var(--text); }
.dev-users-actions { display: flex; flex-wrap: wrap; gap: 0.35rem; }

/* ── Dev: popular artists ─────────────────────────────────────────────────── */

.dev-popular-intro { margin: 1.25rem 0; }

.dev-popular-desc {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 0 0 1rem;
  line-height: 1.55;
}
.dev-popular-desc strong { color: var(--text); }
.dev-popular-desc code   { font-family: var(--mono); font-size: 0.78rem; }

.dev-popular-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.dev-popular-seed-btn {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface2));
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
  color: var(--accent);
}
.dev-popular-seed-btn:hover { border-color: var(--accent); }

.dev-popular-list { margin-top: 1.25rem; }

.dev-popular-table { width: 100%; }

.dev-popular-rank {
  width: 3rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.dev-popular-name { font-weight: 500; }

.dev-popular-mbid {
  font-size: 0.7rem;
  color: var(--muted);
  letter-spacing: 0.01em;
}

/* ── Invites (issue #551) ───────────────────────────────────────────────────
   Reuses .dev-popular-intro/-desc/-actions and .dev-mbid-table-wrap/-table
   for the surrounding layout; these are the pieces genuinely specific to
   this view — the generate form's fields and the freshly-minted-codes panel
   (the page's primary action, so per docs/design-language.md the codes
   themselves are sized as the visual centrepiece, not the form around them). */
.inv-generate-form {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}
.inv-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.78rem;
  color: var(--muted);
}
.inv-field input {
  font-family: var(--sans);
  font-size: 0.85rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  min-width: 8rem;
}
.inv-field-wide input { min-width: 14rem; }
.inv-field input:focus { outline: none; border-color: var(--muted); }
.inv-field input:disabled { opacity: 0.45; cursor: not-allowed; }

.inv-fresh-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 1rem 0 1.5rem;
}
.inv-fresh-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
}
.inv-fresh-code {
  font-family: var(--mono);
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.inv-fresh-actions { display: flex; gap: 0.5rem; }

/* Same semantic-hue mechanism as .dev-mbid-status-*/.dev-mbid-badge above,
   scoped under its own inv- prefix since these are invite-code states, not
   MBID match states, despite sharing the pill look. */
.dev-mbid-badge.inv-status-active  { background: color-mix(in srgb, #22b3ac 15%, transparent); color: #22b3ac; }
.dev-mbid-badge.inv-status-used    { background: color-mix(in srgb, #7c5cff 15%, transparent); color: #7c5cff; }
.dev-mbid-badge.inv-status-revoked { background: color-mix(in srgb, var(--berry) 15%, transparent); color: var(--berry); }
.dev-mbid-badge.inv-status-expired { background: color-mix(in srgb, #e0a015 15%, transparent); color: #e0a015; }

/* ── Landing page (issue #315) ─────────────────────────────────────────────── */

/* Logged-out header (header.js's buildHeader(currentPage, { user: null })) —
   the SAME <header> element/rules as the logged-in app bar (full accent
   background, --navText logo, dark-mode darkening included for free), just a
   simpler 3-column layout: an empty balancing spacer, the centered logo, and
   the public nav (page links + "Log in/Sign up") on the right. No separate
   light/neutral variant — see docs/design-language.md and the PR that
   unified this with the app header. */
.header-left-spacer { justify-self: start; }

.public-nav {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  justify-content: flex-end;
}
.public-nav .nav-btn:not(.active) { opacity: 0.92; }

@media (max-width: 600px) {
  header.header--public { grid-template-columns: auto 1fr; }
  .header-left-spacer { display: none; }
  header.header--public .logo { justify-self: start; }
  header.header--public .header-right { display: flex; }
  .public-nav { gap: 0.85rem; }
}

.landing-main {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 1.5rem 4rem;
}

/* .landing-main carries no top padding (unlike the signed-in page's `main`,
   padding: 2.5rem 1.5rem 4rem), so the header card's own 2rem top margin left
   it ~0.5rem closer to the nav bar than the identical card on profile.html —
   the extra margin-top below corrects that.
   The base .profile-header is otherwise a row (identity left, actions right)
   — the signed-in page still needs that for its Follow/Edit button. The
   public page dropped that button (see profile-follow-stat-static above),
   leaving just the following/followers pills, which read better stacked
   below the identity block than pinned to the top-right on their own. */
body[data-page="public-profile"] .profile-header {
  margin-top: 2.5rem;
}

/* Logged-out public profile: top-list rows and recent-play rows aren't
   clickable here (no JS entity-navigate wired up on this static page), so
   don't borrow the signed-in profile's hover/pointer affordance. */
body[data-page="public-profile"] .home-list-row {
  cursor: default;
}
body[data-page="public-profile"] .home-list-row:hover {
  background: transparent;
}
body[data-page="public-profile"] .track-row:hover {
  background: var(--surface);
}

/* Logged-out public profile: page background stays flat/untinted (bg-tint
   intensity 0) regardless of the visitor's own stored colour-scheme
   saturation — theme.js's applyBgTint() tints --bg globally via an inline
   style on <html>, but a signed-out visitor's local settings shouldn't
   bleed onto someone else's public page. Redeclaring --bg directly on body
   here overrides the inherited tinted value with the plain light/dark
   default (matching the [data-theme] fallback values above, i.e. what
   applyBgTint() itself uses at saturation 0). Light/dark mode itself is
   unaffected — only the accent-tint saturation is neutralized. */
:root[data-theme="light"] body[data-page="public-profile"] { --bg: #faf7f2; }
:root[data-theme="dark"]  body[data-page="public-profile"] { --bg: #131118; }

.landing-hero {
  padding: 5rem 0 3.5rem;
  text-align: center;
}

.landing-hero h1 {
  font-family: var(--sans);
  font-size: clamp(2rem, 5vw, 2.75rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text);
  max-width: 36rem;
  margin: 0 auto 1rem;
}

.landing-hero-sub {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--muted);
  max-width: 32rem;
  margin: 0 auto;
}

.landing-cta {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.8rem 1.35rem;
  border-radius: 24px;
  text-decoration: none;
  display: inline-block;
}

.landing-hero-cta {
  background: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText));
  border: none;
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.8rem 1.35rem;
  border-radius: 24px;
  text-decoration: none;
  display: inline-block;
}
.landing-hero-cta:hover { filter: brightness(1.08); }

.landing-features {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  padding: 1rem 0;
}

.landing-feature {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.5rem;
}

.landing-feature h3 {
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.45rem;
}

.landing-feature p {
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--muted);
}

.landing-closing {
  text-align: center;
  padding: 4rem 0 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
}

@media (max-width: 900px) {
  .landing-features { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .landing-hero { padding: 3rem 0 2.5rem; }
  .landing-features { grid-template-columns: 1fr; }
}

/* ── Demo / example profile page (/demo) ─────────────────────────────────── */
/* A public, server-rendered showcase of what a Stick profile looks like, built
   from sample data. Reuses the landing layout shell (.landing-header/.landing-main)
   plus the stat vocabulary below. */

.demo-hero { padding: 4rem 0 2rem; }
.demo-note { font-family: var(--mono); font-size: 0.8rem; color: var(--muted); margin-top: 1rem; }
.demo-note a { color: var(--accent); text-decoration: none; }
.demo-note a:hover { text-decoration: underline; }

.demo-section { padding: 2rem 0; border-top: 1px solid var(--border); }
.demo-lead { font-size: 0.95rem; line-height: 1.6; color: var(--muted); max-width: 46rem; margin: 0 0 1.5rem; }
.demo-caption { font-size: 0.85rem; color: var(--muted); margin-top: 1rem; }

/* Headline stat row */
.demo-stat-row { display: flex; flex-wrap: wrap; gap: 1rem; }
.demo-stat {
  flex: 1 1 8rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.demo-stat-num { font-family: var(--sans); font-size: 1.6rem; font-weight: 700; letter-spacing: -0.02em; color: var(--text); }
.demo-stat-label { font-family: var(--mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }

/* Top artists / albums / tracks cards */
.demo-grid { display: grid; gap: 1rem; }
.demo-grid-2 { grid-template-columns: repeat(2, 1fr); }
.demo-grid-3 { grid-template-columns: repeat(3, 1fr); }
.demo-card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 1.5rem; }
.demo-card-title { font-family: var(--sans); font-size: 1rem; font-weight: 600; color: var(--text); margin: 0 0 1rem; }
.demo-rank-list { list-style: none; margin: 0; padding: 0; counter-reset: demo-rank; }
.demo-rank-list li {
  counter-increment: demo-rank;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}
.demo-rank-list li:last-child { border-bottom: none; }
.demo-rank-list li::before {
  content: counter(demo-rank);
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  min-width: 1.2rem;
}
.demo-rank-name { color: var(--text); flex: 1; }
.demo-rank-name em { color: var(--muted); font-style: normal; font-size: 0.82rem; }
.demo-rank-count { font-family: var(--mono); font-size: 0.8rem; color: var(--muted); }

/* Listening clock heatmap */
.demo-clock { display: flex; flex-direction: column; gap: 4px; max-width: 40rem; }
.demo-clock-head, .demo-clock-row { display: grid; grid-template-columns: 2.6rem repeat(8, 1fr); gap: 4px; align-items: center; }
.demo-clock-head span { font-family: var(--mono); font-size: 0.62rem; color: var(--muted); text-align: center; }
.demo-clock-day { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); }
.demo-clock-row i { aspect-ratio: 1 / 1; border-radius: 4px; background: var(--accentFill, var(--accent)); display: block; }
.demo-clock-row i.l0 { background: var(--surface); border: 1px solid var(--border); }
.demo-clock-row i.l1 { opacity: 0.25; }
.demo-clock-row i.l2 { opacity: 0.5; }
.demo-clock-row i.l3 { opacity: 0.75; }
.demo-clock-row i.l4 { opacity: 1; }

/* Horizontal bar lists (plays by year, genres) */
.demo-bars { list-style: none; margin: 0; padding: 0; max-width: 42rem; }
.demo-bars li { display: grid; grid-template-columns: 7rem 1fr 3rem; align-items: center; gap: 0.75rem; padding: 0.35rem 0; }
.demo-bar-label { font-size: 0.85rem; color: var(--text); }
.demo-bar { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; height: 0.85rem; overflow: hidden; }
.demo-bar i { display: block; height: 100%; background: var(--accentFill, var(--accent)); }
.demo-bar-val { font-family: var(--mono); font-size: 0.78rem; color: var(--muted); text-align: right; }

/* How-it-works steps */
.demo-steps { margin: 0; padding-left: 1.2rem; max-width: 46rem; }
.demo-steps li { font-size: 0.95rem; line-height: 1.6; color: var(--muted); margin-bottom: 0.9rem; }
.demo-steps li strong { color: var(--text); font-weight: 600; }

@media (max-width: 760px) {
  .demo-grid-2 { grid-template-columns: 1fr; }
  .demo-grid-3 { grid-template-columns: 1fr; }
  .demo-bars li { grid-template-columns: 5.5rem 1fr 2.6rem; }
}

/* ── Connect onboarding wizard ────────────────────────────────────────────── */
/* Minimal onboarding header — the full app nav/search icons are noise during
   a single-purpose setup wizard; keep just the logo (still links home) and
   the account avatar. */
body[data-page="connect"] header .nav-center nav,
body[data-page="connect"] header .search-icon-btn,
body[data-page="connect"] header .pro-nav-btn,
body[data-page="connect"] header .pro-nav-btn-divider {
  display: none;
}

.connect-page {
  max-width: 640px;
  margin: 3rem auto;
  padding: 0 1.5rem;
}
.connect-heading {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  margin: 0 0 0.5rem;
}
.connect-heading--center { text-align: center; }
.connect-sub {
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.5;
  margin: 0 0 2rem;
  max-width: 52ch;
}
.connect-sub--center { text-align: center; margin-left: auto; margin-right: auto; }

.connect-source-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.85rem;
  margin-bottom: 2rem;
}
@media (max-width: 560px) {
  .connect-source-grid { grid-template-columns: 1fr; }
}

.connect-source-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  padding: 1.1rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  cursor: pointer;
  text-align: left;
  text-decoration: none;
  color: var(--text);
  font-family: inherit;
  transition: border-color 0.15s, background 0.15s;
}
.connect-source-card:hover { border-color: var(--accent); }
.connect-source-card.selected {
  border-color: var(--accent);
  background: var(--surface2);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
.connect-source-card.disabled,
.connect-source-card:disabled {
  opacity: 0.5;
  cursor: default;
  pointer-events: none;
}
.connect-source-card--link:hover { border-color: var(--accent); }

.connect-source-icon {
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 10px;
  background: var(--chip);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text);
}
/* Fixed per-service brand colors — not accent-tinted, so each source stays
   recognizable regardless of the user's chosen scheme (same reasoning as
   .source-lastfm/-spotify/-applemusic elsewhere). */
.connect-source-icon--applemusic { background: #c0405a; color: #fff; }
.connect-source-icon--plex       { background: #e5a00d; color: #1a1206; }
.connect-source-icon--spotify    { background: #2f8f4e; color: #fff; }
.connect-source-icon--import     { font-size: 1.1rem; }
.connect-source-name { font-weight: 700; font-size: 0.95rem; }
.connect-source-desc { font-size: 0.78rem; color: var(--muted); line-height: 1.4; }
.connect-source-badge {
  font-family: var(--mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  background: var(--chip);
  border-radius: 20px;
  padding: 0.1rem 0.55rem;
  align-self: flex-start;
}

.connect-step-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
}
.connect-done-actions { justify-content: center; }

.connect-setup-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.connect-setup-row {
  padding: 1.1rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
}
.connect-setup-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.6rem;
}
.connect-setup-row-title { display: flex; align-items: center; gap: 0.7rem; }
.connect-setup-status {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
}
.connect-setup-status.connected { color: #4caf7d; }

/* Honest disclosure list — what the connection actually does, shown before
   the real connect action (there is no simulated OAuth consent screen). */
.connect-permission-list {
  list-style: none;
  margin: 0 0 0.9rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.connect-permission-list li {
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--muted);
  padding-left: 1.2rem;
  position: relative;
}
.connect-permission-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--accent);
  font-weight: 700;
}

.connect-done-tiles {
  display: flex;
  gap: 0.6rem;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0 0 1.5rem;
}
.connect-done-tile {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.6rem 0.9rem;
}
.connect-done-tile-name { font-weight: 700; font-size: 0.85rem; }
.connect-done-tile-status { font-family: var(--mono); font-size: 0.65rem; color: #4caf7d; text-transform: uppercase; letter-spacing: 0.04em; }
.connect-setup-desc {
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.5;
  margin: 0 0 0.6rem;
}
.connect-setup-error {
  font-size: 0.78rem;
  color: var(--danger);
  margin: 0.5rem 0 0;
}
.connect-plex-done-btn { margin-top: 0.75rem; }

.connect-done-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--accentFill, var(--accent));
  color: var(--accentFillText, var(--navText, #fff));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin: 0 auto 1rem;
}

/* ── Guides (/guides, /guides/<slug>) ────────────────────────────────────── */
/* Public how-to articles. Reuse the unified header (see header.js) and the
   demo vocabulary (.demo-section/.demo-note); this block only adds the
   long-form article typography. */
.guide-hero { padding: 3rem 0 1.5rem; }
.guide-hero h1 { font-family: var(--sans); font-size: 2rem; font-weight: 700; letter-spacing: -0.02em; color: var(--text); margin: 0 0 0.75rem; }
.guide-breadcrumb { font-family: var(--mono); font-size: 0.78rem; color: var(--muted); margin: 0 0 1.25rem; }
.guide-breadcrumb a { color: var(--accent); text-decoration: none; }
.guide-breadcrumb a:hover { text-decoration: underline; }

.guide-article { max-width: 46rem; }
.guide-article h2 { font-family: var(--sans); font-size: 1.3rem; font-weight: 600; color: var(--text); margin: 2.25rem 0 0.75rem; }
.guide-article > h2:first-child { margin-top: 0; }
.guide-article h3 { font-family: var(--sans); font-size: 1.05rem; font-weight: 600; color: var(--text); margin: 1.75rem 0 0.5rem; }
.guide-article p, .guide-article li { font-size: 0.95rem; line-height: 1.65; color: var(--muted); }
.guide-article p { margin: 0 0 1rem; }
.guide-article strong { color: var(--text); font-weight: 600; }
.guide-article a { color: var(--accent); text-decoration: none; }
.guide-article a:hover { text-decoration: underline; }
.guide-article ol, .guide-article ul { margin: 0 0 1rem; padding-left: 1.3rem; }
.guide-article li { margin-bottom: 0.5rem; }
.guide-article code {
  font-family: var(--mono);
  font-size: 0.85em;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 0.1em 0.35em;
  color: var(--text);
}
.guide-aside {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.9rem 1.1rem;
  margin: 1.25rem 0;
}
.guide-aside p { margin: 0; font-size: 0.88rem; }

/* Related-guides footer + index cards */
.guide-related { border-top: 1px solid var(--border); margin-top: 2.5rem; padding-top: 1.5rem; }
.guide-related h2 { margin-top: 0; }
.guide-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; }
.guide-card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.25rem 1.4rem;
  text-decoration: none;
}
.guide-card:hover { border-color: var(--accent); }
.guide-card h3 { font-family: var(--sans); font-size: 0.98rem; font-weight: 600; color: var(--text); margin: 0 0 0.4rem; }
.guide-card p { font-size: 0.85rem; line-height: 1.5; color: var(--muted); margin: 0; }

@media (max-width: 760px) {
  .guide-cards { grid-template-columns: 1fr; }
  .guide-hero h1 { font-size: 1.6rem; }
}

/* ── Public profile page (/u/<username>, anonymous viewers) ──────────────── */
/* Server-rendered from profile-public.html; reuses the demo vocabulary. */
.pp-hero .pp-avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--border);
  display: block;
  margin-bottom: 1rem;
}
.pp-username { margin-top: 0.25rem; }
