/* =============================================================================
   Unison
   =============================================================================

   Two environments, two sets of rules:

   - CHROME (library, editor, settings) — you use this in a rehearsal room, a
     kitchen, a train. It can be light or dark, and it can have some personality.

   - STAGE (the performance view) — you use this under lights, at arm's length,
     mid-song. It is ALWAYS dark, always high contrast, and deliberately dull.
     Colour here competes with the chart for your attention, and the chart has
     to win. This is why the light theme doesn't reach it.

   ============================================================================= */

/* ------------------------------------------------------------------ tokens */

:root {
  /* Type scale — 1.2 ratio. Sizes are decided here, never in a component. */
  --t-xs: 11px;
  --t-sm: 13px;
  --t-md: 15px;
  --t-lg: 18px;
  --t-xl: 22px;
  --t-2xl: 28px;

  /* Spacing — a 4px grid. Everything lands on it. */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-full: 999px;

  /* One easing curve everywhere. Mixed easings are what make an interface feel
     assembled from parts rather than designed. */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --fast: .14s var(--ease);
  --med: .22s var(--ease);

  /* Poppins for the interface. The system stack stays as the fallback so the app
     still renders correctly while the webfont loads — or forever, if it never
     does, because a gig app must not depend on a CDN.

     NOT for the chart: chords must sit exactly over their syllable, and tab
     alignment IS the notation. Those stay monospace. */
  --font: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* One solid accent. No gradients anywhere.
     A gradient has to clear contrast at BOTH ends, which is why the old one
     forced awkward text colours. A single solid colour is one decision, checked
     once — and it's what every serious tool uses. --grad is kept as an alias so
     nothing breaks, but it resolves to the flat brand colour. */
  --grad: var(--brand);

  /* Stage colours. Fixed — these never respond to the theme. */
  --stage-bg: #050a09;
  --stage-panel: #0c1412;
  --stage-line: #16302a;
  --stage-text: #f1f5f9;
  --stage-muted: #7c9088;
  --stage-chord: #34d399;      /* emerald chords on forest black — on brand */
  --stage-note: #ffb703;

  --sec-verse: #7c9088;
  --sec-chorus: #34d399;
  --sec-bridge: #c77dff;
  --sec-tab: #10b981;

  --chart-size: 20px;
  --chart-font: var(--mono);
}

/* Dark chrome (default) — Unison "Green Fire": deep forest black, glowing emerald.
   This is the brand's home. Colour here is the identity, not decoration. */
:root, [data-theme="dark"] {
  --bg: #050a09;           /* Forest Black */
  --surface: #0c1412;      /* Forest Surface */
  --surface-2: #12201c;
  --line: #16302a;         /* dark emerald hairline */
  --text: #f1f5f9;
  --text-2: #9fb3ab;
  --muted: #7c9088;        /* clears AA on the forest bg */
  --danger: #ff6b6b;
  --ok: #34d399;
  --shadow-1: 0 1px 2px rgba(0,0,0,.5);
  --shadow-2: 0 8px 24px -6px rgba(0,0,0,.6);
  --shadow-3: 0 20px 48px -12px rgba(0,0,0,.75);

  /* Emerald Core is the primary accent; a lighter emerald is the secondary. Dark
     forest text sits on the solid emerald for legibility. */
  --brand: #10b981;        /* Emerald Core */
  --brand-2: #34d399;      /* accent only — admin pills, bridge spine */
  --on-brand: #04140c;
  --glow: 0 0 24px rgba(16,185,129,.22);   /* the "green fire" glow */
  color-scheme: dark;
}

/* Light chrome — deeper gradient so white text on it is actually legible. */
[data-theme="light"] {
  --bg: #fbfbfd;
  --surface: #ffffff;
  --surface-2: #f2f2f5;
  --line: #e3e3e8;
  --text: #16161a;
  --text-2: #55555f;
  --muted: #6e6e78;        /* 4.88:1 — the 8e8e98 it was managed only 3.14 */
  --danger: #d92d20;
  --ok: #17a34a;
  --shadow-1: 0 1px 2px rgba(16,16,24,.06);
  --shadow-2: 0 8px 24px -8px rgba(16,16,24,.14);
  --shadow-3: 0 20px 48px -12px rgba(16,16,24,.2);

  /* Light chrome — the same emerald brand, deepened so white text on it is legible. */
  --brand: #047857;        /* emerald-700 — 4.5:1 with white */
  --brand-2: #059669;
  --on-brand: #ffffff;
  --glow: 0 0 24px rgba(16,185,129,.18);
  color-scheme: light;
}

/* =============================================================================
   Colour + layout schemes
   =============================================================================

   A scheme re-skins the accent (and gives the whole app a corner-radius
   personality) WITHOUT touching the dark/light machinery — the two are
   independent, so every scheme works in both themes. The default ("classic")
   defines no overrides, so it just uses the cyan above.

   The accent is set per-theme with a compound selector so it beats the base
   token in that theme; the radius is set once, since roundness reads the same
   light or dark. Every brand/on-brand pair below was contrast-checked: bright
   accent + near-black text in dark, deeper accent + white text in light.
   ============================================================================= */

