/* Setlist — one stylesheet, no framework. Dark throughout: this lives on a music
   stand in a dark room, and build mode and show mode should not flash white at
   each other. Touch targets are 44px minimum because it is played with a bow in
   the other hand. */

:root {
  --bg: #0f1113;
  --bg2: #171a1d;
  --row: #1c2024;
  --row2: #212629;
  --line: #2c3238;
  --fg: #e9edf1;
  --dim: #8b969f;
  --accent: #7fc4a0;
  /* Keys get a colour of their own: on the second line of a build row they sit
     beside the ABC, and in one dim grey the two read as a single run of text. */
  --keys: #c9a96a;
  --warn: #e0796b;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--bg); color: var(--fg);
  font-family: var(--sans); font-size: 16px;
  overscroll-behavior: none;
}

button, input, select, textarea {
  font: inherit; color: inherit;
  background: var(--row2); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; min-height: 44px;
}
button { cursor: pointer; }
button.primary { background: var(--accent); color: #0d1210; border-color: var(--accent); font-weight: 600; }
button.danger { color: var(--warn); border-color: #4a3230; }
button.link { background: none; border: none; color: var(--accent); text-decoration: underline; min-height: 0; padding: 0; }

/* ---------------- build mode ---------------- */

#topbar {
  display: flex; gap: 8px; align-items: center;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px) * 0);
  padding-left: max(12px, env(safe-area-inset-left));
  padding-right: max(12px, env(safe-area-inset-right));
  background: var(--bg2); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 5;
}
#showTitle {
  flex: 0 1 26ch; min-width: 12ch; background: none; border: 1px solid transparent;
  font-size: 19px; font-weight: 600; padding: 8px 10px;
}
#showTitle:focus { border-color: var(--line); background: var(--row); outline: none; }
.grow { flex: 1 1 auto; }
/* The running version, small and dim, so "which one is this iPad on?" is
   answerable without opening anything. */
.vertag { color: var(--dim); font-size: 11px; opacity: 0.7; font-family: var(--mono); margin: 0; }
.tb { white-space: nowrap; }

#build { padding: 8px 0 120px; }

/* View by type. One row of chips under the header: All is pinned to the left
   where the thumb expects it, and the rest scroll sideways when there are more
   types than fit. Every chip is a 44px target. */
