:root {
  --navy-darkest: #03183d;
  --navy: #0a2b5e;
  --indigo: #42426f;
  --accent: #f2a93c;
  --accent-hover: #e0922a;
  --bg: #ffffff;
  --bg-soft: #f6f7fb;
  --text-primary: #1b2333;
  --text-dim: #5a6478;
  --border: #e4e7ee;
  --radius: 14px;
  --topnav-h: 64px;
  /* App-nav background and floating-panel surface — split out from --navy-darkest
     (which also colors marketing/auth pages that never carry a data-theme attribute)
     so a theme only has to override the tokens the authenticated shell actually uses. */
  --nav-bg: var(--navy-darkest);
  --bg-surface: #ffffff;
}

* { box-sizing: border-box; }

/* Without !important, a later class rule setting its own `display` (e.g. `.songs-pagination
   { display: flex }`) silently wins over the [hidden] attribute at equal specificity — toggle
   visibility with the `hidden` attribute/property everywhere and this stays correct regardless. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  color: var(--text-primary);
  background: var(--bg);
  line-height: 1.5;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Belt-and-suspenders: nothing on the site is meant to scroll horizontally at the
     page level (mock/preview elements that legitimately overflow, like the perform-mode
     mock's <pre>, scroll internally via their own overflow-x instead). */
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: inherit; }

input, select, textarea {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: .6rem .8rem;
  width: 100%;
  font-size: .9rem;
  font-family: inherit;
  transition: border-color .15s;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
input:disabled, select:disabled, textarea:disabled { background: var(--bg-soft); color: var(--text-dim); cursor: not-allowed; }
label { display: block; margin-bottom: .35rem; color: var(--text-dim); font-size: .8rem; }

/* iOS/mobile Safari auto-zooms in on focusing any field under 16px, then stays zoomed in
   after the field blurs — global, not scoped to one layout, since it hits every text input
   on the site (login/register/search/song editor all use plain <input>/<textarea>). */
@media (max-width: 768px) {
  input, select, textarea { font-size: 16px; }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .7rem 1.4rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: .95rem;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: transform .1s ease, background .15s ease;
}
.btn:active { transform: scale(.97); }

.btn-primary { background: var(--accent); color: var(--navy-darkest); }
.btn-primary:hover { background: var(--accent-hover); }

.btn-ghost { background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.35); }
.btn-ghost:hover { background: rgba(255,255,255,.1); }

/* Same idea as .btn-ghost but for light-background pages (dashboard, songs) — .btn-ghost's
   white text/border reads invisible outside the dark navy hero/auth-card contexts it was built for. */
.btn-outline { background: transparent; color: var(--text-primary); border: 1px solid var(--border); }
.btn-outline:hover { background: var(--bg-soft); }
.btn-outline:disabled { opacity: .4; cursor: not-allowed; }

/* Fixed red rather than a theme token — a destructive action should read as "red" the
   same way in every color theme, not shift with the accent color. White-on-red keeps
   its contrast regardless of theme, so it doesn't need a per-theme override. */
.btn-danger { background: #c0392b; color: #fff; }
.btn-danger:hover { background: #a93226; }
.btn-lg { padding: .75rem 1.4rem; font-size: 1rem; }

/* ── Hero ────────────────────────────────────────── */
.home-hero {
  background: linear-gradient(180deg, var(--navy-darkest) 0%, var(--navy) 100%);
  color: #fff;
  padding: 4rem 2rem;
}
.home-hero-inner {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 3rem;
}
.home-hero-copy { flex: 1; min-width: 0; }
.home-hero-side { flex: 1; min-width: 0; }

.home-eyebrow {
  display: inline-block;
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .02em;
  background: rgba(242,169,60,.16);
  color: var(--accent);
  padding: .3rem .75rem;
  border-radius: 999px;
  margin-bottom: 1rem;
}

.home-hero h1 {
  font-size: 3.2rem;
  line-height: 1.12;
  margin: 0;
}
.home-hero h1 em { color: var(--accent); font-style: normal; }

.home-hero-sub {
  font-size: 1.05rem;
  color: #c6d0e6;
  max-width: 46ch;
  margin: 0 0 1.4rem;
}

.home-hero-ctas { display: flex; gap: .8rem; flex-wrap: wrap; margin-bottom: .8rem; }
.home-hero-note { font-size: .85rem; color: #8fa0c2; margin: 0; }

/* ── Sections ────────────────────────────────────── */
.home-section {
  max-width: 1280px;
  margin: 0 auto;
  padding: 3.5rem 2rem;
}
.home-section-head { text-align: center; max-width: 640px; margin: 0 auto 2.5rem; }
.home-section-head h2 { font-size: 1.9rem; margin: 0 0 .6rem; }
.home-section-head p { color: var(--text-dim); margin: 0; }

.home-features {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
}
.home-feature {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
}
.home-feature-icon {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 12px;
  background: var(--navy-darkest);
  font-size: 1.3rem;
  margin-bottom: .9rem;
}
.home-feature h3 { margin: 0 0 .4rem; font-size: 1.05rem; }
.home-feature p { margin: 0; color: var(--text-dim); font-size: .92rem; }

/* ── How it works ────────────────────────────────── */
.home-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}
.home-step { text-align: center; padding: 0 1rem; }
.home-step-num {
  width: 40px; height: 40px;
  margin: 0 auto .9rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--indigo);
  color: #fff;
  font-weight: 700;
}
.home-step h3 { margin: 0 0 .4rem; font-size: 1.05rem; }
.home-step p { margin: 0; color: var(--text-dim); font-size: .92rem; }

/* ── Perform mode showcase ───────────────────────── */
.home-perform {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 3rem;
}
.home-perform-copy { flex: 1; min-width: 0; }
.home-perform-copy h2 { font-size: 1.9rem; margin: .8rem 0; }
.home-perform-copy > p { color: var(--text-dim); max-width: 52ch; margin: 0 0 1.2rem; }
.home-perform-points { list-style: none; margin: 0 0 1.6rem; padding: 0; display: grid; gap: .6rem; }
.home-perform-points li { position: relative; padding-left: 1.5rem; color: var(--text-dim); font-size: .92rem; }
.home-perform-points li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--accent);
  font-weight: 700;
}

/* A CSS-only mock of the real perform-overlay UI (see .perform-bar/.perform-controls/
   .perform-content) — deliberately not a screenshot, so it never goes stale relative to
   the real thing and stays crisp at any size. */