/* Ocean — teal, indigo accent, standard radius. */
[data-scheme="ocean"][data-theme="dark"]  { --brand:#0ea5b7; --brand-2:#818cf8; --on-brand:#03121a; }
[data-scheme="ocean"][data-theme="light"] { --brand:#0e7490; --brand-2:#4f46e5; --on-brand:#ffffff; }

/* Sunset — warm orange, rose accent, soft (large) radius. */
[data-scheme="sunset"][data-theme="dark"]  { --brand:#fb923c; --brand-2:#fb7185; --on-brand:#1c0a01; }
[data-scheme="sunset"][data-theme="light"] { --brand:#c2410c; --brand-2:#be123c; --on-brand:#ffffff; }
[data-scheme="sunset"] { --r-sm:12px; --r-md:16px; --r-lg:22px; --r-xl:28px; }

/* Forest — green, teal accent, standard radius. */
[data-scheme="forest"][data-theme="dark"]  { --brand:#34d399; --brand-2:#2dd4bf; --on-brand:#04140c; }
[data-scheme="forest"][data-theme="light"] { --brand:#15803d; --brand-2:#0f766e; --on-brand:#ffffff; }

/* Berry — magenta, violet accent, extra-round (pill) radius. */
[data-scheme="berry"][data-theme="dark"]  { --brand:#f472b6; --brand-2:#c084fc; --on-brand:#1c0512; }
[data-scheme="berry"][data-theme="light"] { --brand:#be185d; --brand-2:#7c3aed; --on-brand:#ffffff; }
[data-scheme="berry"] { --r-sm:12px; --r-md:16px; --r-lg:20px; --r-xl:26px; }

/* Slate — steel blue, cool grey accent, tight (squared) radius: the professional
   one, for a leader who wants it to look like admin software, not a toy. */
[data-scheme="slate"][data-theme="dark"]  { --brand:#60a5fa; --brand-2:#94a3b8; --on-brand:#040d1a; }
[data-scheme="slate"][data-theme="light"] { --brand:#2563eb; --brand-2:#475569; --on-brand:#ffffff; }
[data-scheme="slate"] { --r-sm:5px; --r-md:7px; --r-lg:10px; --r-xl:12px; }

/* ------------------------------------------------------------------- base */

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; overscroll-behavior: none; }

body {
  background: var(--bg);
  color: var(--text);
  font: 300 var(--t-md)/1.5 var(--font);      /* Poppins Light — the base weight */
  -webkit-font-smoothing: antialiased;
  transition: background var(--med), color var(--med);
}

/* Poppins Light means headings carry the weight, not the body. Medium (500) for
   headings reads clean and confident without going heavy — the monochrome look
   leans on weight and space for hierarchy, not colour. */
h1, h2, h3, h4 { font-weight: 500; letter-spacing: -.2px; }

.screen { display: none; height: 100dvh; flex-direction: column; }
.screen.on { display: flex; animation: rise var(--med); }

/* Boot splash: shown until auth resolves, so no flash of the app before login.
   While booting, every screen is suppressed and only the splash shows. */
body.booting .screen { display: none !important; }
.boot-splash {
  position: fixed; inset: 0; z-index: 200; display: none;
  align-items: center; justify-content: center; background: var(--bg);
}
body.booting .boot-splash { display: flex; }
.boot-splash .badge.lg { width: 64px; height: 64px; border-radius: var(--r-xl); animation: bootpulse 1.4s ease-in-out infinite; }
.boot-splash .badge.lg .flamemark { width: 40px; height: 40px; }
@keyframes bootpulse { 0%, 100% { opacity: .55; transform: scale(.96); } 50% { opacity: 1; transform: scale(1); } }

/* The content pane inside a screen — a flex column that fills and owns its
   scroll. Both the library and the dashboard use it. */
.main { display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0; }

@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .screen.on { animation: none; }
  * { transition: none !important; }
}

/* Icons: size and colour come from the parent, so one <use> works everywhere. */
.ic {
  width: 20px; height: 20px; flex: none;
  fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.ic.sm { width: 16px; height: 16px; }
.ic.lg { width: 24px; height: 24px; }
/* Play/pause read better solid than outlined at small sizes. */
.ic.solid { fill: currentColor; stroke: none; }
/* The flame logo is an inline gradient SVG (not a stroke icon), so it renders its
   own colour reliably everywhere. Sized to sit inside its badge. */
.flamemark { width: 26px; height: 26px; display: block; }
.side-mark .badge .flamemark { width: 24px; height: 24px; }

/* ------------------------------------------------------------------- bars */

.bar {
  display: flex; align-items: center; gap: var(--s-2);
  padding: calc(env(safe-area-inset-top) + var(--s-4)) var(--s-4) var(--s-3);
  flex: none;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.bar h1 {
  font-size: var(--t-xl); font-weight: 650; letter-spacing: -.5px; flex: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bar h1.sm { font-size: var(--t-lg); }

.icon {
  background: var(--surface); border: 1px solid var(--line); color: var(--text);
  width: 40px; height: 40px; border-radius: var(--r-md);
  display: grid; place-items: center; cursor: pointer; flex: none;
  transition: background var(--fast), transform var(--fast), border-color var(--fast);
}
.icon:hover { border-color: var(--muted); }
.icon:active { transform: scale(.93); background: var(--surface-2); }
.icon.brand { background: var(--brand); border: none; color: var(--on-brand); }
.icon.danger { color: var(--danger); }

/* ---------------------------------------------------------------- controls */

/* One button contract. Height is governed by min-height so every button — in a
   toolbar, a modal, a card — lines up regardless of any padding override. Labels
   stay on one line so a long label never grows a button taller than its sibling. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  background: var(--brand); color: var(--on-brand); border: none;
  border-radius: var(--r-md); padding: var(--s-2) var(--s-5); min-height: 44px;
  font: 600 var(--t-md) var(--font); line-height: 1.2; text-align: center;
  cursor: pointer; transition: transform var(--fast), filter var(--fast);
}
.btn:hover { filter: brightness(1.08); }
.btn:active { transform: scale(.97); filter: brightness(1.08); }
.btn.ghost {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); box-shadow: none;
}
.btn.ghost:active { background: var(--surface-2); }
.btn.danger { background: none; color: var(--danger); border: 1px solid var(--line); box-shadow: none; }
/* Small + block modifiers, so callers never hand-roll a size with inline padding. */
.btn.sm { min-height: 36px; padding: 0 var(--s-4); font-size: var(--t-sm); }
.btn.block { width: 100%; }
/* A stacked choice button may need two lines — allow it, but keep both tall and
   equal via a shared min-height. */
.btn.tall { min-height: 52px; white-space: normal; text-align: center; }

input[type=text], input[type=date], input[type=url], input[type=email],
input[type=number], input[type=search], input[type=tel], input[type=password],
textarea, select {
  width: 100%; background: var(--surface); border: 1px solid var(--line);
  color: var(--text); border-radius: var(--r-md);
  padding: 12px 14px; font: 400 var(--t-md) var(--font);
  transition: border-color var(--fast), box-shadow var(--fast);
}
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}
/* Date fields: match the app, and colour the calendar icon to the accent so it
   reads as ours rather than a raw browser control. */
input[type=date] { position: relative; }
input[type=date]::-webkit-calendar-picker-indicator {
  cursor: pointer; opacity: .55; border-radius: 4px; padding: 3px;
}
input[type=date]::-webkit-calendar-picker-indicator:hover {
  opacity: 1; background: color-mix(in srgb, var(--brand) 16%, transparent);
}
[data-theme="dark"] input[type=date]::-webkit-calendar-picker-indicator { filter: invert(1); }
input::placeholder, textarea::placeholder { color: var(--muted); }

/* Segmented control */
.seg-ctl {
  display: flex; background: var(--surface-2); border-radius: var(--r-md);
  padding: 3px; gap: 2px;
}
.seg-ctl button {
  flex: 1; background: none; border: none; color: var(--text-2);
  padding: 9px var(--s-2); border-radius: var(--r-sm); min-height: 38px;
  font: 600 var(--t-sm) var(--font); cursor: pointer;
  transition: background var(--fast), color var(--fast);
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
}
.seg-ctl button.on {
  background: var(--surface); color: var(--text); box-shadow: var(--shadow-1);
}
[data-theme="light"] .seg-ctl button.on { background: #fff; }

/* Sort control bar (e.g. the team picker: sort by name / instrument). */
.sort-bar { display: flex; align-items: center; gap: 10px; padding: 8px 16px 4px; }
.sort-bar .lbl { color: var(--muted); font-size: var(--t-sm); font-weight: 500; flex: none; }
.sort-bar .seg-ctl { flex: 1; max-width: 300px; }

.switch {
  width: 50px; height: 30px; border-radius: var(--r-full); background: var(--line);
  border: none; cursor: pointer; position: relative; flex: none;
  transition: background var(--med);
}
.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px; border-radius: 50%;
  background: #fff; box-shadow: var(--shadow-1);
  transition: transform var(--med);
}
.switch.on { background: var(--brand); }
.switch.on::after { transform: translateX(20px); }

/* -------------------------------------------------------------- navigation */

.tabs {
  display: flex; gap: 3px; margin: var(--s-3) var(--s-4) 0;
  background: var(--surface-2); border-radius: var(--r-md); padding: 3px; flex: none;
}
.tab {
  flex: 1; background: none; border: none; color: var(--text-2);
  padding: 9px var(--s-2); border-radius: var(--r-sm); min-height: 38px;
  font: 600 var(--t-sm) var(--font); cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.tab.on { background: var(--surface); color: var(--text); box-shadow: var(--shadow-1); }
[data-theme="light"] .tab.on { background: #fff; }

.searchwrap { padding: var(--s-3) var(--s-4); flex: none; position: relative; }
.searchwrap .ic {
  position: absolute; left: calc(var(--s-4) + 13px); top: 50%;
  transform: translateY(-50%); color: var(--muted); pointer-events: none;
}
.searchwrap input { padding-left: 42px; }

/* ------------------------------------------------------------------- lists */

.list { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 var(--s-3) var(--s-6); }

/* Every scrollable page body scrolls the same way by default — so no screen has
   to re-declare it inline. (Editor-style bodies override to a flex column below.) */
.body { flex: 1; min-height: 0; overflow-y: auto; display: block; -webkit-overflow-scrolling: touch; }

.row {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-2); min-height: 56px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); cursor: pointer;
  transition: transform var(--fast), border-color var(--fast), background var(--fast);
}
.row:hover { border-color: var(--muted); }
.row:active { transform: scale(.985); background: var(--surface-2); }
.row .meta { flex: 1; min-width: 0; }
.row .t {
  font-weight: 550; font-size: var(--t-md);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: flex; align-items: center; gap: 6px;
}
.row .t .ic { color: var(--muted); }
.row .a {
  font-size: var(--t-sm); color: var(--text-2); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row .k {
  font: 650 var(--t-sm)/1 var(--mono); color: var(--text-2);
  background: var(--surface-2);
  border-radius: var(--r-sm); padding: var(--s-2) var(--s-2); flex: none;
}
/* Your OWN key (a personal choice) gets the brand accent; the original stays
   neutral. So at a glance you know whether you're on the church key or your own. */
.row .k.mine {
  color: var(--brand);
  background: color-mix(in srgb, var(--brand) 14%, transparent);
}
.row .n {
  color: var(--muted); font: 650 var(--t-sm) var(--mono);
  width: 22px; flex: none; text-align: center;
}
.mini {
  background: none; border: none; color: var(--muted);
  width: 34px; height: 34px; border-radius: var(--r-sm);
  display: grid; place-items: center; cursor: pointer; flex: none;
  transition: background var(--fast), color var(--fast);
}
.mini:hover { color: var(--text); background: var(--surface-2); }
.mini:active { transform: scale(.9); }

/* ------------------------------------------------------------ empty states */

.empty { padding: var(--s-7) var(--s-5); text-align: center; }
.empty.full { grid-column: 1 / -1; }

/* "Looks like a pasted chart" convert banner in the editor. */
.fix-banner {
  display: flex; gap: var(--s-3); align-items: center;
  padding: var(--s-3); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  border: 1px solid var(--brand);
}
.fix-banner .fix-copy { flex: 1; }
.fix-banner .tt { font-size: var(--t-sm); }
.fix-banner .desc { margin-top: 2px; }
.fix-banner .btn { flex: none; }
.empty .art {
  width: 64px; height: 64px; margin: 0 auto var(--s-4);
  border-radius: var(--r-xl); display: grid; place-items: center;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
}
.empty .art .ic { width: 30px; height: 30px; }
.empty h2 { font-size: var(--t-lg); font-weight: 600; margin-bottom: 6px; }
.empty p {
  font-size: var(--t-sm); color: var(--text-2); line-height: 1.6;
  margin: 0 auto var(--s-5); max-width: 30ch;
}
.btns { display: flex; gap: var(--s-2); justify-content: center; flex-wrap: wrap; }

/* =========================================================== PERFORMANCE ===
   Always dark. Never themed. The chart is the only thing that matters here. */

#perf {
  position: relative;
  background: var(--stage-bg);
  color: var(--stage-text);
}

#chart {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  touch-action: pan-y;   /* one finger scrolls; a two-finger pinch is handled in JS to zoom the chart */
  padding: calc(env(safe-area-inset-top) + var(--s-5)) var(--s-4) 55vh;
  font-family: var(--chart-font);
  font-size: var(--chart-size);
  line-height: 1.3;
}
#content { position: relative; }

.head { margin-bottom: var(--s-5); padding-bottom: var(--s-4); border-bottom: 1px solid var(--stage-line); }
.head .ht {
  font: 700 1.1em/1.2 var(--font); letter-spacing: -.5px;
  color: var(--stage-text); margin-bottom: 4px;
}
.head .hc { font: 400 .6em/1.4 var(--font); color: var(--stage-muted); }
.head .hm { margin-top: 11px; display: flex; gap: 6px; flex-wrap: wrap; }
.head .hm span {
  font: 650 .5em/1 var(--mono); letter-spacing: .5px;
  color: var(--stage-chord);
  background: color-mix(in srgb, var(--stage-chord) 14%, transparent);
  border-radius: 6px; padding: 6px 8px;
}
.head .hm span.dim {
  color: var(--stage-muted);
  background: color-mix(in srgb, var(--stage-muted) 12%, transparent);
}

/* Chords over lyrics. One inline-block per chord+syllable chunk — which is what
   lets any font work and lets long lines wrap instead of running off-screen. */
.ln { margin-bottom: 11px; }
.seg { display: inline-block; vertical-align: bottom; white-space: pre; }
/* Chords are styled independently of the lyrics — size, weight, colour and font
   all come from settings. They're the thing you scan for mid-song, so "make them
   bigger and yellow" is a legitimate request, not fiddling. */
.seg .c {
  display: block;
  color: var(--chord-colour, var(--stage-chord));
  font-weight: var(--chord-weight, 700);
  font-family: var(--chord-font, var(--mono));
  font-size: calc(1em * var(--chord-scale, 1));
  line-height: 1.15; min-height: 1.15em; letter-spacing: -.2px;
}
.seg .w { display: block; line-height: 1.35; color: var(--stage-text); }
.seg .c:not(:empty) { padding-right: .6em; }

.instr {
  color: var(--chord-colour, var(--stage-chord));
  font-weight: var(--chord-weight, 700);
  font-family: var(--chord-font, var(--mono));
  font-size: calc(1em * var(--chord-scale, 1));
  margin-bottom: 11px; letter-spacing: .5px;
}
.cmt {
  color: var(--stage-note); font: 400 .72em/1.5 var(--font);
  margin: var(--s-3) 0 var(--s-2); padding-left: 10px;
  border-left: 2px solid color-mix(in srgb, var(--stage-note) 50%, transparent);
}

.sec {
  font: 700 .55em/1 var(--font); letter-spacing: 2.5px;
  margin: var(--s-5) 0 var(--s-2); color: var(--stage-muted);
}

body.sections .block {
  border-left: 2px solid transparent; padding-left: 13px; margin-left: -15px;
  transition: border-color var(--med);
}
body.sections .block.verse { border-color: color-mix(in srgb, var(--sec-verse) 45%, transparent); }
body.sections .block.chorus { border-color: var(--sec-chorus); }
body.sections .block.bridge { border-color: var(--sec-bridge); }
body.sections .block.tab { border-color: var(--sec-tab); }
body.sections .block.chorus .sec { color: var(--sec-chorus); }
body.sections .block.bridge .sec { color: var(--sec-bridge); }
body.sections .block.tab .sec { color: var(--sec-tab); }

/* Tab is monospace whatever font you chose — there, the alignment IS the notation. */
.tabline {
  font-family: var(--mono); font-size: .8em; line-height: 1.4;
  white-space: pre; color: var(--stage-text); overflow-x: auto;
  letter-spacing: -.3px;
}

/* My private tab block on the stage — marked so it's obviously personal. */
.block.mytab { border-top: 1px dashed var(--stage-line); margin-top: 1em; padding-top: .6em; }
.block.mytab .sec.mine { color: var(--stage-chord); }

/* Vocal markup — badges on a section heading, and the editor's tap affordance. */
.sec.veditable { cursor: pointer; }
.sec.veditable:hover { text-decoration: underline dotted; text-underline-offset: 3px; }
.vbadges { display: inline-flex; flex-wrap: wrap; gap: 5px; margin-left: 8px; vertical-align: middle; }
.vbadge {
  font: 600 var(--t-xs) var(--font); letter-spacing: normal; text-transform: none;
  padding: 2px 8px; border-radius: var(--r-full);
  background: color-mix(in srgb, var(--stage-chord) 18%, transparent);
  color: var(--stage-chord);
}

/* ------------------------------------------------------------------ modals
   ONE modal system. Both .modal-overlay and the legacy .modal wrapper share the
   same card, header, and action-row metrics so every dialog looks identical. */
.modal-overlay, .modal {
  position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: var(--s-4);
  background: rgba(0,0,0,.55); backdrop-filter: blur(2px);
}
.modal-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-5);
  width: 100%; max-width: 420px; max-height: 85vh; overflow-y: auto;
  box-shadow: var(--shadow-3, 0 10px 40px rgba(0,0,0,.3));
}
.modal-card h3 { font-size: var(--t-lg); margin-bottom: var(--s-2); }
/* Body area inside a card (replaces ad-hoc inline overflow styles). */
.modal-body { display: block; overflow-y: auto; }
.modal-actions { display: flex; gap: var(--s-2); justify-content: flex-end; margin-top: var(--s-5); }
.modal-actions .btn { flex: 0 0 auto; }
/* Stacked full-width choice buttons in a dialog all share one height. */
.modal-card .stack > .btn { width: 100%; }
.vpick { display: flex; flex-wrap: wrap; gap: 8px; }
.vpick-item {
  background: var(--surface); border: 1px solid var(--line); color: var(--text-2);
  border-radius: var(--r-full); padding: 8px 14px; cursor: pointer;
  font: 500 var(--t-sm) var(--font);
}
.vpick-item.on {
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  border-color: var(--brand); color: var(--brand); font-weight: 600;
}
.vpick-add { display: flex; gap: 8px; margin-top: var(--s-4); }
.vpick-add input {
  flex: 1; padding: 12px 14px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--surface); color: var(--text);
}

/* Vocal parts manager screen. */
.vm-body { padding: var(--s-4); overflow-y: auto; }
/* Editable label chips: name (rename) + × (remove). */
.vm-chip {
  display: inline-flex; align-items: stretch; border-radius: var(--r-full);
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  border: 1px solid var(--brand); overflow: hidden;
}
.vm-chip-name {
  background: none; border: none; color: var(--brand); cursor: pointer;
  font: 600 var(--t-sm) var(--font); padding: 7px 6px 7px 13px;
}
.vm-chip-x {
  background: none; border: none; color: var(--brand); cursor: pointer;
  font-size: var(--t-md); line-height: 1; padding: 0 11px 0 6px; opacity: .7;
}
.vm-chip-x:hover { opacity: 1; }
.vm-song, .vm-sec {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  width: 100%; text-align: left; cursor: pointer; min-height: 56px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: var(--s-3) var(--s-4); margin-bottom: var(--s-2);
  color: var(--text); font: inherit;
}
.vm-song:hover, .vm-sec:hover { border-color: var(--muted); }
.vm-song-t, .vm-sec-name { font-weight: 600; font-size: var(--t-md); }
.vm-song-n { color: var(--muted); font-size: var(--t-sm); flex: none; }
.vm-sec .vbadges { margin-left: 0; justify-content: flex-end; }
.vm-secs { max-height: 52vh; overflow-y: auto; }
@media (min-width: 900px) {
  .vm-body { max-width: 760px; margin: 0 auto; width: 100%; padding: var(--s-6) var(--s-6) var(--s-7); }
}

/* --------------------------------------------------------------- hud */

#hud {
  position: absolute; top: calc(env(safe-area-inset-top) + var(--s-3)); right: var(--s-4);
  display: flex; align-items: center; gap: var(--s-2); pointer-events: none;
  font: 650 var(--t-xs)/1 var(--mono); color: var(--stage-muted);
  background: color-mix(in srgb, var(--stage-panel) 88%, transparent);
  border: 1px solid var(--stage-line);
  padding: 8px 10px; border-radius: var(--r-sm);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
}
#hud b { color: var(--stage-chord); font-weight: 700; }
#beat {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--stage-line); transition: background .05s, transform .05s;
}
#beat.hit { background: var(--stage-chord); transform: scale(1.35); }
#beat.hit.down { background: var(--stage-note); transform: scale(1.6); }

/* ---------------------------------------------------------- stage controls */

#controls {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 10;
  background: color-mix(in srgb, var(--stage-panel) 92%, transparent);
  border-top: 1px solid var(--stage-line);
  border-radius: 18px 18px 0 0;
  padding: var(--s-4) var(--s-4) calc(env(safe-area-inset-bottom) + var(--s-4));
  transform: translateY(110%);
  transition: transform var(--med);
  backdrop-filter: blur(20px) saturate(1.2); -webkit-backdrop-filter: blur(20px) saturate(1.2);
  box-shadow: 0 -12px 40px -12px rgba(0,0,0,.55);
}
#controls.on { transform: none; }
/* A little grab-handle hint at the top of the sheet. */
#controls::before {
  content: ""; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  width: 36px; height: 4px; border-radius: 2px;
  background: color-mix(in srgb, var(--stage-text) 22%, transparent);
}
/* Everything in the sheet sits in a centred column, so on a tablet/desktop the
   controls don't hug the left edge with dead space to the right. */
.ctl-inner { max-width: 560px; margin: 0 auto; }
/* Small section headers group the controls (grouped + flat/minimal style). */
.ctl-grp {
  font-size: 10px; letter-spacing: .9px; text-transform: uppercase;
  color: var(--stage-muted); font-weight: 600; margin: 13px 0 6px; padding-left: 3px;
}
/* space-between spreads each row to both edges of the centred column — the first
   control sits flush left, the last flush right. */
.ctl-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.ctl-row:first-child { margin-top: 4px; }
.ctl-row:last-child { margin-bottom: 0; }

/* Flat, minimal buttons: quiet surface, no borders or shadows — clean and modern. */
.ctl {
  background: color-mix(in srgb, var(--stage-text) 7%, transparent);
  border: 1px solid transparent; color: var(--stage-text);
  border-radius: var(--r-md); padding: 11px 14px; min-height: 44px;
  font: 600 var(--t-md) var(--font); cursor: pointer; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  transition: background var(--fast), color var(--fast), transform var(--fast);
}
.ctl:hover { background: color-mix(in srgb, var(--stage-text) 13%, transparent); }
.ctl:active { transform: scale(.95); }
/* Active toggles (Scroll, Click, Nashville) fill with the chord colour — flat. */
.ctl.on { background: var(--stage-chord); color: #04121a; border-color: transparent; }
.ctl.on:hover { background: var(--stage-chord); }
.ctl.wide { flex: 1; }
/* The key selector is the headline control — tint it the chord colour so the eye
   lands on it first. */
select.ctl {
  -webkit-appearance: none; appearance: none; text-align: center;
  font-family: var(--mono); font-weight: 650;
  color: var(--stage-chord);
  border-color: color-mix(in srgb, var(--stage-chord) 32%, transparent);
  background: color-mix(in srgb, var(--stage-chord) 9%, transparent);
}
.ctl .ic { width: 17px; height: 17px; }

input[type=range] {
  flex: 1; accent-color: var(--stage-chord); min-width: 0; height: 22px;
}
.lbl { font-size: var(--t-xs); color: var(--stage-muted); flex: none; font-weight: 500; }

/* --------------------------------------------------------------- notes */

.note {
  position: absolute; z-index: 5;
  background: var(--stage-note); color: #1a1200;
  font: 400 14px/1.45 var(--font);
  padding: 11px 13px; border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  cursor: grab; touch-action: none;   /* or the browser eats the drag as a scroll */
  word-break: break-word;
  transition: transform var(--fast), box-shadow var(--fast);
}
.note .grip { opacity: .45; margin-bottom: 5px; height: 14px; }
.note .grip .ic { width: 15px; height: 15px; }
.note p { margin: 0 0 5px; }
.note p:last-child { margin-bottom: 0; }
.note b { font-weight: 700; }
.note ul { margin: 0 0 5px; padding-left: 18px; }
.note li { margin-bottom: 2px; }
.note .sp { height: 7px; }
.note.dragging { cursor: grabbing; transform: scale(1.03) rotate(-.6deg); box-shadow: 0 24px 50px -10px rgba(0,0,0,.75); }
/* Shared (band-wide) notes get a small ribbon so they read differently from your
   own private ones; read-only ones (shared, and you're not an editor) can't be
   dragged, so no grip and no grab cursor. */
.note.shared { box-shadow: var(--shadow-3), inset 3px 0 0 var(--brand); }
.note.ro { cursor: default; }
.note.ro .grip { display: none; }

.note.pink { background: #ff6b8a; color: #2a0009; }
.note.green { background: #52d67a; color: #00220c; }
.note.blue { background: #4cc9f0; color: #04121a; }
.note.plain { background: var(--stage-panel); color: var(--stage-text); border: 1px solid var(--stage-line); }

/* ========================================================= EDITORS ======== */

#editor .body, #tabed .body, #noteed .body, #settings .body {
  flex: 1; display: flex; flex-direction: column;
  padding: var(--s-4); gap: var(--s-3); min-height: 0;
}
#settings .body { overflow-y: auto; display: block; }

#source {
  flex: 1; font-family: var(--mono); font-size: var(--t-sm);
  line-height: 1.6; resize: none; min-height: 0;
}
#noteText { flex: 1; min-height: 0; resize: none; line-height: 1.6; }

.hint { font-size: var(--t-xs); color: var(--muted); line-height: 1.6; }
.hint code {
  font-family: var(--mono); color: var(--brand);
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  padding: 2px 5px; border-radius: 5px;
}
audio { width: 100%; border-radius: var(--r-md); }

.palette { flex: none; }
.prow {
  display: flex; gap: 6px; overflow-x: auto;
  padding-bottom: var(--s-2); scrollbar-width: none;
}
.prow::-webkit-scrollbar { display: none; }
.plabel {
  font: 650 var(--t-xs)/1 var(--font); color: var(--muted);
  letter-spacing: 1.2px; text-transform: uppercase;
  margin: var(--s-2) 0 var(--s-2);
}
.chip {
  background: var(--surface); border: 1px solid var(--line); color: var(--text);
  border-radius: var(--r-sm); padding: 9px 12px; cursor: pointer; flex: none;
  font: 600 var(--t-sm) var(--mono); white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px;
  transition: background var(--fast), border-color var(--fast), transform var(--fast);
}
.chip:active, .chip.on {
  background: var(--brand); border-color: var(--brand); color: var(--on-brand);
  transform: scale(.95);
}
.chip.chord { color: var(--brand); border-color: color-mix(in srgb, var(--brand) 30%, var(--line)); }
.chip.chord:active, .chip.chord.on { color: var(--on-brand); }
.chip .deg { color: var(--muted); font-weight: 400; font-size: var(--t-xs); }
.chip:active .deg, .chip.on .deg { color: var(--on-brand); opacity: .75; }
.chip .ic { width: 15px; height: 15px; }

/* ---------------------------------------------------------- tab editor */

.tabgrid {
  /* Size to the tab, not the screen: the card used to be flex:1 and stretched to
     fill the whole viewport, leaving six short rows stranded in a huge empty box.
     Now it hugs its content and scrolls internally only once the tab gets long. */
  flex: 0 1 auto; overflow: auto; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: var(--s-4) var(--s-3); font-family: var(--mono);
  width: fit-content; max-width: 100%; max-height: 62vh;
}
.tabrow { display: flex; align-items: center; margin-bottom: 2px; }
.tabname {
  width: 26px; flex: none; color: var(--muted);
  font: 700 var(--t-md) var(--mono);
}
/* A real fixed-layout table: the browser forces every column to the same width,
   so bars can never come out uneven. */
.tabtable { border-collapse: collapse; table-layout: fixed; }
.tabtable .tabname {
  width: 26px; text-align: left; padding-right: 4px;
  color: var(--muted); font: 700 var(--t-md) var(--mono); font-weight: 700;
}
.cell {
  width: 22px; height: 34px; padding: 0; text-align: center; vertical-align: middle;
  border: none; background: none; line-height: 34px;
  color: var(--muted); font: 700 var(--t-sm) var(--mono); cursor: pointer;
  border-bottom: 1px solid var(--line);
  transition: background var(--fast), color var(--fast);
}
.cell:hover { background: var(--surface-2); }
.cell.set { color: var(--brand); background: color-mix(in srgb, var(--brand) 10%, transparent); }
/* A bar line: a clean divider spanning the row height at each measure boundary. */
.cell.bar { border-left: 1px solid var(--line); }

/* ---------------------------------------------------------- note editor */

.swatches { display: flex; gap: var(--s-2); }
.swatch {
  flex: 1; height: 40px; border-radius: var(--r-md);
  border: 2px solid transparent; cursor: pointer;
  transition: transform var(--fast), border-color var(--fast);
}
.swatch:active { transform: scale(.93); }
.swatch.on { border-color: var(--text); }
.swatch[data-c=amber] { background: #ffb703; }
.swatch[data-c=pink] { background: #ff6b8a; }
.swatch[data-c=green] { background: #52d67a; }
.swatch[data-c=blue] { background: #4cc9f0; }
.swatch[data-c=plain] { background: var(--surface-2); border: 2px solid var(--line); }
.swatch[data-c=plain].on { border-color: var(--text); }

.preview {
  background: #ffb703; color: #1a1200;
  border-radius: var(--r-md); padding: 13px 15px;
  font: 400 14px/1.45 var(--font);
  max-height: 160px; overflow-y: auto;
  box-shadow: var(--shadow-2);
}
.preview.pink { background: #ff6b8a; color: #2a0009; }
.preview.green { background: #52d67a; color: #00220c; }
.preview.blue { background: #4cc9f0; color: #04121a; }
.preview.plain { background: var(--surface-2); color: var(--text); border: 1px solid var(--line); }
.preview p { margin: 0 0 5px; }
.preview p:last-child { margin-bottom: 0; }
.preview ul { margin: 0 0 5px; padding-left: 18px; }
.preview .sp { height: 7px; }

/* ------------------------------------------------------------- settings */

.group { margin-bottom: var(--s-6); }
.group h3 {
  font: 650 var(--t-xs)/1 var(--font); color: var(--muted);
  letter-spacing: 1.2px; text-transform: uppercase; margin-bottom: var(--s-3);
}
.desc { font-size: var(--t-sm); color: var(--text-2); margin-top: var(--s-3); line-height: 1.6; }
.toggle { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.toggle .tt { font-weight: 550; }
.stack { display: flex; flex-direction: column; gap: var(--s-2); }

/* --------------------------------------------------------------- sheet */

#sheet {
  position: fixed; inset: 0; z-index: 50; display: none;
  align-items: flex-end;
  background: rgba(0,0,0,.5);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}
#sheet.on { display: flex; animation: fade var(--fast); }
@keyframes fade { from { opacity: 0 } to { opacity: 1 } }

.sheet-inner {
  width: 100%; background: var(--surface);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  padding: var(--s-2) var(--s-3) calc(env(safe-area-inset-bottom) + var(--s-3));
  box-shadow: var(--shadow-3);
  animation: slideup var(--med);
}
@keyframes slideup { from { transform: translateY(100%) } to { transform: none } }

.sheet-grab {
  width: 36px; height: 4px; border-radius: var(--r-full); background: var(--line);
  margin: var(--s-2) auto var(--s-3);
}
.sheet-title {
  padding: 0 var(--s-2) var(--s-3); font-weight: 650; font-size: var(--t-md);
  border-bottom: 1px solid var(--line); margin-bottom: var(--s-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sheet-inner button {
  width: 100%; background: none; border: none; color: var(--text);
  padding: 14px 12px; text-align: left;
  font: 500 var(--t-md) var(--font); cursor: pointer;
  border-radius: var(--r-md);
  display: flex; align-items: center; gap: var(--s-3);
  transition: background var(--fast);
}
.sheet-inner button:active { background: var(--surface-2); }
.sheet-inner button .ic { color: var(--muted); }
.sheet-inner button.danger { color: var(--danger); }
.sheet-inner button.danger .ic { color: var(--danger); }

/* ============================================================== AUTH =====
   A proper sign-up, not the app chrome with inputs dropped into it.

   On a wide screen it's the standard SaaS split: pitch on the left, form on the
   right. On a phone the left panel disappears entirely — a marketing panel above
   a form is what makes mobile signups feel endless. */

.auth {
  flex: 1; display: grid; grid-template-columns: 1fr;
  min-height: 0; overflow: hidden;
}
@media (min-width: 900px) {
  .auth { grid-template-columns: 1fr 1fr; }
}

/* ---- left: the pitch. Desktop only. */
.auth-aside { display: none; }
@media (min-width: 900px) {
  .auth-aside {
    display: flex; flex-direction: column; justify-content: space-between;
    padding: var(--s-7) var(--s-6);
    background: var(--surface);
    border-right: 1px solid var(--line);
    position: relative; overflow: hidden;
  }
  /* Centre the left content as a fixed-width column, mirroring the right card
     (also a centred 380px block). Now both sides sit the same distance in from
     their outer edge instead of the pitch hugging the window edge. */
  .auth-aside > * { width: 100%; max-width: 380px; margin-inline: auto; }
}
.auth-aside h2 {
  font-size: clamp(26px, 2.4vw, 34px); font-weight: 700;
  letter-spacing: -1px; line-height: 1.15; margin-bottom: var(--s-4);
  max-width: 15ch;
}
.auth-aside h2 em { font-style: normal; color: var(--brand); }

.auth-points { display: flex; flex-direction: column; gap: var(--s-4); }
.auth-point { display: flex; gap: var(--s-3); align-items: flex-start; }
.auth-point .bullet {
  width: 30px; height: 30px; border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  color: var(--brand);
}
.auth-point .bullet .ic { width: 16px; height: 16px; }
.auth-point .pt { font-weight: 600; font-size: var(--t-sm); }
.auth-point .pd { font-size: var(--t-sm); color: var(--text-2); line-height: 1.5; margin-top: 1px; }

.auth-foot { font-size: var(--t-xs); color: var(--muted); }

/* ---- right: the form. */
.auth-main {
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--s-6) var(--s-5) var(--s-7);
  overflow-y: auto;
}
.auth-card { width: 100%; max-width: 380px; margin: 0 auto; }

.auth-mark {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: var(--s-6); font-weight: 700; letter-spacing: -.3px;
}
.auth-mark .badge {
  width: 34px; height: 34px; border-radius: 10px;
  background: #04140c; border: 1px solid #12352b; box-shadow: var(--glow);
  display: grid; place-items: center;
}
.auth-mark .badge .ic { width: 26px; height: 26px; }

.auth-h1 {
  font-size: var(--t-2xl); font-weight: 700; letter-spacing: -.7px;
  margin-bottom: 6px;
}
.auth-sub {
  color: var(--text-2); font-size: var(--t-sm); line-height: 1.6;
  margin-bottom: var(--s-6);
}

/* Fields with the label attached, the way every SaaS form does it. */
.field { margin-bottom: var(--s-4); }
/* Auth field labels share the app-wide label look (.plabel) so a label is a
   label everywhere — same case, weight, and colour on the sign-in form as in
   the team editor. */
.field label {
  display: block; font: 650 var(--t-xs)/1.2 var(--font); color: var(--muted);
  letter-spacing: 1.2px; text-transform: uppercase; margin-bottom: 8px;
}
.field .sub {
  font-weight: 400; color: var(--muted); font-size: var(--t-xs);
  letter-spacing: 0; text-transform: none;
}
.field input {
  width: 100%; background: var(--surface); border: 1px solid var(--line);
  color: var(--text); border-radius: var(--r-md);
  padding: 13px 14px; font: 400 var(--t-md) var(--font);
  transition: border-color var(--fast), box-shadow var(--fast);
}
.field input:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 16%, transparent);
}
.field input::placeholder { color: var(--muted); }
[data-theme="light"] .field input { background: #fff; }

.auth-submit { width: 100%; padding: 14px; margin-top: var(--s-2); }

.auth-divider {
  display: flex; align-items: center; gap: var(--s-3);
  margin: var(--s-5) 0; color: var(--muted); font-size: var(--t-xs);
}
.auth-divider::before, .auth-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}

.auth-alt {
  margin-top: var(--s-5); text-align: center;
  font-size: var(--t-sm); color: var(--text-2);
}
.auth-alt button {
  background: none; border: none; color: var(--brand);
  font: 600 var(--t-sm) var(--font); cursor: pointer; padding: 0;
}
.auth-alt button:hover { text-decoration: underline; }

/* [hidden] is a UA rule (display:none). ANY author `display` beats it — so a
   .err with display:flex renders as an empty red bar even when it's hidden.
   This bit us on sign-in, sign-up and the instrument screen. Never set display
   on something you also toggle with [hidden] without this guard. */
.err[hidden] { display: none !important; }

.err {
  display: flex; gap: 9px; align-items: flex-start;
  color: var(--danger); font-size: var(--t-sm); line-height: 1.5;
  background: color-mix(in srgb, var(--danger) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 25%, transparent);
  border-radius: var(--r-md); padding: 11px 13px; margin-bottom: var(--s-3);
  white-space: pre-wrap;
}
.err .ic { width: 16px; height: 16px; margin-top: 2px; flex: none; }

input[type=password] {
  width: 100%; background: var(--surface); border: 1px solid var(--line);
  color: var(--text); border-radius: var(--r-md);
  padding: 13px 14px; font: 400 var(--t-md) var(--font);
  transition: border-color var(--fast), box-shadow var(--fast);
}
input[type=password]:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 16%, transparent);
}
[data-theme="light"] input[type=password] { background: #fff; }

/* ------------------------------------------------------------ profile */

.avatar {
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--brand); color: var(--on-brand);
  display: grid; place-items: center; flex: none;
  font: 700 var(--t-lg) var(--font); letter-spacing: -.5px;
}
.avatar.sm { width: 26px; height: 26px; font-size: var(--t-xs); }

.profile-head {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) 0 var(--s-5); margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}

/* ----------------------------------------------------------- dashboard */

#home .body { padding: var(--s-4); }

.stat-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3); margin-bottom: var(--s-4);
}
.stat {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-4);
}
.stat .k { font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .5px; }
.stat .v { font-size: var(--t-2xl); font-weight: 500; letter-spacing: -.5px; margin-top: 4px; line-height: 1.1; }
.stat .v .unit { font-size: var(--t-sm); color: var(--muted); font-weight: 400; }

/* One monochrome "hero" tile on the dashboard for depth without colour — the
   first stat goes inverse (dark card, white number). Light theme only; the dark
   chrome already has the contrast. */
#homeStats .stat:first-child {
  background: #04140c; border-color: #0f3329;
}
#homeStats .stat:first-child .k { color: #7c9088; }
#homeStats .stat:first-child .v { color: #34d399; }

.home-cols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--s-3); margin-bottom: var(--s-4);
}
.home-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-4); margin-bottom: var(--s-4);
}
.home-card:last-child { margin-bottom: 0; }
.home-cols .home-card { margin-bottom: 0; }
.home-card h3 { font-size: var(--t-sm); color: var(--text-2); margin-bottom: var(--s-3); font-weight: 600; }
.home-card .muted-line { color: var(--muted); font-size: var(--t-sm); }
.home-line {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 0; border-top: 1px solid var(--line); font-size: var(--t-sm);
}
.home-line:first-of-type { border-top: none; }
.home-line .r { color: var(--muted); font-variant-numeric: tabular-nums; }
.home-card .btn { width: 100%; margin-top: var(--s-3); }
.home-line[data-set], .home-line[data-open] { cursor: pointer; }