#typeBar { padding: 2px max(8px, env(safe-area-inset-left)) 4px max(8px, env(safe-area-inset-right)); }
.chiprow { display: flex; gap: 8px; align-items: center; min-width: 0; }
.chipscroll {
  display: flex; gap: 8px; flex: 1 1 auto; min-width: 0;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  padding: 2px 0;
}
.chipscroll::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto; min-height: 44px; min-width: 44px; padding: 8px 16px; font-size: 15px;
  border-radius: 22px; background: var(--row); color: var(--dim); white-space: nowrap;
}
.chip.on { background: var(--accent); color: #0d1210; border-color: var(--accent); font-weight: 600; }
#typeCount { color: var(--dim); font-size: 13px; margin: 4px 0 0; padding: 0 6px; }
/* Where a set sits among the ones that will be played, for when the list around
   it is hidden. The space is reserved so a row does not change height. */
.ctx { color: var(--dim); font-size: 12px; margin-top: 3px; min-height: 15px; }
.passed { color: var(--keys); font-size: 12px; margin-top: 2px; }
.nomatch { list-style: none; color: var(--dim); font-size: 14px; margin: 6px 0; padding: 6px 6px 6px 52px; }
/* The two slots a filtered drag needs that no visible row can express. They are
   in the list the whole time and only appear while something is being dragged. */
.droptarget { display: none; }
body.dragging-active .droptarget {
  display: flex; align-items: center; justify-content: center;
  height: 44px; margin: 6px 0; border: 1px dashed var(--accent); border-radius: 10px;
  color: var(--accent); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; opacity: 0.85;
}
#empty { color: var(--dim); padding: 24px max(16px, env(safe-area-inset-left)); }

#list { list-style: none; margin: 0; padding: 0 max(8px, env(safe-area-inset-left)) 0 max(8px, env(safe-area-inset-right)); }

.row {
  display: grid;
  grid-template-columns: 44px 44px 2.6ch 1fr auto;
  grid-template-areas: "handle inc num body btns";
  align-items: center; gap: 4px;
  background: var(--row); border: 1px solid var(--line); border-radius: 10px;
  margin: 6px 0; padding: 8px 6px;
  touch-action: pan-y;               /* horizontal moves are ours (swipe to remove) */
  position: relative;
}
.row.excluded { opacity: 0.45; }
/* Briefly after "already in this show", so the eye finds the row it meant. */
.row.flash { border-color: var(--accent); background: #1b2521; }
.row.brk { grid-template-columns: 44px 44px 1fr auto; grid-template-areas: "handle inc body btns"; background: var(--bg2); }
/* Passive labels for the pages show mode will make, above the row each one
   starts at. Not a row: nothing to drag, tap or count. */
.secthead {
  list-style: none; color: var(--accent); font-size: 12px; letter-spacing: 0.18em;
  text-transform: uppercase; margin: 16px 0 2px; padding: 0 6px 0 52px; opacity: 0.85;
}
.secthead:first-child { margin-top: 4px; }
.row.dragging { opacity: 0.92; box-shadow: 0 10px 24px rgba(0,0,0,0.55); border-color: var(--accent); z-index: 3; }
.row.swiping { background: #2a1d1c; }
/* No overflow lock on the body while dragging: edge autoscroll has to be able
   to move the page. The touchmove handler in app.js is what stops the finger
   scrolling the list out from under a drag. */
body.dragging-active .row:not(.dragging) { transition: transform 0.12s ease; }

.handle {
  grid-area: handle; touch-action: none; background: none; border: none;
  color: var(--dim); font-size: 22px; line-height: 1; padding: 0;
  width: 44px; height: 44px;
}
.inc { grid-area: inc; width: 26px; height: 26px; margin: 0 auto; min-height: 0; accent-color: var(--accent); }
.num { grid-area: num; color: var(--dim); font-variant-numeric: tabular-nums; text-align: right; }
.row:not(.excluded) .num { color: var(--fg); }
.body { grid-area: body; min-width: 0; padding: 0 8px; }
.btns { grid-area: btns; display: flex; gap: 2px; }
.btns button { background: none; border: none; color: var(--dim); width: 40px; padding: 0; font-size: 17px; }
.btns .rm { color: #7d5c58; font-size: 22px; }

.line1 { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.type { color: var(--accent); font-weight: 600; flex: 0 0 auto; min-width: 8ch; }
.type.editable { text-decoration: underline dotted var(--line); }
.tunes { font-size: 17px; }
.line2 { display: flex; gap: 18px; margin-top: 2px; color: var(--dim); font-size: 14px; flex-wrap: wrap; }
.keys { min-width: 8ch; flex: 0 0 auto; color: var(--keys); }
.abc { font-family: var(--mono); }
.note { margin-top: 3px; color: #b9a97e; font-size: 13px; }
.missing { color: var(--warn); }
.brk .body { text-align: center; color: var(--dim); letter-spacing: 0.24em; text-transform: uppercase; font-size: 13px; }

/* ---------------- show mode ---------------- */

body[data-mode="show"] #topbar,
body[data-mode="show"] #build { display: none; }
body[data-mode="build"] #show { display: none; }

/* Show mode is a fixed header over one scrolling page. The header's height is
   reserved whether or not it has anything to say, so the first tune sits in the
   same place on every page. */
#show {
  background: #07080a; height: 100%;
  display: flex; flex-direction: column;
}
#showHead {
  flex: 0 0 auto; height: 60px; display: flex; align-items: center; gap: 14px;
  padding: 0 max(24px, env(safe-area-inset-right)) 0 max(24px, env(safe-area-inset-left));
  border-bottom: 1px solid #14181c;
}
#pageLabel { font-size: 17px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); }
#pageOf { font-size: 15px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim); }
/* --ss is the show-mode text size: Fit works it out by measuring (app.js), a
   fixed percentage sets it outright. Every type size, gap and margin below is
   written as its base times --ss, so one number scales the whole page and
   nothing drifts out of proportion. The page buttons are deliberately NOT
   scaled: they are a target for a finger, not something to read. */
#showScroll { --ss: 1; flex: 1 1 auto; overflow-y: auto; display: flex; flex-direction: column;
  padding-top: calc(18px * var(--ss)); }
#showList { flex: 0 0 auto; padding: 0 max(24px, env(safe-area-inset-right)) 0 max(24px, env(safe-area-inset-left)); }
/* The nav sits at the foot of the screen when the page fits and below the last
   item when it does not; either way 32px clear of the music, never over it. */
#showNav {
  flex: 0 0 auto; margin-top: auto; display: flex; gap: 24px; flex-wrap: nowrap; align-items: flex-end;
  padding: 32px max(24px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom))
           max(24px, env(safe-area-inset-left));
}
#btnPrevPage { margin-right: auto; }
#btnNextPage { margin-left: auto; }
.showrow { display: grid; grid-template-columns: calc(2.2ch * var(--ss)) 1fr; gap: calc(14px * var(--ss));
  margin: 0 0 calc(20px * var(--ss));
  border-left: 5px solid transparent; padding-left: 9px; margin-left: -14px; }
/* "Now" is a left border as well as a colour, so it reads at stand distance
   and does not depend on seeing the difference between two dark greens. */
.showrow.now { background: #12211b; border-left-color: var(--accent); border-radius: 0 10px 10px 0; padding: 6px 8px 6px 9px; }
.snum { font-size: calc(26px * var(--ss)); color: var(--dim); font-variant-numeric: tabular-nums; cursor: pointer; }
.showrow.now .snum { color: var(--accent); }
.stype { font-size: calc(19px * var(--ss)); letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); }
.snames { font-size: calc(28px * var(--ss)); line-height: 1.22; margin-top: calc(2px * var(--ss)); }
.skeys { font-size: calc(19px * var(--ss)); color: var(--keys); margin-top: calc(2px * var(--ss)); }
.sabc { font-size: calc(22px * var(--ss)); font-family: var(--mono); color: #b7c3cc; margin-top: calc(4px * var(--ss)); }
.snote { font-size: calc(18px * var(--ss)); color: var(--dim); margin-top: calc(4px * var(--ss)); }
#showEmpty { color: var(--dim); font-size: 20px; }
#sleepWarn { color: var(--dim); font-size: 13px; opacity: 0.8; }

/* The show clock, centred in the header between the page label and edit. The
   time itself is monospace and tabular so the digits do not shuffle sideways
   every second. */
#showTimer { display: flex; align-items: center; gap: 10px; }
#timerTime {
  font-family: var(--mono); font-size: 22px; color: var(--fg);
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
.timerbtn {
  min-height: 48px; min-width: 48px; font-size: 14px; padding: 8px 14px;
  background: rgba(30,35,39,0.85); color: var(--dim); border-color: #262c31;
}
#btnTimerReset.held { border-color: var(--accent); }

/* Hold-and-release. The fill is the whole feedback: it grows across the button
   for 600ms, and vanishes the moment the gesture is cancelled. */
.holdbtn { position: relative; overflow: hidden; white-space: nowrap; touch-action: none; }
.holdbtn .fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: var(--accent); opacity: 0.28; pointer-events: none;
}
.holdbtn.holding .fill { width: 100%; transition: width 600ms linear; }
.holdbtn .lbl { position: relative; }
#btnEdit {
  background: rgba(30,35,39,0.85); color: var(--dim); border-color: #262c31;
  font-size: 14px; padding: 8px 14px; min-height: 48px; min-width: 48px;
}
.pagebtn {
  min-height: 64px; min-width: 240px; font-size: 21px; font-weight: 600;
  background: var(--row2); border-color: #333c43; padding: 12px 20px;
}
.pagebtn.held { border-color: var(--accent); }