.home-perform-mock {
  flex: 1;
  min-width: 0;
  background: var(--navy-darkest);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 20px 50px -20px rgba(0,0,0,.5);
}
.home-perform-mock-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .7rem 1rem;
  border-bottom: 1px solid rgba(255,255,255,.08);
  color: #fff;
  font-size: .85rem;
}
.home-perform-mock-exit { color: #8fa0c2; }
.home-perform-mock-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.home-perform-mock-title em { margin-left: .5rem; color: #8fa0c2; font-style: normal; font-weight: 400; }
.home-perform-mock-dots { color: #8fa0c2; }
.home-perform-mock-controls {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
  padding: .6rem 1rem;
  border-bottom: 1px solid rgba(255,255,255,.08);
  font-size: .78rem;
  color: #8fa0c2;
}
.home-perform-mock-chip,
.home-perform-mock-scroll,
.home-perform-mock-step {
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px;
  padding: .25rem .65rem;
  white-space: nowrap;
}
.home-perform-mock-scroll { border-color: transparent; background: var(--accent); color: var(--navy-darkest); font-weight: 600; }
.home-perform-mock-step b { color: #fff; }
.home-perform-mock-slider { position: relative; width: 70px; height: 4px; border-radius: 999px; background: rgba(255,255,255,.16); }
.home-perform-mock-slider span { position: absolute; inset: 0 40% 0 0; border-radius: 999px; background: var(--accent); }
.home-perform-mock-content {
  margin: 0;
  padding: 1.5rem;
  font-family: ui-monospace, Menlo, Consolas, "Courier New", monospace;
  font-size: .85rem;
  line-height: 1.7;
  color: #dfe6f5;
  white-space: pre;
  overflow-x: auto;
}

/* ── Personality / about blurb ──────────────────── */
.home-story {
  display: flex;
  align-items: center;
  gap: 2.5rem;
  background: var(--bg-soft);
  border-radius: var(--radius);
  padding: 2.5rem;
}
.home-story img { max-width: 140px; flex-shrink: 0; }
.home-story p { margin: 0 0 .8rem; color: var(--text-dim); }
.home-story p:last-child { margin-bottom: 0; }
.home-story h2 { margin: 0 0 .8rem; font-size: 1.5rem; }

/* ── Final CTA band ──────────────────────────────── */
.home-cta-band {
  background: var(--navy-darkest);
  color: #fff;
  text-align: center;
  padding: 3.5rem 2rem;
}
.home-cta-band h2 { margin: 0 0 .5rem; font-size: 1.8rem; }
.home-cta-band p { color: #b9c4de; margin: 0 0 1.4rem; }

/* ── Footer ──────────────────────────────────────── */
.app-footer,
.home-footer {
  background: var(--nav-bg);
  color: #8fa0c2;
  border-top: 1px solid rgba(255,255,255,.08);
  padding: 1.25rem 2rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: .85rem;
  flex-wrap: wrap;
  gap: .5rem;
}
.app-footer-brand,
.home-footer-brand { display: flex; align-items: center; gap: .6rem; }
.app-footer-brand img,
.home-footer-brand img { height: 22px; filter: brightness(0) invert(1); }

/* ── Home features tablet step-down ──────────────── */
/* 4 columns is roomy on desktop but cramped by ~900px (icon + heading + paragraph per card) —
   step to 2 columns here, then the general 768px mobile block below drops it to 1. Must stay
   ABOVE that block: both apply at e.g. 700px, and the later rule wins the cascade tie. */
@media (max-width: 900px) {
  .home-features { grid-template-columns: repeat(2, 1fr); }
}

/* ── Mobile ──────────────────────────────────────── */
@media (max-width: 768px) {
  .home-hero { padding: 2.5rem 1.25rem; }
  .home-hero-inner { flex-direction: column; text-align: center; gap: 1.75rem; }
  .home-hero-sub { margin: 0 auto 1.4rem; }
  .home-hero-ctas { justify-content: center; }
  .home-hero h1 { font-size: 2.1rem; }

  .home-section { padding: 2.5rem 1.25rem; }
  .home-features { grid-template-columns: 1fr; }
  .home-steps { grid-template-columns: 1fr; gap: 2rem; }

  .home-perform { flex-direction: column; }
  .home-perform-copy > p { margin-left: auto; margin-right: auto; }

  .home-story { flex-direction: column; text-align: center; padding: 1.75rem; }

  .app-footer,
  .home-footer { flex-direction: column; text-align: center; }

  /* The longest chord/lyric line in the perform-mode mock is ~40 monospace
     characters — comfortably fits on desktop, but at full size can nudge past
     a narrow phone's viewport and cause slight page-level horizontal scroll. */
  .home-perform-mock-content { padding: 1rem; font-size: .72rem; }
}

/* ── Alerts ──────────────────────────────────────── */
/* Each alert-* keeps a fixed semantic hue (green/red/blue) but blends it with the
   *current theme's* surface/border/text tokens via color-mix(), rather than a flat hex
   triple — a flat hex always renders as a light-blue-on-white card no matter which
   data-theme is active, which looks jarring against a dark theme's own surfaces. */
.alert {
  padding: .7rem 1rem;
  border-radius: 10px;
  margin-bottom: 1rem;
  font-size: .875rem;
}
.alert-success {
  background: color-mix(in srgb, #1a7f4e 18%, var(--bg-soft));
  border: 1px solid color-mix(in srgb, #1a7f4e 45%, var(--border));
  color: color-mix(in srgb, #1a7f4e 70%, var(--text-primary));
}
.alert-error {
  background: color-mix(in srgb, #b3261e 18%, var(--bg-soft));
  border: 1px solid color-mix(in srgb, #b3261e 45%, var(--border));
  color: color-mix(in srgb, #b3261e 70%, var(--text-primary));
}
.alert-info {
  background: color-mix(in srgb, #1a4f9c 18%, var(--bg-soft));
  border: 1px solid color-mix(in srgb, #1a4f9c 45%, var(--border));
  color: color-mix(in srgb, #1a4f9c 70%, var(--text-primary));
}

/* ── Login / register / forgot-password card ────────── */
.auth-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: var(--navy-darkest);
  padding: 1.5rem;
}
.auth-card {
  background: #fff;
  border-radius: var(--radius);
  padding: 2.5rem;
  width: 100%;
  max-width: 400px;
}
.auth-brand { display: flex; justify-content: center; margin-bottom: 2rem; }
.auth-brand-logo { height: 44px; width: auto; }
.auth-field { margin-bottom: 1rem; }
.auth-hint {
  font-size: .8rem;
  color: var(--text-dim);
}

.btn-full { width: 100%; }

.auth-footer-link {
  text-align: center;
  margin-top: 1.25rem;
  font-size: .85rem;
  color: var(--text-dim);
}

.mt-2 { margin-top: 1rem; }
.mb-2 { margin-bottom: 1rem; }

/* ── Top bar — shared by every page via fragments/topnav.html ────────── */
.app-nav {
  position: relative;
  /* Elements elsewhere on the page that trigger their own stacking context (e.g. the
     tuner instrument tabs' icons, via `filter: drop-shadow`) paint in DOM order among
     other z-index:auto contexts — without a z-index here, one of those can render on
     top of the nav's own positioned children, like the mobile .app-nav-links dropdown,
     since the icons come later in the document than the nav does. */
  z-index: 50;
  height: var(--topnav-h);
  display: flex;
  align-items: center;
  /* Gap between the logo and whatever comes next (nav links, or the anonymous
     Sign In/Get Started actions) — a bit more breathing room than the nav's own
     internal link spacing below. */
  gap: 2rem;
  padding: 0 2rem;
  background: var(--nav-bg);
}
.app-nav-brand { display: flex; align-items: center; }
/* Logo artwork is dark navy line-art on transparent — force it white so it reads
   against the dark navy bar. Same size everywhere the bar appears. */
.app-nav-logo { height: 52px; width: auto; filter: brightness(0) invert(1); }
/* Anonymous (logged-out) state — no nav links exist yet, so these push themselves
   to the far right instead of sitting right after the logo like the nav links do. */
.app-nav-actions { display: flex; align-items: center; gap: .75rem; margin-left: auto; }
.app-nav-links { display: flex; align-items: center; gap: 1.5rem; flex: 1; }
.app-nav-link {
  color: #c6d0e6;
  text-decoration: none;
  font-size: 1rem;
  font-weight: 600;
  /* Five links plus the logo and username stop fitting on one line well before a
     phone-width viewport — wrapping mid-link (e.g. "My Songs" breaking across two
     lines) reads as broken, so this forces the whole nav to switch to the mobile
     dropdown (see the 768px breakpoint below) instead of ever wrapping in place. */
  white-space: nowrap;
}
.app-nav-link:hover { color: #fff; }

/* Hamburger toggle — hidden on desktop, only ever shown under the mobile breakpoint. */
.app-nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}
.app-nav-toggle span { display: block; width: 22px; height: 2px; background: #fff; border-radius: 2px; }

/* ── User menu (click username to open) ──────────────── */
.app-nav-user { position: relative; }
.app-nav-user-btn {
  display: flex;
  align-items: center;
  gap: .35rem;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
}
.app-nav-user-chevron { font-size: 1.1rem; opacity: .9; line-height: 1; }
/* "hooners (logged in as joe)" while an admin is impersonating — deliberately louder
   than the plain username so it's never mistaken for your own normal session. */
.app-nav-impersonating {
  color: var(--accent);
  background: rgba(242, 169, 60, .15);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: .2rem .55rem;
  font-size: .875rem;
}
.app-nav-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  min-width: 230px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(0,0,0,.18);
  padding: .4rem 0;
  z-index: 300;
}
.app-nav-dropdown.open { display: block; }
.app-nav-dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: .55rem 1rem;
  font-size: .87rem;
  font-weight: 500;
  color: var(--text-primary);
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
}
.app-nav-dropdown-item:hover { background: var(--bg-soft); }
/* Blended toward --text-primary (not a flat hex) so the red stays legible against
   --bg-surface in dark themes too — a plain dark red reads as near-invisible on
   Nord/dark/midnight/etc.'s dark surfaces, since both land at similar luminance. */
.app-nav-dropdown-item.app-nav-signout { color: color-mix(in srgb, #b3261e 40%, var(--text-primary) 60%); }
.app-nav-dropdown-divider { height: 1px; background: var(--border); margin: .35rem 0; }
.app-nav-theme-label { font-size: .72rem; color: var(--text-dim); padding: .3rem 1rem .35rem; }
.app-nav-theme-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  justify-items: center;
  gap: .5rem;
  padding: 0 1rem .5rem;
}
.app-nav-theme-btn {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
  background: none;
  flex-shrink: 0;
}
.app-nav-theme-btn span { display: block; width: 100%; height: 100%; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.app-nav-theme-btn:hover, .app-nav-theme-btn.active { border-color: var(--accent); }

.app-nav-item-dropdown { position: relative; }
.app-nav-dropdown-toggle {
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: .3rem;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 600;
  color: #c6d0e6;
  padding: 0;
}
.app-nav-dropdown-toggle:hover { color: #fff; }
.app-nav-tools-dropdown { left: 0; right: auto; min-width: 170px; }

.app-content {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: 2.5rem 2rem;
  flex: 1 0 auto;
}

@media (max-width: 768px) {
  .app-nav { padding: 0 1rem; gap: 1rem; }
  .app-nav-logo { height: 42px; }
  .app-content { padding: 1.5rem 1.25rem; }

  /* Anonymous mobile nav only (logo + Sign In/Get Started) — .app-nav-actions never
     renders once logged in (replaced by the hamburger + dropdown below), so scoping
     via :has() leaves the authenticated single-row layout untouched. Two full pill
     buttons don't fit next to the logo at phone width without crushing "Get Started"
     onto two lines, so instead they drop to their own centered row under a slightly
     bigger logo, where there's room for both without wrapping. */
  .app-nav:has(.app-nav-actions) {
    flex-wrap: wrap;
    justify-content: center;
    height: auto;
    padding-block: .85rem;
    row-gap: .75rem;
  }
  .app-nav-brand:has(+ .app-nav-actions) {
    flex-basis: 100%;
    justify-content: center;
  }
  .app-nav-brand:has(+ .app-nav-actions) .app-nav-logo {
    height: 56px;
  }
  .app-nav-actions {
    flex-basis: 100%;
    justify-content: center;
    margin-left: 0;
  }

  .app-nav-toggle { display: flex; margin-left: auto; }
  .app-nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--nav-bg);
    padding: .5rem 1rem 1rem;
    box-shadow: 0 12px 20px rgba(0, 0, 0, .2);
  }
  .app-nav-links.open { display: flex; }
  .app-nav-link {
    padding: .85rem 0;
    border-bottom: 1px solid rgba(255, 255, 255, .1);
    white-space: normal;
  }
  .app-nav-link:last-child { border-bottom: none; }

  .app-nav-item-dropdown {
    width: 100%;
    border-bottom: 1px solid rgba(255, 255, 255, .1);
  }
  .app-nav-dropdown-toggle {
    width: 100%;
    padding: .85rem 0;
    justify-content: space-between;
  }
  .app-nav-tools-dropdown {
    position: static;
    box-shadow: none;
    border: none;
    background: transparent;
    padding: 0 0 .5rem 1rem;
    min-width: auto;
  }
  .app-nav-tools-dropdown .app-nav-dropdown-item {
    color: #c6d0e6;
    padding: .5rem 0;
    font-size: .95rem;
    background: none;
  }
  .app-nav-tools-dropdown .app-nav-dropdown-item:hover {
    color: #fff;
    background: none;
  }
}

/* ── My Songs ─────────────────────────────────────── */
.songs-toolbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
}
.search-wrap { flex: 1; min-width: 200px; }
.songs-tabs { display: flex; gap: .25rem; background: var(--bg-soft); border-radius: 10px; padding: .25rem; }
.songs-tab {
  border: none;
  background: none;
  padding: .45rem 1rem;
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 600;
  color: var(--text-dim);
  cursor: pointer;
}
.songs-tab.active { background: var(--bg-surface); color: var(--text-primary); box-shadow: 0 1px 2px rgba(0,0,0,.08); }

.songs-empty {
  text-align: center;
  color: var(--text-dim);
  padding: 3rem 1rem;
}

.songs-list-toolbar { display: flex; justify-content: flex-end; align-items: center; gap: .75rem; margin-bottom: .5rem; }
/* My Songs' toolbar only — a count on the left, "Show all" on the right. Scoped by id
   (not the shared .songs-list-toolbar class) since Songlists and the songlist-manage
   columns reuse that same class with only one child, which space-between would shove
   to the wrong edge. */
#songs-list-toolbar { justify-content: space-between; }
.songs-count { font-size: .82rem; font-weight: 600; color: var(--text-dim); }
.link-btn {
  background: none;
  border: none;
  padding: 0;
  font-size: .82rem;
  font-weight: 600;
  color: var(--text-dim);
  cursor: pointer;
}
.link-btn:hover { color: var(--text-primary); text-decoration: underline; }

.songs-table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); }
.songs-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.songs-table th, .songs-table td { padding: .8rem 1rem; text-align: left; }
.songs-table thead th {
  background: var(--bg-soft);
  color: var(--text-dim);
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .03em;
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}
.songs-table th.sortable { cursor: pointer; user-select: none; }
.songs-table th.sortable:hover { color: var(--text-primary); }

/* Admin: Users has more columns than any other .songs-table user (username/email/status/
   songs/created/updated/logins/last-login/action) — reduced font size and tighter padding
   give all 9 columns comfortable breathing room without cramping or wrapping. */
.admin-users-table { font-size: .8rem; }
.admin-users-table thead th { font-size: .72rem; padding: .5rem .55rem; }
.admin-users-table td { padding: .45rem .55rem; }
.admin-users-table .btn { white-space: nowrap; font-size: .75rem; padding: .22rem .55rem; }
.song-row { border-bottom: 1px solid var(--border); cursor: pointer; }
.song-row:last-child { border-bottom: none; }
.song-row:hover { background: var(--bg-soft); }

/* Built-in All Songs / Favorites rows (Song Lists page) — each its own <tbody>, so
   :last-child above would otherwise drop a border whenever there are zero custom lists
   below them. Both get the same soft background so the two built-ins read as one visually
   consistent group, set apart from the user's own lists below. */
.songlist-all-songs-row,
.songlist-favorites-row { background: var(--bg-soft); border-bottom: 1px solid var(--border); }
/* Nudged toward --text-primary rather than a flat light grey — that stayed a
   subtle darkening on the default light theme but became "light grey on light
   text" (unreadable) on dark themes, same failure mode as .songlist-row.is-selected. */
.songlist-all-songs-row:hover,
.songlist-favorites-row:hover { background: color-mix(in srgb, var(--bg-soft) 92%, var(--text-primary) 8%); }
.songlist-builtin-tag { color: var(--text-dim); font-weight: 400; font-size: .82em; }

.songs-fav-col { width: 1%; white-space: nowrap; text-align: center; }
.song-fav-toggle {
  background: none;
  border: none;
  padding: 0;
  line-height: 1;
  cursor: pointer;
}
/* Same path for both states (JS) — only fill/stroke change, so the shape and size
   never shift between outline and filled, unlike swapping two different glyphs. */
.song-fav-toggle svg { fill: none; stroke: var(--border); stroke-width: 1.8; }
.song-fav-toggle:hover svg { stroke: #d94f4f; }
.song-fav-toggle.is-favorite svg { fill: #e0374a; stroke: #e0374a; }
.song-title-link { color: var(--text-primary); font-weight: 600; }

.songs-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1.25rem;
  font-size: .85rem;
  color: var(--text-dim);
}
.btn-sm { padding: .4rem .9rem; font-size: .82rem; }

@media (max-width: 640px) {
  .hide-mobile { display: none; }
  .songs-toolbar { flex-direction: column; align-items: stretch; }
  /* Same reasoning as banana's .btn-xs/.btn-icon bump: under the 44px (iOS) / 48dp
     (Android) tap-target minimum is risky next to Archive, a semi-destructive action. */
  .song-dropdown-item { min-height: 40px; display: flex; align-items: center; }
  .song-row { min-height: 44px; }
  /* A mis-tap here shouldn't fall through to the row's "open dropdown" handler instead
     of toggling the favorite — same 40px+ tap-target reasoning as .song-dropdown-item. */
  .song-fav-toggle { min-width: 40px; min-height: 40px; display: flex; align-items: center; justify-content: center; }
  .song-fav-toggle svg { width: 22px; height: 22px; }
}

/* ── Song row dropdown (View/Edit/Print/YouTube/Archive) ─── */
/* Whole row is the click target (.song-row, above). This wrap just groups the title +
   menu in markup — actual menu position is set inline by songs.js's openMenuAt(), at
   the click point (clamped to stay on-screen), not anchored under the title; a click on
   Last Updated shouldn't force a trip back across the row to reach the menu. */
.song-row-dropdown-wrap { display: inline-block; }
.song-dropdown-menu {
  z-index: 20;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 6px 20px rgba(0,0,0,.12);
  min-width: 170px;
  padding: .35rem;
}
.song-dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: .5rem .7rem;
  border-radius: 7px;
  border: none;
  background: none;
  font-size: .85rem;
  color: var(--text-primary);
  text-decoration: none;
  cursor: pointer;
  font-family: inherit;
}
.song-dropdown-item:hover { background: var(--bg-soft); }
/* Same color-mix fix as .app-nav-signout — a flat dark red is unreadable against
   the dark --bg-surface that dark themes use for this menu. */
.song-dropdown-item-danger { color: color-mix(in srgb, #c0392b 40%, var(--text-primary) 60%); }
.song-dropdown-item-danger:hover { background: color-mix(in srgb, #c0392b 15%, var(--bg-soft)); }
.song-dropdown-divider { border: none; border-top: 1px solid var(--border); margin: .35rem 0; }

/* ── Inline rename (Song Lists) ──────────────────────── */
.inline-rename-input {
  font-size: .9rem;
  font-weight: 600;
  padding: .3rem .5rem;
  border: 1px solid var(--accent);
  border-radius: 6px;
  width: 100%;
  max-width: 320px;
}

/* ── Perform page ─────────────────────────────────────── */
.perform-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1rem;
}
.perform-header .page-title {
  margin: 0;
}
.perform-source-field { max-width: 420px; margin-bottom: 1rem; }
.perform-sort-actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; }

.perform-song-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.perform-set-header {
  padding: .6rem 1rem;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: .85rem;
  color: var(--text-dim);
}
.perform-song-item {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .65rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
  cursor: pointer;
}
.perform-song-item:last-child { border-bottom: none; }
.perform-song-item:hover { background: var(--bg-soft); }
.perform-song-item.is-filtered-out,
.perform-set-header.is-filtered-out { display: none; }
.perform-song-title { font-weight: 600; }
.perform-song-artist { color: var(--text-dim); font-size: .88rem; }

/* Fixed full-viewport overlay — covers the app nav and everything else so performance
   mode feels distraction-free without ever leaving this tab (a real new window would add
   popup-blocker and window-juggling problems, and couldn't share state with the picker
   below it for the in-performance "Songs" drawer). */
.perform-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}
.perform-bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .6rem 1rem;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.perform-bar-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perform-bar-title #perform-current-title { font-weight: 700; }
.perform-current-artist { color: var(--text-dim); margin-left: .4rem; }
.perform-bar-actions { display: flex; gap: .4rem; flex-wrap: wrap; }

.perform-controls {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .5rem 1rem;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  font-size: .85rem;
}
.perform-controls-divider { width: 1px; height: 20px; background: var(--border); }
.perform-speed-label { display: flex; align-items: center; gap: .5rem; color: var(--text-dim); }
/* Fully custom slider (not a native <input type="range">) — a native thumb's own width
   keeps its *center* from ever reaching the true track ends (it can't hang off the edge),
   which reads as a dead zone at min/max no matter how small the thumb is styled. Driving
   this by hand from pointer events maps a click/drag position directly onto the value with
   no such inset, so the whole width is live edge-to-edge.
   The thumb itself (positioned in JS, see setSpeed) is kept inset by its own radius so it
   never overhangs past the track — an overhanging thumb sits outside this container's
   clickable box, so clicking the visible thumb at either extreme would silently do
   nothing, which is its own dead-zone bug. */
.perform-speed-slider {
  position: relative;
  width: 140px;
  height: 20px;
  cursor: pointer;
  touch-action: none;
}
.perform-speed-slider::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 4px;
  transform: translateY(-50%);
  background: var(--border);
  border-radius: 999px;
}
.perform-speed-fill {
  position: absolute;
  top: 50%;
  left: 0;
  height: 4px;
  width: 0;
  transform: translateY(-50%);
  background: var(--accent);
  border-radius: 999px;
  pointer-events: none;
}
.perform-speed-thumb {
  position: absolute;
  top: 50%;
  left: 7px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.perform-speed-slider:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 999px;
}
.perform-step-group { display: flex; align-items: center; gap: .4rem; color: var(--text-dim); }
.perform-step-label { white-space: nowrap; }
.perform-step-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 999px;
  padding: .25rem .6rem;
  font-size: .8rem;
  cursor: pointer;
}
.perform-step-btn:hover { border-color: var(--accent); color: var(--text-primary); }
.perform-step-btn.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--navy-darkest);
  font-weight: 600;
}
.perform-wake-status { color: var(--text-dim); margin-left: auto; }

.perform-content {
  flex: 1;
  overflow: auto;
  margin: 0;
  border: none;
  border-radius: 0;
  padding: 1.5rem;
  font-size: 1.4rem;
}

.perform-drawer {
  position: absolute;
  inset: 0;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  padding: 1rem;
  gap: .75rem;
}
.perform-drawer-header { display: flex; gap: .75rem; align-items: center; }
.perform-drawer-header .add-songs-filter { flex: 1; }
.perform-drawer .perform-song-list { flex: 1; overflow-y: auto; }

@media (max-width: 640px) {
  .perform-bar, .perform-controls { padding: .5rem .75rem; }
  /* padding: cut the left/right gutter well below the desktop 1.5rem — on a narrow phone
     every pixel of padding is a pixel the auto-fit math has to shrink text to make up for,
     and unlike top/bottom padding it buys nothing readability-wise.
     letter-spacing: no system monospace face installed on iOS/Android is meaningfully
     "condensed," but a small negative letter-spacing has the same practical effect — it's a
     uniform per-character adjustment, so a monospace font stays perfectly monospace (every
     chord still lands directly above the lyric character it's aligned to), just packed a
     bit tighter. Desktop/tablet already have enough width and stay at normal spacing. Kept
     in sync with fitFontSize's measurement in perform.js, which copies this onto its hidden
     probe span — change one, change both. */
  .perform-content { padding: .75rem .4rem; letter-spacing: -0.03em; }
  .perform-bar-actions { width: 100%; }
  /* Same iOS/Android tap-target minimum as .setlist-song-row and .song-dropdown-item —
     these rows are the primary "tap to perform" action, so they get the same guard. */
  .perform-song-item { min-height: 44px; }
}

/* ── Song view page ──────────────────────────────────── */
.back-link { color: var(--text-dim); text-decoration: none; font-size: .85rem; }
.back-link:hover { color: var(--text-primary); }
.song-view-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.song-view-title { font-size: 1.6rem; margin: .4rem 0 .2rem; }
.song-view-meta { color: var(--text-dim); margin: 0; font-size: .9rem; }
.song-view-actions { display: flex; gap: .5rem; flex-wrap: wrap; }
.song-content {
  font-family: ui-monospace, Menlo, Consolas, "Courier New", monospace;
  font-size: .9rem;
  line-height: 1.5;
  white-space: pre;
  overflow-x: auto;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin: 0;
}

/* ── Song edit page ──────────────────────────────────── */
.song-form { margin-top: 1.5rem; max-width: 760px; }
.song-form-meta {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1rem;
  margin-bottom: .5rem;
}
.song-form-hint { color: var(--text-dim); font-size: .8rem; margin: 0 0 .5rem; }
.song-content-editor {
  font-family: ui-monospace, Menlo, Consolas, "Courier New", monospace;
  font-size: .9rem;
  line-height: 1.5;
  resize: vertical;
}
.song-form-actions { display: flex; gap: .75rem; margin-top: 1.5rem; }

@media (max-width: 640px) {
  .song-form-meta { grid-template-columns: 1fr; }
  .song-view-actions { width: 100%; }
}

/* ── Song Lists index ────────────────────────────────── */
.songlist-create { max-width: 360px; }

/* ── Manage Songs on a list ──────────────────────────── */
.songlist-manage-header { margin-bottom: 1.25rem; }
.songlist-manage-header h1 { font-size: 1.5rem; margin: .4rem 0 .3rem; }
.songlist-manage-sub { color: var(--text-dim); font-size: .88rem; margin: 0; }

.songlist-filter-wrap { max-width: 420px; margin-bottom: 1.25rem; }

.songlist-columns {
  display: flex;
  align-items: flex-start;
  gap: 1.25rem;
}
.songlist-column {
  flex: 1;
  min-width: 0;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}
.songlist-column-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: .75rem;
  flex-wrap: wrap;
}
.songlist-column-head h2 { font-size: 1rem; margin: 0; }
.songlist-column-actions { display: flex; gap: .9rem; }

.songlist-table .songlist-row { cursor: pointer; }
/* Blended from --accent into --bg-soft (rather than a flat light cream) so the
   selected-row text stays readable in every theme: the default theme's --text-primary
   is dark and this mix stays light, but a dark theme's --text-primary is light and a
   flat #fdf1dc left it near-invisible (the reported Nord bug) — mixing in --bg-soft
   keeps the tint on the correct end of the light/dark spectrum for the active theme. */
.songlist-row.is-selected { background: color-mix(in srgb, var(--accent) 25%, var(--bg-soft)); }
.songlist-row.is-selected:hover { background: color-mix(in srgb, var(--accent) 25%, var(--bg-soft)); }
.songlist-row-disabled { cursor: default; opacity: .45; }
.songlist-row-disabled:hover { background: none; }

.songlist-arrows {
  display: flex;
  flex-direction: column;
  gap: .6rem;
  align-self: flex-start;
  /* Pinned near the top (below the column headers), not centered against
     whichever column happens to be taller — with 300+ available songs vs.
     an empty list, centering pushed these far down the page. */
  position: sticky;
  top: calc(var(--topnav-h) + 1rem);
  padding-top: 2.5rem;
}
.songlist-arrow-btn {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--bg-surface);
  font-size: 1.2rem;
  cursor: pointer;
}
.songlist-arrow-btn:hover:not(:disabled) { background: var(--bg-soft); border-color: var(--accent); }
.songlist-arrow-btn:disabled { opacity: .35; cursor: not-allowed; }

@media (max-width: 640px) {
  .songlist-columns { flex-direction: column; }
  .songlist-arrows {
    flex-direction: row;
    align-self: stretch;
    justify-content: center;
    position: static;
    padding-top: 0;
  }
}

/* ── Create a Setlist (wizard + drag-and-drop editor) ─── */
.setlist-wizard {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin-top: 2rem;
}
.setlist-wizard h2 { font-size: 1.1rem; margin: 0 0 1rem; }
/* Explicit column widths rather than equal auto-fit shares — the setlist name field
   needs real room for a placeholder like "The Roadhouse — Sat night", while Set count
   only ever holds a couple digits. */
.setlist-wizard-grid {
  display: grid;
  grid-template-columns: 1.1fr 2fr 0.9fr 0.6fr 1.3fr;
  gap: 1rem;
  align-items: end;
}
.setlist-wizard-grid .auth-field { margin-bottom: 0; }
.setlist-wizard-actions { margin-top: 1.25rem; }

@media (max-width: 900px) {
  .setlist-wizard-grid { grid-template-columns: 1fr 1fr 1fr; }
}
@media (max-width: 560px) {
  .setlist-wizard-grid { grid-template-columns: 1fr; }
}

/* Songbooks have no date/set-count fields, so its wizard is just source/name/sort — a
   standalone grid (not layered onto .setlist-wizard-grid) so its own breakpoints don't
   fight with that class's for cascade priority. */
.songbook-wizard-grid {
  display: grid;
  grid-template-columns: 1fr 2fr 1.3fr;
  gap: 1rem;
  align-items: end;
}
.songbook-wizard-grid .auth-field { margin-bottom: 0; }
@media (max-width: 560px) {
  .songbook-wizard-grid { grid-template-columns: 1fr; }
}

.setlist-edit-header { margin-bottom: 1.5rem; }
.setlist-edit-header h1 { font-size: 1.5rem; margin: .4rem 0 .3rem; }
.setlist-edit-meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin-top: .9rem;
}
.setlist-edit-inputs {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: flex-end;
  flex: 1;
}
.setlist-edit-inputs .auth-field { margin-bottom: 0; }
.setlist-meta-name { min-width: 220px; flex: 1; }
.setlist-meta-date { min-width: 140px; }
.setlist-meta-sets { min-width: 105px; }
.setlist-sets-input-wrap {
  display: flex;
  align-items: center;
  gap: .35rem;
}
.setlist-sets-input-wrap input[type="number"] {
  width: 64px;
  text-align: center;
  padding: .6rem .4rem;
}
.setlist-sets-apply-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 10px;
  flex-shrink: 0;
  cursor: pointer;
}
.setlist-edit-actions {
  display: flex;
  gap: .5rem;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-left: auto;
}
.setlist-saving {
  font-size: .8rem;
  color: var(--text-dim);
  margin-top: .5rem;
  min-height: 1.1em;
}

.songbook-search { max-width: 360px; margin-bottom: 1rem; }

.setlist-set {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 1.25rem;
}
.setlist-set-title {
  margin: 0;
  padding: .7rem 1rem;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  font-size: 1rem;
}
/* min-height keeps an empty set a viable drop target even before reconcile() adds its
   placeholder row — an empty <ul> otherwise collapses to 0px and can't be dropped into. */
.setlist-set-songs { list-style: none; margin: 0; padding: 0; min-height: 2.75rem; }
.setlist-set-empty {
  padding: 1rem;
  color: var(--text-dim);
  font-size: .85rem;
  font-style: italic;
}
.setlist-song-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .65rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
  cursor: grab;
}
.setlist-song-row:last-child { border-bottom: none; }
.setlist-song-row:active { cursor: grabbing; }
.setlist-song-row.dragging { opacity: .35; }
.setlist-song-row.is-filtered-out { display: none; }
.setlist-song-handle { color: var(--text-dim); user-select: none; font-size: 1.1rem; line-height: 1; }
.setlist-song-index { color: var(--text-dim); font-size: .82rem; width: 1.5rem; flex-shrink: 0; }
.setlist-song-title { font-weight: 600; }
.setlist-song-artist { color: var(--text-dim); font-size: .88rem; }
.setlist-song-remove {
  margin-left: auto;
  background: transparent;
  border: none;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
  transition: color .15s, background-color .15s;
}
.setlist-song-remove:hover {
  color: #c0392b;
  background: color-mix(in srgb, #c0392b 12%, var(--bg-surface));
}

@media (max-width: 640px) {
  .setlist-song-row { min-height: 44px; }
}

/* ── Page titles ─────────────────────────────────────── */
.page-title { font-size: 1.4rem; margin: 0 0 1rem; }

/* ── Settings page ────────────────────────────────────── */
.settings-form { max-width: 440px; }
.settings-form.wide-form, .wide-form { max-width: 640px; }
.admin-email-audience-hint {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  margin-top: .4rem;
  font-size: .85rem;
  color: var(--text-dim);
}
.admin-email-audience-count {
  font-weight: 600;
  color: var(--accent);
}
.settings-divider { border: none; border-top: 1px solid var(--border); margin: 1.5rem 0; }
.settings-hint { color: var(--text-dim); font-size: .8rem; margin: 0 0 1rem; }
.settings-username { color: var(--text-dim); }

/* ── Dashboard tiles ─────────────────────────────────── */
.dashboard-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin-top: 1.5rem;
}
.dashboard-tile {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.dashboard-tile-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}
.dashboard-tile-head h2 { font-size: 1.05rem; margin: 0; }
.dashboard-tile .songs-table-wrap { background: var(--bg); }

/* Right column: Recent Songlists + Recent Setlists stacked, sharing the same total
   height as the left Recently Touched Songs tile — the grid's default stretch already
   sizes this column to match the row height, so an even flex split is all that's needed here. */
.dashboard-tile-column { display: flex; flex-direction: column; gap: 1.5rem; }
.dashboard-tile-half { flex: 1; }

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

/* ── Modal (see app.js's openModal/confirmModal) ──────── */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  z-index: 1000;
}
.modal-box {
  background: var(--bg-surface);
  border-radius: var(--radius);
  padding: 1.5rem;
  width: 100%;
  max-width: 420px;
  max-height: calc(100vh - 2.5rem);
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
}
.modal-title { font-size: 1.15rem; margin: 0 0 .75rem; }
.modal-body { color: var(--text-primary); }
.modal-message { margin: 0; font-size: .95rem; line-height: 1.5; }
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: .75rem;
  margin-top: 1.5rem;
}