/* Your-own-schedule block sits above the church-wide stats. */
.home-mine .home-card h3 { color: var(--text); }

/* Big calendar on the left, the two schedule cards stacked on the right. */
.home-schedule {
  display: grid; grid-template-columns: 1fr; gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.home-mine-side { display: flex; flex-direction: column; gap: var(--s-3); }
.home-mine-side .home-card { margin-bottom: 0; }
.home-cal-card { margin-bottom: 0; }

@media (min-width: 780px) {
  .home-schedule { grid-template-columns: 1.7fr 1fr; align-items: start; }
}

/* Month calendar on the home dashboard. */
.cal-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--s-3);
}
.cal-head h3 { margin-bottom: 0; }
.cal-nav { display: flex; gap: 6px; }
.cal-arrow {
  width: 30px; height: 30px; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--text-2); font-size: 20px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.cal-arrow:hover { background: var(--surface-2, var(--line)); color: var(--text); }
.cal {
  display: grid; grid-template-columns: repeat(7, 1fr);
  gap: 5px; margin-top: 2px;
}
.cal-dow {
  text-align: center; font-size: var(--t-xs); color: var(--muted);
  padding-bottom: 4px; font-weight: 600;
}
.cal-cell {
  text-align: center; font-size: var(--t-md); padding: 12px 0;
  border-radius: var(--r-md); font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
.cal-cell.empty { visibility: hidden; }
.cal-cell.on {
  background: var(--brand); color: var(--on-brand, #04140c); font-weight: 600;
}
.cal-cell.today { box-shadow: inset 0 0 0 1.5px var(--muted); }
.cal-cell.today.on { box-shadow: inset 0 0 0 1.5px var(--on-brand, #04140c); }

/* My-availability calendar: tap a day to block it out. Sundays are emphasised
   (that's when services usually are); an "away" day reads clearly as unavailable. */
.cal-cell.tappable { cursor: pointer; user-select: none; -webkit-user-select: none; transition: background .1s, color .1s; }
.cal-cell.tappable:hover { background: var(--surface-2, var(--line)); }
.cal-cell.sunday { color: var(--text); font-weight: 600; }
.cal-cell.away {
  background: color-mix(in srgb, var(--danger, #e5484d) 24%, transparent);
  color: var(--danger, #e5484d); font-weight: 600;
  text-decoration: line-through; text-decoration-thickness: 1.5px;
}
.cal-cell.away:hover { background: color-mix(in srgb, var(--danger, #e5484d) 34%, transparent); }
.cal-cell.away.today { box-shadow: inset 0 0 0 1.5px var(--danger, #e5484d); }

/* Availability month nav: keep the arrows tucked either side of the month name
   instead of stretched to the screen edges. */
#availability .rota-month { justify-content: center; }
#availability .rota-month .rm-label { flex: 0 0 auto; min-width: 160px; }
#availability .body { max-width: 520px; margin: 0 auto; width: 100%; }

@media (min-width: 900px) {
  #home .body { padding: var(--s-5) var(--s-6) var(--s-7); max-width: 1000px; }
}

/* A church admin's home carries both their own schedule AND the church overview.
   On a wide screen, stand them side by side so the whole thing fills the width
   and stops being one tall scroll. Members / solo users keep the single column. */
@media (min-width: 1180px) {
  #home.wide .body { max-width: 1560px; }
  .home-grid.two-col {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: var(--s-5); align-items: start;
  }
  .home-grid.two-col .home-mine { margin-bottom: 0; }
  /* Inside a half-width column the schedule reads better stacked than split. */
  .home-grid.two-col .home-schedule { grid-template-columns: 1fr; margin-bottom: 0; }
}

/* --------------------------------------------------------- knowledge base */

.kb-searchwrap {
  position: relative; margin: var(--s-3) var(--s-4) 0; flex: none;
}
.kb-searchwrap input { padding-left: 38px; }
.kb-searchwrap .ic {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  color: var(--muted); pointer-events: none;
}

.kb-list { flex: 1; overflow-y: auto; padding: var(--s-4); }
.kb-cat {
  font: 650 var(--t-sm) var(--font); color: var(--text-2);
  text-transform: uppercase; letter-spacing: .6px;
  margin: var(--s-5) 0 var(--s-3);
}
.kb-cat:first-child { margin-top: 0; }
.kb-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--s-3);
}
.kb-card {
  text-align: left; cursor: pointer; display: flex; flex-direction: column; gap: 6px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-4);
  transition: border-color var(--fast), transform var(--fast);
}
.kb-card:hover { border-color: var(--muted); transform: translateY(-2px); }
.kb-card:active { transform: none; background: var(--surface-2); }
.kb-card-t { font-weight: 600; font-size: var(--t-md); color: var(--text); }
.kb-card-s { font-size: var(--t-sm); color: var(--text-2); line-height: 1.5; }
.kb-card-go {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 2px;
  font-size: var(--t-xs); font-weight: 600; color: var(--brand);
}
.kb-card-go .ic { width: 13px; height: 13px; }

.ka-cat {
  font: 650 var(--t-xs) var(--font); color: var(--brand);
  text-transform: uppercase; letter-spacing: .6px; margin-bottom: 6px;
}
.ka-title { font-size: var(--t-2xl); font-weight: 650; letter-spacing: -.5px; margin-bottom: var(--s-4); }
.ka-body { color: var(--text); line-height: 1.7; }
.ka-body p { margin-bottom: var(--s-3); }
.ka-body ul { margin: 0 0 var(--s-3) var(--s-4); }
.ka-body li { margin-bottom: 4px; }
.ka-body code {
  font: var(--t-sm) var(--mono); background: var(--surface-2);
  padding: 1px 5px; border-radius: var(--r-sm);
}

/* ---------------------------------------------------------- church logo */

.logo-row { display: flex; align-items: center; gap: var(--s-3); margin-top: var(--s-2); }
.logo-preview {
  width: 56px; height: 56px; flex: none; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line);
  display: grid; place-items: center; overflow: hidden; color: var(--muted);
}
.logo-preview img { width: 100%; height: 100%; object-fit: cover; }
.logo-preview .ic { width: 22px; height: 22px; }

/* ------------------------------------------------- library filters */

.lib-filters {
  display: flex; gap: var(--s-3); flex-wrap: wrap; flex: none;
  padding: var(--s-2) var(--s-4);
}
.lib-seg {
  display: inline-flex; background: var(--surface-2);
  border-radius: var(--r-full); padding: 3px; gap: 2px;
}
.lib-seg button {
  border: none; background: none; color: var(--text-2);
  font: 600 var(--t-xs) var(--font); padding: 6px 12px; border-radius: var(--r-full);
  cursor: pointer; white-space: nowrap;
  transition: background var(--fast), color var(--fast);
}
.lib-seg button.on { background: var(--surface); color: var(--text); box-shadow: var(--shadow-1); }
[data-theme="light"] .lib-seg button.on { background: #fff; }

@media (min-width: 900px) {
  #library .lib-filters { padding: var(--s-4) var(--s-6) 0; }
}

/* Multi-select: the toggle button, the bulk bar, and picked rows. */
.lib-select-btn {
  margin-left: auto; border: 1px solid var(--line); background: var(--surface);
  color: var(--text-2); font: 600 var(--t-xs) var(--font);
  padding: 6px 14px; border-radius: var(--r-full); cursor: pointer; white-space: nowrap;
}
.lib-select-btn:hover { color: var(--text); border-color: var(--muted); }

.bulk-bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  flex: none; padding: var(--s-2) var(--s-4);
  background: color-mix(in srgb, var(--brand) 8%, transparent);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.bulk-count { font: 600 var(--t-sm) var(--font); color: var(--text); }
.bulk-actions { display: flex; align-items: center; gap: var(--s-3); }
@media (min-width: 900px) { #library .bulk-bar { padding: var(--s-2) var(--s-6); } }

.row.selectable { cursor: pointer; }
.row.selectable .row-check {
  flex: none; width: 22px; height: 22px; margin-right: var(--s-2);
  border: 1.5px solid var(--muted); border-radius: var(--r-sm);
  display: grid; place-items: center; color: var(--on-brand, #04140c);
}
.row.picked .row-check { background: var(--brand); border-color: var(--brand); }
.row.picked { background: color-mix(in srgb, var(--brand) 8%, transparent); }
.row-check.disabled { opacity: .3; border-style: dashed; }

/* ------------------------------------------------------------- reports */

.rep-controls {
  display: flex; gap: var(--s-4); flex-wrap: wrap; flex: none;
  padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line);
}
.rep-controls select { width: auto; padding: 8px 10px; }
.rep-list { flex: 1; overflow-y: auto; padding: var(--s-4); }
@media (min-width: 900px) {
  .rep-list { max-width: 900px; margin: 0 auto; width: 100%; padding: var(--s-5) var(--s-6) var(--s-7); }
  /* The year / leader filters share the list's centred column, so they line up
     over the data instead of drifting to the pane edge. */
  .rep-controls {
    max-width: 900px; margin: 0 auto; width: 100%;
    padding: var(--s-4) var(--s-6) var(--s-3); border-bottom: none;
  }
}

.rep-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-4); margin-top: var(--s-4);
}
.rep-card h3 { font-size: var(--t-sm); color: var(--text-2); margin-bottom: var(--s-3); font-weight: 600; }
.rep-card .muted-line { color: var(--muted); font-size: var(--t-sm); }

.rep-table { display: flex; flex-direction: column; }
.rep-h, .rep-r {
  display: grid; grid-template-columns: 28px 1fr 64px 72px; align-items: center;
  gap: var(--s-2); padding: 9px 0;
}
.rep-h { border-bottom: 1px solid var(--line); font-size: var(--t-xs); color: var(--muted);
  text-transform: uppercase; letter-spacing: .5px; }
.rep-r { border-bottom: 1px solid var(--line); font-size: var(--t-sm); }
.rep-r:last-child { border-bottom: none; }
.rep-r .rank { color: var(--muted); font: 600 var(--t-xs) var(--mono); text-align: center; }
.rep-r .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rep-table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------- web import */

.wi-sites { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-3); }
.wi-sites .btn { flex: 0 0 auto; }
.wi-bm {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  margin: var(--s-3) 0;
}
.wi-paste-row { margin: var(--s-3) 0; }
#wiSource {
  width: 100%; font-family: var(--mono); font-size: var(--t-sm);
  line-height: 1.6; resize: vertical; min-height: 180px; margin-top: var(--s-2);
}

/* ------------------------------------------------------------- schemes */

.scheme-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--s-2);
}
.scheme-card {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 10px var(--s-3); cursor: pointer;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-md);
  font: 600 var(--t-sm) var(--font);
  transition: border-color var(--fast), transform var(--fast);
}
.scheme-card:hover { border-color: var(--muted); }
.scheme-card:active { transform: scale(.97); }
.scheme-card.on { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset; }
.scheme-dot { width: 16px; height: 16px; border-radius: var(--r-full); flex: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
.scheme-name { white-space: nowrap; }

/* --------------------------------------------------------------- rota */

.rota-month {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-4); flex: none;
  border-bottom: 1px solid var(--line);
}
.rm-label { flex: 1; text-align: center; font-weight: 650; font-size: var(--t-lg); letter-spacing: -.3px; }

.rota-actions {
  display: flex; gap: var(--s-2); padding: var(--s-3) var(--s-4); flex: none;
  border-bottom: 1px solid var(--line);
}
.rota-actions .btn { flex: 1; }

#rotaBody { padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); }

.rcard {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: var(--s-4);
}
.rcard.fifth { border-color: color-mix(in srgb, var(--brand-2) 45%, var(--line)); }
.rcard-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: var(--s-3); }
.rcard-title { font-weight: 650; font-size: var(--t-md); }
.rcard-date { color: var(--muted); font-size: var(--t-sm); }

.rgroup { padding: var(--s-2) 0; border-top: 1px solid var(--line); }
.rgroup:first-of-type { border-top: none; }
.rgroup-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.rgroup-name { font-size: var(--t-sm); font-weight: 600; color: var(--text-2); }
.rgroup-count { font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; min-width: 30px; text-align: center; }
.rgroup.short .rgroup-count, .rgroup-count.short { color: var(--danger); font-weight: 700; }
.rgroup-req { display: inline-flex; align-items: center; gap: 4px; }
.rgroup-req .mini { width: 26px; height: 26px; }
.rgroup-chips { display: flex; flex-wrap: wrap; gap: 6px; }

.rchip {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-full); padding: 5px 8px 5px 11px;
  font-size: var(--t-sm); cursor: pointer;
  transition: border-color var(--fast), background var(--fast);
}
.rchip:hover { border-color: var(--muted); }
.rchip:active { transform: scale(.96); background: var(--surface); }
.rchip.me { background: color-mix(in srgb, var(--brand) 16%, transparent); color: var(--brand); border-color: transparent; }
.rchip.swapping { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset; }
.rchip.empty { color: var(--muted); cursor: default; border-style: dashed; }
.rchip.add { color: var(--brand); border-style: dashed; background: transparent; text-transform: lowercase; }
.rchip-x {
  display: grid; place-items: center; width: 18px; height: 18px;
  border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: var(--r-full);
}
.rchip-x:hover { color: var(--danger); background: var(--surface); }
.rchip-x:active { transform: scale(.9); }
.rchip.tappable { cursor: pointer; }
.rchip.tappable:hover { border-color: var(--brand); }

/* Accept/decline status on a rota chip. */
.rchip-st { display: inline-flex; align-items: center; font-size: var(--t-xs); }
.rchip-st.ok  { color: var(--brand); }
.rchip-st.no  { color: var(--danger, #e5484d); }
.rchip-st.pending { color: var(--muted); font-size: 10px; letter-spacing: .2px; }
.rchip.r-accepted { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand) 45%, transparent); }
.rchip.r-declined { background: color-mix(in srgb, var(--danger, #e5484d) 12%, transparent); }
.rchip.r-declined .rchip-name { text-decoration: line-through; text-decoration-thickness: 1px; }

/* Requests inbox */
#reqBody { padding: var(--s-4) var(--s-4) var(--s-7); max-width: 640px; margin: 0 auto; width: 100%; }
.req-card {
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-2); min-height: 56px;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap;
}
.req-text { flex: 1; min-width: 200px; line-height: 1.5; }
.req-actions { display: flex; gap: var(--s-2); }
.req-actions .btn { min-height: 36px; padding: 0 var(--s-4); font-size: var(--t-sm); }
.req-tag { font-size: var(--t-xs); font-weight: 600; text-transform: capitalize; }
.req-tag.accepted { color: var(--brand); }
.req-tag.declined, .req-tag.cancelled { color: var(--muted); }
.req-tag.answered { color: var(--brand); }
.req-tag.open { color: var(--danger, #e5484d); }
.req-tag.resolved { color: var(--muted); }

/* Support tickets */
#supBody { padding: var(--s-4) var(--s-4) var(--s-7); max-width: 680px; margin: 0 auto; width: 100%; }
.sup-thread { display: flex; flex-direction: column; gap: var(--s-3); margin-bottom: var(--s-4); }
.sup-msg {
  border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) var(--s-4);
  background: var(--surface); max-width: 85%; line-height: 1.5;
}
.sup-msg.mine { align-self: flex-end; background: color-mix(in srgb, var(--brand) 10%, transparent); border-color: transparent; }
.sup-msg.staff { align-self: flex-start; }
.sup-who { font-size: var(--t-xs); color: var(--muted); font-weight: 600; margin-bottom: 4px; }
.sup-reply { display: flex; gap: var(--s-2); align-items: flex-end; }
.sup-reply textarea { flex: 1; }
.sup-reply .btn { flex: none; }

.swap-banner {
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand) 40%, transparent);
  color: var(--text); border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-3); font-size: var(--t-sm);
}
.linkbtn { background: none; border: none; color: var(--brand); cursor: pointer; font: inherit; text-decoration: underline; padding: 0; }

/* Requirements editor */
.req-row { display: flex; align-items: center; justify-content: space-between; padding: var(--s-2) 0; border-bottom: 1px solid var(--line); }
.req-name { font-weight: 500; }
.stepper { display: flex; align-items: center; gap: var(--s-3); }
.req-n { min-width: 22px; text-align: center; font-variant-numeric: tabular-nums; font-weight: 650; }

/* --------------------------------------------------------------- team */

/* Tiles, not a list. A 30-person team as a single column is all scrolling; a
   grid fills the width and shows the whole band at a glance. auto-fill keeps the
   tiles a sensible width and simply adds columns as the screen grows — two on a
   phone, five on a desktop, no breakpoints to maintain. */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--s-3);
}