/* ---------------- panels ---------------- */

#drawer, #editor, #sharePanel, #askPanel {
  position: fixed; z-index: 20; background: var(--bg2);
  border: 1px solid var(--line); border-radius: 14px;
  display: flex; flex-direction: column;
  box-shadow: 0 18px 50px rgba(0,0,0,0.6);
}
#drawer { top: 0; right: 0; bottom: 0; width: min(520px, 92vw); border-radius: 14px 0 0 14px; }
#editor { top: 4vh; left: 50%; transform: translateX(-50%); width: min(720px, 94vw); max-height: 92vh; }
#sharePanel, #askPanel { top: 8vh; left: 50%; transform: translateX(-50%); width: min(620px, 94vw); max-height: 84vh; }
#scrim { position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 10; }

.panelhead { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
.panelhead.sub { border-bottom: none; border-top: 1px solid var(--line); margin-top: 10px; padding-left: 0; padding-right: 0; }
/* The drawer's two jobs, kept visibly apart: what you add to this show, and
   the shows themselves. */
.sechead { color: var(--dim); font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; margin: 0 0 8px; }
.shows { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 4px; }
.panelhead strong { font-size: 17px; }
.panelhead .x, .panelhead span { margin-left: auto; background: none; border: none; color: var(--dim); font-size: 26px; }
.panelhead span { display: flex; gap: 6px; }
.panelbody { padding: 12px 14px; overflow: auto; flex: 1 1 auto; }
.panelfoot { display: flex; gap: 8px; align-items: center; padding: 12px 14px; border-top: 1px solid var(--line); }
.hint { color: var(--dim); font-size: 14px; margin: 0 0 10px; }
.hint.warn { color: var(--warn); }

.quick { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.q { padding: 8px 12px; min-height: 40px; font-size: 15px; }
.libtop { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
#libSearch { flex: 1 1 14ch; min-width: 12ch; }
/* Segmented control: two 44px targets, because this is tapped with a finger. */
.seg { display: flex; flex: 0 0 auto; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.segbtn {
  border: none; border-radius: 0; background: var(--row); color: var(--dim);
  min-height: 44px; padding: 10px 12px; font-size: 14px; white-space: nowrap;
}
.segbtn + .segbtn { border-left: 1px solid var(--line); }
.segbtn.on { background: var(--accent); color: #0d1210; font-weight: 600; }
.libgroup { margin: 14px 0 6px; color: var(--dim); font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase; }
.gcount { color: var(--dim); opacity: 0.75; letter-spacing: 0; }
.libset {
  display: block; width: 100%; text-align: left; margin: 5px 0; padding: 9px 11px;
  background: var(--row); border-radius: 9px; position: relative;
}
/* A set already in this show: dimmed, marked, and tapping it adds nothing. */
.libset.inshow { opacity: 0.5; }
.inmark { position: absolute; top: 9px; right: 11px; color: var(--accent); font-size: 12px; }
.libset .lt { color: var(--accent); font-size: 13px; }
.libset .ln { font-size: 16px; }
.libset .la { color: var(--dim); font-size: 13px; font-family: var(--mono); }
.showitem { display: flex; gap: 8px; align-items: center; margin: 5px 0; }
.showitem .open { flex: 1 1 auto; text-align: left; background: var(--row); }
.showitem.current .open { border-color: var(--accent); }

.tuneedit { display: grid; grid-template-columns: 1fr 7ch 1fr 44px; gap: 6px; margin: 6px 0; }
.tuneedit input { width: 100%; }
.tuneedit .abcin { font-family: var(--mono); }
.tuneedit .del { background: none; border: none; color: #7d5c58; font-size: 22px; }
.field { display: block; margin: 10px 0; }
.field span { display: block; color: var(--dim); font-size: 13px; margin-bottom: 4px; }
.field input, .field textarea { width: 100%; }
#importPaste { font-family: var(--mono); font-size: 13px; resize: vertical; }
.setting { display: flex; gap: 10px; align-items: center; margin-top: 14px; flex-wrap: wrap; }
.setting > span { color: var(--dim); font-size: 14px; }
.setting input { width: 24px; height: 24px; min-height: 0; accent-color: var(--accent); }
.row-btns { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
#shareUrl { width: 100%; font-family: var(--mono); font-size: 13px; }

/* Cloud sync: the second half of the Share panel, fenced off the same way the
   drawer fences its two jobs. The status line is the whole story — off, synced,
   offline or error — so it is the one thing that changes colour. */
.synsec { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 12px; }
#syncStatus[data-state="synced"] { color: var(--accent); }
#syncStatus[data-state="error"] { color: var(--warn); }
#syncCode, #syncCodeIn { width: 100%; font-family: var(--mono); font-size: 16px; letter-spacing: 0.06em; }

#status {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 18px; z-index: 40;
  margin: 0; padding: 6px 8px 6px 16px; border-radius: 22px;
  background: #23292e; border: 1px solid var(--line); color: var(--fg); font-size: 14px;
  display: flex; align-items: center; gap: 2px;
  opacity: 0; transition: opacity 0.2s; pointer-events: none;
}
#status.on { opacity: 1; }
/* The toast is inert except for the Undo button, which has to be tappable. */
#undoBtn {
  pointer-events: auto; background: none; border: none; color: var(--accent);
  font-size: 14px; font-weight: 600; min-height: 36px; padding: 6px 12px;
}

/* Portrait iPad: the toolbar wraps rather than squeezing the title to nothing. */
@media (max-width: 900px) {
  #topbar { flex-wrap: wrap; }
  #showTitle { flex: 1 1 100%; }
  .row { grid-template-columns: 44px 40px 2.6ch 1fr auto; }
  .row.brk { grid-template-columns: 44px 40px 1fr auto; }
  .secthead { padding-left: 48px; }
  .type { min-width: 0; }
  .keys { min-width: 0; }
}