@media (max-width: 480px) {
  /* Full-width stacked buttons — easier to hit accurately than two narrow side-by-side
     buttons, same 44px+ tap-target reasoning as the row dropdowns elsewhere. */
  .modal-actions { flex-direction: column; }
  .modal-actions .btn { width: 100%; min-height: 44px; }
}

.modal-box-lg {
  max-width: 580px;
}
.add-songs-container {
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.add-songs-filter {
  width: 100%;
  padding: .55rem .75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text-primary);
  font-size: .9rem;
  box-sizing: border-box;
}
.add-songs-filter:focus {
  outline: none;
  border-color: var(--accent);
}
.add-songs-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  font-size: .85rem;
  color: var(--text-dim);
}
.add-songs-shortcuts {
  display: flex;
  gap: .75rem;
}
.add-songs-shortcuts button {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  padding: 0;
  font-size: .85rem;
  text-decoration: underline;
}
.add-songs-shortcuts button:hover {
  color: var(--accent-hover);
}
.add-songs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  max-height: 48vh;
  overflow-y: auto;
  background: var(--bg);
}
.add-song-item {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .65rem .85rem;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  user-select: none;
  min-height: 44px;
  transition: background .12s ease;
}
.add-song-item:last-child {
  border-bottom: none;
}
.add-song-item:hover,
.add-song-item.is-checked {
  background: var(--bg-soft);
}
.add-song-checkbox {
  width: 1.15rem;
  height: 1.15rem;
  flex-shrink: 0;
  cursor: pointer;
  accent-color: var(--accent);
}
.add-song-info {
  display: flex;
  align-items: baseline;
  gap: .45rem;
  min-width: 0;
  flex-wrap: wrap;
}
.add-song-title {
  font-weight: 600;
  color: var(--text-primary);
}
.add-song-artist {
  font-size: .85rem;
  color: var(--text-dim);
}
.add-songs-empty,
.add-songs-loading {
  padding: 1.5rem;
  text-align: center;
  color: var(--text-dim);
  font-size: .9rem;
  font-style: italic;
}