/* Sort / group controls above the tiles. */
.team-toolbar {
  display: flex; gap: var(--s-4); justify-content: flex-end; flex-wrap: wrap;
  margin-bottom: var(--s-4);
}
.tt-ctl {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: var(--t-sm); color: var(--text-2); font-weight: 500;
}
.team-toolbar select { width: auto; padding: 0 var(--s-3); min-height: 40px; }

/* A section heading when the team is grouped by role or instrument. */
.team-group-h {
  display: flex; align-items: center; gap: 8px;
  font: 650 var(--t-sm) var(--font); color: var(--text-2);
  text-transform: uppercase; letter-spacing: .6px;
  margin: var(--s-5) 0 var(--s-3);
}
.team-group-h:first-of-type { margin-top: 0; }
.team-group-h .c { font: 600 var(--t-xs) var(--mono); color: var(--muted); text-transform: none; }

.tile {
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-3);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  transition: border-color var(--fast), transform var(--fast), background var(--fast);
}
.tile.tap { cursor: pointer; }
.tile.tap:hover { border-color: var(--muted); transform: translateY(-2px); }
.tile.tap:active { transform: none; background: var(--surface-2); }

.tile .avatar {
  width: 46px; height: 46px; font-size: var(--t-md);
}
.tile-name {
  font-weight: 600; font-size: var(--t-sm); line-height: 1.25;
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap; justify-content: center;
}
.tile-inst {
  font-size: var(--t-xs); color: var(--muted); line-height: 1.3;
  /* Keep long instrument lists from making one tile taller than the rest. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tile .role-pill, .tile .role-edit { margin-top: auto; }

/* A quiet remove control in the corner — present, not shouting. */
.tile-x {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px; border-radius: var(--r-full);
  display: grid; place-items: center; cursor: pointer;
  background: transparent; border: none; color: var(--muted);
  opacity: 0; transition: opacity var(--fast), background var(--fast), color var(--fast);
}
.tile:hover .tile-x { opacity: 1; }
.tile-x:hover { background: var(--surface-2); color: var(--danger); }
/* Touch devices have no hover — always show it there. */
@media (hover: none) { .tile-x { opacity: .7; } }

.role-pill {
  font: 650 var(--t-xs)/1 var(--font); letter-spacing: .4px;
  padding: 6px 9px; border-radius: var(--r-full); flex: none;
  text-transform: uppercase;
}
.role-pill.admin {
  background: color-mix(in srgb, var(--brand-2) 18%, transparent);
  color: var(--brand-2);
}
.role-pill.leader {
  background: color-mix(in srgb, var(--brand) 16%, transparent);
  color: var(--brand);
}
.role-pill.member { background: var(--surface-2); color: var(--text-2); }

/* The editable version of the tag: it IS the coloured pill, with a caret, and a
   real <select> laid transparently over it. So it reads as a status tag but
   behaves as a control — no separate "edit" affordance to hunt for. The colour
   is driven by the wrapper's role class, exactly like the static pill, so the
   two are visually identical at rest. */
.role-edit {
  position: relative; display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 8px 6px 10px; border-radius: var(--r-full); flex: none;
  cursor: pointer; transition: filter var(--fast), box-shadow var(--fast);
}
.role-edit:hover { filter: brightness(1.06); box-shadow: 0 0 0 1px currentColor inset; }
.role-edit .role-label {
  font: 650 var(--t-xs)/1 var(--font); letter-spacing: .4px; text-transform: uppercase;
}
.role-edit .ic { width: 13px; height: 13px; opacity: .8; }

/* The label and caret are DECORATION — they must never eat the click. Without
   this, the caret icon (painted after the select in the DOM) sat on top of it
   and swallowed taps, which is exactly why the dropdown "only worked if you
   clicked slightly off it". pointer-events:none sends every click straight
   through to the transparent select stretched across the whole pill. */
.role-edit .role-label,
.role-edit .ic { pointer-events: none; }

.role-edit.admin  { background: color-mix(in srgb, var(--brand-2) 18%, transparent); color: var(--brand-2); }
.role-edit.leader { background: color-mix(in srgb, var(--brand) 16%, transparent);  color: var(--brand); }
.role-edit.member { background: var(--surface-2); color: var(--text-2); }

/* The real control: invisible, absolutely filling the pill, on top of the
   decoration, taking every click. We get a native OS dropdown (and its
   accessibility) with none of its default chrome fighting our tag. */
.role-edit .role-select {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: none; padding: 0; margin: 0;
  -webkit-appearance: none; appearance: none;
}

.opt { color: var(--muted); font-weight: 400; text-transform: none; letter-spacing: 0; }

/* A member row whose name/instruments can be tapped to edit. */
.meta.tap { cursor: pointer; border-radius: var(--r-sm); }
.meta.tap:hover .t { color: var(--brand); }

.you { font-size: var(--t-xs); color: var(--muted); }

/* -------------------------------------------------------------- toast */
/* Confirmation without interruption. A leader setting eight keys should not have
   to dismiss eight alerts. */
.toast {
  position: fixed; left: 50%; bottom: 32px; transform: translate(-50%, 20px);
  background: var(--text); color: var(--bg);
  font: 600 var(--t-sm) var(--font);
  padding: 11px 18px; border-radius: var(--r-full);
  box-shadow: var(--shadow-3); z-index: 100;
  opacity: 0; pointer-events: none;
  transition: opacity var(--fast), transform var(--fast);
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }

/* The band's key, chosen by the leader. Deliberately prominent — it's the single
   most consequential control in the app. */
.keysel {
  /* width:auto and flex:none are load-bearing.
     The global `select { width: 100% }` rule applies here too, so without these
     the key dropdown expands to fill the row and squashes the song title to zero
     width — the title is rendered, you just can't see it. */
  width: auto !important;
  flex: none;
  min-width: 72px;

  font-family: var(--mono); font-weight: 650; font-size: var(--t-sm);
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand); border: 1px solid transparent;
  border-radius: var(--r-sm); padding: 8px 10px;
  -webkit-appearance: none; appearance: none; text-align: center;
  cursor: pointer;
}
.keysel:hover { border-color: var(--brand); }
.keysel:focus { outline: none; border-color: var(--brand); }

/* ======================================================================
   DESKTOP SHELL
   ======================================================================

   Everything above is mobile-first, which is correct — the app is used on a
   phone, on a stand, on a stage. But a phone layout stretched across a 2000px
   monitor is not a desktop app: full-bleed rows, tabs a metre wide, a gradient
   button the size of a door.

   So above 900px we switch to the layout every SaaS tool converges on for good
   reason: persistent sidebar, constrained content column, quiet secondary
   actions. Nothing below this line affects the phone.
   ====================================================================== */

.sidebar { display: none; }

@media (min-width: 900px) {

  /* ---- the persistent shell.
     The sidebar is FIXED and lives at the top level (not inside a screen), so it
     stays put while the content pane — whichever .screen is .on — swaps beneath
     it. This is what turns a stack of full-screen pages into a real app shell.
     Every chrome screen is offset right by the sidebar's width. */
  .sidebar {
    display: flex; flex-direction: column;
    position: fixed; top: 0; left: 0; bottom: 0; width: 248px; z-index: 20;
    background: var(--surface);
    border-right: 1px solid var(--line);
    padding: var(--s-4) var(--s-3);
    overflow-y: auto;
  }

  /* Charcoal sidebar (the default). We re-declare the tokens the sidebar's own
     components read, so a dark rail sits beside a light workspace — the
     GoHighLevel look — without rewriting a single component rule. Toggle it off
     (Settings → Sidebar → Light) and it falls back to the theme surface. */
  body[data-sidebar="charcoal"] .sidebar {
    background: #030807;
    border-right-color: #123028;
    --surface: #030807;
    --surface-2: rgba(16,185,129,.12);
    --line: #123028;
    --text: #eef5f2;
    --text-2: #93a8a0;
    --muted: #74897f;
    --brand: #34d399;
    --on-brand: #04140c;
  }

  .screen { padding-left: 248px; }

  /* Signed-out and on-stage have no chrome: full width, no sidebar. */
  body.no-chrome .sidebar { display: none; }
  body.no-chrome .screen { padding-left: 0; }

  #library.screen.on { display: flex; height: 100dvh; }

  .side-mark {
    display: flex; align-items: center; gap: 10px;
    padding: var(--s-2) var(--s-2) var(--s-5);
    font-weight: 500; letter-spacing: -.3px; font-size: var(--t-md);
    /* Read the sidebar's own --text. Without this the wordmark inherited the
       light theme's near-black body colour and vanished on the charcoal rail. */
    color: var(--text);
  }
  .side-mark .badge {
    width: 30px; height: 30px; border-radius: 9px; flex: none;
    background: #04140c; border: 1px solid #12352b; box-shadow: var(--glow);
    display: grid; place-items: center;
  }
  .side-mark .badge .ic { width: 24px; height: 24px; }
  .side-mark .org {
    font-size: var(--t-xs); color: var(--muted); font-weight: 500;
    display: block; margin-top: 1px;
  }

  .side-group { margin-bottom: var(--s-5); }
  .side-label {
    font: 650 10px/1 var(--font); letter-spacing: 1.2px; text-transform: uppercase;
    color: var(--muted); padding: 0 var(--s-2) var(--s-2);
  }

  .side-item {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 9px var(--s-2); border-radius: var(--r-sm);
    background: none; border: none; cursor: pointer;
    color: var(--text-2); font: 500 var(--t-sm) var(--font);
    text-align: left; margin-bottom: 1px;
    transition: background var(--fast), color var(--fast);
  }
  .side-item .ic { width: 17px; height: 17px; }
  .side-item:hover { background: var(--surface-2); color: var(--text); }
  .side-item.on {
    background: color-mix(in srgb, var(--brand) 12%, transparent);
    color: var(--brand); font-weight: 600;
  }
  .side-item .count {
    margin-left: auto; font: 600 var(--t-xs) var(--mono); color: var(--muted);
  }
  .side-item.on .count { color: var(--brand); }

  .side-foot { margin-top: auto; padding-top: var(--s-4); }
  .side-user {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 9px var(--s-2); border-radius: var(--r-sm);
    background: none; border: none; cursor: pointer; text-align: left;
    transition: background var(--fast);
  }
  .side-user:hover { background: var(--surface-2); }
  .side-user .who { min-width: 0; }
  .side-user .nm {
    font: 600 var(--t-sm) var(--font); color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .side-user .rl { font-size: var(--t-xs); color: var(--muted); text-transform: capitalize; }

  /* ---- the content column */
  .main {
    display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  }

  /* The phone's top bar and tab strip are redundant once there's a sidebar.
     NOTE the descendant selectors: these live inside .main, not as direct
     children of #library. Using `>` here silently matched nothing, and the whole
     mobile layout rendered underneath the sidebar. */
  #library .main > .bar,
  #library .main > .tabs,
  #library .main > #newServiceBtn,
  #library .main > .searchwrap,
  #home .main > .bar,
  #kb .main > .bar,
  #reports .main > .bar,
  #vocalmgr .main > .bar,
  #superadmin .main > .bar,
  #superChurch .main > .bar { display: none; }

  /* Full-width buttons read as mobile. On a desktop, buttons size to their
     label and sit inline, not stretched across the pane. */
  #teamInstruments,
  #newServiceBtn,
  .home-card .btn,
  .rota-actions .btn {
    width: auto !important; flex: none !important;
  }
  .rota-actions { justify-content: flex-end; }
  .home-card .btn { align-self: flex-start; }

  /* Buttons stacked in a form column shouldn't stretch to the column width;
     inputs still do (they're not .btn). */
  .stack > .btn { align-self: flex-start; width: auto; }
  /* ...except where a stack of buttons IS a menu of equal choices — the auth
     card and the settings groups (Church nav, Library actions, logo). Ragged
     content-widths there look like a mistake; matched full-width reads as one
     tidy list. */
  .auth-card .stack > .btn,
  #settings .stack > .btn { align-self: stretch; width: 100%; justify-content: center; }
  /* Settings button rows read best left-aligned with their icon, not centred. */
  #settings .stack > .btn { justify-content: flex-start; }

  /* The main column is a flex column that owns its own scroll. */
  #library .main { display: flex; flex-direction: column; height: 100dvh; }
  #library .list { flex: 1; overflow-y: auto; }

  .main-head {
    display: flex; align-items: center; gap: var(--s-3);
    padding: var(--s-5) var(--s-6) var(--s-4);
    border-bottom: 1px solid var(--line);
  }
  .main-head h1 {
    font-size: var(--t-xl); font-weight: 650; letter-spacing: -.5px; flex: 1;
  }
  .main-head .sub {
    font-size: var(--t-sm); color: var(--muted); font-weight: 400;
    display: block; margin-top: 2px; letter-spacing: 0;
  }

  .main-search { position: relative; width: 260px; flex: none; }
  .main-search input { padding-left: 38px; }
  .main-search .ic {
    position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
    color: var(--muted); pointer-events: none;
  }

  /* The content itself: a readable column, not a smear across the monitor. */
  #library .list {
    padding: var(--s-5) var(--s-6) var(--s-7);
    max-width: 900px; width: 100%;
  }

  /* Rows become table-like: quieter, denser, hover-reveal actions. */
  #library .row {
    border: none; border-bottom: 1px solid var(--line);
    border-radius: 0; margin-bottom: 0; padding: 13px var(--s-3);
    background: none;
  }
  #library .row:first-child { border-top: 1px solid var(--line); }
  #library .row:hover { background: var(--surface); transform: none; }
  #library .row .mini { opacity: 0; transition: opacity var(--fast); }
  #library .row:hover .mini { opacity: 1; }

  .main-actions { display: flex; gap: var(--s-2); }



  /* The big gradient button belongs on a phone, not up here. */
  .main-head .btn { padding: 10px 16px; font-size: var(--t-sm); }
}