/* ── Tools: Chord Chart ──────────────────────────────────── */
.chord-chart-page {
  max-width: 960px;
  margin: 0 auto;
  padding-bottom: 3rem;
}
.chord-chart-card {
  display: flex;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .06);
}
.chord-chart-image-wrap {
  flex: 0 0 320px;
  background: var(--bg-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  border-right: 1px solid var(--border);
}
.chord-chart-preview {
  max-width: 100%;
  height: auto;
  display: block;
  transition: transform .2s ease;
}
.chord-chart-preview:hover {
  transform: scale(1.03);
}
.chord-chart-info {
  flex: 1;
  padding: 2rem;
  display: flex;
  flex-direction: column;
}
.chord-chart-title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: .3rem;
}
.chord-chart-meta {
  font-size: .85rem;
  color: var(--text-dim);
  font-weight: 500;
  margin-bottom: 1.25rem;
}
.chord-chart-story {
  color: var(--text-primary);
  font-size: .95rem;
  line-height: 1.6;
  margin-bottom: 1.5rem;
}
.chord-chart-story p {
  margin-bottom: .75rem;
}
.chord-chart-story p:last-child {
  margin-bottom: 0;
}
.chord-chart-actions {
  display: flex;
  gap: .85rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.chord-chart-tip {
  font-size: .88rem;
  color: var(--text-dim);
  background: var(--bg-soft);
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: .85rem 1rem;
  line-height: 1.45;
  margin-top: auto;
}
.chord-chart-tip a {
  color: var(--accent);
  text-decoration: underline;
}

/* ── Tools: Instrument Tuner ────────────────────────────── */
.tuner-page {
  max-width: 760px;
  margin: 0 auto;
  padding-bottom: 3rem;
}
.tuner-header {
  margin-bottom: 1.25rem;
}
.tuner-instrument-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: nowrap;
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.tuner-instrument-tabs {
  display: inline-flex;
  gap: .35rem;
  background: var(--bg-surface);
  padding: .35rem;
  border-radius: 10px;
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.tuner-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: .9rem;
  font-weight: 600;
  padding: .5rem .9rem;
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
  transition: all .15s ease;
}
.tuner-tab-icon {
  width: 22px;
  height: 22px;
  object-fit: contain;
  flex-shrink: 0;
  vertical-align: -3px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .25));
}
.tuner-tab:hover:not(.active) {
  color: var(--text-primary);
  background: var(--bg-soft);
}
.tuner-tab.active {
  background: var(--accent);
  color: var(--navy-darkest);
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .15);
}
.tuner-mic-controls {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-shrink: 0;
}
.tuner-mic-controls .btn {
  min-width: 124px;
  white-space: nowrap;
  justify-content: center;
}
.tuner-mic-status {
  display: flex;
  align-items: center;
  gap: .45rem;
  font-size: .85rem;
  color: var(--text-dim);
  white-space: nowrap;
  min-width: 75px;
}
.tuner-status-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--text-dim);
  display: inline-block;
  transition: background .3s;
}
.tuner-status-dot.active {
  background: #2ecc71;
  box-shadow: 0 0 8px #2ecc71;
  animation: tunerPulse 1.5s infinite;
}
@keyframes tunerPulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .4; transform: scale(1.15); }
}
.tuner-settings-btn {
  padding: 0;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  color: var(--text-dim);
  border: 1px solid var(--border);
  background: var(--bg-surface);
  flex-shrink: 0;
  cursor: pointer;
  transition: all .15s ease;
}
.tuner-settings-btn:hover,
.tuner-settings-btn.active {
  color: var(--text-primary);
  background: var(--bg-soft);
  border-color: var(--accent);
}
.tuner-settings-drawer {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  padding: 1rem 1.5rem;
  animation: tunerDrawerSlide .18s ease-out;
}
@keyframes tunerDrawerSlide {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
.tuner-settings-inner {
  max-width: 100%;
}
.tuner-settings-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: .75rem;
}
.tuner-settings-title {
  font-weight: 700;
  font-size: .92rem;
  color: var(--text-primary);
  display: flex;
  align-items: center;
}
.tuner-settings-close-btn {
  background: transparent;
  border: none;
  font-size: .95rem;
  color: var(--text-dim);
  cursor: pointer;
  padding: .2rem .45rem;
  border-radius: 4px;
  line-height: 1;
}
.tuner-settings-close-btn:hover {
  color: var(--text-primary);
  background: rgba(0, 0, 0, .08);
}
.tuner-settings-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
.tuner-settings-field {
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.tuner-settings-label {
  font-size: .78rem;
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.tuner-device-select {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .5rem .75rem;
  font-size: .88rem;
  font-family: inherit;
  width: 100%;
  cursor: pointer;
  outline: none;
  transition: border-color .15s ease;
}
.tuner-device-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(230, 126, 34, .25);
}
.tuner-settings-hint {
  grid-column: 1 / -1;
  font-size: .82rem;
  color: var(--text-dim);
  margin: .25rem 0 0;
  line-height: 1.45;
}
@media (max-width: 600px) {
  .tuner-settings-body {
    grid-template-columns: 1fr;
  }
}
.tuner-main-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, .08);
  overflow: hidden;
}
.tuner-display-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  padding: 1.75rem 1.5rem 1.25rem;
  border-bottom: 1px solid var(--border);
  gap: 1.5rem;
}
.tuner-meter-wrap {
  display: flex;
  justify-content: center;
  align-items: center;
}
.tuner-meter-svg {
  width: 100%;
  max-width: 280px;
  height: auto;
  display: block;
}
.tuner-meter-label {
  font-size: 11px;
  fill: var(--text-dim);
  text-anchor: middle;
  font-family: inherit;
}
.tuner-meter-label-center {
  font-size: 13px;
  font-weight: 700;
  fill: #2ecc71;
  text-anchor: middle;
  font-family: inherit;
}
.tuner-note-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.tuner-note-large {
  font-size: 4.25rem;
  font-weight: 800;
  line-height: 1;
  color: var(--text-primary);
  min-height: 4.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.tuner-note-octave {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-top: -.4rem;
  margin-bottom: .4rem;
}
.tuner-guidance-badge {
  display: inline-block;
  padding: .35rem .95rem;
  border-radius: 20px;
  font-size: .85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  background: var(--bg-soft);
  color: var(--text-dim);
  border: 1px solid transparent;
  margin-bottom: .5rem;
  transition: all .2s ease;
}
.tuner-guidance-badge.is-intune {
  background: rgba(46, 204, 113, .16);
  color: #2ecc71;
  border-color: rgba(46, 204, 113, .4);
}
.tuner-guidance-badge.is-flat {
  background: rgba(230, 126, 34, .16);
  color: var(--accent);
  border-color: rgba(230, 126, 34, .4);
}
.tuner-guidance-badge.is-sharp {
  background: rgba(231, 76, 60, .16);
  color: #e74c3c;
  border-color: rgba(231, 76, 60, .4);
}
.tuner-freq-readout {
  font-size: .85rem;
  color: var(--text-dim);
  font-family: monospace;
}
.tuner-cents-readout {
  font-size: 1.15rem;
  font-weight: 700;
  min-height: 1.5rem;
  margin-top: .15rem;
}
.tuner-subbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: .75rem 1.5rem;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  font-size: .85rem;
  color: var(--text-dim);
  flex-wrap: wrap;
  gap: .6rem;
}
.tuner-mode-toggle {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.tuner-mode-label {
  display: flex;
  align-items: center;
  gap: .45rem;
  cursor: pointer;
  user-select: none;
  color: var(--text-primary);
  font-weight: 500;
  margin-bottom: 0;
}
.tuner-mode-label input {
  flex-shrink: 0;
  width: auto;
  padding: 0;
}
.tuner-hint {
  font-style: italic;
  color: var(--text-dim);
}
.tuner-headstock-container {
  padding: 1.5rem 1rem 2rem;
  display: flex;
  justify-content: center;
  align-items: center;
  background: radial-gradient(circle at center, var(--bg-soft) 0%, var(--bg-surface) 75%);
}
.tuner-headstock-svg-wrap {
  width: 100%;
  max-width: 330px;
  display: flex;
  justify-content: center;
}
.tuner-headstock-svg {
  width: 100%;
  height: auto;
  max-height: 520px;
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, .3));
}
.tuner-peg-group {
  cursor: pointer;
  outline: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.tuner-peg-group:hover .tuner-peg-btn {
  transform-origin: center;
  filter: brightness(1.2);
}
.tuner-peg-btn {
  fill: var(--bg-surface);
  stroke: var(--text-dim);
  stroke-width: 2;
  transition: all .2s ease;
}
.tuner-peg-btn.peg-active {
  fill: var(--accent);
  stroke: #fff;
  stroke-width: 2.5;
  filter: drop-shadow(0 0 6px var(--accent));
}
.tuner-peg-btn.peg-intune {
  fill: #2ecc71;
  stroke: #fff;
  stroke-width: 2.5;
  filter: drop-shadow(0 0 8px #2ecc71);
}
.tuner-peg-btn.peg-locked {
  stroke: var(--accent);
  stroke-dasharray: 4 3;
  stroke-width: 2.5;
}
.tuner-peg-label {
  fill: var(--text-primary);
  font-size: 13px;
  font-weight: 700;
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  transition: fill .2s ease;
}
.tuner-peg-btn.peg-active ~ .tuner-peg-label {
  fill: var(--navy-darkest);
}
.tuner-peg-btn.peg-intune ~ .tuner-peg-label {
  fill: #fff;
}
.tuner-fret-string {
  transition: stroke .2s, stroke-width .2s;
}
.tuner-fret-string-hit {
  cursor: pointer;
  outline: none;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.tuner-fret-string.string-active {
  stroke: var(--accent) !important;
  stroke-width: 3.5px;
}
.tuner-fret-string.string-intune {
  stroke: #2ecc71 !important;
  stroke-width: 4px;
}
.tuner-headstock-string-guide {
  transition: stroke .2s, opacity .2s, stroke-width .2s;
}
.tuner-headstock-string-guide.string-active {
  stroke: var(--accent) !important;
  opacity: .9 !important;
  stroke-width: 1.8px !important;
}
.tuner-headstock-string-guide.string-intune {
  stroke: #2ecc71 !important;
  opacity: 1 !important;
  stroke-width: 2.2px !important;
}

/* ── Home: Tuner showcase ────────────────────────── */
.home-tuner {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 3.5rem;
}
.home-tuner-copy { flex: 1; min-width: 0; }
.home-tuner-copy h2 { font-size: 1.9rem; margin: .8rem 0; }
.home-tuner-copy > p { color: var(--text-dim); max-width: 52ch; margin: 0 0 1.2rem; }
.home-tuner-points { list-style: none; margin: 0 0 1.6rem; padding: 0; display: grid; gap: .6rem; }
.home-tuner-points li { position: relative; padding-left: 1.5rem; color: var(--text-dim); font-size: .92rem; }
.home-tuner-points li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--accent);
  font-weight: 700;
}

/* CSS/SVG mock of the Tuner UI */
.home-tuner-mock {
  flex: 1;
  min-width: 0;
  background: var(--navy-darkest);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 20px 50px -20px rgba(0,0,0,.5);
  padding: 1.5rem;
  border: 1px solid rgba(255,255,255,.08);
}
[data-theme="dark"] .home-tuner-mock,
[data-theme="midnight"] .home-tuner-mock,
[data-theme="forest"] .home-tuner-mock,
[data-theme="nord"] .home-tuner-mock,
[data-theme="gruvbox"] .home-tuner-mock,
[data-theme="tokyonight"] .home-tuner-mock,
[data-theme="solarized"] .home-tuner-mock {
  background: var(--bg-surface);
  border-color: var(--border);
}

.home-tuner-mock-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding-bottom: .85rem;
  border-bottom: 1px solid rgba(255,255,255,.1);
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.home-tuner-mock-chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .78rem;
  padding: .25rem .65rem;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,.16);
  color: #8fa0c2;
  white-space: nowrap;
}
.home-tuner-mock-icon {
  width: 17px;
  height: 17px;
  object-fit: contain;
  flex-shrink: 0;
  vertical-align: -3px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .25));
}
.home-tuner-mock-chip.active {
  background: var(--accent);
  color: var(--navy-darkest);
  font-weight: 700;
  border-color: transparent;
}
.home-tuner-mock-live {
  font-size: .78rem;
  color: #2ecc71;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: .3rem;
}
.home-tuner-mock-display {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 1rem;
}
.home-tuner-mock-dial {
  display: flex;
  justify-content: center;
}
.home-tuner-mock-svg {
  width: 100%;
  max-width: 220px;
  height: auto;
}
.home-tuner-mock-readout {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.home-tuner-mock-note {
  font-size: 3.25rem;
  font-weight: 800;
  color: #fff;
  line-height: 1;
}
[data-theme="dark"] .home-tuner-mock-note,
[data-theme="midnight"] .home-tuner-mock-note,
[data-theme="forest"] .home-tuner-mock-note,
[data-theme="nord"] .home-tuner-mock-note,
[data-theme="gruvbox"] .home-tuner-mock-note,
[data-theme="tokyonight"] .home-tuner-mock-note,
[data-theme="solarized"] .home-tuner-mock-note {
  color: var(--text-primary);
}
.home-tuner-mock-note sub {
  font-size: 1.15rem;
  color: #8fa0c2;
  font-weight: 600;
}
.home-tuner-mock-badge {
  display: inline-block;
  background: rgba(46, 204, 113, .2);
  color: #2ecc71;
  border: 1px solid rgba(46, 204, 113, .4);
  padding: .25rem .75rem;
  border-radius: 20px;
  font-size: .75rem;
  font-weight: 700;
  margin: .35rem 0;
  letter-spacing: .05em;
}
.home-tuner-mock-freq {
  font-size: .8rem;
  color: #8fa0c2;
  font-family: ui-monospace, monospace;
}

@media (max-width: 768px) {
  .chord-chart-card {
    flex-direction: column;
  }
  .chord-chart-image-wrap {
    flex: none;
    border-right: none;
    border-bottom: 1px solid var(--border);
    padding: 1.5rem;
  }
  .chord-chart-preview {
    max-height: 220px;
    width: auto;
  }
  .chord-chart-info {
    padding: 1.5rem;
  }
  .home-tuner {
    flex-direction: column;
  }
  .home-tuner-copy > p {
    margin-left: auto;
    margin-right: auto;
  }
}
@media (max-width: 640px) {
  .tuner-instrument-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .tuner-instrument-tabs {
    width: 100%;
    justify-content: center;
  }
  .tuner-tab {
    flex: 1;
    text-align: center;
    padding: .5rem .4rem;
    font-size: .85rem;
  }
  .tuner-mic-controls {
    justify-content: space-between;
  }
  .tuner-display-section {
    grid-template-columns: 1fr;
    padding: 1.25rem 1rem;
    gap: 1rem;
  }
  .tuner-meter-svg {
    max-width: 240px;
  }
  .tuner-subbar {
    flex-direction: column;
    align-items: flex-start;
    padding: .75rem 1rem;
  }
  .tuner-mode-toggle,
  .tuner-mode-label {
    width: 100%;
  }
  .tuner-mode-label span {
    flex: 1;
    min-width: 0;
  }
  .tuner-headstock-container {
    padding: 1rem .5rem 1.5rem;
  }
  .home-tuner-mock-display {
    grid-template-columns: 1fr;
    gap: .75rem;
  }
}
@media (max-width: 480px) {
  .chord-chart-actions {
    flex-direction: column;
  }
  .chord-chart-actions .btn {
    width: 100%;
    justify-content: center;
  }
}


/* ── Color themes ────────────────────────────────────────
   The default (:root, no data-theme attribute) is the site's original navy/gold
   look — kept as-is and selected on first load. Every other theme only needs to
   override the tokens the authenticated app shell actually uses (see --nav-bg /
   --bg-surface above) — --navy/--indigo are marketing-page-only and never seen
   under a data-theme attribute, so themes don't redefine them. */
[data-theme="dark"] {
  --nav-bg: #16213e;
  --bg-surface: #0f3460;
  --accent: #e5a00d;
  --accent-hover: #c4880a;
  --bg: #1a1a2e;
  --bg-soft: #1e2d5a;
  --text-primary: #e8e8e8;
  --text-dim: #9a9ab0;
  --border: #2a2a4a;
}
[data-theme="midnight"] {
  --nav-bg: #141414;
  --bg-surface: #1c1c2e;
  --accent: #6c63ff;
  --accent-hover: #5a52e0;
  --bg: #0d0d0d;
  --bg-soft: #252540;
  --text-primary: #e8e8ff;
  --text-dim: #9090c0;
  --border: #2a2a4a;
}
[data-theme="forest"] {
  --nav-bg: #141f14;
  --bg-surface: #1a2b1a;
  --accent: #4caf50;
  --accent-hover: #3d8b40;
  --bg: #0f1a0f;
  --bg-soft: #223022;
  --text-primary: #dff0df;
  --text-dim: #8fb89f;
  --border: #2a402a;
}
[data-theme="nord"] {
  --nav-bg: #333a48;
  --bg-surface: #3b4252;
  --accent: #88c0d0;
  --accent-hover: #5e81ac;
  --bg: #2e3440;
  --bg-soft: #434c5e;
  --text-primary: #eceff4;
  --text-dim: #d8dee9;
  --border: #4c566a;
}
[data-theme="gruvbox"] {
  --nav-bg: #32302f;
  --bg-surface: #3c3836;
  --accent: #fe8019;
  --accent-hover: #d65d0e;
  --bg: #282828;
  --bg-soft: #504945;
  --text-primary: #ebdbb2;
  --text-dim: #bdae93;
  --border: #45403d;
}
[data-theme="tokyonight"] {
  --nav-bg: #1f2335;
  --bg-surface: #2d3348;
  --accent: #7aa2f7;
  --accent-hover: #3d59a1;
  --bg: #24283b;
  --bg-soft: #363b54;
  --text-primary: #c0caf5;
  --text-dim: #a9b1d6;
  --border: #363b54;
}
[data-theme="solarized"] {
  /* Nav bg uses the accent directly rather than --bg-surface — solarized's surface
     tone is a light cream, and .app-nav-username/.app-nav-link are hardcoded light
     colors that need a dark-ish bar behind them, the same fix banana applies to its
     own light-background themes. */
  --nav-bg: #268bd2;
  --bg-surface: #fdf6e3;
  --accent: #268bd2;
  --accent-hover: #1e6ba8;
  --bg: #eee8d5;
  --bg-soft: #e3dcc5;
  --text-primary: #073642;
  --text-dim: #586e75;
  --border: #d3cbb7;
}