/* ------------------------------------------------------------------ misc */

.footer-actions {
  padding: var(--s-3) var(--s-4) calc(env(safe-area-inset-bottom) + var(--s-3));
  border-top: 1px solid var(--line); display: flex; gap: var(--s-2);
  background: var(--bg); flex: none;
}
.footer-actions .btn { flex: 1; }


/* The desktop header is desktop-only. Below 900px the bar + tab strip do the job. */
@media (max-width: 899px) {
  .main-head { display: none; }
  #library .main { display: flex; flex-direction: column; min-height: 0; flex: 1; }
}

/* ======================================================================
   THE STAGE, ON A DESKTOP
   ======================================================================

   A chart stretched across a 2000px monitor is unreadable — your eye can't
   track back to the start of the next line. Charts are a COLUMN, the way sheet
   music is a column, whatever size the screen is.

   This also fixes a real bug: notes are positioned as a fraction of #content,
   so when #content was 2000px wide, a note at x=0.5 ended up a metre from the
   chart it was annotating. Constraining the column constrains the notes with it.
   ====================================================================== */

@media (min-width: 900px) {

  #chart {
    padding: var(--s-6) var(--s-5) 40vh;
  }

  /* The column. Notes, being absolute against #content, now stay with the song. */
  #content {
    max-width: 820px;
    margin: 0 auto;
  }

  /* Controls become a floating bar, not a wall across the bottom of the screen. */
  #controls {
    left: 50%; right: auto; bottom: var(--s-5);
    transform: translate(-50%, 200%);
    width: min(860px, calc(100vw - 64px));
    border: 1px solid var(--stage-line);
    border-radius: var(--r-lg);
    padding: var(--s-3);
    box-shadow: var(--shadow-3);
  }
  #controls.on { transform: translate(-50%, 0); }

  /* Rows fill the centred column edge to edge — first control flush left, last
     flush right — rather than bunching at the left. */

  #hud { top: var(--s-5); right: var(--s-6); }
}

/* An always-there way off the stage, top-left, quiet enough not to fight the
   chart but obvious enough to find at a glance. */
.stage-back {
  position: absolute; z-index: 6;
  top: calc(env(safe-area-inset-top) + 12px); left: 14px;
  width: 40px; height: 40px; border-radius: var(--r-md);
  background: rgba(255, 255, 255, .06); border: 1px solid var(--stage-line);
  color: var(--stage-text); display: grid; place-items: center; cursor: pointer;
  transition: background var(--fast), transform var(--fast);
}
.stage-back:hover { background: rgba(255, 255, 255, .16); }
.stage-back:active { transform: scale(.92); }

/* Always-visible previous/next-song buttons on the stage edges (only during a
   set). Big tap targets so you never hunt for them mid-song. */
.stage-nav {
  position: absolute; z-index: 6; top: 50%; transform: translateY(-50%);
  width: 46px; height: 64px; border-radius: var(--r-md);
  background: rgba(255,255,255,.06); border: 1px solid var(--stage-line);
  color: var(--stage-text); display: grid; place-items: center; cursor: pointer;
  transition: background var(--fast), transform var(--fast);
}
.stage-nav .ic { width: 26px; height: 26px; }
.stage-nav.prev { left: 8px; }
.stage-nav.next { right: 8px; }
.stage-nav:hover { background: rgba(255,255,255,.16); }
.stage-nav:active { transform: translateY(-50%) scale(.92); }

/* The running order, as a drawer from the right. Dark to match the stage. */
.stage-list {
  position: absolute; z-index: 8; top: 0; right: 0; bottom: 0;
  width: min(340px, 86vw);
  background: var(--stage-panel); border-left: 1px solid var(--stage-line);
  box-shadow: -12px 0 40px rgba(0,0,0,.5);
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top);
}
.stage-list-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 16px 12px; color: var(--stage-text);
  font: 500 var(--t-md) var(--font); border-bottom: 1px solid var(--stage-line);
}
.stage-list-head button {
  background: none; border: none; color: var(--stage-muted); cursor: pointer;
  width: 32px; height: 32px; display: grid; place-items: center; border-radius: var(--r-sm);
}
.stage-list-head button:hover { background: rgba(255,255,255,.08); color: var(--stage-text); }
#stageListItems { overflow-y: auto; padding: 8px; }
.slrow {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 12px; border-radius: var(--r-md); cursor: pointer;
  background: none; border: none; text-align: left; color: var(--stage-text);
  transition: background var(--fast);
}
.slrow:hover { background: rgba(255,255,255,.06); }
.slrow .n {
  width: 22px; flex: none; text-align: center; color: var(--stage-muted);
  font: 600 var(--t-sm) var(--mono);
}
.slrow .tt { flex: 1; min-width: 0; font-size: var(--t-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.slrow .kk { flex: none; color: var(--stage-muted); font: 600 var(--t-sm) var(--mono); }
.slrow.now {
  background: color-mix(in srgb, var(--stage-chord) 16%, transparent);
}
.slrow.now .n, .slrow.now .kk { color: var(--stage-chord); }
.slrow.now .tt { color: var(--stage-chord); font-weight: 600; }

/* ------------------------------------------------- streaming links */
.ed-links { display: flex; flex-direction: column; gap: 8px; margin-top: var(--s-4); }
.ed-links .plabel { margin-bottom: 0; }

.stage-links { display: flex; gap: 8px; flex-wrap: wrap; }
.stage-link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--r-full);
  font: 600 var(--t-xs) var(--font); color: #fff; text-decoration: none;
  background: var(--c, #444);
}
.stage-link:active { transform: scale(.95); }
.stage-link .dot { width: 8px; height: 8px; border-radius: 50%; background: #fff; }
/* Reserve a strip at the top so the song title clears the button. */
#chart { padding-top: calc(env(safe-area-inset-top) + 64px); }

/* ======================================================================
   SECONDARY SCREENS ON DESKTOP

   Profile, settings, editors. Same disease as the library had: a form field
   stretched to 2000px is not a form, it's a horizon. Forms are a column.
   ====================================================================== */

@media (min-width: 900px) {

  /*
   * One rule for EVERY secondary screen, not a hand-maintained list.
   *
   * I originally enumerated the screens here and promptly forgot to add the
   * instruments one — so it rendered full-bleed while everything around it was
   * a column. A list you have to remember to update is a list that will be
   * wrong. `.screen:not(...)` inverts it: new screens are columns by default,
   * and only the two that genuinely want the whole viewport opt out.
   */
  /* Team and Rota are excluded here — they're wide boards, styled just below.
     They have to be excluded rather than overridden because this generic
     selector's :not() chain carries several IDs of specificity, which a plain
     `#team .list` could never outweigh. */
  .screen:not(#library):not(#home):not(#perf):not(#welcome):not(#signin):not(#signup):not(#rota):not(#settings):not(#profile):not(#instruments) .body,
  .screen:not(#library):not(#home):not(#perf):not(#team) .list {
    max-width: 640px;
    width: 100%;
    margin: 0 auto;
    padding-left: var(--s-5);
    padding-right: var(--s-5);
  }

  .screen:not(#library):not(#home):not(#perf):not(#rota):not(#settings):not(#profile):not(#instruments) .body {
    padding-top: var(--s-6);
    padding-bottom: var(--s-7);
  }

  /* The exceptions, and why:
     - the song editor wants room for a chart
     - a service shows songs + team, so it gets a little more
     - Team is a tile grid and Rota is a board of Sundays: both are laid out to
       fill horizontal space, so they get a wide column, not the 640px reading
       measure used for forms and lists. */
  #editor .body  { max-width: 920px; }
  #service .list { max-width: 760px; }
  #team .list {
    max-width: 1120px; width: 100%; margin: 0 auto;
    padding: var(--s-5) var(--s-5) var(--s-7);
  }
  #rota .body {
    max-width: 1120px; width: 100%; margin: 0 auto;
    padding: var(--s-4) var(--s-5) var(--s-7);
  }

  /* SaaS forms. On a phone, settings is a flat scroll of sections; on a desktop
     that reads as unfinished. Sections become cards; settings lays them out as a
     masonry-ish grid that fills the width, profile/instruments stay a single
     comfortable column. */
  #settings .body {
    max-width: 1080px; margin: 0 auto; padding: var(--s-6) var(--s-6) var(--s-7);
    display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--s-4); align-content: start;
  }
  #profile .body, #instruments .body {
    max-width: 760px; margin: 0 auto; padding: var(--s-6) var(--s-5) var(--s-7);
  }
  #settings .body .group,
  #profile .body .group,
  #instruments .body .group {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: var(--s-5); margin-bottom: 0;
  }
  #profile .body .group, #instruments .body .group { margin-bottom: var(--s-4); }
  #addmember .body .stack,
  #rotaReqScreen .body .stack {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-lg); padding: var(--s-5);
  }

  /* Secondary headers read as page titles, not phone nav bars. */
  .screen:not(#library):not(#home):not(#perf):not(#welcome):not(#signin):not(#signup) .bar h1.sm {
    font-size: var(--t-xl); font-weight: 650;
  }

  /* Sundays become a responsive board rather than a single tall column — far
     better use of a desktop. The swap banner spans the whole width. */
  #rotaBody {
    display: grid; align-content: start;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--s-3); padding: 0;   /* the wide .body provides the outer padding now */
  }
  #rotaBody .swap-banner { grid-column: 1 / -1; }

  /* The rota's month bar and action row sit BETWEEN the header and the body, so
     the generic rules don't reach them. Match the wider column. */
  #rota .rota-month, #rota .rota-actions {
    max-width: 1120px; width: 100%; margin: 0 auto;
  }

  /* Every secondary page header lines up at ONE left edge — the same gutter the
     .main-head screens (library, home, vocal parts) use — so the page title never
     jumps position from one screen to the next. Content below keeps its own width. */
  .screen:not(#library):not(#home):not(#perf):not(#welcome):not(#signin):not(#signup) .bar {
    padding-left: var(--s-6);
    padding-right: var(--s-6);
  }

  /* Sidebar destinations don't need a back chevron on desktop — the sidebar IS
     the nav. (Drill-in screens like the editor keep theirs.) Mobile keeps them
     all, since there's no sidebar there. */
  #rota #rotaBack, #team #teamBack, #availability #availBack,
  #requests #reqBack, #settings #setsBack { display: none; }

  .footer-actions { justify-content: center; }
  .footer-actions .btn { flex: 0 1 240px; }
}

/* -------------------------------------------------------- instrument chips */
/* A multi-select, not a dropdown. People play more than one thing, and a
   dropdown that only holds one is what created this whole problem. */
.chips { display: flex; flex-wrap: wrap; gap: 7px; }

.chips button {
  background: var(--surface); border: 1px solid var(--line); color: var(--text-2);
  border-radius: var(--r-full); padding: 8px 14px;
  font: 500 var(--t-sm) var(--font); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  transition: background var(--fast), border-color var(--fast), color var(--fast);
}
.chips button:hover { border-color: var(--muted); }
.chips button.on {
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  border-color: var(--brand); color: var(--brand); font-weight: 600;
}
.chips button .ic { width: 14px; height: 14px; }

/* Something they play that the admin has since removed from the list. We do NOT
   delete it from their profile — that would be destroying data behind their
   back — so we show it, marked. */
.chips button.orphan {
  border-style: dashed; color: var(--muted);
}
.chips button.orphan.on {
  background: color-mix(in srgb, var(--muted) 12%, transparent);
  border-color: var(--muted); color: var(--text-2);
}

.ins-row {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 12px 14px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md);
}
.ins-row .nm { flex: 1; font-weight: 500; }
.ins-row .cnt { font-size: var(--t-xs); color: var(--muted); }


/* Same guard, applied broadly: an author `display` must never resurrect a
   [hidden] element. */
[hidden] { display: none !important; }

.mini[disabled] { opacity: .25; pointer-events: none; }

/* ---------------------------------------------------- instrument admin */

.ins-row {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.ins-row .nm { flex: 1; font-weight: 500; font-size: var(--t-md); min-width: 0; }
.ins-row .cnt {
  font-size: var(--t-xs); color: var(--muted); flex: none;
  margin-right: var(--s-2); white-space: nowrap;
}
.ins-row .mini { width: 30px; height: 30px; }
.ins-row .mini[data-rm] { color: var(--muted); }
.ins-row .mini[data-rm]:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }

/* Tighter than the default .stack — this is a list, not a stack of cards. */
#insList { gap: 6px; }

.ins-add { display: flex; gap: var(--s-2); align-items: stretch; }
.ins-add input { flex: 1; }
.ins-add .btn { flex: none; padding: 0 18px; }

/* --------------------------------------------------------- chord styling */
/* Chords are SCANNED, lyrics are READ. Different jobs, so they get their own
   type controls rather than inheriting the lyric ones. */
:root {
  --chord-colour: #4cc9f0;
  --chord-weight: 700;
  --chord-scale: 1;
  --chord-font: var(--mono);
}
.seg .c, .instr {
  color: var(--chord-colour);
  font-weight: var(--chord-weight);
  font-size: calc(1em * var(--chord-scale));
  font-family: var(--chord-font);
}

.chord-preview {
  background: var(--stage-bg); border: 1px solid var(--stage-line);
  border-radius: var(--r-md); padding: 18px 16px; margin-bottom: var(--s-4);
  font-family: var(--chart-font); font-size: 18px; line-height: 1.3;
  overflow-x: auto;
}
.chord-preview .seg .w { color: var(--stage-text); }

/* ------------------------------------------------ song coordination markers */
/* "last sung 3 weeks ago" / "next Sun 27 Jul" — shown in the set maker and the
   library so a leader can avoid repeating a song across teams. */
.coord { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
.coord .mark {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--t-xs); color: var(--muted);
  background: var(--surface-2); border-radius: var(--r-full);
  padding: 2px 9px 2px 7px; white-space: nowrap;
}
.coord .mark .ic { width: 12px; height: 12px; }
/* "Next" is the one that changes a decision — give it the brand accent. */
.coord .mark.next {
  color: var(--brand);
  background: color-mix(in srgb, var(--brand) 12%, transparent);
}

/* -------------------------------------------------------------- modal */
/* .modal overlay + card + actions now inherit the unified rules above; dialog
   fields use the same .plabel + input pattern as every other form. */

.key-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
.key-grid button {
  padding: 11px 0; border-radius: var(--r-sm); cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text);
  font: 600 var(--t-sm) var(--mono);
}
.key-grid button:hover { border-color: var(--muted); }
.key-grid button.on {
  background: var(--brand); color: var(--on-brand); border-color: var(--brand);
}

/* The library key badge is a control when you're signed in. */
.row .k.pickable { cursor: pointer; }
.row .k.pickable:hover { outline: 1px solid var(--brand); }

/* ------------------------------------------------------ trial banner */
/* A quiet strip on the dashboard. Warn = in trial, bad = lapsed. */
.trial-banner {
  border-radius: var(--r-md); padding: 12px 16px; margin-bottom: var(--s-4);
  font: 500 var(--t-sm) var(--font); line-height: 1.4;
  border: 1px solid var(--line);
}
.trial-banner.warn {
  background: color-mix(in srgb, #f5a524 12%, transparent);
  border-color: color-mix(in srgb, #f5a524 40%, transparent); color: var(--text);
}
.trial-banner.bad {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  border-color: color-mix(in srgb, var(--danger) 40%, transparent); color: var(--text);
}

/* -------------------------------------------------------- superadmin */
.sa-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3); margin-bottom: var(--s-4);
  max-width: 1120px; width: 100%;
}
.sa-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: var(--s-4);
}
.sa-card-val { font: 700 var(--t-xl) var(--font); color: var(--text); }
.sa-card-lbl { font-size: var(--t-sm); color: var(--text-2); margin-top: 2px; }
.sa-card-note { font-size: var(--t-xs); color: var(--muted); margin-top: 4px; }

.sa-controls {
  margin-bottom: var(--s-3); max-width: 1120px;
  display: flex; gap: var(--s-3); align-items: center; flex-wrap: wrap;
}
.sa-controls #saSearch { flex: 1; min-width: 220px; max-width: 420px; }

.chip.sm.ghost { background: none; }

/* ------------------------------------------------- support (impersonation) bar */
#supportBar {
  position: fixed; top: 0; left: 0; right: 0; height: 40px; z-index: 40;
  display: flex; align-items: center; justify-content: center; gap: var(--s-3);
  background: #171717; color: #fff;
  font: 500 var(--t-sm) var(--font); padding: 0 var(--s-4);
  border-bottom: 1px solid #333;
}
#supportBar strong { font-weight: 700; }
#supportBar .chip {
  background: rgba(255,255,255,.16); color: #fff; border: none;
}
#supportBar .chip:hover { background: rgba(255,255,255,.28); }

/* Push the whole shell down by the bar's height so it never covers content. */
body.supporting .sidebar { top: 40px; }
body.supporting .screen  { margin-top: 40px; height: calc(100dvh - 40px); }
/* The library screen sets its own height by id (higher specificity) — match it. */
body.supporting #library.screen.on { height: calc(100dvh - 40px); }

.sa-list { display: flex; flex-direction: column; gap: 8px; max-width: 1120px; width: 100%; }

/* On desktop the console content lines up under its page title instead of sitting
   flush against the sidebar. Everything shares one left-aligned column so the
   finance cards, tabs, search and church list all start at the same edge. */
@media (min-width: 900px) {
  #superadmin .sa-cards,
  #superadmin .sa-controls,
  #superadmin #saTabs,
  #superadmin .sa-list {
    padding-left: var(--s-6); padding-right: var(--s-6);
    box-sizing: border-box;
  }
  #superadmin .sa-list { padding-bottom: var(--s-7); }
}
.sa-row {
  display: flex; align-items: center; gap: var(--s-3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px 14px;
}
.sa-row-main { flex: 1; min-width: 0; }
.sa-row-name { font-weight: 600; font-size: var(--t-md); }
.sa-row-sub { font-size: var(--t-xs); color: var(--muted); margin-top: 2px; }
.sa-row-plan { text-align: right; flex: none; }
.sa-tier { font-size: var(--t-sm); color: var(--text-2); font-weight: 500; }
.sa-row-act { flex: none; }
.sa-row.sup-t { width: 100%; text-align: left; cursor: pointer; font: inherit; color: var(--text); margin-bottom: var(--s-2); }
.sa-row.sup-t:hover { border-color: var(--muted); }
.side-version { font-size: 11px; color: var(--muted); opacity: .7; padding: 6px 12px 2px; }
.chip.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--line)); }

.sa-badge {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: var(--r-full);
  font-size: 10px; font-weight: 700; letter-spacing: .3px; vertical-align: middle;
  background: color-mix(in srgb, var(--brand) 18%, transparent); color: var(--brand);
}

.sa-pill {
  display: inline-block; margin-top: 4px; padding: 2px 10px;
  border-radius: var(--r-full); font: 600 var(--t-xs) var(--font);
}
.sa-pill.ok   { background: color-mix(in srgb, #17c964 18%, transparent); color: #17c964; }
.sa-pill.warn { background: color-mix(in srgb, #f5a524 18%, transparent); color: #f5a524; }
.sa-pill.bad  { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.sa-pill.mut  { background: var(--surface-2); color: var(--muted); }

.chip.sm { padding: 6px 12px; font-size: var(--t-xs); }
.sa-row[data-open] { cursor: pointer; }
.sa-row[data-open]:hover { border-color: var(--muted); }

/* At-risk groups */
.sa-group { margin-bottom: var(--s-4); max-width: 1120px; }
.sa-group-h {
  font: 700 var(--t-xs) var(--font); text-transform: uppercase;
  letter-spacing: .4px; color: var(--muted); margin-bottom: 8px;
}
.sa-group .sa-row { margin-bottom: 8px; }

/* Activity / audit log */
.sa-audit { display: flex; flex-direction: column; gap: 2px; max-width: 1120px; }
.sa-audit-row {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: 10px 12px; border-bottom: 1px solid var(--line);
}
.sa-audit-act { font-weight: 600; font-size: var(--t-sm); flex: none; min-width: 130px; }
.sa-audit-det { flex: 1; color: var(--text-2); font-size: var(--t-sm); min-width: 0; }
.sa-audit-meta { flex: none; color: var(--muted); font-size: var(--t-xs); white-space: nowrap; }

/* Church detail */
.sa-detail { max-width: 760px; display: flex; flex-direction: column; gap: var(--s-4); }
.sa-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.sa-kv {
  display: flex; justify-content: space-between; gap: var(--s-3);
  padding: 6px 0; border-bottom: 1px solid var(--line); font-size: var(--t-sm);
}
.sa-kv:last-child { border-bottom: none; }
.sa-kv span:first-child { color: var(--muted); }
.sa-member {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: var(--t-sm);
}
.sa-member:last-child { border-bottom: none; }
.sa-member .nm { flex: 1; font-weight: 500; min-width: 0; }
.sa-member .rl { flex: none; color: var(--muted); text-transform: capitalize; width: 64px; }
.sa-member .in { flex: none; color: var(--text-2); max-width: 40%; text-align: right; }
#scNotes { margin-bottom: var(--s-3); }

@media (max-width: 640px) {
  .sa-row { flex-wrap: wrap; }
  .sa-row-plan { text-align: left; }
  .sa-audit-row { flex-wrap: wrap; }
  .sa-audit-act { min-width: 0; }
}
