/* GreenRoom local — jam-room / backstage aesthetic. Dark default + light theme. */
:root{
  --bg:#14110e; --bg2:#1b1714; --bg3:#241f1a; --line:#362f28;
  --text:#ece4d8; --muted:#9a9083; --accent:#f5a623; --accent-ink:#2a1c05;
  --in:#6fce9f; --maybe:#e8b84b; --out:#e8635a; --danger:#e8635a;
  --radius:12px; --shadow:0 6px 20px rgba(0,0,0,.35);
  --mono:ui-monospace,"SFMono-Regular",Menlo,Consolas,monospace;
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
:root[data-theme="light"]{
  /* A warm, muted tan rather than near-white — the original (#ece5d8/#f6f1e8/#fffdf8) read as
     glaringly bright, especially with a big pale card on a paler page. Darkened and desaturated
     the whole trio; text/muted darkened to match so contrast stays as good or better. */
  --bg:#d9cdb7; --bg2:#e6dcc7; --bg3:#efe6d3; --line:#c1b294;
  --text:#221d15; --muted:#5b5142; --accent:#7a4a00; --accent-ink:#fff6e6;
  --in:#08603c; --maybe:#6e4b00; --out:#9c2a1b; --danger:#9c2a1b;
  --shadow:0 4px 16px rgba(50,38,15,.22);
}
*{box-sizing:border-box}
/* Must beat the explicit display rules below (.btn is inline-flex, label is flex, etc.),
   or anything toggled with the `hidden` attribute stays stubbornly visible. */
[hidden]{display:none!important}
body{margin:0;background:var(--bg);color:var(--text);font-family:var(--sans);line-height:1.5;
  background-image:radial-gradient(circle at 12% -10%,rgba(245,166,35,.06),transparent 45%),radial-gradient(circle at 90% 0,rgba(111,206,159,.05),transparent 40%);
  background-attachment:fixed;min-height:100vh;overflow-x:hidden;overflow-x:clip}
html{overflow-x:hidden;overflow-x:clip;touch-action:pan-x pan-y;-webkit-text-size-adjust:100%}
a{color:inherit;text-decoration:none}
h1{font-size:1.5rem;margin:.1rem 0}h2{font-size:1.05rem;margin:0 0 .6rem}h3{font-size:.95rem;margin:1rem 0 .5rem}
.muted{color:var(--muted)}.small{font-size:.82rem}.grow{flex:1;min-width:0}.center{text-align:center}

/* Topbar */
.topbar{display:flex;align-items:center;gap:1rem;padding:.55rem 1rem;max-width:var(--site-max);margin-inline:auto;width:100%;background:var(--bg2);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:50}
.brand{font-weight:800;letter-spacing:.5px;font-size:1.15rem;display:flex;align-items:center;gap:.5rem;flex:0 0 auto}
.brand:before{content:"●";color:var(--accent)}
.tag{font-family:var(--mono);font-size:.6rem;text-transform:uppercase;letter-spacing:.18em;color:var(--accent);
  border:1px solid var(--line);padding:.15em .5em;border-radius:5px;background:var(--bg3)}
.betabadge{font-family:var(--mono);font-size:.52rem;text-transform:uppercase;letter-spacing:.1em;font-weight:700;
  color:#fff;background:#b71c1c;border-radius:3px;padding:.1em .4em;margin-left:.1rem;
  display:inline-block;transform:rotate(-5deg);vertical-align:middle;opacity:.9}
.feedbackfab{position:fixed;bottom:5rem;right:1rem;z-index:96;
  background:var(--bg2);border:1px solid var(--line);border-radius:20px;
  color:var(--muted);padding:.4rem 1rem;font-size:.82rem;cursor:pointer;
  box-shadow:0 2px 10px rgba(0,0,0,.5);transition:transform .15s,color .15s;
  display:flex;align-items:center;gap:.35rem}
.feedbackfab:hover{color:var(--accent);transform:translateY(-2px)}
@media(max-width:767px){.feedbackfab{bottom:4.5rem}} /* clear mobile tab bar */
/* Never wraps to a second row, from a 1920x1080 landscape laptop up to 4K — flex-shrink:1 (the
   default) plus the internal overflow:hidden lets .mainnav give ground first, while .brand and
   .topright hold their natural size. fitMainNav() in app.js keeps it looking intentional: as
   room runs out, lowest-priority links move into the "More" dropdown instead of ever letting
   the browser actually clip anything — see the .navmore rules below. */
.mainnav{display:flex;gap:.15rem;flex-wrap:nowrap;overflow:hidden;align-items:center;min-width:0}
.mainnav a{padding:.4rem .7rem;border-radius:8px;color:var(--muted);font-weight:600;font-size:.9rem;white-space:nowrap;flex:0 0 auto}
.mainnav a:hover{color:var(--text);background:var(--bg3)}
.mainnav a.active{color:var(--accent-ink);background:var(--accent)}
.mainnav .navmore{flex:0 0 auto}
.mainnav .navmore .menu a{color:var(--muted);white-space:nowrap}
.mainnav .navmore .menu a:hover{color:var(--text)}
.mainnav .navmore .menu a.active{color:var(--accent)}
.mainnav .navmore>summary{white-space:nowrap}
.mainnav .navmore.has-active>summary{color:var(--accent);border-color:var(--accent)}
/* Sonar/Platform chips that land in the dropdown stack one per row like the other entries. */
.mainnav .navmore .menu a.navchip{display:flex;margin:.15rem 0}
/* The name + gear used to be two separate controls (a dropdown menu, and a lone gear icon) —
   now one link to a real page, so there's one thing to click instead of a menu to open first. */
.topname{display:flex;align-items:center;gap:.35rem;padding:.35rem .6rem;border-radius:8px;color:var(--text);font-weight:700;font-size:.92rem;white-space:nowrap}
.topname:hover{background:var(--bg3)}
.topname .topname-gear{font-size:1rem;opacity:.75}
.topavatar{width:24px;height:24px;border-radius:50%;object-fit:cover;flex:none}
/* No picture yet: a plain accent dot, same footprint as a picture so the name never jumps. */
.topavatar-dot{display:inline-block;width:12px;height:12px;margin:0 6px;background:var(--accent)}

/* Account → profile picture: current image big and clear, history as a small clickable strip. */
.avatarrow{display:flex;gap:1rem;align-items:center}
/* Thin nudge banner (two-factor). Hidden by [hidden] when dismissed. */
.nagbar{display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;padding:.5rem .8rem;margin:0 0 .9rem;border:1px solid var(--accent);border-radius:10px;background:color-mix(in srgb,var(--accent) 10%,transparent);font-size:.85rem}
.nagbar[hidden]{display:none}
.nagbar>span{flex:1 1 260px}
.avatargrid{display:grid;grid-template-columns:repeat(6,1fr);gap:.5rem;margin:.6rem 0}
.avatarpick{background:none;border:2px solid transparent;border-radius:50%;padding:2px;cursor:pointer;line-height:0}
.avatarpick img{width:100%;height:auto;aspect-ratio:1;border-radius:50%;display:block}
.avatarpick:hover{border-color:var(--muted)}
.avatarpick.on{border-color:var(--accent)}
@media (max-width:520px){.avatargrid{grid-template-columns:repeat(4,1fr)}}
/* Upload progress: a thin bar under the button while a file is going up. */
.upbar{position:relative;flex-basis:100%;height:18px;margin-top:.45rem;border:1px solid var(--line);border-radius:9px;background:var(--bg3);overflow:hidden}
.upbar i{position:absolute;inset:0 auto 0 0;width:0;background:var(--accent);opacity:.85;transition:width .15s linear}
.upbar span{position:relative;display:block;text-align:center;font-size:.7rem;line-height:16px;font-weight:700;color:var(--text)}
/* Account › Profile: picture and "Play with more people" side by side; stacked on a phone. */
.acctpair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;align-items:start;margin-bottom:1rem}
.acctpair>.card{margin:0}
@media (max-width:820px){.acctpair{grid-template-columns:1fr}}
.avatarbig{width:72px;height:72px;border-radius:50%;object-fit:cover;flex:none;border:1px solid var(--line)}
.avatarblank{display:flex;align-items:center;justify-content:center;background:var(--bg3);color:var(--muted);font-size:1.6rem;font-weight:700}
.avatarhistory{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.5rem}
.avatarhistitem{margin:0}
.avatarhistbtn{padding:0;border:2px solid var(--line);border-radius:50%;background:none;cursor:pointer;width:48px;height:48px;overflow:hidden}
.avatarhistbtn:hover{border-color:var(--accent)}
.avatarhistbtn img{width:100%;height:100%;object-fit:cover;display:block}

.navposform{display:flex;gap:1.2rem;flex-wrap:nowrap}
.navposopt{display:flex;align-items:center;gap:.4rem;font-weight:600;cursor:pointer;position:relative;white-space:nowrap}
/* While the auto-submit is in flight (no Save button to show it instead), a small ring spins
   in place of the radio's own bullet so picking an option doesn't look like it did nothing. */
.navposopt.is-busy input{visibility:hidden}
.navposopt.is-busy:before{content:"";position:absolute;left:0;width:14px;height:14px;margin:3px;
  border-radius:50%;border:2px solid var(--accent);border-right-color:transparent;animation:spin .6s linear infinite}
.topright{margin-left:auto;display:flex;align-items:center;gap:.5rem;flex:0 0 auto}
/* The band-picker's name (arbitrary length, someone else's band could be a mouthful) always
   truncates instead of growing — previously this only happened under the 820px mobile
   breakpoint, so a long band name on desktop could still crowd the nav into wrapping. */
.topright .dropdown>summary{max-width:200px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:1.6}
.iconbtn{background:var(--bg3);border:1px solid var(--line);color:var(--text);width:34px;height:34px;border-radius:8px;cursor:pointer;font-size:1rem}
/* Theme slider: the track IS the shade preview (dark → light). */
.themepick>summary.iconbtn{display:flex;align-items:center;justify-content:center;padding:0;gap:0;width:34px;max-width:none;overflow:visible}
.themebox{min-width:240px;padding:.75rem .85rem}
.themeends{display:flex;justify-content:space-between;font-size:.78rem;font-weight:700;margin-bottom:.45rem}
.themerange{-webkit-appearance:none;appearance:none;width:100%;height:20px;border-radius:999px;border:1px solid var(--line);cursor:pointer;margin:0 0 .5rem;
  background:linear-gradient(90deg,#14110e,#4f4941 30%,#8a8273 60%,#d9cdb7)}
.themerange::-webkit-slider-thumb{-webkit-appearance:none;width:26px;height:26px;border-radius:50%;background:var(--accent);border:3px solid var(--text);box-shadow:0 1px 4px rgba(0,0,0,.45)}
.themerange::-moz-range-thumb{width:20px;height:20px;border-radius:50%;background:var(--accent);border:3px solid var(--text);box-shadow:0 1px 4px rgba(0,0,0,.45)}
.themerange::-moz-range-track{background:transparent}
/* Phones: a fixed panel that stays clear of the side rail (which sits on the left or the right). */
@media (max-width:820px){
  .topright .themepick{position:static}
  .topright .themepick .menu.themebox{position:fixed;top:calc(var(--topbar-h,56px) + 4px);left:12px;right:auto;width:min(300px,calc(100vw - 110px));min-width:0;z-index:70}
  [data-navpos="left"] .topright .themepick .menu.themebox{left:96px}
  [data-navpos="bottom"] .topright .themepick .menu.themebox{left:auto;right:12px;width:min(300px,calc(100vw - 24px))}
}
.iconbtn:hover{border-color:var(--accent)}

/* Dropdowns (native details) */
.dropdown{position:relative}
.dropdown>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:.45rem;padding:.4rem .7rem;
  background:var(--bg3);border:1px solid var(--line);border-radius:8px;font-weight:600;font-size:.9rem}
.dropdown>summary::-webkit-details-marker{display:none}
.dropdown .menu{position:absolute;top:calc(100% + 6px);left:0;min-width:200px;background:var(--bg2);
  border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow);padding:.35rem;z-index:60}
.dropdown.right .menu{left:auto;right:0}
.dropdown .menu a{display:flex;align-items:center;gap:.5rem;padding:.5rem .6rem;border-radius:7px;font-size:.9rem}
.dropdown .menu a:hover{background:var(--bg3)}
.dropdown .menu a.on{color:var(--accent)}
.menudivider{height:1px;background:var(--line);margin:.35rem .3rem}
.dot{width:10px;height:10px;border-radius:50%;display:inline-block;flex:none}

/* Layout */
.wrap{max-width:var(--site-max);margin:0 auto;padding:1.4rem 1rem 4rem}
.pagehead{display:flex;justify-content:space-between;align-items:flex-end;gap:1rem;margin-bottom:1.2rem;flex-wrap:wrap}
/* A quiet, easy-to-miss-on-purpose way to invite another musician — the dashboard's job is
   the band's day-to-day, not recruiting, so this stays a small text link, not a button. */
.subtleinvite{display:inline-flex;align-items:center;gap:.3rem;font-size:.78rem;color:var(--muted);margin-top:.5rem}
.subtleinvite:hover{color:var(--accent)}
.grid2{display:grid;grid-template-columns:repeat(2,1fr);gap:1rem;margin-bottom:1rem}
.grid2 .span{grid-column:1/-1}
/* Band settings: details on the left; logo/banner and links stacked on the right. */
.bandside{display:flex;flex-direction:column;gap:1rem;min-width:0}
.bandside>.card,.bandgrid>.card{margin-bottom:0}
/* Band settings (2026-10-06): band profile on the left, members on the right (desktop); on phones members come first, profile below, both collapsible. */
.setgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:1rem;align-items:start;margin-bottom:1rem}
.setgrid>.card{margin-bottom:0;min-width:0}
.setgrid>#details{grid-column:1;grid-row:1}
.setgrid>#members{grid-column:2;grid-row:1}
.setgrid .colbtn{display:none}
.setgrid .subblock{margin-top:1.2rem;padding-top:.2rem}
.setgrid .identblock{margin-bottom:1.2rem}
.identchoice{display:flex;gap:.4rem;flex-wrap:wrap}
.identbtn{min-height:44px;padding:.4rem .9rem;border-radius:8px;border:1px solid var(--line);background:var(--bg3);color:var(--muted);font-weight:700;font-family:inherit;cursor:pointer}
.identbtn.on{color:var(--text);border-color:var(--accent)}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@media(max-width:820px){
  .setgrid{grid-template-columns:1fr}
  .setgrid>#members,.setgrid>#details{grid-column:1}
  .setgrid>#members{grid-row:1}
  .setgrid>#details{grid-row:2}
  .setgrid .colbtn{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;margin-left:auto;border:1px solid var(--line);background:var(--bg3);color:var(--text);border-radius:8px;cursor:pointer;font-size:1.1rem}
  .setgrid .colbtn .chev{display:inline-block;transition:transform .15s}
  .setgrid .collapsed .colbtn .chev{transform:rotate(-90deg)}
  .setgrid .collapsed>.colbody{display:none}
  .setgrid>.card>.cardhead{align-items:center}
}
.sitefav{width:16px;height:16px;vertical-align:-2px;border-radius:3px}

/* ── Reorderable dashboard panels: grab the grip on any panel and drag it (see the panel block in app.js). */
/* The band name can be long — it shrinks/wraps to two lines before it's ever allowed to push
   the scope button (Show all bands / Hide other bands) out of view or onto its own line. */
.bandnameline{display:flex;align-items:flex-start;gap:.6rem;flex-wrap:nowrap}
.bandnameline .bandpick{flex:0 1 auto;min-width:0}
.bandnameline .bandpick h1{white-space:normal}
.bandname-text{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word;min-width:0}
.bandnameline .scopeform{flex:0 0 auto;margin:0}
.bandnameline .scopebtn{white-space:nowrap}
.scopeicons{display:flex;gap:.2rem;align-items:center}
.scopeicnform{margin:0;padding:0}
.scopeicn{background:none;border:1.5px solid transparent;border-radius:7px;cursor:pointer;padding:.2rem .3rem;font-size:1rem;line-height:1;opacity:.5;transition:opacity .15s,border-color .15s}
.scopeicn:hover{opacity:.85}
.scopeicn.on{opacity:1;border-color:var(--accent)}
#dashGrid .card{position:relative}
/* Every panel carries its own small toolbar in the top-right corner: a grip you drag (mouse or finger),
   plus hide and full-width. The grip is the only part that blocks touch scrolling (touch-action:none),
   so the rest of the card scrolls normally on a phone. No "reorder mode" any more. */
#dashGrid .card>h2:first-of-type,#dashGrid .card>.cardhead{padding-right:7.7rem}
.panelhandle,.panelwide,.panelhide{position:absolute;top:.5rem;z-index:2;display:flex;align-items:center;justify-content:center;
  background:var(--bg3);border:1px solid var(--line);border-radius:8px;color:var(--muted);padding:0;line-height:1;cursor:pointer}
.panelhandle{right:.4rem;width:40px;height:40px;font-size:1.25rem;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.panelhide{right:3.1rem;width:32px;height:32px;top:.65rem;font-size:.95rem}
.panelwide{right:5.3rem;width:32px;height:32px;top:.65rem;font-size:.95rem}
.panelhandle:active{cursor:grabbing}
.panelhandle:hover,.panelwide:hover,.panelhide:hover,.panelhandle:focus-visible,.panelwide:focus-visible,.panelhide:focus-visible{color:var(--accent);border-color:var(--accent);background:var(--bg2)}
/* On a single-column phone layout "full width" means nothing, so that button goes away. */
@media(max-width:820px),(max-height:500px) and (orientation:landscape){.panelwide{display:none}#dashGrid .card>h2:first-of-type,#dashGrid .card>.cardhead{padding-right:5.5rem}}
/* While a panel is picked up it floats under the pointer; a dashed slot shows where it will land. */
#dashGrid .card.dragging{position:fixed;z-index:60;margin:0;pointer-events:none;box-shadow:0 14px 36px rgba(0,0,0,.45);opacity:.96;transform:rotate(.6deg)}
.dropslot{border:2px dashed var(--accent);border-radius:12px;background:color-mix(in srgb,var(--accent) 10%,transparent);min-height:3.5rem}
.dropslot.span{grid-column:1/-1}
body.paneldrag,body.paneldrag *{user-select:none;-webkit-user-select:none;cursor:grabbing!important}
/* Panels with nothing to show (no next gig, no upcoming gigs, no other events) don't render. */
#dashGrid .card.emptypanel{display:none}
/* A hidden panel collapses to a slim bar (title + the same buttons) so it can still be moved and brought back. */
#dashGrid .card.panelhidden{min-height:0;padding-top:.55rem;padding-bottom:.55rem;border-style:dashed;opacity:.75}
#dashGrid .card.panelhidden > *:not(.panelhandle):not(.panelwide):not(.panelhide):not(h2):not(.cardhead){display:none}
#dashGrid .card.panelhidden .cardhead>*:not(h2){display:none}
#dashGrid .card.panelhidden h2{margin:0;font-size:.95rem;min-height:36px;display:flex;align-items:center}
#dashGrid .card.panelhidden .panelwide{display:none}
.srlive{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* "Platform: do now" can shrink to one slim bar (state remembered per browser). */
.platbar{display:flex;align-items:center;gap:.6rem}
.platbar h2{flex:1;margin:0;min-width:0}
.platurgent{display:inline-block;font-size:.72rem;font-weight:700;padding:.05rem .45rem;border-radius:99px;background:var(--danger,#d64545);color:var(--bg);vertical-align:middle}
.plattoggle{display:inline-flex;align-items:center;gap:.35rem;min-height:36px;padding:.2rem .7rem;border:1px solid var(--line);border-radius:8px;background:var(--bg3);color:var(--muted);font:inherit;font-size:.85rem;cursor:pointer}
.plattoggle:hover,.plattoggle:focus-visible{color:var(--accent);border-color:var(--accent)}
.platchev{display:inline-block;transition:transform .15s}
.platcard.collapsed{padding-top:.35rem;padding-bottom:.35rem;margin-bottom:.6rem}
.platcard.collapsed .platbar{cursor:pointer}
.platcard.collapsed .platbar h2{font-size:.95rem;display:flex;align-items:center;gap:.35rem;white-space:nowrap}
.platcard.collapsed .plattitle{min-width:0;overflow:hidden;text-overflow:ellipsis}
.platcard.collapsed .platcount,.platcard.collapsed .platurgent{flex:none}
.platcard.collapsed .platchev{transform:rotate(-90deg)}
.platcard.collapsed #platformTasksBody{display:none}
@media(prefers-reduced-motion:reduce){.platchev{transition:none}#dashGrid .card.dragging{transform:none}}
/* "Is this a phone" for nav purposes: narrow (portrait), OR short or same in landscape — a
   landscape phone is often WIDER than 820px (844px on an iPhone 14, 915px on a Pixel 7), so
   width alone missed it and the desktop text nav (.mainnav) showed up at the top instead of
   the tab bar, with nothing switching it back. Height catches landscape phones that width can't. */
@media(max-width:820px),(max-height:500px) and (orientation:landscape){.grid2{grid-template-columns:1fr}.mainnav{display:none}}
.card{background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);padding:1.1rem;margin-bottom:1rem;box-shadow:var(--shadow)}
.card.center{text-align:center;padding:3rem}

/* Stats */
.statrow{display:flex;gap:.5rem;flex-wrap:wrap}
.stat{background:var(--bg3);border:1px solid var(--line);border-radius:10px;padding:.5rem .9rem;text-align:center;min-width:74px}
.stat b{display:block;font-size:1.3rem;color:var(--accent)}
.stat span{font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.05em}

/* Forms */
:root{--site-max:1800px}
label{display:flex;flex-direction:column;gap:.2rem;font-size:.8rem;color:var(--muted);font-weight:600}
input,select,textarea{font:inherit;background:var(--bg);border:1px solid var(--line);color:var(--text);
  padding:.5rem .6rem;border-radius:8px;width:100%}
/* Fields never stretch across a very wide screen. */
input:not([type=checkbox]):not([type=radio]),select{max-width:36rem}
textarea{max-width:56rem}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(245,166,35,.15)}
.stack{display:flex;flex-direction:column;gap:.6rem}
.stack.tight{gap:.4rem}
.row{display:flex;gap:.6rem;flex-wrap:wrap}.row>label{flex:1;min-width:90px}
.inline{display:flex;gap:.5rem;margin-bottom:.8rem}.inline input{flex:1}
.check-inline{flex-direction:row;align-items:center;gap:.5rem;color:var(--text)}
.check-inline input{width:auto}

/* Buttons */
.btn{background:var(--bg3);border:1px solid var(--line);color:var(--text);padding:.5rem .9rem;border-radius:8px;
  font-weight:700;font-size:.88rem;cursor:pointer;display:inline-flex;align-items:center;gap:.4rem}
.btn:hover{border-color:var(--accent)}
.btn.primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.btn.primary:hover{filter:brightness(1.08)}
.btn.ghost{background:transparent}
.btn.block{width:100%;justify-content:center;padding:.7rem}
.btn.sm{padding:.35rem .6rem;font-size:.8rem}
/* "Invite a musician" (Requests card header) — bigger than a normal button on every screen size,
   since growing the band is worth calling out, with the heart icon sized up further so it reads
   before the word does. */
.btn.invitemusician{padding:.7rem 1.3rem;font-size:1.05rem}
.btn.invitemusician .invitemusician-icon{font-size:1.3em;line-height:1}
.btn.danger,.linkbtn.danger{color:var(--danger)}
.linkbtn{background:none;border:none;color:var(--muted);cursor:pointer;font-weight:700;padding:.25rem .4rem;border-radius:6px;font-size:.85rem}
.linkbtn:hover{color:var(--text);background:var(--bg3)}
.linkbtn:disabled{opacity:.3;cursor:default}
.headbtns{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}
.back{color:var(--muted);font-size:.85rem;font-weight:600}
.backlink{display:inline-flex;align-items:center;padding:.45rem 0}
.backlink:hover{color:var(--text)}
@media (pointer:coarse){.backlink{min-height:44px;min-width:44px}}

/* Chips / pills */
.chip{background:var(--bg);border:1px solid var(--line);color:var(--muted);padding:.3rem .6rem;border-radius:20px;
  font-size:.75rem;font-weight:700;cursor:pointer;text-transform:lowercase}
.chip:hover{border-color:var(--accent);color:var(--text)}
.chip.on.in,.chip.on.available{background:var(--in);color:var(--bg);border-color:var(--in)}
.chip.on.maybe{background:var(--maybe);color:#2a1e02;border-color:var(--maybe)}
.chip.on.out{background:var(--out);color:#2a0b08;border-color:var(--out)}
.pill{font-family:var(--mono);font-size:.66rem;text-transform:uppercase;letter-spacing:.08em;padding:.2em .6em;border-radius:6px;
  border:1px solid var(--line);background:var(--bg3);color:var(--muted);font-weight:700;white-space:nowrap}
.pill.inquiry{color:var(--maybe)}.pill.confirmed{color:var(--in)}.pill.played{color:var(--accent)}.pill.canceled{color:var(--out)}
.pill.admin{color:var(--accent-ink);background:var(--accent);border-color:var(--accent)}
.pill.role.owner{color:var(--accent)}.pill.role.manager{color:var(--in)}
.pill.inst{color:var(--accent)}
.kind{font-family:var(--mono);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;padding:.2em .5em;border-radius:5px;border:1px solid var(--line);color:var(--muted)}
.kind.show{color:var(--accent);border-color:var(--accent)}.kind.rehearsal{color:var(--in)}
.infobtn{flex:none;background:none;border:none;color:var(--muted);cursor:pointer;font-size:1rem;line-height:1;padding:.1rem .2rem;border-radius:6px}
.infobtn:hover{color:var(--accent);background:var(--bg3)}
.eventdlgrow{margin:.35rem 0}
.eventdlgrow b{color:var(--muted);font-weight:700}
.pay{color:var(--in);font-weight:800}.pay.sm{font-size:.8rem}

/* Feeds / lists */
.feed{list-style:none;margin:0;padding:0}
.feed li{display:flex;gap:.6rem;align-items:center;padding:.6rem 0;border-bottom:1px solid var(--line)}
.feed li:last-child{border:none}
/* A long event title used to just run into the date/location on the same line and wrap
   messily, or shove the RSVP buttons out of the row. Same fix as the to-do list: title on its
   own truncated line, meta truncated on the line under it, so a long name never breaks the row. */
.feed li .grow>b{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.feed li .grow>.muted{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.78rem;margin-top:.05rem}
/* DESIGN RULE (site-wide): a label/title sits right on top of its value/description. No blank line, no big gap.
   A <br> after a block-level label inside a list row used to add an empty line between "Band name" and the name itself. */
.feed li .grow>b+br,.feed li .grow>.muted+br{display:none}
/* A heading and the line that describes it read as one unit: tight gap, not a paragraph break. Tap targets are untouched. */
h1+p,h2+p,h3+p{margin-top:0}
h2:has(+p),h3:has(+p){margin-bottom:.25rem}
.rsvp{display:flex;gap:.25rem}.rsvp.col{flex-direction:column}
.tasks{list-style:none;margin:.4rem 0 0;padding:0}
.tasks li{display:flex;align-items:center;gap:.5rem;padding:.35rem 0}
/* Title on top, due date/assignee truncated to one line underneath — kept tight (small type,
   close line-height) so the two-line stack doesn't grow taller than the Mark done button next
   to it, instead of letting a long title + due date + assignee wrap and stretch the row. */
.tasktitle{display:block;line-height:1.25}
.taskmeta{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:.72rem;line-height:1.2;color:var(--muted);margin-top:.05rem}
.check{background:none;border:none;color:var(--muted);cursor:pointer;font-size:1.1rem}
.check:hover{color:var(--in)}
.chips{display:flex;gap:.5rem;flex-wrap:wrap}
.member{background:var(--bg3);border:1px solid var(--line);border-radius:9px;padding:.4rem .7rem;display:flex;flex-direction:column}
.member .muted{font-size:.75rem}
.giglead{display:flex;flex-direction:column;gap:.2rem;margin-bottom:.8rem;min-width:0}
.gigdate{font-family:var(--mono);color:var(--accent);font-weight:700}
.gigtitle,.giglead>b{font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.gigcontact,.gignotes{margin:0}
.gignotes{white-space:pre-wrap}

/* Events */
.events{display:flex;flex-direction:column;gap:.6rem}
.event{display:flex;flex-direction:column;gap:.5rem;background:var(--bg3);border:1px solid var(--line);border-radius:10px;padding:.7rem}
.event.past{opacity:.6}
/* Title leads, as its own row, with a small date badge beside it — not a full-height column
   eating the side of the card the way it used to. */
.etop{display:flex;align-items:flex-start;gap:.6rem}
.ecal{background:var(--bg);border:1px solid var(--line);border-radius:8px;width:44px;flex:none;
  text-align:center;padding:.25rem 0}
.ecal .em{display:block;font-size:.58rem;text-transform:uppercase;color:var(--accent);font-family:var(--mono)}
.ecal .ed{display:block;font-size:1.05rem;font-weight:800}
.etitlewrap{flex:1;min-width:0}
.etitle{display:block;font-size:1.05rem;line-height:1.3}
.emeta{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin-top:.2rem}
.note{font-style:italic}
.attend{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.4rem}
.att{font-size:.72rem;color:var(--muted);border:1px solid var(--line);border-radius:6px;padding:.15rem .4rem}
.att.in{color:var(--in)}.att.maybe{color:var(--maybe)}.att.out{color:var(--out)}
.att .names{color:var(--muted);margin-left:.3rem}
/* Edit/delete live here now — under everything, in the card's normal flow, not off to the side. */
.eactions{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;margin-top:.3rem;padding-top:.5rem;border-top:1px solid var(--line)}

/* Availability */
.availgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:.4rem}
.availcell .dow{font-size:.65rem;color:var(--text);text-transform:uppercase}
.availcell .dnum{font-size:1.2rem;font-weight:800}
.availcell .dmon{font-size:.62rem;color:var(--muted)}
/* dmon-contrast: month label on filled day cells must reach WCAG AA (4.5:1); muted was too faint on the tints */
.availcell.available:not(.outmonth) .dmon:not(.evday),.availcell.unavailable:not(.outmonth) .dmon:not(.evday),.availcell.maybe:not(.outmonth) .dmon:not(.evday),.availcell.hasholiday:not(.outmonth) .dmon:not(.evday){color:var(--text)}
.availcell.available{background:rgba(111,206,159,.16);border-color:var(--in)}
.availcell.maybe{background:rgba(232,184,75,.16);border-color:var(--maybe)}
.availcell.unavailable{background:rgba(226,88,75,.16);border-color:var(--out)}
.legend,.key{display:inline-flex;align-items:center;gap:.4rem;margin-top:.7rem;font-size:.78rem;color:var(--muted)}
.legend{gap:1rem}
.key:before{content:"";width:12px;height:12px;border-radius:3px;background:var(--line)}
.key.available:before{background:var(--in)}.key.maybe:before{background:var(--maybe)}.key.unavailable:before{background:var(--out)}
.availtable{border-collapse:collapse;width:100%;font-size:.8rem}
.availtable th,.availtable td{border:1px solid var(--line);text-align:center}
.availtable th{padding:.3rem;color:var(--muted);font-weight:600}
.availtable th span{display:block}
.availtable td.mname{text-align:left;padding:.4rem .6rem;white-space:nowrap}
/* The member column stays put while the day columns scroll past it — the table can scroll on
   any screen size now (who's-around spans up to 8 weeks), not just mobile, so this isn't a
   mobile-only concern. The header's own leftmost cells pin the same way so "Member" doesn't
   scroll off along with the day labels above it. */
.availtable th.mname,.availtable td.mname{position:sticky;left:0;background:var(--bg2);z-index:2;box-shadow:1px 0 0 var(--line)}
/* Name on top, instruments in their own row(s) below it — each row holds at most 4 pills
   (chunked server-side), so a member with a long instrument list wraps predictably instead of
   stretching the member column ever wider. */
.mnamestack{display:flex;flex-direction:column;gap:.25rem}
.mninsts{display:flex;flex-direction:column;gap:.15rem}
.instrow{display:flex;gap:.25rem}
.availtable td.cell{width:26px;height:26px}
.availtable td.available{background:var(--in)}.availtable td.maybe{background:var(--maybe)}.availtable td.unavailable{background:var(--out)}

/* Tables */
.tablescroll{overflow-x:auto}
/* Who's around week buttons (card #276): 44px tap targets */
.wa-nav{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:.4rem;margin:.2rem 0 .5rem}
.wa-nav .btn{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center;text-decoration:none;font-size:.9rem}
.wa-nav .wa-step{font-size:1.2rem;font-weight:800}
.wa-nav .wa-more{margin-right:auto}
.wa-nav .wa-btns{display:inline-flex;gap:.4rem;margin-left:auto}
.songtable{width:100%;border-collapse:collapse;font-size:.88rem}
.songtable th{text-align:left;color:var(--muted);font-weight:600;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;padding:.4rem .5rem;border-bottom:1px solid var(--line)}
.songtable td{padding:.5rem .5rem;border-bottom:1px solid var(--line)}
/* Song links (setlists table, song page, Show Mode): look and space out like small buttons,
   not run-together text, so video/tabs/edit read as three separate actions. */
.songlinks{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem}
.ytlink{color:var(--out);font-weight:700}.ytlink.sm{font-size:.85rem}

/* Song library toolbar: search + genre/key filters + column chooser + page size, all in a row
   that wraps on narrow screens rather than overflowing. */
.songtoolbar{display:flex;flex-direction:column;gap:.5rem;margin:.8rem 0;width:80%}
@media(max-width:900px){.songtoolbar{width:100%}}
.sbrow{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}
.sbsearch input[type=search]{flex:1 1 220px;min-width:0}
.sbsearch .btn{flex:0 0 auto;white-space:nowrap}
.sbbulk{padding:.2rem 0}
.bulkrun{font-family:var(--mono);margin-left:.3rem}
.bulkpanel{border-color:var(--accent)}
.collbtn{all:unset;cursor:pointer;font:inherit;display:inline-flex;gap:.35rem;align-items:center}
.collbtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.collarrow{display:inline-block;transition:transform .15s}
.collbtn[aria-expanded=false] .collarrow{transform:rotate(-90deg)}
.collcard>summary{cursor:pointer;font-weight:600}
.collcard[open]>summary{margin-bottom:.6rem}
.totopfab{position:fixed;right:1rem;bottom:8rem;z-index:95;width:44px;height:44px;border-radius:50%;
  border:1px solid var(--line);background:var(--bg2);color:var(--text);font-size:1.3rem;line-height:1;cursor:pointer;
  box-shadow:0 4px 14px rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center}
.totopfab[hidden]{display:none}
.totopfab:hover{color:var(--accent);border-color:var(--accent)}
.totopfab:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
.totopfab svg{display:block}
/* No Feedback pill (signed out / public pages): sit in the corner instead of floating above an empty slot. */
body:not(:has(.feedbackfab)):not(:has(.tabbar)) .totopfab{bottom:1.25rem}
@media (prefers-reduced-motion:no-preference){.totopfab{animation:totopin .18s ease-out}@keyframes totopin{from{opacity:0;transform:translateY(8px)}}}
.songtoolbar input[type=search]{min-width:0;background:var(--bg3);border:1px solid var(--line);
  border-radius:8px;color:var(--text);padding:.4rem .6rem;font-size:.9rem}
.songtoolbar select{background:var(--bg3);border:1px solid var(--line);border-radius:8px;
  color:var(--text);padding:.4rem .6rem;font-size:.85rem;flex-shrink:1}
.coldd{position:relative}
.colmenu{position:absolute;top:calc(100% + 6px);right:0;min-width:150px;background:var(--bg2);
  border:1px solid var(--line);border-radius:10px;box-shadow:var(--shadow);padding:.5rem .6rem;z-index:20;
  display:flex;flex-direction:column;gap:.3rem}
.songtable th.sortable{cursor:pointer;user-select:none}
.songtable th.sortable:hover{color:var(--text)}
.songtable th.sort-asc:after{content:" ▲";font-size:.7em}
.songtable th.sort-desc:after{content:" ▼";font-size:.7em}
.setlist-status{font-size:.65rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700;
  border-radius:4px;padding:.1em .5em;display:inline-block;vertical-align:middle}
.setlist-status.draft{background:rgba(232,184,75,.2);color:var(--maybe);border:1px solid rgba(232,184,75,.4)}
.setlist-status.archived{background:var(--bg3);color:var(--muted);border:1px solid var(--line)}
.colgearth{width:2rem;padding:.3rem .2rem}
.colgeartd{width:2rem}
.addtosetlist{display:flex;gap:.3rem;align-items:center;flex-wrap:nowrap}
.addtosetlist select{background:var(--bg3);border:1px solid var(--line);border-radius:7px;
  color:var(--text);padding:.3rem .4rem;font-size:.82rem;max-width:130px}
.addsetbtn:disabled{opacity:.55;cursor:default}
.songpaginate{display:flex;align-items:center;flex-wrap:wrap;gap:.3rem;margin-top:.9rem;padding-top:.5rem;border-top:1px solid var(--line)}
.pagesizelabel{display:flex;align-items:center;gap:.3rem;font-size:.82rem;color:var(--muted);margin-right:.5rem}
.pagesizesel{background:var(--bg3);border:1px solid var(--line);border-radius:7px;color:var(--text);
  padding:.25rem .4rem;font-size:.82rem;width:auto}
.btn.pgactive{background:var(--maybe);color:#000;border-color:var(--maybe);opacity:1}
.btn.pgnav{min-width:2rem;padding-left:.4rem;padding-right:.4rem}

/* Band branding: logo (small, square-ish) and banner (wide) previews on Settings, plus the
   live versions on the dashboard header. */
.brandpreview{display:flex;flex-wrap:wrap;gap:1rem;margin-top:.4rem}
.brandimg{display:flex;flex-direction:column;align-items:flex-start;gap:.3rem}
.bandlogo-preview{width:72px;height:72px;object-fit:cover;border-radius:10px;border:1px solid var(--line)}
.bandbanner-preview{max-width:100%;max-height:120px;object-fit:cover;border-radius:10px;border:1px solid var(--line)}
.dashbanner{width:100%;max-height:180px;object-fit:cover;border-radius:12px;margin-bottom:1rem;display:block}
.dashlogo{width:44px;height:44px;object-fit:cover;border-radius:9px;border:1px solid var(--line);vertical-align:middle;margin-right:.5rem}

/* Setlists */
.setlist-list,.tabs-list{list-style:none;margin:0;padding:0}
.setlist-list li{display:flex;align-items:center;gap:.6rem;padding:.55rem 0;border-bottom:1px solid var(--line)}
.setlist-list a.grow{display:flex;justify-content:space-between}
.setitems{list-style:none;margin:0;padding:0;counter-reset:s}
.setitems li{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem;padding:.6rem;border:1px solid var(--line);border-radius:10px;margin-bottom:.5rem;background:var(--bg3)}
.setitems li.dragging{opacity:.45;border-color:var(--accent);border-style:dashed}
/* Drag handle: its own small target so a tap anywhere else on the row (a link, a button) never
   starts a drag by accident. touch-action:none stops the phone from scrolling the page instead
   of picking up the row. */
.draghandle{cursor:grab;color:var(--muted);font-size:1rem;line-height:1;touch-action:none;
  user-select:none;-webkit-user-select:none;flex:none;padding:.2rem .1rem}
.draghandle:hover{color:var(--accent)}
/* On a phone the glyph itself is too small to reliably thumb-hit; grow the invisible padding
   (offset by a matching negative margin so the visible glyph and row layout don't shift) so the
   tap target is close to the ~40px minimum, without eating into the row's other controls. */
@media (max-width:820px){
  .draghandle{padding:.7rem .6rem;margin:-.5rem -.45rem}
}
.setitems .num{font-family:var(--mono);font-weight:800;color:var(--accent);width:26px;text-align:center;font-size:1.05rem}
/* A divider row — "Set 2", "Encore" — breaks the running order into sections without being a
   song itself: no number, no song controls, just a label between two rule lines so it reads as
   a break in the flow rather than another item in it. */
.setitems li.setsection{background:none;border:none;border-radius:0;padding:.3rem 0;margin:.3rem 0}
.sectiontitle{flex:1;text-align:center;font-size:.72rem;font-weight:800;text-transform:uppercase;
  letter-spacing:.12em;color:var(--muted);position:relative}
.sectiontitle:before,.sectiontitle:after{content:"";position:absolute;top:50%;width:32%;border-top:1px solid var(--line)}
.sectiontitle:before{left:0}
.sectiontitle:after{right:0}
.addsection{display:flex;gap:.4rem;align-items:center;flex-wrap:wrap}
.addsection input{background:var(--bg3);border:1px solid var(--line);border-radius:8px;
  color:var(--text);padding:.35rem .6rem;font-size:.82rem}
.addsection input[name=label]{width:130px}
.addsection-note{width:160px}
.addsection-dur{display:inline-flex;align-items:center;gap:.2rem}
.addsection-mm,.addsection-ss{width:48px;text-align:center}
.addsection-mm{width:64px}
.sectiondur{font-weight:400;font-size:.68rem;letter-spacing:.04em;margin-left:.35em;opacity:.75}
.sectionnote{display:block;font-size:.7rem;font-weight:400;letter-spacing:0;text-transform:none;
  color:var(--muted);margin-top:.15rem;white-space:normal}
.setctl{display:flex;align-items:center;gap:.15rem}
/* Stacked, not side by side — reads as "this moves the row" the way a real up/down control does. */
.updown{display:flex;flex-direction:column;gap:.05rem;line-height:1}
.updown .linkbtn{padding:.05rem .35rem;min-height:0}
/* Invisible to layout on desktop — their children sit directly in .setctl's row, exactly as
   before there were two named groups. Mobile turns them into two real, separate rows. */
.setlinks,.setreorder{display:contents}
.itnote{display:block;font-size:.78rem;color:var(--accent)}
/* Chords render in two places in the markup — right after the title (mobile) and on their own
   line (desktop) — but only one is ever visible at a time; see the mobile block below. */
.itchords{font-size:.78rem;font-family:var(--mono);color:var(--in)}
.itchords-block{display:block}
.itchords-inline{display:none}
/* The desktop line (title, then artist · key · bpm · length all run together) is untouched —
   .itmetadesktop is just the original .muted span. These two are its phone-only replacements,
   each on their own line; hidden here, shown in the mobile block below. */
.itartist,.itmetamobile{display:none}
.hlform{margin:0;display:inline-flex}
.hlbtn{background:none;border:1px solid var(--line);border-radius:999px;color:var(--muted);font:inherit;font-size:.8rem;font-weight:700;padding:.2rem .6rem;cursor:pointer;min-height:32px}
.hlbtn:hover{color:var(--text);border-color:var(--muted)}
.hlbtn.on{background:color-mix(in srgb,var(--in) 22%,transparent);border-color:var(--in);color:var(--in)}
@media (max-width:820px){.hllabel{display:none}.hlbtn{font-size:1.05rem;padding:.15rem .6rem}}
/* Running total through this song, dim and after a slash — same look as Show Mode's. */
.itrun{color:var(--muted);font-size:.85em;margin-left:.35em}
.itrun:before{content:"/ "}
.notebar{display:flex;gap:.3rem;flex-basis:100%;margin-left:32px}
.notebar input{font-size:.8rem;padding:.3rem .5rem}

/* Song detail */
.videowrap{position:relative;padding-top:56.25%;border-radius:10px;overflow:hidden;border:1px solid var(--line)}
.videowrap iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.tabs-list li{display:flex;align-items:center;gap:.5rem;padding:.45rem 0;border-bottom:1px solid var(--line)}
.tabform{margin-top:.6rem;border-top:1px dashed var(--line);padding-top:.8rem}

/* Gear */
.geargrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:.7rem}
.gearcard{background:var(--bg3);border:1px solid var(--line);border-radius:10px;overflow:hidden;display:flex;flex-direction:column}
.gearphoto{height:120px;background:var(--bg);display:flex;align-items:center;justify-content:center}
.gearphoto img{width:100%;height:100%;object-fit:cover}
.gearphoto.ph .gtype{font-family:var(--mono);text-transform:uppercase;letter-spacing:.1em;color:var(--muted);font-size:.8rem}
/* Extra photos beyond the cover — a thumbnail strip right under it, each opening full-size in
   a new tab (no lightbox JS needed for what's meant to be a quick "more angles" glance). */
.gearthumbs{display:flex;gap:.3rem;padding:.3rem;background:var(--bg);overflow-x:auto}
.gearthumb{flex:none;width:36px;height:36px;border-radius:6px;overflow:hidden;border:1px solid var(--line)}
.gearthumb img{width:100%;height:100%;object-fit:cover;display:block}
/* Photo management inside "edit" — same thumbnail size, plus a remove button per photo. */
.gearphotolist{display:flex;gap:.5rem;flex-wrap:wrap}
.gearphotoitem{display:flex;flex-direction:column;align-items:center;gap:.2rem}
.gearphotoitem img{width:52px;height:52px;object-fit:cover;border-radius:7px;border:1px solid var(--line)}
.gearbody{padding:.6rem;display:flex;flex-direction:column;gap:.15rem}
.gearbody .loc{font-size:.78rem;color:var(--muted)}
.gearctl{display:flex;justify-content:space-between;align-items:center;margin-top:.4rem}
/* Ownership is always visible on the card — "Me" for your own gear, the owner's name for
   anything a bandmate shared with the band. Never the same thing as the shared toggle. */
.gearname{display:flex;align-items:center;justify-content:space-between;gap:.4rem}
.ownerbadge{font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);
  background:var(--bg);border:1px solid var(--line);border-radius:20px;padding:.1rem .5rem;white-space:nowrap}
.ownerbadge.me{color:var(--in);border-color:rgba(111,206,159,.45)}
/* Band names inside a .chip shouldn't inherit its lowercase styling — proper nouns stay as typed. */
.chipband{text-transform:none}

/* Pipeline */
.pipeline{display:grid;grid-template-columns:repeat(4,1fr);gap:.8rem}
@media(max-width:900px){.pipeline{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.pipeline{grid-template-columns:1fr}}
.pipecol h3{display:flex;justify-content:space-between;align-items:center;margin:.2rem 0 .6rem}
.showcard{background:var(--bg2);border:1px solid var(--line);border-radius:10px;margin-bottom:.6rem}
.showcard>summary{list-style:none;cursor:pointer;padding:.6rem;display:flex;flex-direction:column;gap:.15rem}
.showcard>summary::-webkit-details-marker{display:none}
.showcard[open]>summary{border-bottom:1px solid var(--line)}
.showcard .stack{padding:.7rem}
/* A pooled booking card from a non-selected band (scope: all bands) — same shell, but flat
   (no expand) since there's nothing interactive to open, just a switch-to-manage link. */
.showcard-other{padding:.6rem;display:flex;flex-direction:column;gap:.15rem;opacity:.85}
.showcard-other-head{display:flex;align-items:center;gap:.35rem;margin-bottom:.1rem}
.showcard-other .btn{align-self:flex-start;margin-top:.4rem}

/* Auth */
/* Column, not row: the site footer sits below the card as a normal block. A plain row here
   centers the CARD+FOOTER PAIR as one group — with the footer's own 1200px max-width in the
   mix, that shoves the (much narrower) card off to the left and strands the footer beside it. */
.authpage{display:flex;flex-direction:column;align-items:center;min-height:100vh;padding:2rem 1rem}
.authcard{background:var(--bg2);border:1px solid var(--line);border-radius:16px;box-shadow:var(--shadow);padding:2rem;max-width:400px;width:100%;margin-top:auto;margin-bottom:auto}
.authbrand{font-weight:800;font-size:1.6rem;display:flex;align-items:center;gap:.5rem}
.authbrand:before{content:"●";color:var(--accent)}
.authsub{color:var(--muted);margin:.2rem 0 1.3rem}
.authcard form{display:flex;flex-direction:column;gap:.7rem}
.captcha{background:var(--bg3);border:1px dashed var(--line);border-radius:10px;padding:.7rem;display:flex;gap:.8rem;align-items:center;flex-wrap:wrap}
.captcha-img{flex:none;line-height:0}
.captcha-input{flex:1;min-width:140px}
.alert{background:rgba(226,88,75,.15);border:1px solid var(--out);color:var(--text);padding:.6rem .8rem;border-radius:9px;margin-bottom:1rem;font-size:.88rem}
.authfoot{margin-top:1.2rem;font-size:.85rem;color:var(--muted);text-align:center}
.authfoot a{color:var(--accent);font-weight:700}
.demo{background:var(--bg3);border:1px solid var(--line);border-radius:9px;padding:.7rem;text-align:left;margin-bottom:.9rem;line-height:1.6}
code{font-family:var(--mono);background:var(--bg);padding:.1em .4em;border-radius:5px;color:var(--accent);font-size:.85em}

/* Show mode has its own self-contained <style> now (views/show-mode.ejs) — it no longer loads
   this stylesheet at all, so none of these rules used to belong to it live here any more. */

/* Comments */
.commentlist{list-style:none;margin:.4rem 0;padding:0}
.commentlist li{display:flex;gap:.6rem;padding:.6rem 0;border-bottom:1px solid var(--line);align-items:flex-start}
.commentlist li:last-child{border:none}
.cavatar{width:30px;height:30px;border-radius:50%;background:var(--accent);color:var(--accent-ink);display:flex;align-items:center;justify-content:center;font-weight:800;flex:none;font-size:.85rem}
.cmeta{font-size:.8rem}
.cbody{font-size:.92rem;margin-top:.15rem;white-space:pre-wrap;word-break:break-word}
.nocom{padding:.6rem 0}
.commentform{display:flex;gap:.5rem;margin-top:.6rem}.commentform input{flex:1}

/* Tasks */
.tasklist{list-style:none;margin:0;padding:0}
.tasklist>li{border-bottom:1px solid var(--line);padding:.5rem 0}
.tasklist>li:last-child{border:none}
.taskrow{display:flex;align-items:center;gap:.6rem}
.taskmeta{display:inline-flex;gap:.4rem;margin-left:.5rem;align-items:center}
.due{font-size:.75rem;color:var(--muted);border:1px solid var(--line);border-radius:5px;padding:.1rem .4rem}
.due.over{color:var(--out);border-color:var(--out)}
.strike{text-decoration:line-through;color:var(--muted)}
.check.on{color:var(--in)}
.tasklist.done .taskrow{opacity:.7}
.cbtn>summary,.taskcomments>summary{cursor:pointer;list-style:none;font-size:.8rem;color:var(--muted)}
.cbtn>summary::-webkit-details-marker,.taskcomments>summary::-webkit-details-marker{display:none}
.taskcomments{margin:.3rem 0 0 2rem}.taskcomments>summary{padding:.2rem 0}

/* Find-a-date */
.bestdates{display:flex;gap:.6rem;flex-wrap:wrap}
.bestcard{background:var(--bg3);border:1px solid var(--line);border-radius:10px;padding:.7rem;display:flex;flex-direction:column;gap:.5rem;align-items:center;min-width:118px}
.bd-date{text-align:center;line-height:1.15}
.bd-date b{display:block;font-size:1.5rem;color:var(--accent)}
.bd-date span{font-size:.66rem;color:var(--muted);display:block;text-transform:uppercase}
.bd-counts{display:flex;flex-direction:column;gap:.1rem;font-size:.72rem;text-align:center}
.c-in{color:var(--in)}.c-maybe{color:var(--maybe)}.c-out{color:var(--out)}

/* Inline edit disclosures */
/* Required fields — a quiet dot normally, a loud outline once a submit is blocked */
.reqmark{color:var(--accent);font-size:.9em;line-height:1;margin-left:.25em}
.lbltext{display:inline}
input[required],select[required],textarea[required]{border-left:2px solid rgba(245,166,35,.55)}
label.missing{color:var(--out)}
input.missing,select.missing,textarea.missing{border-color:var(--out);box-shadow:0 0 0 3px rgba(226,88,75,.18)}
.fieldlabel{display:block;font-size:.8rem;color:var(--muted);font-weight:600;margin-bottom:.2rem}

/* Availability window nav */
.cardhead{display:flex;justify-content:space-between;align-items:center;gap:1rem;flex-wrap:wrap;margin-bottom:.2rem}
.cardhead h2{margin:0}
.winnav{display:flex;gap:.3rem;align-items:center;flex-wrap:wrap}
.winnav input[type="date"]{width:auto;padding:.35rem .5rem;font-size:.82rem}

/* Who's-around table: band row, week dividers, today marker */
.availtable.wide td.cell,.availtable.wide th{min-width:22px}
.availtable th.wkstart,.availtable td.wkstart{border-left:2px solid var(--accent)}
.availtable th.istoday{color:var(--accent);font-weight:800}
.availtable tr.bandrow td{border-top:1px solid var(--accent);border-bottom:1px solid var(--accent)}
.availtable tr.bandrow td.mname{background:var(--bg3)}
.availtable td.cell.partial{background-image:repeating-linear-gradient(45deg,rgba(0,0,0,.28) 0 3px,transparent 3px 6px)}
.instpills{display:inline-flex;gap:.25rem;flex-wrap:wrap}

/* Personal grid: weekday header, selection, part-day segments */
.availgrid.dowhead{margin-bottom:.4rem}
.dowpick{background:var(--bg3);border:1px solid var(--line);color:var(--muted);border-radius:8px;padding:.35rem .2rem;
  font-weight:700;font-size:.78rem;cursor:pointer;text-transform:uppercase;letter-spacing:.04em}
.dowpick:hover{border-color:var(--accent);color:var(--accent)}
.availcell{position:relative;background:var(--bg3);border:1px solid var(--line);border-radius:9px;color:var(--text);
  cursor:pointer;padding:.5rem .2rem;display:flex;flex-direction:column;align-items:center;gap:.1rem;user-select:none}
.availcell:hover{border-color:var(--accent)}
.availcell.istoday{box-shadow:inset 0 0 0 1px var(--accent)}
.availcell.sel{outline:2px solid var(--accent);outline-offset:1px}
/* Day cell as three stacked layers: morning (top), afternoon (middle), evening (bottom). Each third
   lights up in the day's status colour when it applies; all-day fills the whole square. */
.availcell.available,.availcell.maybe,.availcell.unavailable{background:var(--bg3)}
.availcell .thirds{position:absolute;inset:0;display:flex;flex-direction:column;border-radius:inherit;overflow:hidden;z-index:0;pointer-events:none}
.availcell .thirds i{flex:1;background:transparent}
.availcell .thirds i+i{border-top:1px solid rgba(128,128,128,.22)}
.availcell.available .thirds i.on{background:rgba(111,206,159,.40)}
.availcell.maybe .thirds i.on{background:rgba(232,184,75,.40)}
.availcell.unavailable .thirds i.on{background:rgba(226,88,75,.40)}
.availcell>.dow,.availcell>.dnum,.availcell>.dmon{position:relative;z-index:1}
.slotbar{display:flex;gap:2px;margin-top:.25rem}
.slotbar i{width:10px;height:4px;border-radius:2px;background:var(--line)}
.slotbar i.on{background:var(--in)}

/* Availability popup */
.avmodal{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;padding:1rem}
.avmodal[hidden]{display:none}
.avmodal-back{position:absolute;inset:0;background:rgba(0,0,0,.6)}
.avmodal-card{position:relative;background:var(--bg2);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
  padding:1.3rem;max-width:420px;width:100%;display:flex;flex-direction:column;gap:.8rem}
.avmodal-card h3{margin:0}
.slotpick{border:1px solid var(--line);border-radius:10px;padding:.7rem;margin:0}
.slotpick legend{font-size:.8rem;color:var(--muted);font-weight:600;padding:0 .4rem}
.avchoice{display:grid;grid-template-columns:1fr 1fr;gap:.5rem}
.avchoice .btn{justify-content:center}

/* Roster instrument editor */
.instlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:.3rem .6rem;
  border:1px solid var(--line);border-radius:10px;padding:.6rem;background:var(--bg3)}
.instedit>summary{cursor:pointer;list-style:none;display:flex;gap:.3rem;align-items:center;flex-wrap:wrap;padding:.2rem 0}
.instedit>summary::-webkit-details-marker{display:none}
.instedit[open]>summary{margin-bottom:.5rem}
.editblock{margin-top:.6rem;padding-top:.7rem;border-top:1px dashed var(--line)}
.editblock>summary{font-weight:700;color:var(--accent)}

/* Dashboard "needs you" */
.needsyou{border-color:var(--accent)}
.needsyou h3{margin:.6rem 0 .2rem;color:var(--muted);font-size:.82rem;text-transform:uppercase;letter-spacing:.06em}
.tasks li.mine,.feed li.mine{background:rgba(245,166,35,.08);border-radius:8px;padding-left:.4rem;padding-right:.4rem}
.pill.yours{color:var(--accent-ink);background:var(--accent);border-color:var(--accent)}
.pill.danger{color:var(--danger);border-color:var(--danger)}
.btn.ghost.sm.on{border-color:var(--accent);color:var(--accent)}

/* Event type indicators — existing palette only: shows get the accent, rehearsals the
   "available" green, meetings stay neutral so the loud ones actually stand out. */
.event{border-left-width:4px}
.event.kind-show{border-left-color:var(--accent);background:linear-gradient(90deg,rgba(245,166,35,.07),transparent 40%)}
.event.kind-rehearsal{border-left-color:var(--in)}
.event.kind-meeting{border-left-color:var(--muted)}
.event.kind-other{border-left-color:var(--line)}
.kind.meeting{color:var(--muted)}.kind.other{color:var(--muted)}
.showstrip{display:flex;gap:1rem;flex-wrap:wrap;margin-top:.4rem;padding:.4rem .6rem;border:1px solid var(--accent);
  border-radius:8px;background:rgba(245,166,35,.1);font-size:.85rem}
.showstrip b{color:var(--accent);font-family:var(--mono);font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;margin-right:.25rem}
.evnote{margin-top:.4rem;font-size:.85rem;color:var(--text);font-style:italic}
/* "Repeats every week until Oct 30, 2026" — plain-language, the way Outlook/Google Calendar say
   it, right under the date line rather than a cryptic little pill next to the title. */
.repeatsline{margin-top:.3rem;font-size:.82rem;color:var(--muted)}

/* Upcoming events: the first few show straight away, the rest fold behind one line so a busy
   band's calendar doesn't turn into an endless scroll on first load. */
details.showmore{margin-top:.6rem}
details.showmore>summary{cursor:pointer;list-style:none;font-size:.85rem;color:var(--accent);font-weight:700;padding:.3rem 0}
details.showmore>summary::-webkit-details-marker{display:none}
details.showmore>summary:before{content:"▾ ";display:inline-block;transition:transform .15s}
details.showmore[open]>summary:before{transform:rotate(-90deg)}
details.showmore .events{margin-top:.6rem}

/* Map embed */
.maprow{display:flex;flex-direction:column;gap:.4rem}
.mapbox{border:1px solid var(--line);border-radius:10px;overflow:hidden;height:190px}
.mapbox iframe{width:100%;height:100%;border:0;display:block}
.mapbox[hidden]{display:none}
.evmap,.agenda{margin-top:.5rem;flex-basis:100%}
.evmap>summary,.agenda>summary{cursor:pointer;list-style:none;font-size:.78rem;color:var(--muted);font-weight:700;padding:.2rem 0}
.evmap>summary::-webkit-details-marker,.agenda>summary::-webkit-details-marker{display:none}
.evmap[open]>summary,.agenda[open]>summary{color:var(--accent)}
.evmap .mapbox{margin:.4rem 0}

/* Meeting agenda */
.agendalist{list-style:decimal;margin:.4rem 0 .6rem 1.4rem;padding:0}
.agendalist li{display:flex;align-items:center;gap:.5rem;padding:.35rem 0;border-bottom:1px solid var(--line)}
.agendalist li:last-child{border:none}
.agendalist li::marker{color:var(--accent);font-family:var(--mono);font-weight:800}

/* Notification bell */
.invitebtn{display:inline-flex;align-items:center;justify-content:center;text-decoration:none}
.invitebtn[hidden]{display:none}
.notifbtn{position:relative;display:inline-flex;align-items:center;justify-content:center;text-decoration:none}
.notifbtn .badge{position:absolute;top:-5px;right:-5px;background:var(--out);color:var(--bg);border-radius:10px;
  font-size:.62rem;font-weight:800;padding:.05rem .3rem;min-width:16px;text-align:center}
.notiflist li.unread{background:rgba(245,166,35,.08);border-radius:8px;padding-left:.4rem;padding-right:.4rem}
.notiflist li.unread b:before{content:"●";color:var(--accent);font-size:.7em;margin-right:.4em;vertical-align:middle}

/* Duplicate-band warning */
.dupewarn{border-color:var(--maybe)}
.dupewarn h2{color:var(--maybe)}

/* Invite links */
.invitelink{display:flex;gap:.4rem;align-items:center;margin:.35rem 0;max-width:460px}
.invitelink input{font-family:var(--mono);font-size:.78rem;padding:.35rem .5rem}

/* Gear check-in/out */
.outstrip{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin-top:.4rem;padding:.35rem .5rem;
  border:1px solid var(--out);border-radius:8px;background:rgba(226,88,75,.12);font-size:.78rem}
.outstrip b{font-family:var(--mono);color:var(--out);letter-spacing:.08em}
.outstrip.overdue{background:rgba(226,88,75,.24);border-width:2px}
.gearctl{gap:.4rem;flex-wrap:wrap}
.gearout{margin-top:.4rem}
.gearout>summary{cursor:pointer;list-style:none;font-size:.78rem;color:var(--muted);font-weight:700}
.gearout>summary::-webkit-details-marker{display:none}
.gearout[open]>summary{color:var(--accent)}

/* Booking approval roll-call */
.approvalbox{display:flex;gap:.8rem;align-items:center;flex-wrap:wrap;margin:.6rem;padding:.6rem;
  border:1px solid var(--maybe);border-radius:9px;background:rgba(232,184,75,.1)}

/* PWA: install offer and offline notice. Both sit above the phone tab bar. */
.installbar,.offlinebar{position:fixed;left:.6rem;right:.6rem;z-index:95;
  background:var(--bg2);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);
  padding:.7rem .9rem;font-size:.85rem;display:flex;gap:.8rem;align-items:center;flex-wrap:wrap}
.installbar{bottom:.6rem;border-color:var(--accent)}
.offlinebar{bottom:.6rem;border-color:var(--maybe);background:rgba(232,184,75,.14)}
.installbar .installactions{margin-left:auto;display:flex;gap:.5rem;align-items:center}
@media (max-width:820px){
  .installbar,.offlinebar{bottom:calc(60px + env(safe-area-inset-bottom))}
}

/* Requests box — the first thing on the front page when something needs an answer */
.requestsbox{border-color:var(--accent)}
.requestsbox h3{margin:.7rem 0 .2rem;color:var(--muted);font-size:.78rem;text-transform:uppercase;letter-spacing:.06em}
.requestsbox .feed li{align-items:flex-start}

/* Musician directory */
.musgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:1rem}
.muscard{margin-bottom:0}
.mushead{display:flex;gap:.5rem;align-items:flex-start}
.mushead .grow{display:flex;flex-direction:column;gap:.1rem}
.inviteform{margin-top:.5rem;border-top:1px dashed var(--line);padding-top:.6rem}
.inviteform>summary{cursor:pointer;list-style:none;font-size:.85rem;color:var(--accent);font-weight:700}
.inviteform>summary::-webkit-details-marker{display:none}
tr.guestrow td{background:rgba(232,184,75,.06)}

/* ── Speed-layer feedback ──────────────────────────────────────────────────── */
/* Top progress bar — only appears once something is slow enough to notice. */
.napbar{position:fixed;top:0;left:0;height:2px;width:0;background:var(--accent);z-index:200;
  opacity:0;transition:opacity .15s}
.napbar.on{opacity:1;width:90%;transition:width 1.4s cubic-bezier(.1,.8,.2,1),opacity .15s}

/* Buttons say what they're doing rather than going quiet. */
.btn.is-busy,.linkbtn.is-busy{opacity:.75;cursor:progress;position:relative}
.btn.is-busy:after{content:"";width:10px;height:10px;margin-left:.15rem;border-radius:50%;
  border:2px solid currentColor;border-right-color:transparent;display:inline-block;animation:spin .6s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.btn.is-done{background:var(--in)!important;border-color:var(--in)!important;color:var(--bg)!important}
.chip.is-busy{opacity:.6}
button:disabled{cursor:not-allowed}
.btn:disabled{opacity:.4}
/* Anything clickable should react on press, even before the server answers. */
.btn:active,.chip:active,.availcell:active,.dowpick:active{transform:translateY(1px)}
a,.btn,.chip{-webkit-tap-highlight-color:transparent}

/* Band links + inactive state */
.linkrowheader{display:flex;gap:.4rem;margin-bottom:.2rem;font-size:.75rem;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em}
.linkrowheader span:first-child{flex:0 0 32%}
.linkrowheader span:last-child{flex:1}
.savedlinkhdr{margin-top:.6rem}
.savedlinkrow{display:flex;gap:.4rem;align-items:center;padding:.35rem 0;border-bottom:1px solid var(--line)}
.savedlinkrow:last-of-type{border-bottom:none}
.savedlabel{flex:0 0 32%;font-size:.88rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.savedurl{flex:1;font-size:.82rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.savedurl a{color:var(--muted)}
.savedlinkrow .editlinksel{flex:0 0 32%;min-width:0;font-size:.85rem}
.savedlinkrow .editlinkurl{flex:1;font-size:.85rem}
.linkpager{display:flex;align-items:center;gap:.5rem;margin-top:.5rem}
.linkrow{display:flex;gap:.4rem;align-items:center;margin-bottom:.4rem}
.linkrow select{flex:0 0 32%;min-width:0}
.linkrow input{flex:1}
.activerow{display:flex;gap:.8rem;align-items:center;flex-wrap:wrap;margin-top:1rem;padding-top:.8rem;border-top:1px solid var(--line)}
.colorpickrow{margin-top:1rem;padding-top:.8rem;border-top:1px solid var(--line);display:flex;flex-direction:column;gap:.4rem}
.swatches{display:flex;gap:.5rem;flex-wrap:wrap;margin:0}
.swatch{width:28px;height:28px;border-radius:50%;border:2px solid var(--line);cursor:pointer;padding:0;box-shadow:inset 0 0 0 2px var(--bg2)}
.swatch:hover{border-color:var(--text)}
.swatch.on{border-color:var(--accent);box-shadow:inset 0 0 0 2px var(--bg2),0 0 0 2px var(--accent)}
.rosteractions{display:flex;gap:.6rem;align-items:center;justify-content:flex-end;white-space:nowrap}
.inactivebanner{background:rgba(154,144,131,.14);border-color:var(--muted)}
.inactivebanner a{color:var(--accent);font-weight:700}

/* "More" menu (phone) */
.morelist{list-style:none;margin:0;padding:0}
.morelist li{border-bottom:1px solid var(--line)}
.morelist li:last-child{border:none}
.morelist a,.morelist button.morelistbtn{display:flex;align-items:center;gap:.8rem;padding:.9rem .2rem;width:100%;text-align:left;background:none;border:none;font:inherit;color:inherit;cursor:pointer}
.morelist .mi{font-size:1.3rem;width:1.6rem;text-align:center}
.morelist .grow{display:flex;flex-direction:column}

/* FAQ page */
.faqcard{padding:0}
.faqitem{border-bottom:1px solid var(--line);padding:.75rem 1rem}
.faqitem:last-child{border:none}
.faqitem>summary{cursor:pointer;list-style:none;font-weight:600;font-size:.95rem;padding:.1rem 0}
.faqitem>summary::-webkit-details-marker{display:none}
.faqitem>summary::before{content:'›';display:inline-block;margin-right:.4rem;transition:transform .15s;color:var(--muted)}
.faqitem[open]>summary::before{transform:rotate(90deg)}
.faqq{color:var(--text)}
.faqa{padding:.6rem 0 .2rem 1.1rem;font-size:.9rem;line-height:1.55}
.faqa p{margin:.5rem 0}
.faqa ol{margin:.4rem 0;padding-left:1.3rem}
.faqa li{margin:.3rem 0}
.faqos{margin-top:.9rem!important;margin-bottom:.1rem!important}

/* ── Mobile ───────────────────────────────────────────────────────────────── */
/* Bottom tab bar replaces the top nav on phones. Hidden on desktop. */
.tabbar{display:none}
@media (max-width:820px),(max-height:500px) and (orientation:landscape){
  .tabbar{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:90;
    background:var(--bg2);border-top:1px solid var(--line);
    padding-bottom:calc(env(safe-area-inset-bottom) + 6px);
  }
  .tabbar a{flex:1;display:flex;flex-direction:column;align-items:center;gap:.1rem;
    padding:.5rem .2rem;color:var(--muted);font-size:.65rem;font-weight:700;min-height:52px;justify-content:center}
  .tabbar a.active{color:var(--accent)}
  /* --vvshift (nav.js vvSync) re-pins bottom-anchored things to the visible bottom when iOS Safari's
     fixed layer drifts; `translate` is separate from `transform`, so hover nudges still work. */
  [data-navpos="bottom"] .tabbar,.feedbackfab,.totopfab,.nettoast{translate:0 var(--vvshift,0px)}
  .kbd-open .tabbar,.kbd-open .feedbackfab,.kbd-open .totopfab{display:none}
  .kbd-open .wrap{padding-bottom:1rem}
  /* iOS Safari zooms in on any field under 16px when it's tapped, and coming back from that zoom
     can strand the fixed tab bar mid-screen. 16px on phones means no zoom in the first place. */
  input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),select,textarea{font-size:16px!important}
  .tabbar .ti{font-size:1.15rem;line-height:1}
  .wrap{padding:1rem .8rem calc(78px + env(safe-area-inset-bottom))}

  /* Nav position (Account → Mobile navigation). Bottom is the default, above: an edge-to-edge
     bar. Left/right are a different shape entirely — a floating rail, inset from every edge and
     starting below the top bar (--topbar-h, kept current by setTopbarHeight() in app.js) so it
     never sits on top of the settings/refresh icons up there. Its own border and radius on all
     four sides make it read as a distinct panel, not a second bar fused onto the first. */
  [data-navpos="left"] .tabbar,[data-navpos="right"] .tabbar{
    top:calc(var(--topbar-h, 56px) + .6rem);bottom:.6rem;width:60px;height:auto;
    flex-direction:column;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
  }
  [data-navpos="left"] .tabbar{left:.6rem;right:auto;padding-left:env(safe-area-inset-left)}
  [data-navpos="right"] .tabbar{right:.6rem;left:auto;padding-right:env(safe-area-inset-right)}
  [data-navpos="left"] .tabbar a,[data-navpos="right"] .tabbar a{flex:1;width:100%;min-height:44px;padding:.5rem .2rem}
  [data-navpos="left"] .tabbar a[hidden],[data-navpos="right"] .tabbar a[hidden]{display:none}
  [data-navpos="left"] .wrap{padding:1rem .8rem 1rem calc(84px + env(safe-area-inset-left))}
  [data-navpos="right"] .wrap{padding:1rem calc(84px + env(safe-area-inset-right)) 1rem .8rem}

  /* Tap targets: 44px minimum, per touch guidelines. */
  .chip{padding:.55rem .9rem;font-size:.85rem;min-height:40px;display:inline-flex;align-items:center}
  .btn{min-height:42px}
  .linkbtn{min-height:36px;padding:.4rem .6rem}
  .availcell{min-height:60px;padding:.6rem .2rem}
  .dowpick{min-height:38px}
  .check{font-size:1.5rem;padding:.2rem .4rem}

  /* Stack the two-column grids. */
  .grid2{grid-template-columns:1fr}
  .pagehead{align-items:flex-start}
  h1{font-size:1.3rem}
  .card{padding:.9rem;border-radius:10px}

  /* Topbar: the band name is the thing most likely to wrap to three lines. Clamp it. */
  .topbar{gap:.5rem;padding:.5rem .7rem}
  .brand{font-size:1rem}
  .brand .tag{display:none}
  .tag.beta{font-size:.58rem;padding:.15em .4em}
  .dropdown>summary{max-width:38vw;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;
    line-height:1.6;padding:.45rem .6rem}
  .topright{gap:.35rem;min-width:0}
  /* Mobile top bar is tight for space — the name would either truncate or crowd everything
     else out, and the gear icon alone (linking to the same Account page) is enough. */
  .topname{padding:.35rem .4rem;font-size:.85rem}
  .topname .topname-name{display:none}

  /* Setlist running order: a compact scannable LIST, not a stack of spaced-out cards. The
     title gets most of the row's width with the chords lined up on the right of that same
     row (shrunk a touch so both fit without wrapping into each other); under that, one line
     each for artist, then key·bpm·length, then any note; then links, then reorder/edit, each
     their own tight row. */
  .setitems li{align-items:flex-start;padding:.35rem .5rem;margin-bottom:.25rem;border-radius:8px}
  .setitems .num{padding-top:.1rem;font-size:.95rem}
  .setitems li .grow{display:grid;grid-template-columns:1fr auto;column-gap:.5rem;align-items:baseline}
  .ititle{grid-column:1;min-width:0;overflow-wrap:break-word;font-size:.92rem}
  .itchords-inline{grid-column:2;display:block;margin-left:0;white-space:nowrap;text-align:right}
  .itchords-block{display:none}
  .itmetadesktop{display:none}
  .itartist{grid-column:1/-1;display:block;color:var(--muted);font-size:.82rem;margin-top:.05rem}
  .itmetamobile{grid-column:1/-1;display:block;font-family:var(--mono);color:var(--muted);font-size:.78rem;margin-top:.05rem}
  .itnote{grid-column:1/-1;margin-top:.05rem}
  /* Row 2: icons (video/listen/tabs/edit) and reorder all on one compact line */
  .setctl{flex:1 1 100%;display:flex;align-items:center;gap:.35rem;margin-top:.25rem;padding-top:.25rem;border-top:1px dashed var(--line);flex-wrap:wrap}
  .setlinks{display:flex;flex-wrap:nowrap;gap:.3rem;align-items:center;flex:0 1 auto}
  .setreorder{display:flex;gap:.25rem;align-items:center;margin-left:auto;flex:0 0 auto}
  /* pencil icon: inline with the links row; expands to its own full row when open */
  /* .setctl prefix raises specificity above .editevent{flex-basis:100%} at line 906 */
  .setctl .songedit{flex:0 0 auto;width:auto;display:inline-flex}
  .setctl .songedit>summary{display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:8px;
    padding:.25rem .4rem;font-size:.76rem;cursor:pointer}
  .setctl .songedit[open]>summary{border-color:var(--accent)}
  .setctl .songedit[open]{flex:1 1 100%;margin-top:.3rem;display:block}
  .setctl .songedit .editlabel{display:none}
  .setctl .songedit .editicon{font-size:.9rem}

  /* Dashboard feed rows: stack the detail above the answer chips instead of side by side. */
  .feed li{flex-wrap:wrap;gap:.4rem;padding:.7rem 0}
  .feed li .grow{flex:1 1 100%;min-width:0}
  .feed li .rsvp{flex:1 1 100%;justify-content:flex-start;gap:.4rem}
  .feed li .kind{align-self:flex-start}

  /* Event cards: actions already sit in their own full-width row (see .eactions) — on a phone
     they just need to wrap onto more lines rather than squeeze. */
  .event{flex-wrap:wrap}
  .attend{gap:.3rem}
  .att .names{display:none} /* the counts matter on a phone; the roll-call doesn't fit */

  /* The sticky name column (base rule above, all screen sizes) gets narrower on a phone, and
     instruments are dropped here — the pills are wider than the names and would eat the grid. */
  .availtable td.mname{font-size:.75rem;max-width:104px;width:104px;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  .availtable td.mname .pill.inst,.availtable td.mname .muted.small{display:none}
  .availtable.wide td.cell,.availtable.wide th{min-width:26px}

  /* Forms: one field per row, bigger controls. Mobile nav position stays in its one horizontal
     row even here — three short options are more scannable side by side than stacked. */
  .row{flex-direction:column;gap:.5rem}
  .row>label{width:100%}
  .navposform{gap:.8rem}
  input,select,textarea{font-size:16px;padding:.6rem} /* 16px stops iOS zooming on focus */
  input:not([type=checkbox]):not([type=radio]):not([type=range]),select,textarea{font-size:16px!important}
  .winnav{width:100%}
  .winnav .btn{flex:1;justify-content:center}

  /* Booking pipeline: one column, not four squeezed ones. */
  .pipeline{grid-template-columns:1fr}
  .avmodal-card{max-width:none}
  .avchoice{grid-template-columns:1fr 1fr}
  .instlist{grid-template-columns:repeat(auto-fill,minmax(96px,1fr))}
  .linkrow{flex-wrap:wrap}
  .linkrow select{flex:1 1 100%}
  .topright .small{display:none} /* "My gear" etc. live in the More tab on a phone */
}

/* Phone in landscape: barely 350–420px of HEIGHT to work with, and a fixed top bar plus a
   fixed bottom tab bar were eating a fixed chunk of it regardless — proportionally a much
   bigger loss than in portrait. Shrink both, and give back the padding .wrap reserved for the
   taller version of the tab bar. */
@media (max-height:500px) and (orientation:landscape){
  .topbar{padding:.3rem .7rem}
  /* A bar pinned to the bottom of a landscape phone eats the one dimension it can't spare —
     height — so the default (bottom) falls back to a right-hand column here. An explicit
     left/right choice already gets a full-height column from the rules above and just keeps it. */
  [data-navpos="bottom"] .tabbar{
    top:calc(var(--topbar-h, 48px) + .5rem);left:auto;right:.5rem;bottom:.5rem;width:60px;height:auto;
    flex-direction:column;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);
    padding-right:env(safe-area-inset-right);
  }
  [data-navpos="bottom"] .wrap{padding:1rem calc(80px + env(safe-area-inset-right)) 1rem .8rem}
  [data-navpos="left"] .tabbar,[data-navpos="right"] .tabbar{top:calc(var(--topbar-h, 48px) + .5rem)}
  .tabbar a{flex:1;width:100%;min-height:36px;padding:.5rem .2rem}
  .tabbar a[hidden]{display:none}
  .tabbar .ti{font-size:1.05rem}
  .tabbar .tl{font-size:.6rem}
}

@media (max-width:480px){
  .statrow .stat{min-width:64px;padding:.4rem .6rem}
  .stat b{font-size:1.1rem}
  .geargrid{grid-template-columns:1fr 1fr}
  .bestdates{overflow-x:auto;flex-wrap:nowrap;padding-bottom:.3rem}
  .bestcard{flex:0 0 auto}
}

/* Respect a user's reduced-motion setting. */
@media (prefers-reduced-motion:reduce){
  *,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* Big on-screen invite QR: sized to be photographed off a laptop/monitor. Dark-on-white
   inside a generous white frame — a dark theme around it makes scanners fail. */
.qrshow{text-align:center}
.qrhow{font-size:1.05rem;margin:.2rem 0 .8rem}
.qrbig{background:#fff;border-radius:14px;padding:14px;max-width:100%;height:auto;border:1px solid var(--line)}

/* QR thumbnails on the owner campaign page — always dark-on-white or scanners refuse them */
.qrthumb{flex:none;background:#fff;border-radius:6px;padding:2px;border:1px solid var(--line)}

.editevent,.gearedit{margin-top:.5rem;flex-basis:100%}
.editevent>summary,.gearedit>summary{cursor:pointer;list-style:none;font-size:.78rem;color:var(--muted);font-weight:700;padding:.2rem 0}
.editevent>summary::-webkit-details-marker,.gearedit>summary::-webkit-details-marker{display:none}
.editevent[open]>summary,.gearedit[open]>summary{color:var(--accent)}
.gearedit{padding-top:.5rem;border-top:1px dashed var(--line)}

/* Everything a song's per-instrument tabs/video/notes used to need a click-through to
   /songs/:id for, right inside the setlist item's own disclosure — name+chords lead,
   quick links sit to the side, tabs and notes follow. */
.songdetail{padding:.5rem 0 .7rem;border-bottom:1px dashed var(--line);margin-bottom:.5rem}
.songdetailhead{display:flex;align-items:baseline;justify-content:space-between;gap:.8rem;flex-wrap:wrap}
.sdtitle{font-size:.95rem}
.songdetailhead .itchords{margin-left:.5rem}
.sdlinks{flex:none;display:flex;gap:.5rem}
.sdtabs{list-style:none;margin:.5rem 0 0;padding:0;display:flex;flex-wrap:wrap;gap:.4rem .8rem}
.sdtabs li{display:flex;align-items:center;gap:.4rem;font-size:.85rem}
.sdnotes{margin:.5rem 0 0}
.showcomments{padding:.7rem;border-top:1px solid var(--line)}

/* ── Gear next to the username ───────────────────────────────────────────── */
.gearbtn{display:inline-flex;align-items:center;justify-content:center;font-size:1.15rem;line-height:1}

/* ── Impersonation ─────────────────────────────────────────────────────────
   Unmissable on purpose: a striped bar across the top and a big stop button right
   next to the band name. */
.impbar{background:repeating-linear-gradient(135deg,#b3261e 0 14px,#8f1d17 14px 28px);color:#fff;text-align:center;
  padding:.35rem .8rem;font-size:.82rem;font-weight:600;letter-spacing:.01em}
.impbar b{color:#fff}
.impform{margin:0}
.imp-stop{background:#e2584b;color:#fff;border:2px solid #fff;border-radius:10px;padding:.5rem .95rem;font:inherit;
  font-weight:800;font-size:.92rem;cursor:pointer;display:flex;flex-direction:column;align-items:center;line-height:1.15;
  box-shadow:0 0 0 3px rgba(226,88,75,.45),0 4px 14px rgba(0,0,0,.4);animation:imppulse 2.4s ease-in-out infinite}
.imp-stop:hover{background:#c8402f}
.imp-who{font-weight:600;font-size:.72rem;opacity:.95;max-width:12rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@keyframes imppulse{0%,100%{box-shadow:0 0 0 3px rgba(226,88,75,.45),0 4px 14px rgba(0,0,0,.4)}50%{box-shadow:0 0 0 6px rgba(226,88,75,.2),0 4px 14px rgba(0,0,0,.4)}}
@media (max-width:820px){
  .imp-stop{padding:.35rem .6rem;font-size:.78rem}
  .imp-who{display:none}
}
.bigbtn{font-size:1rem;padding:.7rem 1.2rem}

/* Platform-wide announcement */
.platformbanner{background:rgba(232,184,75,.14);border:1px solid var(--maybe);padding:.6rem .9rem;border-radius:9px;margin-bottom:1rem;font-size:.9rem}

/* ── Platform settings ───────────────────────────────────────────────────── */
.ptabs,.jumpnav{display:flex;gap:.3rem;flex-wrap:wrap;margin:-.4rem 0 1rem}
.ptabs a,.jumpnav a,.ptabs button{padding:.4rem .8rem;border-radius:8px;border:1px solid var(--line);background:var(--bg3);color:var(--muted);font-weight:700;font-size:.85rem;font-family:inherit;cursor:pointer}
.ptabs a:hover,.jumpnav a:hover,.ptabs button:hover{color:var(--text);border-color:var(--accent)}
.ptabs a.on,.ptabs button.on{color:var(--accent-ink);background:var(--accent);border-color:var(--accent)}
.jumpnav a{font-size:.8rem;padding:.3rem .65rem}
a.stat{color:inherit}
a.stat:hover{border-color:var(--accent)}
.bigstats .stat{min-width:104px}
.bars{display:flex;align-items:flex-end;gap:.35rem;height:130px;padding-top:.4rem}
.bars .bar{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;height:100%;min-width:0;position:relative;color:var(--muted);font-size:.66rem}
.bars .bar i{display:block;width:100%;background:var(--accent);border-radius:4px 4px 0 0;min-height:2px;opacity:.85}
.bars .bar:hover i{opacity:1}
.bars .bar em{font-style:normal;position:absolute;top:0;font-size:.7rem;color:var(--text)}
.bars .bar span{margin-top:.2rem;white-space:nowrap}
.bars.dense{gap:2px;height:90px}
.bars.dense .bar i{border-radius:2px 2px 0 0}
.meter{display:inline-block;width:80px;height:7px;background:var(--bg);border:1px solid var(--line);border-radius:5px;vertical-align:middle;overflow:hidden}
.meter i{display:block;height:100%;background:var(--accent)}
.filterrows{display:flex;flex-direction:column;gap:.4rem}
.filterrow{display:grid;grid-template-columns:minmax(120px,1.2fr) minmax(110px,1fr) minmax(120px,1.4fr) auto;gap:.4rem;align-items:center}
@media (max-width:640px){.filterrow{grid-template-columns:1fr 1fr}.filterrow input{grid-column:1/-1}}
.usertable th a{color:inherit;white-space:nowrap}
.usertable td{white-space:nowrap;max-width:22ch;overflow:hidden;text-overflow:ellipsis}
.pager{display:flex;gap:.8rem;align-items:center;justify-content:center;margin-top:.8rem}
.subhead{font-size:.82rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:1.1rem 0 .5rem}
/* A cross-band group (Tasks page, dashboard panels once scope is "all") — a left border in the
   band's own accent color, so even a quick glance (not just reading the label) tells you where
   one band's items end and another's begin. The header sits inside it, not above it. */
.banddash-group{border-left:3px solid var(--line);padding-left:.7rem;margin:.7rem 0}
.banddash-group:first-child{margin-top:.2rem}
.tasksection{display:flex;align-items:center;gap:.4rem;font-size:.82rem;text-transform:uppercase;
  letter-spacing:.08em;color:var(--muted);margin:0 0 .5rem}
.tasksection .dot{width:8px;height:8px}
.rolechange{margin:0}
.rolechange select{width:auto;padding:.3rem .5rem;font-size:.85rem}
.contactcell a{color:var(--accent)}
.contactcell div{white-space:nowrap}

/* ── Setlist library picker ──────────────────────────────────────────────── */
.filterbox{width:100%;margin-bottom:.5rem}
.libpick{list-style:none;margin:0 0 .4rem;padding:0;max-height:280px;overflow-y:auto;border:1px solid var(--line);border-radius:10px;background:var(--bg)}
.libpick li{display:flex;align-items:center;gap:.6rem;padding:.45rem .7rem;border-bottom:1px solid var(--line)}
.libpick li:last-child{border-bottom:none}
.libpick li[hidden]{display:none!important}

/* ── Date picker: type it or pick it ─────────────────────────────────────── */
.dpwrap{display:flex;align-items:stretch;gap:.3rem;width:100%}
.dpwrap .dpinput{flex:1;min-width:0}
.dpbtn{background:var(--bg3);border:1px solid var(--line);color:var(--text);border-radius:8px;cursor:pointer;padding:0 .6rem;font-size:1rem}
.dpbtn:hover{border-color:var(--accent)}
.dppop{position:absolute;z-index:200;width:288px;max-width:calc(100vw - 16px);background:var(--bg2);border:1px solid var(--line);
  border-radius:12px;box-shadow:var(--shadow);padding:.6rem;color:var(--text)}
.dphead{display:flex;align-items:center;justify-content:space-between;gap:.2rem;margin-bottom:.4rem}
.dphead b{flex:1;text-align:center;font-size:.92rem}
.dphead button{background:none;border:1px solid transparent;color:var(--text);border-radius:7px;cursor:pointer;width:32px;height:32px;font-size:1rem}
.dphead button:hover{background:var(--bg3);border-color:var(--line)}
.dpgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}
.dpgrid .dow{font-size:.68rem;color:var(--muted);padding:.2rem 0;text-transform:uppercase}
.dpgrid button{background:none;border:1px solid transparent;color:var(--text);border-radius:8px;cursor:pointer;height:34px;font:inherit;font-size:.88rem}
.dpgrid button:hover{background:var(--bg3);border-color:var(--line)}
.dpgrid button.out{color:var(--muted);opacity:.55}
.dpgrid button.today{border-color:var(--accent)}
.dpgrid button.sel{background:var(--accent);color:var(--accent-ink);font-weight:800}
.dpfoot{display:flex;justify-content:space-between;margin-top:.4rem}
.dpfoot button{background:none;border:none;color:var(--accent);cursor:pointer;font-weight:700;font-size:.85rem;padding:.3rem .4rem;border-radius:6px}
.dpfoot button:hover{background:var(--bg3)}

/* ── Repeat controls ─────────────────────────────────────────────────────── */
.recopts{display:contents}
.recsummary{margin:.2rem 0 0}

/* Grid children must be allowed to shrink or a wide chart/table pushes the page sideways on a phone. */
.grid2>*{min-width:0}
.bars .bar span{overflow:hidden;text-overflow:clip;max-width:100%}
@media (max-width:560px){.bars:not(.dense) .bar span{display:none}}

/* Phone: the band switcher's menu opens toward the middle of the screen instead of off the
   right edge (the wide "stop impersonating" button pushes the switcher right). */
@media (max-width:820px){
  .topright .dropdown:not(.right) .menu{left:auto;right:0;max-width:calc(100vw - 16px)}
}
@media (max-width:820px){
  /* Room is tight on a phone: keep "⏹ Stop" big and drop the extra words, and let the
     right-hand cluster wrap onto a second row rather than push the page sideways. */
  .imp-more{display:none}
  .topright{flex-wrap:wrap;justify-content:flex-end;row-gap:.3rem;column-gap:.25rem}
  .topright .dropdown>summary{max-width:26vw}
  .topright .iconbtn{width:32px;height:32px}
}

/* Song links: watch (video, red), hear (stream, green), play (tabs, amber) — three ways to
   know a song, each its own color, all open in a new window. Button-shaped so they read as
   controls, with real space between them (see .songlinks above). */
.ytlink,.streamlink,.tabslink{display:inline-flex;align-items:center;gap:.3rem;padding:.3rem .6rem;
  border:1px solid var(--line);border-radius:8px;background:var(--bg3)}
.ytlink:hover,.streamlink:hover,.tabslink:hover{border-color:currentColor}
.streamlink{color:var(--in);font-weight:700}.streamlink.sm{font-size:.85rem}
.tabslink{color:var(--accent);font-weight:700}.tabslink.sm{font-size:.85rem}
.songedit{margin-left:32px}

/* Band name on the dashboard doubles as the band switcher when you're in more than one */
.pagehead .bandpick{display:inline-block}
.bandpick>summary{background:none;border:none;padding:0;border-radius:8px;cursor:pointer;display:block}
.bandpick>summary:hover h1{color:var(--accent)}
.bandpick h1{display:flex;align-items:center;gap:.5rem;margin:0}
.bandpick .caret{font-size:.9rem;color:var(--muted)}
.bandpick .menu{min-width:240px}
.bandflags{margin-left:.4rem}
.tasks li.mine .grow{font-weight:600}
.bandpick>summary{max-width:none;white-space:normal;overflow:visible;line-height:inherit}
.bandpick .menu{left:0;right:auto;max-width:calc(100vw - 24px)}

/* ── Who's in / maybe / out / hasn't answered ─────────────────────────────── */
.attsum{margin-top:.45rem;display:flex;flex-wrap:wrap;align-items:center;gap:.4rem .7rem}
.attcounts{display:flex;flex-wrap:wrap;gap:.3rem}
.ac{font-size:.74rem;border:1px solid var(--line);border-radius:7px;padding:.12rem .45rem;color:var(--muted);white-space:nowrap}
.ac b{color:inherit}
.ac .am{font-weight:800}
.ac.in{color:var(--in);border-color:rgba(111,206,159,.45)}
.ac.maybe{color:var(--maybe);border-color:rgba(232,184,75,.45)}
.ac.out{color:var(--out);border-color:rgba(226,88,75,.45)}
.ac.none{color:var(--muted);border-style:dashed}
.ac.zero{color:var(--muted);border-color:var(--line);border-style:dashed}
.attdots{display:inline-flex;flex-wrap:wrap;gap:3px}
.adot{font-style:normal;width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  font-size:.68rem;font-weight:800;border:2px solid var(--line);color:var(--muted);background:var(--bg);cursor:default}
.adot.in{background:var(--in);border-color:var(--in);color:var(--bg)}
.adot.maybe{background:var(--maybe);border-color:var(--maybe);color:#2a1e02}
.adot.out{background:var(--out);border-color:var(--out);color:#2a0b08}
.adot.none{border-style:dashed;background:transparent}
.adot.me{box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--accent)}
.attflag{font-size:.75rem;font-weight:700;padding:.12rem .5rem;border-radius:7px}
.attflag.ok{color:var(--in);background:rgba(111,206,159,.12)}
.attflag.wait{color:var(--maybe);background:rgba(232,184,75,.12)}
.attflag.done{color:var(--muted);background:var(--bg3)}
.attroll{flex-basis:100%;display:flex;flex-direction:column;gap:.15rem;font-size:.8rem}
.atgroup{display:flex;gap:.5rem;align-items:baseline}
.atlabel{flex:none;min-width:9.5rem;font-weight:700}
.atgroup.in .atlabel{color:var(--in)}.atgroup.maybe .atlabel{color:var(--maybe)}.atgroup.out .atlabel{color:var(--out)}.atgroup.none .atlabel{color:var(--muted)}
.atnames{color:var(--text)}
.attsum.compact{margin-top:.25rem}
.attsum.compact .ac{font-size:.68rem;padding:.08rem .35rem}
.attsum.compact .adot{width:18px;height:18px;font-size:.6rem;border-width:2px}
@media (max-width:820px){
  .atgroup{flex-direction:column;gap:0}
  .atlabel{min-width:0}
  .attsum.compact .attdots{display:none} /* the counts carry a phone row; dots + names live on the schedule */
}

/* ── Availability: one window bar that clearly drives the whole page ───────────────── */
.windowbar{background:var(--bg2);border:1px solid var(--accent);border-radius:var(--radius);padding:.7rem .9rem;margin-bottom:.9rem;
  box-shadow:0 0 0 3px rgba(245,166,35,.10),var(--shadow)}
@media (min-width:821px){.windowbar{position:sticky;top:calc(var(--topbar-h,58px) + 6px);z-index:40}}
.wb-top{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:.3rem 1rem;margin-bottom:.55rem}
.wb-title{display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .7rem}
.wb-label{font-family:var(--mono);font-size:.68rem;text-transform:uppercase;letter-spacing:.14em;color:var(--accent)}
.wb-range{font-size:1.15rem}
.wb-scope{margin:0;font-size:.8rem;color:var(--muted)}
.wb-scope b{color:var(--text)}
.wb-controls{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem .9rem}
.seg{display:inline-flex;flex-wrap:wrap;gap:.25rem}
.wb-jump{display:inline-flex;align-items:center;gap:.35rem;margin:0}
.wb-jumplabel{font-size:.75rem;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.wb-jump select,.wb-jump input[type="text"]{width:auto;padding:.3rem .45rem;font-size:.82rem}
.wb-jump .dpwrap{width:auto}
.wb-jump .dpinput{width:8.6rem}

/* the three sections that follow the bar hang off a shared rail so they read as one unit */
.windowgroup{border-left:3px solid var(--accent);padding-left:.9rem;margin-left:.2rem}
.windowgroup>.card{margin-bottom:1rem}
.stepno{display:inline-flex;align-items:center;justify-content:center;width:1.35rem;height:1.35rem;border-radius:50%;background:var(--accent);
  color:var(--accent-ink);font-size:.75rem;font-weight:800;margin-right:.5rem;vertical-align:.1em}
.rangechip{font-family:var(--mono);font-size:.72rem;color:var(--accent);border:1px solid var(--accent);border-radius:999px;padding:.15rem .6rem;white-space:nowrap}
.rangechip:before{content:"🗓 "}
.availtable tr.monthrow th{font-size:.7rem;text-transform:uppercase;letter-spacing:.08em;color:var(--accent);border-bottom:none;background:var(--bg3)}
.findpager{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:.8rem}
.btn.is-disabled{opacity:.35;cursor:default;pointer-events:none}
@media (max-width:820px){
  .windowgroup{padding-left:.6rem;margin-left:0}
  .wb-range{font-size:1rem}
  .seg .btn{flex:1 1 auto;justify-content:center}
}

/* ── Birthdays ─────────────────────────────────────────────────────────────── */
.event.birthday{background:linear-gradient(135deg,rgba(245,166,35,.16),rgba(244,114,182,.12));border:1px dashed var(--accent);border-left:4px solid #f472b6}
.event.birthday .ecal{background:rgba(244,114,182,.18)}
.kind.bday{background:rgba(244,114,182,.18);color:#f9a8d4;border-color:rgba(244,114,182,.5)}
.bdaycard{border:1px dashed var(--accent);background:linear-gradient(135deg,rgba(245,166,35,.10),rgba(244,114,182,.08));margin-bottom:1rem}
.availtable tr.bdayrow td{height:24px;background:var(--bg3);font-size:.85rem;line-height:1;padding:0}
.availtable td.bdaycell{cursor:default}
.availcell{position:relative}
.availcell .bday{position:absolute;top:1px;right:2px;font-size:.8rem;line-height:1}
.availcell.hasbday{box-shadow:inset 0 0 0 1px #f472b6}
/* Ticket #93: today stands out on the calendar (also when the day has a birthday ring). */
.availcell.istoday,.availcell.istoday.hasbday{border-color:var(--accent);box-shadow:inset 0 0 0 2px var(--accent)}
.availcell.istoday .dnum{color:var(--accent)}
/* The holiday name is its own header line at the top of the same box — not a ring or a
   separate element — so a holiday reads as information, not another "you're free/busy" state.
   Turning the "Show US holidays" setting off means holidaysOn is never populated, so hasholiday
   never applies and the box needs no special-case: it's already an ordinary day. */
.availcell .holname{display:block;align-items:center;justify-content:center;gap:.2rem;
  font-size:.56rem;font-weight:800;line-height:1.15;color:var(--accent);text-align:center;white-space:normal;max-width:100%;min-width:0;flex-direction:column;overflow-wrap:break-word;hyphens:auto}
.availcell .holname>span{display:block}
@media (max-width:560px){.availcell .holname{font-size:.5rem;gap:0}}
.availcell.outmonth{background:transparent;border-style:dashed}.availcell.outmonth .dow,.availcell.outmonth .dnum,.availcell.outmonth .dmon{color:var(--muted)}

/* Event marker: replaces the month abbreviation with the event's own type (icon + word) on any
   day something's happening — a full-width band across the bottom of the cell so it reads at a
   glance instead of a tiny corner dot, and still clearly not the availability coloring
   underneath it. Color-coded by event kind (gig/rehearsal/meeting each their own hue, distinct
   from the green/red/amber already used for availability) so the type registers even before the
   word does. A filled band means everyone's RSVP'd in; a dashed outline + faint tint means it's
   still waiting on someone — confirmed vs pending stays tellable apart at a glance too. */
.availcell .dmon.evday{display:block;width:100%;box-sizing:border-box;font-weight:800;
  font-size:.68rem;line-height:1.25;white-space:normal;padding:.3em .3em;border-radius:7px;
  margin-top:.25rem;text-align:center}
.availcell .dmon.evday.kind-show{--evc:230,90,150}
.availcell .dmon.evday.kind-rehearsal{--evc:91,159,214}
.availcell .dmon.evday.kind-meeting{--evc:168,125,219}
.availcell .dmon.evday.kind-other,.availcell .dmon.evday.kind-mixed{--evc:154,144,131}
.availcell .dmon.evday.confirmed{background:rgb(var(--evc));color:#0d0b08;border:1.5px solid rgb(var(--evc))}
.availcell .dmon.evday.pending{border:1.5px dashed rgb(var(--evc));background:rgba(var(--evc),.10);color:var(--text)}
.availtable th.outmonth,.availtable td.outmonth{color:var(--muted)}.availtable .outmonth span{color:var(--muted)}

/* Window bar, revised: no outline; week / month steppers are labelled pairs; date on top, "or" month+year beneath */
.windowbar{border:0;box-shadow:none;background:var(--bg2)}
.wb-controls{align-items:flex-start;gap:.7rem 2rem}
.wb-nav{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem 1.1rem}
.wb-step{display:inline-flex;align-items:center;gap:.3rem}
.wb-steplabel{font-size:.75rem;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-right:.1rem}
.wb-step .btn{min-width:2.2rem;justify-content:center;font-size:1rem;line-height:1}
.wb-goto{display:flex;flex-direction:column;gap:.4rem}
.wb-jumplabel{min-width:5.4rem}

/* Window bar, revision 3: soft shadow instead of an outline; go-to block pushed right; big Go under the month/year pickers */
.windowbar{box-shadow:0 4px 18px rgba(0,0,0,.35),0 1px 3px rgba(0,0,0,.25)}
.wb-controls{width:100%;justify-content:space-between}
.wb-goto{margin-left:auto;align-items:flex-end}
.wb-monthyear{align-items:flex-start}
.wb-my{display:flex;flex-direction:column;gap:.4rem}
.wb-selects{display:flex;gap:.35rem}
.wb-go{width:100%;justify-content:center;padding:.5rem 1rem;font-size:.95rem}
@media (max-width:820px){.wb-goto{margin-left:0;align-items:stretch;width:100%}.wb-my{flex:1}}

/* Window bar, revision 4: reads as a toolbar — tinted control surface, joined stepper buttons, obvious hover/press */
.windowbar{background:linear-gradient(180deg,rgba(245,166,35,.20),rgba(245,166,35,.09)),var(--bg2);border-radius:14px;padding:.8rem 1rem .9rem}
.wb-label{color:var(--text);font-weight:800;letter-spacing:.12em}
.wb-range{font-size:1.3rem}
.wb-nav{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem .9rem}
.tbtn,.stepbtn{cursor:pointer;user-select:none;transition:background .12s,transform .05s,box-shadow .12s;text-decoration:none}
.tbtn{display:inline-flex;align-items:center;gap:.4rem;height:2.5rem;padding:0 1.1rem;border-radius:10px;font-weight:800;font-size:.95rem;
  background:var(--accent);color:var(--accent-ink);box-shadow:0 2px 0 rgba(0,0,0,.35),0 4px 10px rgba(0,0,0,.25)}
.tbtn:hover{filter:brightness(1.08)}
.tbtn:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(0,0,0,.35)}
.tbtn.is-here{background:var(--bg3);color:var(--accent);box-shadow:inset 0 0 0 2px var(--accent)}
.stepper{display:inline-flex;align-items:stretch;height:2.5rem;border-radius:10px;overflow:hidden;background:var(--bg3);
  box-shadow:0 2px 0 rgba(0,0,0,.35),0 4px 10px rgba(0,0,0,.25),inset 0 0 0 1px var(--line)}
.stepbtn{display:flex;align-items:center;justify-content:center;width:2.7rem;font-size:1.5rem;line-height:1;font-weight:700;color:var(--text);background:var(--bg3)}
.stepbtn:hover{background:var(--accent);color:var(--accent-ink)}
.stepbtn:active{transform:translateY(1px)}
.wb-steplabel{display:flex;align-items:center;padding:0 .9rem;font-size:.82rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em;
  color:var(--text);background:var(--bg2);box-shadow:inset 1px 0 0 var(--line),inset -1px 0 0 var(--line);margin:0}
.wb-goto select,.wb-goto input{height:2.3rem}
.wb-go{height:2.5rem;font-weight:800;box-shadow:0 2px 0 rgba(0,0,0,.35),0 4px 10px rgba(0,0,0,.25)}
.tbtn.is-here{background:var(--accent);color:var(--accent-ink);box-shadow:0 2px 0 rgba(0,0,0,.35),0 4px 10px rgba(0,0,0,.25)}

/* Window bar, revision 5: one "Go to month / year" control in the same joined-button style, on the nav row */
.wb-controls{align-items:center;justify-content:flex-start;gap:.6rem .9rem}
.wb-top{margin-bottom:.5rem}
.jumper{display:inline-flex;align-items:stretch;height:2.5rem;margin:0 0 0 auto;border-radius:10px;overflow:hidden;background:var(--bg3);
  box-shadow:0 2px 0 rgba(0,0,0,.35),0 4px 10px rgba(0,0,0,.25),inset 0 0 0 1px var(--line)}
.jumper select{width:auto;height:100%;border:0;border-radius:0;background:var(--bg3);color:var(--text);font-weight:700;font-size:.9rem;padding:0 .6rem;
  cursor:pointer;box-shadow:inset 1px 0 0 var(--line)}
.jumper select:hover{background:var(--bg2)}
.jumper select:focus{box-shadow:inset 0 0 0 2px var(--accent)}
.jgo{border:0;cursor:pointer;background:var(--accent);color:var(--accent-ink);font-weight:800;font-size:.95rem;padding:0 1.2rem;font-family:inherit}
.jgo:hover{filter:brightness(1.08)}.jgo:active{transform:translateY(1px)}
@media (max-width:820px){.jumper{margin-left:0;width:100%}.jumper select{flex:1}.jumper .wb-steplabel{padding:0 .6rem}}

/* the range readout now lives with the availability calendar */
.availrange{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15}
.ar-label{font-family:var(--mono);font-size:.62rem;text-transform:uppercase;letter-spacing:.14em;color:var(--muted)}
.ar-range{font-size:1.1rem;color:var(--accent)}
@media (max-width:820px){.availrange{align-items:flex-start}.ar-range{font-size:1rem}}

/* ── Notes (multi-line, bulleted) + setlist attachments + rehearsal plan ────────────────── */
.notesarea{min-height:9rem;resize:vertical;line-height:1.5}
textarea[data-bullets]{font-family:inherit}
.evnote.notes{display:block}
.notes b{display:block;font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:.15rem}
.notes p{margin:.15rem 0}
.notes ul{margin:.2rem 0 .2rem 1.1rem;padding:0}
.notes li{margin:.1rem 0}
.notes a{color:var(--accent);text-decoration:underline}
.setlistline{margin:.35rem 0;font-size:.9rem}
.setlistline a:first-of-type{color:var(--accent);font-weight:700}
.setlink{display:inline-block;margin-top:.25rem;font-size:.8rem;color:var(--accent);font-weight:700}
.setpill{color:var(--accent)}
.rehearsalplan{border-left:3px solid #6fce9f;padding-left:.7rem;display:flex;flex-direction:column;gap:.6rem}
.rehearsalplan[hidden]{display:none!important}
.lenrow{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem}

/* ── Account settings: view mode ↔ inline edit mode ───────────────────────── */
.acctform .acctbtns{display:flex;gap:.4rem;align-items:center}
.acctform .editonly{display:none}
.acctform .e{display:none;margin-top:.25rem}
.acctform.editing .editonly{display:inline-flex;gap:.4rem}
.acctform.editing .acctfoot.editonly{display:flex;margin-top:.8rem}
.acctform.editing .e{display:block}
.acctform.editing .v{display:none}
.acctform.editing [data-acct-edit]{display:none}
.acctform .acctlist .always{margin-top:.1rem}
.acctform.editing .acctlist>li{background:rgba(245,166,35,.04)}
.acctform .e input:not([type=checkbox]),.acctform .e select{max-width:32rem}
.acctform .e p{margin:.3rem 0 0}
.acctform .v{margin-top:.1rem}
.field-error{border-color:var(--danger)!important;outline-color:var(--danger)!important}
.field-error-lbl{color:var(--danger)!important}

/* ── Pop-up dialogs ───────────────────────────────────────────────────────── */
dialog.dlg{border:1px solid var(--line);background:var(--bg2);color:var(--text);border-radius:14px;padding:0;width:min(30rem,92vw);
  box-shadow:0 20px 60px rgba(0,0,0,.6)}
dialog.dlg::backdrop{background:rgba(0,0,0,.62)}
.dlgcard{padding:1.1rem 1.25rem 1.2rem}
.dlgcard h2{margin-top:0}

.acctform .help{font-weight:400;font-style:italic}
.linkbtn.tiny{font-size:.72rem;font-weight:500;text-transform:none;letter-spacing:0;padding:.05rem .35rem;margin-left:.3rem;color:var(--accent);min-height:0}
.linkbtn.tiny:hover{text-decoration:underline;background:none}

a.setpill{text-decoration:none}a.setpill:hover{text-decoration:underline;border-color:var(--accent)}

/* ── Tasks: a real Done / Reopen button, due dates, and OVERDUE in red ───────────────── */
.donebtn,.reopenbtn{font:inherit;font-size:.78rem;font-weight:800;border-radius:8px;padding:.28rem .6rem;cursor:pointer;white-space:nowrap;border:1px solid var(--in);
  background:transparent;color:var(--in);transition:background .12s,color .12s}
.donebtn:hover{background:var(--in);color:var(--bg)}
.donebtn:active,.reopenbtn:active{transform:translateY(1px)}
.reopenbtn{border-color:var(--line);color:var(--muted)}
.reopenbtn:hover{border-color:var(--accent);color:var(--accent)}
.taskadd{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center}
.taskadd input[name="title"]{flex:1 1 12rem;min-width:0}
.dueinline{display:inline-flex;flex-direction:row;align-items:center;gap:.35rem;font-size:.78rem;color:var(--muted)}
.dueinline .dpwrap{width:auto}.dueinline .dpinput{width:8.4rem;padding:.4rem .5rem}
.tasks li.overdue,.tasklist>li.overdue{background:rgba(226,88,75,.26);border-radius:8px;padding-left:.55rem;padding-right:.55rem;box-shadow:inset 4px 0 0 var(--out)}
.tasks li.overdue .grow,.tasklist>li.overdue .grow{font-weight:700}
.overduepill{display:inline-block;font-family:var(--mono);font-size:.62rem;font-weight:800;letter-spacing:.1em;color:var(--bg);background:var(--out);border-radius:5px;padding:.1rem .4rem;margin-left:.3rem;vertical-align:.05em}
.overduetag{color:var(--out);font-weight:800}
.recentdone{margin-top:.7rem;border-top:1px dashed var(--line);padding-top:.5rem}
.recentdone>summary{cursor:pointer;font-size:.8rem;color:var(--muted);font-weight:700}

/* Task buttons: "Mark done" is a solid, pressable ACTION (not a status chip). */
.donebtn{background:var(--in);color:var(--bg);border:0;border-radius:9px;padding:.45rem .85rem;font-size:.82rem;font-weight:800;letter-spacing:.01em;
  box-shadow:0 2px 0 rgba(0,0,0,.35),0 3px 8px rgba(0,0,0,.25);cursor:pointer}
.donebtn:hover{filter:brightness(1.1);background:var(--in);color:var(--bg);transform:translateY(-1px)}
.donebtn:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(0,0,0,.35)}
.reopenbtn{border-radius:9px;padding:.4rem .75rem;box-shadow:0 2px 0 rgba(0,0,0,.25)}
.tasks li.theirs .bullet{width:1.2rem;text-align:center;color:var(--muted)}

/* ↻ Refresh button beside the gear */
.refreshbtn{display:inline-flex;align-items:center;justify-content:center;font-size:1.2rem;line-height:1;border-radius:50%;padding:0}
.refreshbtn.spinning{animation:grspin .7s linear infinite;opacity:.8}
@keyframes grspin{to{transform:rotate(360deg)}}
.gearbtn{border-radius:50%}
@media (max-width:560px){.topright .iconbtn{width:30px;height:30px}}
@media (max-width:560px){
  .topright{column-gap:.2rem}
  .topright .iconbtn{width:28px;height:28px;font-size:.95rem}
  .topright .refreshbtn{font-size:1.05rem}
  .topright .dropdown>summary{max-width:20vw}
}
.legend{flex-wrap:wrap;row-gap:.3rem}

/* ── Add-form panels: every "create" form opens on demand instead of sitting open ────────── */
/* A page leads with what you already have. The form for adding more is one press away and
   folds back up on its own after a save. (`[hidden]` above already does the hiding.) */
.card.formpanel{margin-bottom:1.2rem;border-color:var(--accent)}
.card.formpanel .cardhead{margin-bottom:.4rem}
/* When a panel scrolls to "start" on open (see togglePanel in app.js), this keeps its title
   from landing right under the sticky top bar instead of below it. */
.formpanel,.editevent,.songedit,.gearedit,.feedbackedit{scroll-margin-top:calc(var(--topbar-h, 56px) + 12px)}
.evpanel-body,.formpanel-body{max-width:46rem}
.formpanel .formactions{margin-top:.3rem}
/* Nested inside a card that's already there (wishlist, song library): a tinted well, not a second card. */
.subpanel{border:1px solid var(--accent);border-radius:10px;padding:.85rem;margin:.1rem 0 .9rem;background:var(--bg3)}
.panelhead{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-bottom:.55rem}
.backupcodes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.4rem;margin:.6rem 0}
.backupcodes code{background:var(--bg2);border:1px solid var(--line);border-radius:6px;padding:.4rem .5rem;text-align:center;font-size:.92rem;letter-spacing:.02em}
@media (max-width:480px){.backupcodes{grid-template-columns:1fr 1fr}}
.panelhead h3{margin:0;font-size:.95rem}
/* The "+ …" button sits on the heading line, hard right, on every page that has one. */
.cardhead .btn{flex:none}
.pagehead .btn.primary{white-space:nowrap}

/* ── Availability: a reason for "not available" (max 140 characters), visible to the band ─── */
.cell.hasnote,.availcell.hasnote{position:relative}
.cell.hasnote::after{content:"";position:absolute;top:2px;right:2px;width:5px;height:5px;border-radius:50%;background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.45)}
.availcell.hasnote::after{content:"💬";position:absolute;top:1px;right:2px;font-size:.62rem;line-height:1}
.cell.hasbusy{position:relative}
.busybar{position:absolute;top:1px;left:2px;right:2px;display:flex;gap:1px;pointer-events:none;height:3px}
.busybar i{flex:1;border-radius:1px;background:transparent}
.busybar i.on{background:#f59e0b;opacity:.9}
.avnote{display:block;margin:.6rem 0}
.avnote input{width:100%}
.avnote-count{display:block;text-align:right}
.reasons{margin-top:.9rem;padding-top:.7rem;border-top:1px dashed var(--line)}
.reasonlist{list-style:none;margin:.3rem 0 0;padding:0;display:grid;gap:.35rem}
.reasonlist li{padding:.4rem .6rem;border-radius:8px;background:rgba(226,88,75,.10);border-left:3px solid var(--out)}
.reasontext{display:block;margin-top:.1rem;word-break:break-word}
@media(min-width:640px){.reasontext{display:inline;margin-left:.3rem}.reasontext::before{content:"— "}}

/* ── Song library: edit / delete dialog ─────────────────────────────────────────────────── */
.dlgdanger{margin-top:1rem;padding-top:.9rem;border-top:1px dashed var(--line)}
.dlgdanger .btn.danger{border:1px solid var(--danger)}
.dlg textarea{width:100%;font:inherit}

/* -- "Lost the connection" message (a form post that got no answer) -- */
.nettoast{position:fixed;left:50%;transform:translateX(-50%);bottom:4.5rem;z-index:60;max-width:min(34rem,calc(100vw - 1.5rem));
  padding:.7rem .9rem;border-radius:12px;background:var(--card,#1b1714);border:1px solid var(--maybe,#e8b84b);
  box-shadow:0 8px 28px rgba(0,0,0,.5);font-size:.9rem;line-height:1.4}
.nettoast .btn{margin:.35rem .4rem 0 0}

/* Song library on phones: each row becomes a card like the setlist running order — title,
   artist, key·bpm·length line, links, then add-to-setlist. Pure CSS so sort/filter/paging
   in app.js keep working on the same <tr>s. */
@media (max-width:820px){
  .songtable,.songtable tbody{display:block}
  .songtable thead{display:none}
  .songtable tr{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:.6rem;padding:.5rem .6rem;margin-bottom:.4rem;
    border:1px solid var(--line);border-radius:10px;background:var(--bg3)}
  .songtable td{display:block;padding:0;border:0}
  .songtable td.colgeartd{display:block;order:0;flex:0 0 auto;align-self:center;width:auto}
  .songtable td:nth-child(2){order:1;flex:1 1 70%;font-size:.95rem;overflow-wrap:break-word}
  .songtable td[data-col=artist]{order:2;flex:1 1 100%;font-size:.82rem}
  .songtable td[data-col=genre],.songtable td[data-col=key],.songtable td[data-col=bpm],.songtable td[data-col=length],.songtable td[data-col=band]{
    order:3;flex:0 0 auto;font-family:var(--mono);color:var(--muted);font-size:.78rem}
  .songtable td[data-col=band]{font-family:inherit}
  .songtable td[data-col=key]:empty,.songtable td[data-col=bpm]:empty,.songtable td[data-col=genre]:empty{display:none}
  .songtable td.songlinks{display:flex;order:4;flex:1 1 100%;margin-top:.35rem;padding-top:.3rem;border-top:1px dashed var(--line)}
}

/* Pull-to-refresh indicator (nav.js). Sits hidden just under the sticky top bar and slides
   down with the finger; spins while the page reloads. */
.ptr{display:none}
@media (max-width:820px){
  html,body{overscroll-behavior-y:none}
  .ptr{display:flex;position:fixed;left:50%;top:var(--topbar-h,48px);z-index:45;width:38px;height:38px;border-radius:50%;
    align-items:center;justify-content:center;background:var(--bg2);border:1px solid var(--line);box-shadow:var(--shadow);
    color:var(--muted);font-size:1.25rem;font-weight:700;opacity:0;transform:translate(-50%,-50px);pointer-events:none;
    transition:transform .2s ease,opacity .2s ease}
  .ptr.pulling{transition:none}
  .ptr.ready{color:var(--accent);border-color:var(--accent)}
  .ptr .ptr-icon{display:block;line-height:1}
  .ptr.spin{color:var(--accent);border-color:var(--accent)}
  .ptr.spin .ptr-icon{animation:ptrspin .7s linear infinite}
}
@keyframes ptrspin{to{transform:rotate(360deg)}}

/* Setlist notes: band-wide (✎) and private "just for me" (🔒). */
.itnote-mine{font-style:italic}
.setnotes{margin:-.3rem 0 .8rem}
.setnotes .itnote{display:block;margin:.1rem 0}
.setnoteedit>summary{list-style:none;cursor:pointer;display:inline-block;font-size:.85rem}
.setnoteedit>summary::-webkit-details-marker{display:none}
.setnoteedit[open] form{margin-top:.4rem;max-width:560px}
.noteedit form{margin-top:.4rem}
.headbtns .setlist-status{white-space:nowrap}
@media (max-width:820px){.headbtns .setlist-status{flex:1 1 100%;text-align:center}}

/* Site footer (partials/site-footer.ejs) + public pages. */
.sitefoot{margin:2.5rem auto 0;padding:1.4rem 1rem 1rem;border-top:1px solid var(--line);max-width:var(--site-max);color:var(--muted)}
.sitefoot-in{display:flex;flex-wrap:wrap;gap:1.2rem 2rem;align-items:flex-start;justify-content:space-between}
.sitefoot-brand p{margin:.2rem 0 0}
.sitefoot-links{display:flex;flex-wrap:wrap;gap:.4rem 1.1rem;font-size:.88rem;flex:1 1 280px}
.sitefoot-links a:hover{color:var(--accent)}
.sitefoot-mail{display:flex;flex-direction:column;gap:.3rem;flex:0 1 320px}
.sitefoot-mailrow{display:flex;gap:.4rem}
.sitefoot-mailrow input[type=email]{flex:1 1 auto;min-width:0}
.sitefoot-copy{margin:1rem 0 0;text-align:center}
.hp{position:absolute!important;left:-9999px!important;width:1px;height:1px;opacity:0}
.todo{display:inline-block;font-size:.66rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:.1rem .4rem;
  border-radius:4px;border:1px dashed var(--maybe);color:var(--maybe);vertical-align:middle}
.pricegrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1rem;margin-bottom:1rem}
.pricecard .price{font-size:1.8rem;font-weight:800;margin:.2rem 0 .6rem;color:var(--accent)}
.pricecard ul{margin:0;padding-left:1.1rem;line-height:1.7}
.pricecard.featured{border-color:var(--accent)}
.legal h2{font-size:1.05rem;margin:1.1rem 0 .3rem}
.legal h2:first-child{margin-top:0}
@media (max-width:820px){
  .sitefoot{margin-top:1.5rem;padding:1rem .2rem calc(8.5rem + env(safe-area-inset-bottom))}
  [data-navpos="left"] .sitefoot{padding:1rem .8rem 4rem calc(84px + env(safe-area-inset-left))}
  [data-navpos="right"] .sitefoot{padding:1rem calc(84px + env(safe-area-inset-right)) 4rem .8rem}
  .sitefoot-mail{flex:1 1 100%}
}

/* Notification settings (notifications page) */
.notifsettings>summary{cursor:pointer}
.notifsettings[open]>summary{margin-bottom:.6rem}
.notifcat{align-items:flex-start;gap:.55rem}
.notifcat input{margin-top:.25rem}

/* Customize bottom bar (nav-edit.ejs) */
.navedit{list-style:none;margin:0;padding:0;counter-reset:ne}
.navedit li{display:flex;align-items:center;gap:.6rem;padding:.5rem .6rem;border:1px solid var(--line);border-radius:10px;margin-bottom:.4rem;background:var(--bg3)}
.navedit .ne-icon{font-size:1.2rem;width:1.6rem;text-align:center}
.navedit .ne-label{flex:1 1 auto}
.navedit .ne-slot{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.navedit li:nth-child(-n+4){border-color:var(--accent)}
.navedit li:nth-child(-n+4) .ne-slot::before{content:"In the bar";color:var(--accent)}
.navedit li:nth-child(n+5) .ne-slot::before{content:"In More"}
.navedit li:nth-child(4){margin-bottom:1.1rem}
.navedit li:first-child [data-ne-move=up],.navedit li:last-child [data-ne-move=down]{visibility:hidden}
.navedit .ne-btns{display:flex;gap:.25rem}

/* Song lookup box (partials/song-lookup.ejs) */
.songlookup{border:1px dashed var(--line);border-radius:10px;padding:.6rem .7rem;background:var(--bg3)}
.songlookup .sl-row{display:flex;gap:.4rem;margin-top:.25rem}
.songlookup .sl-q{flex:1 1 auto;min-width:0}
.songlookup .sl-status{margin:.35rem 0 0}
.songlookup .sl-status:empty{display:none}
.sl-results{list-style:none;margin:.4rem 0 0;padding:0;display:flex;flex-direction:column;gap:.3rem;max-height:320px;overflow:auto}
.sl-pick{width:100%;text-align:left;background:var(--bg2);border:1px solid var(--line);border-radius:8px;padding:.45rem .6rem;color:var(--text);cursor:pointer;font:inherit}
.sl-pick:hover,.sl-pick:focus{border-color:var(--accent)}
.songlookup [data-sl-go]{white-space:nowrap;flex:0 0 auto}

/* Link hover preview (app.js) */
.linkpreview{position:fixed;z-index:120;width:280px;background:var(--bg2);border:1px solid var(--line);border-radius:10px;
  box-shadow:var(--shadow);overflow:hidden;pointer-events:none}
.linkpreview img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover;background:var(--bg3)}
.linkpreview .lp-body{display:flex;flex-direction:column;gap:.1rem;padding:.5rem .65rem;font-size:.88rem}
.linkpreview .lp-site{font-size:.68rem;text-transform:uppercase;letter-spacing:.06em;color:var(--accent);font-weight:700}
.ytthumb{position:relative;display:block;max-width:320px;margin:.4rem 0;border-radius:8px;overflow:hidden;border:1px solid var(--line)}
.ytthumb img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}
.ytthumb span{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:2rem;color:#fff;text-shadow:0 2px 8px rgba(0,0,0,.6)}

/* Campaign offer page (public/offer.ejs) */
.offercard{max-width:620px;margin:1.5rem auto}
.offercard h1{margin:.2rem 0 .5rem}
.offercard .lp-kicker{font-size:.75rem;text-transform:uppercase;letter-spacing:.08em;color:var(--accent);font-weight:700;margin:0}
.offerbig{font-size:1.25rem;font-weight:800;color:var(--accent);margin:.6rem 0}

/* Secret plans ("Make it a surprise") */
.secretopt{border:1px dashed var(--line);border-radius:10px;padding:.45rem .7rem}
.secretopt>summary{cursor:pointer;font-weight:600}
.secretopt[open]>summary{margin-bottom:.4rem}
.secretpill{background:rgba(180,120,255,.15);border:1px solid rgba(180,120,255,.45);color:#c9a7ff}

/* Note blocks (partials/note-block.ejs): band ✎ and private 🔒 notes with edit/delete */
.setnotescard{padding:.7rem .9rem}
.noteblock{display:flex;flex-direction:column;gap:.3rem;grid-column:1/-1;margin-top:.2rem}
.noteblock-h{margin:0 0 .2rem;font-size:.95rem}
.noterow{display:flex;align-items:flex-start;gap:.45rem;font-size:.85rem;color:var(--accent);flex-wrap:wrap}
.noterow.mine .notetext{font-style:italic}
.noterow .notetext{flex:1 1 auto;min-width:0;overflow-wrap:anywhere;white-space:pre-line}
.noterow .noteacts{display:flex;align-items:center;gap:.35rem;flex:0 0 auto}
.noteedit-inline>summary,.noteadd>summary{list-style:none;cursor:pointer}
.noteedit-inline>summary::-webkit-details-marker,.noteadd>summary::-webkit-details-marker{display:none}
.noteedit-inline[open]{flex-basis:100%}
.noterow:has(.noteedit-inline[open]){flex-direction:column;align-items:stretch}
.noteedit-inline form,.noteadd form{margin-top:.35rem;max-width:560px}
.noteadd>summary{font-size:.8rem;color:var(--muted)}
.noteadd>summary:hover{color:var(--accent)}

/* Pricing: struck-out prices under a FREE stamp; add-ons say Coming soon */
.pricewrap{position:relative;display:inline-block;padding-right:1rem}
.pricecard .price s{text-decoration-thickness:3px;text-decoration-color:var(--out);opacity:.75}
.freestamp{position:absolute;right:-1.4rem;top:.1rem;transform:rotate(-14deg);border:3px solid var(--out);color:var(--out);
  font-weight:900;font-size:1.05rem;letter-spacing:.14em;padding:.05rem .45rem;border-radius:6px;background:rgba(0,0,0,.08);
  box-shadow:0 0 0 2px rgba(0,0,0,.05) inset;pointer-events:none}
.soonbtn{display:inline-block;flex:0 0 auto;padding:.45rem .9rem;border-radius:999px;border:2px solid var(--accent);color:var(--accent);
  font-weight:800;font-size:.82rem;letter-spacing:.02em;white-space:nowrap}
.addonlist li{align-items:center}

/* Band scope switch (dashboard): this band only / all my bands */
.scopeswitch{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .6rem;margin:.45rem 0 .2rem}
.scopelabel{font-size:.72rem;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);font-weight:700}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;background:var(--bg3);padding:3px;gap:2px}
.seg form{margin:0}
.segbtn{display:inline-flex;align-items:center;gap:.35rem;border:0;background:none;color:var(--muted);font:inherit;font-size:.85rem;font-weight:600;
  padding:.35rem .8rem;border-radius:999px;cursor:pointer;white-space:nowrap}
.segbtn:hover{color:var(--text)}
.segbtn.on{background:var(--accent);color:var(--accent-ink,#14110e);box-shadow:0 1px 4px rgba(0,0,0,.25)}
.segbtn.on .dot{box-shadow:0 0 0 2px rgba(255,255,255,.6)}
.scopehelp{flex:1 1 100%}
.setlist-list .sldur{flex:0 0 3.6rem;font-family:var(--mono);font-weight:700;color:var(--accent);font-size:.9rem;text-align:right;padding-right:.4rem}
.archivedcamps{margin-top:1rem}.archivedcamps>summary{cursor:pointer;font-weight:600;color:var(--muted)}
.faqacts{display:flex;flex-wrap:wrap;gap:.45rem;margin:.6rem 0 0}
.giftmsg{margin:.6rem 0;padding:.5rem .8rem;border-left:3px solid var(--accent);background:var(--bg3);border-radius:0 8px 8px 0;font-style:italic}

/* Files & photos */
.assetgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:.8rem}
.assetcard{background:var(--bg3);border:1px solid var(--line);border-radius:10px;overflow:hidden;min-width:0;display:flex;flex-direction:column}
.assetcard img{display:block;width:100%;height:130px;object-fit:cover;background:var(--bg2)}
.pdfthumb{display:flex;align-items:center;justify-content:center;height:130px;background:var(--bg2);color:var(--muted);font-family:var(--mono,monospace);font-weight:800;font-size:1.4rem;text-decoration:none}
.assetmeta{padding:.55rem .65rem;display:flex;flex-direction:column;gap:.25rem;min-width:0}
.assetmeta b{overflow-wrap:anywhere}
.assetbtns{display:flex;gap:.6rem;align-items:center;flex-wrap:wrap}
.assetedit summary{cursor:pointer;list-style:none}
.assetedit[open]{flex-basis:100%}

/* Tours */
.tourtiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.6rem;margin-bottom:1rem}
.tourtiles .tile{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:.7rem .85rem;min-width:0}
.tourtiles .tile b{display:block;font-size:1.5rem;font-family:var(--mono,monospace);color:var(--accent);line-height:1.1}
.tourtiles .tile span{display:block;margin-top:.2rem;color:var(--muted);font-size:.82rem}
.nextup{border-color:var(--accent)}
.tourlinks{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.6rem}
.tourstops{display:flex;flex-direction:column}
.tourdrive{padding:.3rem 0 .3rem 3.4rem}
.tourstop{display:flex;gap:.8rem;background:var(--bg3);border:1px solid var(--line);border-radius:10px;padding:.65rem .75rem}
.tourstop.today{border-color:var(--accent)}
.tourstop.st-pending,.tourstop.st-hold{border-style:dashed}
.tourstop.st-off{opacity:.8}
.tsdate{flex:none;width:2.6rem;text-align:center;line-height:1.1}
.tsdate .dow,.tsdate .mon{display:block;font-size:.66rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.tsdate b{display:block;font-size:1.35rem;font-family:var(--mono,monospace)}
.tsbody{min-width:0;flex:1;display:flex;flex-direction:column;gap:.15rem}
.tshead{display:flex;gap:.45rem;align-items:center;flex-wrap:wrap}
.tsbtns{display:flex;gap:.8rem;align-items:center;flex-wrap:wrap}
.tsedit summary{cursor:pointer;list-style:none;margin-top:.2rem}
.tsedit[open]{margin-top:.4rem}

/* names that link to a profile */
a.plink { color: inherit; text-decoration: none; }
a.plink:hover, a.plink:focus-visible { text-decoration: underline; }

/* pricing matrix: features down the side, plans across the top, one plan recommended */
.pm-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
.pricematrix{width:100%;min-width:560px;border-collapse:separate;border-spacing:0;background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius)}
.pricematrix th,.pricematrix td{padding:.6rem .7rem;text-align:center;border-bottom:1px solid var(--line);vertical-align:middle}
.pricematrix .pm-feat{text-align:left;font-weight:500;position:sticky;left:0;background:var(--bg2);min-width:11rem;z-index:1}
.pricematrix thead th{vertical-align:top;border-bottom:2px solid var(--line)}
.pricematrix .pm-name{font-weight:700;font-size:1.05rem}
.pricematrix .pm-price{font-size:1.9rem;font-weight:800;color:var(--accent);line-height:1.2}
.pricematrix .pm-price s{text-decoration-thickness:3px;text-decoration-color:var(--out);opacity:.75}
.pricematrix .pm-free{display:inline-block;margin:.25rem 0;padding:.05rem .45rem;border:2px solid var(--out);border-radius:6px;color:var(--out);font-weight:800;font-size:.72rem;letter-spacing:.06em;transform:rotate(-3deg)}
.pricematrix .pm-tnote{margin-top:.3rem}
.pricematrix .pm-rec{background:rgba(245,166,35,.09);border-left:2px solid var(--accent);border-right:2px solid var(--accent)}
.pricematrix thead .pm-rec{border-top:2px solid var(--accent);border-radius:10px 10px 0 0}
.pricematrix tfoot .pm-rec{border-bottom:2px solid var(--accent);border-radius:0 0 10px 10px}
.pricematrix .pm-badge{display:inline-block;margin-bottom:.3rem;padding:.1rem .55rem;border-radius:999px;background:var(--accent);color:var(--accent-ink);font-weight:800;font-size:.72rem;letter-spacing:.04em;text-transform:uppercase}
.pricematrix .pm-sec th{text-align:left;background:var(--bg3);font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.pricematrix tfoot td{border-bottom:0;padding-top:.9rem}
.pm-yes{color:var(--in);font-weight:800;font-size:1.15rem}
.pm-lim{color:var(--maybe);font-weight:800;font-size:1.1rem}
.pm-add{color:var(--accent);font-weight:800;font-size:1.1rem}
.pm-no{color:var(--muted);opacity:.6}
.pm-soon{color:var(--muted);font-size:.8rem;font-style:italic}
.pm-note{display:block;color:var(--muted);font-size:.78rem;margin-top:.1rem}

/* monthly / yearly switch: flat, high contrast */
.pm-wrap[data-bill="year"] .bill-month,.pm-wrap[data-bill="month"] .bill-year{display:none}
.bill-toggle{display:inline-flex;border:2px solid var(--accent);border-radius:999px;overflow:hidden;margin:.2rem 0 .5rem;background:transparent}
.bill-toggle .bt-opt{appearance:none;border:0;background:transparent;color:var(--text);font:inherit;font-weight:700;padding:.65rem 1.3rem;cursor:pointer;display:flex;flex-direction:column;align-items:center;line-height:1.15;min-width:9.5rem}
.bill-toggle .bt-opt[aria-pressed="true"]{background:var(--accent);color:var(--accent-ink)}
.bill-toggle .bt-sub,.bill-toggle .bt-save{font-size:.72rem;font-weight:700;letter-spacing:.03em}
.bill-toggle .bt-save{color:var(--in)}
.bill-toggle .bt-opt[aria-pressed="true"] .bt-save{color:var(--accent-ink)}
.bill-toggle .bt-opt[aria-pressed="false"] .bt-save{background:var(--in);color:#0d2a1b;padding:.02rem .4rem;border-radius:999px}
.bill-hint{margin:.1rem 0 .8rem;font-weight:600}
.pricematrix .pm-deal th,.pricematrix .pm-deal td{background:rgba(111,206,159,.10)}
.pricematrix .pm-deal .pm-rec{background:rgba(245,166,35,.14)}
.pm-switch{display:inline-block;font-weight:800;color:var(--accent);text-decoration:underline;text-underline-offset:3px}

/* Platform task levels and the small meta row under each platform task */
.ptaskmeta{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;flex-basis:100%;margin-top:.2rem}
.ptaskmeta form{margin:0}
.pill.lvl{text-transform:uppercase;font-size:.68rem;letter-spacing:.03em}
.pill.lvl-urgent{background:#c0392b;color:#fff}
.pill.lvl-high{background:#b35400;color:#fff}
.pill.lvl-low{color:var(--muted)}
.ptasklevel summary{cursor:pointer;list-style:none}

.blockednote{color:var(--muted,#888);margin:.2rem 0}
.holdsnote{margin:.2rem 0;color:var(--accent)}
.flexfull{flex-basis:100%}
.catpill{font-size:.68rem;text-transform:uppercase;letter-spacing:.03em}
.depbox{max-height:11rem;overflow:auto;border:1px solid var(--line,#ddd);border-radius:6px;padding:.3rem .5rem;display:grid;gap:.15rem}
.ptfilters{display:flex;flex-wrap:wrap;gap:.35rem;margin:.4rem 0 .8rem}
.ptfilters a{padding:.2rem .6rem;border:1px solid var(--line,#ccc);border-radius:99px;font-size:.82rem;text-decoration:none}
.ptfilters a.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}

.tnotes{margin:.15rem 0}
.tnote{margin:.2rem 0;padding:.25rem .5rem;border-left:3px solid var(--line,#ccc)}
.tnote-done{border-left-color:var(--in,#2e9e5b)}
.tnote-blocked{border-left-color:#e67e22}
.tnoteresult{margin-top:.15rem}
.tellTim textarea{width:100%}

#dashGrid .card.panelhidden h2::after{content:" · hidden";font-weight:400;font-size:.8rem;color:var(--muted)}
@media(max-width:560px){.platcard.collapsed .platlabel{display:none}.platcard.collapsed .plattoggle{min-width:44px;justify-content:center;padding:.2rem .5rem}.platcard.collapsed .platbar{gap:.4rem}}
.tclose{display:contents}
.tcloseform summary{cursor:pointer;list-style:none}
.tcloseform[open]{flex-basis:100%;order:10}
.tcloseform summary.linkbtn{display:inline;width:auto;background:none;border:0;padding:0}
.tcloseform form{max-width:30rem;text-align:left}
.tcloseform form label{display:block}
.tcloseform form{margin-top:.3rem}
.thistory ul.plain{list-style:none;margin:.3rem 0 0;padding:0}
.thistory li{padding:.2rem 0;border-top:1px solid var(--line,#ddd)}
.brandlogo{vertical-align:middle;max-height:26px;width:auto;margin-right:.3rem}
.envbadge{font-size:.65rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em;padding:.1rem .4rem;border-radius:6px;border:1px solid var(--accent);color:var(--accent);margin-left:.3rem}

/* Pricing page: cards on phones, comparison table on wider screens */
.pm-cards{display:none}
.pm-solo{margin-bottom:1rem}
.pm-card{position:relative;margin-bottom:.9rem}
.pm-card .pm-price{font-size:2rem;font-weight:800;color:var(--accent);line-height:1.2}
.pm-card-rec{border:2px solid var(--accent)}
.pm-card .pm-badge{display:inline-block;padding:.1rem .55rem;border-radius:999px;background:var(--accent);color:var(--accent-ink);font-weight:800;font-size:.72rem;letter-spacing:.04em;text-transform:uppercase}
.pm-list{margin:.4rem 0 .9rem;padding-left:1.2rem}
.pm-list li{margin:.2rem 0}
.pm-card .btn{display:block;text-align:center;width:100%;box-sizing:border-box;padding:.75rem 1rem}
@media (max-width:720px){
  .pm-cards{display:block}
  .pm-scroll{display:none}
  .bill-toggle{display:flex;width:100%}
  .bill-toggle .bt-opt{min-width:0;flex:1}
}


/* Growth: wizard, first steps, ask card, public header */
.authh1{font-size:1.25rem;margin:.2rem 0 .8rem}
.codebox summary{cursor:pointer;padding:.3rem 0}
.wizbar{list-style:none;display:flex;gap:.6rem;margin:0 0 1rem;padding:0;flex-wrap:wrap}
.wizbar li{display:flex;align-items:center;gap:.4rem;color:var(--muted);font-size:.9rem}
.wizbar li.on{color:var(--text);font-weight:700}
.wizbar .stepno{display:inline-grid;place-items:center;color:var(--muted);font-weight:700;width:26px;height:26px;border-radius:50%;border:1px solid var(--line);background:var(--bg3);font-size:.8rem;flex:0 0 auto}
.wizbar li.on .stepno{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.wizsteps li.done .stepno{background:var(--in);color:#102418}
.wizbar li.done .stepno{background:var(--in);color:#102418;border-color:var(--in)}
.wizlinks li{align-items:flex-start;gap:.8rem}
.wizqr{background:#fff;border-radius:8px;padding:4px}
.fsbar{height:6px;background:var(--bg3);border-radius:99px;overflow:hidden;margin:.6rem 0}
.fsbar span{display:block;height:100%;background:var(--accent)}
.askno{margin-top:.2rem}.askno summary{cursor:pointer;padding:.3rem 0}
@media (max-width:560px){ .topbar .hide-sm{display:none} .wizbar .wizname{display:none} .wizbar li.on .wizname{display:inline} }
/* Usability pass (U12): the install banner and the Feedback pill never sit on top of each other.
   While the banner shows, the pill steps aside (Feedback is also in More and the footer). */
body:has(.installbar) .feedbackfab{display:none}
@media (max-width:767px){
  /* U12: on a phone the pill sits just above the tab bar, away from the page's own buttons. */
  .feedbackfab{bottom:calc(64px + env(safe-area-inset-bottom));right:.6rem;padding:.35rem .8rem;min-height:36px}
}

/* Usability pass (U28, U17): footer grouped into columns with comfortable rows; 24px minimum targets. */
.sitefoot-links{display:flex;flex-wrap:wrap;gap:1rem 2.2rem;font-size:.88rem;flex:1 1 280px}
.sitefoot-col{display:flex;flex-direction:column;gap:0;min-width:120px}
.sitefoot-h{margin:0 0 .2rem;font-size:.7rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);opacity:.8}
.sitefoot-col a{display:flex;align-items:center;min-height:28px}
@media (max-width:767px){
  .sitefoot-links{display:grid;grid-template-columns:1fr 1fr;gap:.8rem 1rem}
  .sitefoot-col a{min-height:44px}
}
input[type=checkbox],input[type=radio]{width:24px;height:24px;min-width:24px;min-height:24px;accent-color:var(--accent);vertical-align:middle}
a.plink,.infobtn{display:inline-block;min-height:24px;line-height:24px;padding-top:0;padding-bottom:0}
summary{min-height:24px}
input[type=range]{min-height:24px}

/* U24: add-event form: secondary fields live under "More options". */
.moreopts{border:1px solid var(--line);border-radius:10px;padding:.2rem .8rem .6rem;margin:.4rem 0}
.moreopts>summary{cursor:pointer;padding:.6rem 0;font-weight:600;min-height:44px;display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.moreopts[open]>summary{border-bottom:1px solid var(--line);margin-bottom:.6rem}

/* U25: availability is shown with a mark as well as colour. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.availcell{position:relative}
.availcell .avmark{position:absolute;top:2px;right:4px;font-size:.62rem;font-weight:800;line-height:1;opacity:.85}
.availtable td.cell.available::after,.availtable td.cell.unavailable::after,.availtable td.cell.maybe::after{display:block;text-align:center;font-size:.62rem;font-weight:800;line-height:1;opacity:.85}
.availtable td.cell.available::after{content:"✓"}
.availtable td.cell.unavailable::after{content:"✕"}
.availtable td.cell.maybe::after{content:"~"}

/* U17 / small screens: an opened "Report" box takes its own row instead of spilling past the screen edge. */
.reportbox[open]{display:block!important}
.reportbox[open] form{max-width:100%;min-width:0!important}
.subtleinvite{min-height:24px}
a:has(>b:only-child){display:inline-block;min-height:24px;padding:2px 0}

/* U29: setlist editor "..." menu: big, well-spaced rows; Delete sits apart in red. */
.dropdown .menu .menuitem{display:flex;width:100%;align-items:center;gap:.5rem;min-height:44px;padding:.5rem .8rem;border:0;border-radius:7px;background:none;color:inherit;font:inherit;font-size:.9rem;text-align:left;cursor:pointer}
.dropdown .menu .menuitem:hover{background:var(--bg3)}
.dropdown .menu .menuitem.danger{color:var(--out);margin-top:.3rem;border-top:1px solid var(--line);border-radius:0 0 7px 7px}
.setmenu .menu{min-width:220px}
.setmenu>summary{list-style:none;min-height:36px}
.setmenu>summary::-webkit-details-marker{display:none}
@media (max-width:767px){
  .updown .linkbtn,.setctl .linkbtn,.hlbtn{min-height:32px;min-width:32px}
}
.infobtn{min-width:24px}
.linkbtn{min-height:24px}
summary.linkbtn{display:inline-flex;align-items:center;min-height:24px}

/* Profile / Account / Privacy tabs: a real tab strip (big targets, underline on the active one) that doesn't move the page. */
.acctabs{display:flex;margin:0 0 1.1rem;border-bottom:2px solid var(--line);overflow-x:auto;-webkit-overflow-scrolling:touch}
.acctabs a,.acctabs button{flex:1 1 0;min-width:0;min-height:46px;padding:.55rem .4rem;white-space:nowrap;margin:0 0 -2px;font:inherit;font-size:1rem;font-weight:800;color:var(--muted);background:transparent;border:0;border-bottom:4px solid transparent;border-radius:10px 10px 0 0;text-align:center;text-decoration:none;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:.4rem}
.acctabs a:hover,.acctabs button:hover{color:var(--text);background:var(--bg3)}
.acctabs .on{color:var(--text);background:var(--bg3);border-bottom-color:var(--accent)}
.acctabs a:focus-visible,.acctabs button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* Address block */
.addrblock{font-style:normal;line-height:1.45;margin:.1rem 0}
.addrgrid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.45rem;max-width:32rem}
.addrgrid label{display:block;font-size:.78rem;color:var(--muted);font-weight:600;margin:0}
.addrgrid label input{display:block;width:100%;max-width:none!important;margin-top:.15rem;min-height:40px}
.addrgrid .a-street{grid-column:span 4}.addrgrid .a-unit{grid-column:span 2}
.addrgrid .a-city{grid-column:span 3}.addrgrid .a-region{grid-column:span 3}
.addrgrid .a-postal{grid-column:span 2}.addrgrid .a-country{grid-column:span 4}
@media (max-width:520px){.addrgrid .a-street,.addrgrid .a-unit,.addrgrid .a-city,.addrgrid .a-region,.addrgrid .a-postal,.addrgrid .a-country{grid-column:span 6}}
.addrmap{margin-top:.6rem;max-width:32rem}
.addrmap .addrmapframe{display:none;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.addrmap.ready .addrmapframe{display:block}
.addrmap iframe{display:block;width:100%;height:220px;border:0}

/* Solo / Songwriter box */
.solobox{padding-bottom:.9rem;margin-bottom:.9rem;border-bottom:1px dashed var(--line)}
.solobox h3{margin:0 0 .25rem;font-size:1.05rem}
.solobox .own{margin:.5rem 0 0;font-size:.9rem}
.solobox .btn{min-height:40px}

/* Privacy settings page: one compact row per detail */
.privgrid{list-style:none;margin:0;padding:0}
.privgrid li{display:flex;align-items:center;gap:.6rem;padding:.35rem 0;border-bottom:1px solid var(--line)}
.privgrid li:last-child{border-bottom:0}
.privgrid .grow{min-width:0}
.privgrid select{width:auto;min-height:36px;max-width:55%}
/* ── names with icons, picture block, band logo (identity) ── */
.who{display:inline-flex;align-items:center;gap:.35rem;vertical-align:middle;max-width:100%}
a.plink.who{text-decoration:none}
.who-ic{width:20px;height:20px;border-radius:50%;object-fit:cover;flex:none;display:inline-block;border:0}
.who-dot{width:12px;height:12px;margin:0 4px}
.who-ic.lg{width:28px;height:28px}
.topavatar.who-dot{width:12px;height:12px;margin:0 6px}
img.topavatar{width:24px;height:24px}
.bandmark{width:16px;height:16px;border-radius:4px;object-fit:cover;flex:none;display:inline-block;vertical-align:middle;margin-right:.35rem}
.avatardot{display:inline-block;border:1px solid var(--line)}
.picpicker{margin-top:.5rem}
.picpicker.is-disabled{opacity:.45;filter:grayscale(.6);pointer-events:none}
.picbtns{display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}
.picpicker progress,#logoProg{width:100%;height:8px;margin-top:.4rem}
.picmsg{min-height:1.1em;margin:.3rem 0 0}
.avatarhistbtn.on,.avatarpick.on{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent)}
.avatarhistbtn:disabled{cursor:default}
.dotpicker{margin-top:.6rem}
.dotswatches{display:flex;flex-wrap:wrap;gap:.45rem;margin-top:.35rem}
.dotsw{position:relative;display:inline-flex;cursor:pointer;line-height:0}
.dotsw input{position:absolute;opacity:0;inset:0;width:100%;height:100%;margin:0;cursor:pointer}
.dotsw>span{width:32px;height:32px;border-radius:50%;border:2px solid var(--line);display:block}
.dotsw input:checked+span{border-color:var(--text);box-shadow:0 0 0 2px var(--accent)}
.dotsw input:focus-visible+span{outline:2px solid var(--accent);outline-offset:2px}
.dotcustom input{opacity:1;position:static;width:32px;height:32px;padding:0;border:2px solid var(--line);border-radius:50%;background:none}
.pendingbar{margin-top:.8rem;padding:.7rem;border:1px dashed var(--accent);border-radius:10px;display:flex;flex-direction:column;gap:.6rem}
.pendingpreview{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem}
.logoprevbox{display:flex;align-items:center;gap:.5rem;font-weight:700;font-size:1.2rem;margin-top:.3rem;width:100%}

/* Footer on desktop: three tidy blocks on one line (brand | link columns | email), same 1800px column as the page. */
@media (min-width:821px){
  .sitefoot-in{display:grid;grid-template-columns:minmax(180px,1fr) auto minmax(260px,340px);gap:1.5rem 3rem;align-items:start}
  .sitefoot-links{display:grid;grid-template-columns:repeat(3,minmax(130px,auto));gap:1rem 3rem;flex:none}
  .sitefoot-mail{flex:none}
}
.sbfilters select{width:auto;flex:0 1 220px;min-width:0}
.sitefoot-mailrow .btn{white-space:nowrap}

/* Dashboard columns (Preferences > Screen layout). Desktop only: phones keep one column.
   data-cols 0 = auto (add a column for every ~440px until every panel sits in one row), 1-6 = locked. */
@media (min-width:821px) and (min-height:501px), (min-width:821px) and (orientation:portrait){
  html[data-cols="0"] #dashGrid{grid-template-columns:repeat(auto-fit,minmax(min(100%,440px),1fr))}
  html[data-cols="1"] #dashGrid{grid-template-columns:minmax(0,1fr)}
  html[data-cols="2"] #dashGrid{grid-template-columns:repeat(2,minmax(0,1fr))}
  html[data-cols="3"] #dashGrid{grid-template-columns:repeat(3,minmax(0,1fr))}
  html[data-cols="4"] #dashGrid{grid-template-columns:repeat(4,minmax(0,1fr))}
  html[data-cols="5"] #dashGrid{grid-template-columns:repeat(5,minmax(0,1fr))}
  html[data-cols="6"] #dashGrid{grid-template-columns:repeat(6,minmax(0,1fr))}
}
.layoutform .row label{flex:0 1 18rem}

/* Platform-owner "regular view" switch: same shape as the band scope button, in the admin violet. */
.btn.adminbtn{color:#a98bff;border-color:#a98bff}
.btn.adminbtn:hover,.btn.adminbtn:focus-visible{background:rgba(169,139,255,.14)}
:root[data-theme="light"] .btn.adminbtn{color:#6a3fd6;border-color:#6a3fd6}
.pm-bump{margin-bottom:1rem;border-color:var(--accent);background:color-mix(in srgb,var(--accent) 7%,var(--bg2))}
.pm-bumplist{columns:2;column-gap:2rem;padding-left:1.1rem}
@media(max-width:700px){.pm-bumplist{columns:1}}

/* On screens wider than the site column the top bar itself stays inside the column, with the page, panels and footer. */
@media (min-width:821px){
  .topbar{border-inline:1px solid var(--line);border-radius:0 0 12px 12px}
}
.confirmword{font-family:var(--mono);letter-spacing:.08em;color:var(--danger);user-select:none;-webkit-user-select:none}

/* Floating buttons (Feedback, back to top) never sit on top of the phone navigation: clear the bottom bar, and step inside a side rail. */
@media (max-width:820px),(max-height:500px) and (orientation:landscape){
  [data-navpos="bottom"] .feedbackfab{bottom:calc(76px + env(safe-area-inset-bottom))}
  [data-navpos="bottom"] .totopfab{bottom:calc(124px + env(safe-area-inset-bottom))}
  [data-navpos="right"] .feedbackfab,[data-navpos="right"] .totopfab{right:calc(72px + env(safe-area-inset-right))}
  [data-navpos="left"] .feedbackfab,[data-navpos="left"] .totopfab{right:.6rem}
  [data-navpos="left"] .feedbackfab{bottom:1rem}
  [data-navpos="right"] .feedbackfab,[data-navpos="left"] .feedbackfab{bottom:1rem}
  [data-navpos="left"] .totopfab,[data-navpos="right"] .totopfab{bottom:4.2rem}
}
.maplink{text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px}.maplink:hover{color:var(--accent)}

/* Click-to-edit values (gear pages) and the gear profile page. */
.inl{border-bottom:1px dashed var(--muted);cursor:text;padding:0 .1em}
.inl:hover,.inl:focus-visible{border-bottom-color:var(--accent);color:var(--accent);outline:none}
.inl.empty{color:var(--muted);font-style:italic}
h1 .inl{border-bottom-width:2px}
.inl-input{font:inherit;padding:.15rem .4rem;max-width:22rem;width:min(22rem,100%)}
.gearfacts{display:grid;grid-template-columns:max-content 1fr;gap:.5rem 1.2rem;margin:0}
.gearfacts dt{color:var(--muted);font-size:.82rem;text-transform:uppercase;letter-spacing:.04em;align-self:center}
.gearfacts dd{margin:0;overflow-wrap:anywhere}
.gearbig{border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--bg3);display:flex;align-items:center;justify-content:center;min-height:200px}
a.gearbig{text-decoration:none;cursor:zoom-in}
.linkcard{display:flex;gap:.6rem;align-items:center;margin-top:.6rem;padding:.55rem .7rem;border:1px solid var(--line);border-radius:10px;text-decoration:none;color:inherit;background:var(--bg3)}
.linkcard:hover{border-color:var(--accent)}
.editpanel>summary{cursor:pointer;list-style:none;display:inline-block}
.gearbig img{max-width:100%;max-height:420px;display:block}
.gearbig.ph .gtype{font-size:1.4rem;color:var(--muted);text-transform:uppercase;letter-spacing:.1em}
.wishthumb{width:44px;height:44px;border-radius:8px;object-fit:cover;border:1px solid var(--line);flex:none}

/* ── Sonar chat (views/sonar.ejs, public/js/sonar.js) ─────────────────────────────── */
.sonarboot{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.sonar-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.sonarbox textarea{width:100%;resize:vertical;min-height:4.5rem}
.sonarbar{align-items:center;gap:.6rem;flex-wrap:wrap}
.sonarnew{margin-top:.6rem;text-align:right}
.sonarthread{display:flex;flex-direction:column;gap:1rem;margin:1rem 0}
.sx{display:flex;flex-direction:column;gap:.45rem}
.sbubble{max-width:min(46rem,86%);padding:.6rem .85rem;border-radius:14px;border:1px solid var(--line);background:var(--bg2);color:var(--text)}
.sbubble .stext{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.45}
.sbubble .smeta{display:block;margin-top:.35rem;font-size:.75rem;color:var(--muted)}
.sbubble.me{align-self:flex-end;background:var(--bg3);border-color:var(--accent);border-bottom-right-radius:4px}
.sbubble.me .smeta{text-align:right}
.sbubble.bot{align-self:flex-start;border-bottom-left-radius:4px}
.sbubble.bot .smodel{font-weight:600}
.sbubble .ssources{margin-top:.5rem;font-size:.85rem}
.sbubble .ssources ol{margin:.2rem 0 0;padding-left:1.3rem}
.sbubble .ssources a{overflow-wrap:anywhere}
.sbubble .ssnote{margin:.4rem 0 0}
.sbubble.thinking .stext{color:var(--muted);font-style:italic;animation:sonarPulse 1.4s ease-in-out infinite}
.sbubble.error{border-color:var(--out,#e2584b)}
.sbubble.error .stext{color:var(--muted)}
@keyframes sonarPulse{0%,100%{opacity:1}50%{opacity:.45}}
@media (prefers-reduced-motion:reduce){.sbubble.thinking .stext{animation:none}}
@media (max-width:480px){.sbubble{max-width:92%}}
.sonarusers td,.sonarusers th{vertical-align:middle}
.sonarusers form{margin:0}

/* ── Sonar and Platform nav chips: button-like, distinct from plain links (head.ejs, foot.ejs, solo bar, More) ── */
:root{--platform:#a98bff;--platform-soft:rgba(169,139,255,.16);--sonar:#4fd1c5;--sonar-soft:rgba(79,209,197,.16)}
:root[data-theme="light"]{--platform:#5530b8;--platform-soft:rgba(85,48,184,.12);--sonar:#0b5c55;--sonar-soft:rgba(11,92,85,.12)}
.navchip-platform{--chip:var(--platform);--chip-soft:var(--platform-soft)}
.navchip-sonar{--chip:var(--sonar);--chip-soft:var(--sonar-soft)}
.mainnav a.navchip{display:inline-flex;align-items:center;gap:.35rem;min-height:40px;padding:0 .9rem;border-radius:999px;
  border:1.5px solid var(--chip);background:var(--chip-soft);color:var(--chip);font-weight:700}
.mainnav a.navchip:hover,.mainnav a.navchip.active{background:var(--chip);color:var(--bg)}
.mainnav a.navchip:focus-visible,.tabbar a.navchip:focus-visible{outline:3px solid var(--chip);outline-offset:2px}
.tabbar a.navchip{border-radius:14px;margin:3px;min-height:44px;background:var(--chip-soft);color:var(--chip);border:1.5px solid var(--chip)}
.tabbar a.navchip.active{background:var(--chip);color:var(--bg)}
.morechips{display:grid;gap:.6rem;margin:0 0 .9rem;padding:0 0 .9rem;list-style:none;border-bottom:1px dashed var(--line)}
.morechip{display:flex;align-items:center;gap:.75rem;min-height:56px;padding:.7rem 1rem;border-radius:16px;
  border:1.5px solid var(--chip);background:var(--chip-soft);color:var(--text)}
.morechip .grow{display:flex;flex-direction:column}
.morechip b{color:var(--chip)}
.morechip:hover,.morechip:focus-visible{box-shadow:0 0 0 3px var(--chip-soft)}
.morechip:focus-visible{outline:3px solid var(--chip);outline-offset:2px}
.sonarprivate{text-align:center;padding:2rem 1rem}

/* ── What's new: change log (views/whats-new.ejs) ───────────────────────────────────────── */
.wn-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.wn-current{font-family:var(--mono);font-weight:700;color:var(--text)}
.wn-log details>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:.6rem;justify-content:space-between;border-radius:8px}
.wn-log details>summary::-webkit-details-marker{display:none}
.wn-log details>summary:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
.wn-version{border-bottom:1px solid var(--line)}
.wn-version:last-of-type{border-bottom:0}
.wn-version>summary{padding:.7rem .2rem;font-weight:700;font-size:1.02rem}
.wn-version>summary:before,.wn-day>summary:before{content:"▸";color:var(--accent);display:inline-block;transition:transform .15s;margin-right:.1rem}
.wn-version[open]>summary:before,.wn-day[open]>summary:before{transform:rotate(90deg)}
.wn-version>summary>.wn-vname{flex:1;font-family:var(--mono)}
.wn-day{margin:0 0 .5rem .6rem}
.wn-day>summary{padding:.45rem .2rem;font-weight:600}
.wn-day>summary>span:first-of-type{flex:1}
.wn-list{list-style:none;margin:.2rem 0 .4rem;padding:0}
.wn-row{display:flex;flex-wrap:wrap;align-items:center;gap:.3rem .6rem;padding:.5rem .4rem;border-top:1px solid var(--line)}
.wn-line{display:flex;align-items:center;gap:.5rem;flex:1 1 16rem;min-width:0}
.wn-title{flex:1;min-width:0}
.wn-ver{font-family:var(--mono);white-space:nowrap}
.wn-kind{font-family:var(--mono);font-size:.64rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700;padding:.2em .55em;border-radius:6px;
  border:1px solid var(--k,var(--line));color:var(--k,var(--muted));background:color-mix(in srgb,var(--k,var(--line)) 14%,transparent);white-space:nowrap}
.wn-kind-feature{--k:var(--in)}.wn-kind-fix{--k:var(--maybe)}.wn-kind-security{--k:var(--accent)}.wn-kind-tweak{--k:var(--muted)}
.wn-more{flex:0 0 auto}
.wn-log .wn-more>summary{display:inline-flex;font-size:.82rem;color:var(--accent);padding:.25rem .5rem;border:1px solid var(--line);border-radius:8px;background:var(--bg3);min-height:32px}
.wn-log .wn-more>summary:hover{border-color:var(--accent)}
.wn-more[open]{flex-basis:100%}
.wn-more[open]>.wn-body{margin-top:.5rem;padding:.7rem .8rem;border-left:3px solid var(--accent);background:var(--bg3);border-radius:8px}
.wn-body .wn-paneline{display:none}
.wn-details{margin:0 0 .5rem;white-space:pre-line}
.wn-meta{margin:0}
/* The pane: a side panel on desktop, a bottom sheet on phones. Filled from the row's .wn-body by app.js. */
dialog.wn-pane{margin:0 0 0 auto;height:100dvh;max-height:100dvh;width:min(26rem,92vw);border-radius:14px 0 0 14px;border-right:0}
dialog.wn-pane .wn-paneline{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin:0 0 .6rem}
.wn-panehead{display:flex;align-items:flex-start;justify-content:space-between;gap:.6rem}
.wn-panehead h2{font-size:1.05rem}
@media (max-width:640px){
  .wn-day{margin-left:.2rem}
  .wn-row{padding:.55rem .1rem}
  .wn-row{display:grid;grid-template-columns:auto 1fr auto;gap:.3rem .5rem}
  .wn-line{display:contents}
  .wn-title{grid-column:1/-1;order:-1}
  .wn-more{justify-self:end}
  .wn-more[open]{grid-column:1/-1;justify-self:stretch}
  dialog.wn-pane{inset:auto 0 0 0;margin:0;width:100vw;max-width:100vw;height:auto;max-height:80dvh;border-radius:16px 16px 0 0;border-right:1px solid var(--line);border-bottom:0;
    padding-bottom:env(safe-area-inset-bottom)}
}
.sitefoot-ver{font-family:var(--mono);color:inherit}
.sitefoot-ver:hover{color:var(--accent)}
dialog.wn-pane .wn-panetitle{display:none}

/* ── UI gate fixes (2026-10-04) ────────────────────────────────────────────────────────────────
   Touch screens (phones and tablets): every button, link button, chip and nav control is at least
   44 x 44 px, the size a fingertip needs (Apple HIG; the automated UI check enforces it). */
@media (pointer:coarse){
  .btn,.chip,.dowpick,.jgo,.donebtn,.feedbackfab,.morelistbtn,.panelhandle,.panelhide{min-height:44px}
  .linkbtn,.infobtn,.swatch,.panelhandle,.panelhide,.iconbtn{min-width:44px;min-height:44px}
  .linkbtn,.infobtn{display:inline-flex;align-items:center;justify-content:center}
  .iconbtn,.topright .iconbtn,.themepick>summary.iconbtn{width:44px;height:44px}
  .dropdown>summary,.topname{min-height:44px;display:flex;align-items:center}
  .topname{min-width:44px;justify-content:center}
  .mainnav a,.mainnav .navmore>summary{min-height:44px;display:inline-flex;align-items:center}
  li>a{min-height:44px}
  li>a:not([class]){display:inline-flex;align-items:center}
}
/* Phone top bar: brand + band switcher + 4 icons must fit 375px without pushing the refresh button and the
   account link off the right edge (they used to sit at 387-415px on an iPhone SE and were cut off). The icons
   lose their box so five 44px targets do not look heavy, the account link is the avatar alone, and on the
   narrowest phones the band switcher shows its colour mark only (the name is in its label and its menu). */
@media (max-width:560px){
  .topbar{gap:.35rem;padding:.35rem .5rem}
  .topright{flex:1 1 auto;min-width:0;justify-content:flex-end;column-gap:0;flex-wrap:wrap}
  .topright .iconbtn{background:transparent;border-color:transparent}
  .topright .topname{padding:0 .1rem}
  .topright .topname .topname-gear{display:none}
}
@media (max-width:430px){
  .topbar .brand .betabadge{display:none}
  .topright .dropdown:not(.right)>summary{max-width:none;min-width:44px;justify-content:center;padding:.3rem .4rem}
  .topright .dropdown:not(.right)>summary .bandpick-name{display:none}
  .topright .dropdown:not(.right)>summary .bandmark,.topright .dropdown:not(.right)>summary .dot{margin-right:0;width:20px;height:20px}
}
/* Account details: the field labels carry help text ("Nickname - what you like to be called ..."), which the
   one-line feed style cut off with "..." on a phone. Let them wrap. */
.feed.acctlist li .grow>.muted{white-space:normal;overflow:visible}
/* Calendar grid: seven equal columns that may shrink below their content's natural width, so Saturday no longer
   spills past the right edge of a 375px phone (it did at 402px). */
.availgrid{grid-template-columns:repeat(7,minmax(0,1fr))}
@media (max-width:560px){.availgrid{gap:.2rem}.availcell{padding-inline:0}}
/* Task rows on a phone: the due date / assignee / report link wrap under the title instead of running off the edge. */
@media (max-width:820px){.taskmeta{flex-wrap:wrap;white-space:normal;margin-left:0;max-width:100%;overflow:visible}}
.card code,.wrap code{overflow-wrap:anywhere}
.morechips .muted{color:var(--text)} /* readable on the tinted Sonar/Platform chips */
.showlinks{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center;margin:.5rem 0}
.bars .bar em{background:var(--bg2);padding:0 .25em;border-radius:4px} /* the count stays readable when the bar is full height */
/* Small controls on desktop still need WCAG 2.5.8's 24 x 24 px target. */
.contactlink{display:inline-block;min-height:24px;padding:.15rem 0}
@media (pointer:fine){.reorderform .linkbtn{min-width:28px;min-height:28px}}
/* Touch screens, round two (UI gate): any button or button-like link is at least 44 x 44 px, including the small
   in/out answer chips, the setlist reorder arrows, the collapse toggles and the footer links. */
@media (pointer:coarse){
  button,.btn.btn.btn,.chip,summary.btn.btn,.collbtn,.panelwide,.plattoggle,.hlbtn,.closebtn,.tmbtn,.linkbtn.tiny,.sitefoot-col a,.mainnav a.navchip,.cbtn>summary,li>a{min-width:44px;min-height:44px}
  .linkbtn.tiny{display:inline-flex;align-items:center;justify-content:center}
  .sitefoot-col a{display:flex;align-items:center}
  .tabbar a.navchip{min-width:0}
}
/* Footer on a 821-1180px screen (iPad Pro portrait, small laptop windows): three columns plus the sign-up box did not
   fit and ran 14px past the right edge; the sign-up box now takes its own row. */
@media (min-width:821px) and (max-width:1180px){
  .sitefoot-in{grid-template-columns:minmax(0,1fr) auto}
  .sitefoot-mail{grid-column:1/-1;max-width:480px}
  .sitefoot-links{grid-template-columns:repeat(3,minmax(110px,auto));gap:1rem 2rem}
}
/* Platform sign-up bars: each bar is a link, so keep it at WCAG 2.5.8's 24px minimum even with twelve on a phone. */
.bars:not(.dense) .bar{min-width:24px}
@media (max-width:560px){.bars:not(.dense){gap:.15rem}}
@media (pointer:coarse){
  button.linkbtn.linkbtn,.updown .linkbtn.linkbtn,.setctl .linkbtn.linkbtn,.reorderform .linkbtn.linkbtn,.hlbtn.hlbtn{min-width:44px;min-height:44px}
  .cbtn>summary,.taskcomments>summary{display:inline-flex;align-items:center;justify-content:center}
}
/* The floating Feedback button sits at the bottom-right of the screen; at the very bottom of a page it covered the footer's
   "Sign up" button (seen on every page at 1440x900). Extra room under the footer lets the page scroll past it. */
@media (min-width:821px){ .sitefoot{padding-bottom:5.5rem} }
/* The Sonar privacy note is information, not an error: neutral colours instead of the red .alert look. */
.alert.sonarnote{background:var(--bg2);border-color:var(--line)}

/* Sonar status: a dot plus words (never colour alone). Shapes differ too: ready = filled circle, backup = ring, down = diamond. */
.sdot{display:inline-block;width:.7em;height:.7em;vertical-align:baseline;flex:none;box-sizing:border-box}
.sdot-ready{border-radius:50%;background:var(--in)}
.sdot-backup{border-radius:50%;border:2px solid var(--maybe);background:transparent}
.sdot-down{background:var(--out);transform:rotate(45deg) scale(.85)}
.sdot-unknown{display:none}
.sonarstatus{margin-bottom:.8rem}
.sonarchip{display:inline-flex;align-items:center;gap:.5rem;margin:0 0 .4rem;padding:.35rem .8rem;border:1px solid var(--line);border-radius:999px;font-weight:600;color:var(--text);background:var(--bg2)}
.sonarchip .sdot{width:.8em;height:.8em}
.navchip .sdot,.tabbar .sdot{width:.55em;height:.55em;margin-left:.15em}
.tabbar .tl .sdot{margin-left:.1em}
.navchip .sdot,.tabbar .sdot,.morechip .sdot{box-shadow:0 0 0 1.5px rgba(0,0,0,.6)}

/* ── Phone top bar and band header, 2026-10-05 (Aaron, iPhone 16 Pro Max screenshot) ─────────────────────────
   Root cause 1: the "icons only" rules stopped at 430px, but newer big phones are 440px wide (iPhone 16/17 Pro Max), so
   they got the BETA badge, the band name and a wrapping second row with a stray refresh button.
   Root cause 2: the band name and the Show my bands / Show platform buttons shared one row, squeezing the name to "198 / 0D".
   Fix: phone rules now apply up to 480px, the bar never wraps, refresh is dropped on phones (kept in an installed app, which has no
   browser reload), and the scope buttons sit under the band name. */
.bandnameline{flex-direction:column;align-items:flex-start;gap:.5rem}
.bandnameline .bandpick{max-width:100%}
.scoperow{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}
.scoperow .scopeform{flex:0 0 auto;margin:0}
@media (max-width:560px){
  .topbar{flex-wrap:nowrap;overflow:hidden}
  .topright{flex-wrap:nowrap;row-gap:0}
  .brand{min-width:0;flex:0 1 auto;white-space:nowrap}
}
@media (max-width:480px){
  .topbar .brand .betabadge,.topbar .brand .tag,.topbar .brand .envbadge{display:none}
  .topright .dropdown:not(.right)>summary{max-width:none;min-width:44px;justify-content:center;padding:.3rem .4rem}
  .topright .dropdown:not(.right)>summary .bandpick-name{display:none}
  .topright .dropdown:not(.right)>summary .bandmark,.topright .dropdown:not(.right)>summary .dot{margin-right:0;width:20px;height:20px}
  .topright .refreshbtn{display:none}
}
/* Only a REAL installed app (class set by theme.js from navigator.standalone) gets the button back; a browser tab never does. */
@media (max-width:480px){html.gr-standalone .topright .refreshbtn{display:inline-flex}}
@media (max-width:380px){
  .brand{font-size:.95rem;gap:.35rem}
  .topbar{padding:.35rem .3rem;gap:.2rem}
}

/* ── Public site width rules (Trello aRpyzwRc) ─────────────────────────────────────────────────────────────────
   The copy column is 1080px (the same as the front page). The top bar is a little wider than the copy (copy + 120px),
   and the footer is exactly as wide as the top bar. Below that width everything simply fills the screen. */
:root{--pub-copy:1080px;--pub-bar:1200px}
body.publicpage .wrap{max-width:var(--pub-copy)}
body.publicpage .topbar,body.publicpage .lp-head,body.publicpage .sitefoot{max-width:var(--pub-bar);margin-inline:auto;width:100%}
body.publicpage .lp-head{box-sizing:border-box}
@media (min-width:821px){
  body.publicpage .lp-head{border-inline:1px solid var(--line);border-radius:0 0 12px 12px}
}

/* Drag to reorder tabs (Trello BPaoH0yl): grip on the Customize page, drag feedback on the top bar, divider between Sonar and Platform. */
.navedit .ne-grip{cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;color:var(--muted);font-size:1.2rem;padding:.2rem .35rem;min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
.navedit .ne-grip:active{cursor:grabbing}
.navedit li.dragging{opacity:.75;border-style:dashed;box-shadow:var(--shadow)}
.mainnav a.navdragging{opacity:.5;outline:1px dashed var(--accent);outline-offset:2px}
.mainnav a[data-nav-path]{cursor:grab}
.mainnav a.navchip-platform{position:relative;margin-left:.7rem}
.mainnav a.navchip-sonar + a.navchip-platform::before{content:"";position:absolute;left:-.5rem;top:18%;bottom:18%;border-left:1px solid var(--muted);opacity:.6}

/* Sales on the public pricing page (Trello dIlX1Og6): regular price crossed out, sale price in red. */
.pm-price s.was{color:var(--muted);font-size:.6em;font-weight:500;text-decoration:line-through;text-decoration-thickness:2px;margin-right:.15em}
.pm-price .sale-now{color:var(--sale,#e2584b);font-weight:800}
:root[data-theme="light"]{--sale:#b3261e}
.sale-note{margin:.25rem 0 .4rem;font-size:.85rem;color:var(--sale,#e2584b)}
.sale-note .small{color:var(--muted)}

/* ── Live updates (public/js/live.js) ───────────────────────────────────────────────────────────────────────── */
.livechip{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(env(safe-area-inset-bottom,0px) + 5.5rem);z-index:60;min-height:44px;padding:.55rem 1rem;border-radius:999px;
  border:1px solid var(--accent);background:var(--bg2);color:var(--text);font:inherit;font-weight:600;box-shadow:var(--shadow);cursor:pointer}
.livechip:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
@keyframes livenew{from{background-color:rgba(245,166,35,.35)}to{background-color:transparent}}
.live-new{animation:livenew 2.4s ease-out 1}
@media (prefers-reduced-motion:reduce){.live-new{animation:none;outline:2px solid var(--accent)}}

/* ── "+ New venue" on the gig form (views/shows.ejs, public/js/venue-picker.js) ─────────────────────────────── */
.venuepickrow{display:flex;gap:.6rem;align-items:flex-end;flex-wrap:wrap}
.venuepickrow .grow{flex:1 1 14rem}
.venuenewbtn{min-height:44px;white-space:nowrap}
dialog.venuedlg{width:min(34rem,94vw);max-height:92vh;overflow:auto}
.venuedlg-actions{display:flex;gap:.5rem;position:sticky;bottom:0;background:var(--bg2);padding:.6rem 0 .2rem}
.venuedlg-actions .btn{min-height:44px}
.venuedlg input,.venuedlg textarea{width:100%;font:inherit}
.venueboot{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
@media (max-width:640px){
  /* a full-screen sheet on phones */
  dialog.venuedlg{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0;border-radius:0;border:0;inset:0}
}

/* ── Gear page: collapsible blocks, one-row carousels, see-all grid, in-pane details ─────────────── */
.pagehead-actions{display:flex;gap:.5rem;flex-wrap:wrap}
.gblock{margin-bottom:1rem;min-width:0}
.gblock-head{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.gblock-toggle{display:flex;align-items:center;gap:.5rem;flex:1 1 auto;min-width:0;min-height:44px;background:none;border:0;color:inherit;text-align:left;cursor:pointer;padding:0}
.gblock-toggle h2{margin:0}
.gblock-caret{font-size:1.1rem;color:var(--muted);width:1rem}
.gblock-seeall{min-height:44px;order:3}
.gblock-hint{margin:.1rem 0 .5rem}
.gcar{position:relative;min-width:0}
.gcar-track{display:flex;gap:.7rem;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;padding:.2rem .1rem .6rem;-webkit-overflow-scrolling:touch;scrollbar-width:thin;min-width:0}
.gcar-track:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.gcar-track>.gcard{flex:0 0 min(220px,72vw);scroll-snap-align:start}
.gcar-arrow{position:absolute;top:40%;transform:translateY(-50%);z-index:2;width:44px;height:44px;border-radius:50%;border:1px solid var(--line);background:var(--bg2);color:var(--text);font-size:1.5rem;line-height:1;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.35)}
.gcar-arrow:disabled{opacity:0;pointer-events:none}
.gcar-prev{left:-.3rem}.gcar-next{right:-.3rem}
.gcard{background:var(--bg3);border:1px solid var(--line);border-radius:10px;overflow:hidden;display:flex;flex-direction:column;min-width:0}
.gcard-photo{height:130px;background:var(--bg);display:flex;align-items:center;justify-content:center;overflow:hidden}
.gcard-photo img{width:100%;height:100%;object-fit:cover}
.gcard-photo.ph .gtype{font-family:var(--mono);text-transform:uppercase;letter-spacing:.1em;color:var(--muted);font-size:.8rem}
.gcard-body{padding:.6rem;display:flex;flex-direction:column;gap:.2rem;flex:1}
.gcard-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gcard-sub{color:var(--muted);font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gcard-price{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;min-height:44px}
.gcard-link,.gcard-actions .btn{min-height:44px;display:inline-flex;align-items:center}
.gcard-actions{display:flex;gap:.4rem;flex-wrap:wrap;margin-top:auto}
.gcard-out{color:var(--accent)}
.gall-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:.9rem}
@media (max-width:640px){.gall-grid{grid-template-columns:1fr 1fr}}
.gdetail-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);gap:1rem}
@media (max-width:700px){.gdetail-cols{grid-template-columns:1fr}}
.gdetail-actions{display:flex;gap:.5rem;flex-wrap:wrap;margin:.7rem 0}
.gdetail-actions .btn,.gdetail .btn.sm{min-height:44px}
.gdetail summary{min-height:44px;display:flex;align-items:center}

/* Footer "Safety and reporting" box (partials/site-footer.ejs) */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* Card #278: one compact link with an icon; opens in place into the full box. */
.sitefoot-safety{margin:1rem 0 0;color:var(--text)}
.sfs-sum{display:inline-flex;align-items:center;gap:.45rem;min-height:44px;padding:0 .2rem;cursor:pointer;list-style:none;color:var(--accent);font-weight:700;font-size:.95rem;text-decoration:underline;text-underline-offset:3px;border-radius:8px}
.sfs-sum::-webkit-details-marker{display:none}
.sfs-sum::marker{content:""}
.sfs-sum:hover{filter:brightness(1.1)}
.sfs-sum:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sfs-icon{flex:none;color:var(--accent)}
.sfs-title{color:inherit}
.sfs-chev{width:.5rem;height:.5rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);margin:-.2rem 0 0 .15rem;transition:transform .15s}
.sfs-det[open] .sfs-chev{transform:rotate(-135deg);margin-top:.2rem}
.sfs-body{margin:.4rem 0 0;padding:.9rem 1.1rem;border:2px solid var(--accent);border-radius:12px;background:var(--bg2)}
.sfs-18{margin:0;font-size:.92rem}
.sfs-lead{margin:.6rem 0 .5rem;color:var(--muted)}
.sfs-links{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:0 1.4rem;font-size:.9rem}
.sfs-links a{display:flex;align-items:center;min-height:44px;color:var(--text);text-decoration:underline;text-underline-offset:2px}
.sfs-links a:hover,.sfs-links a:focus-visible{color:var(--accent)}
.sfs-links a.sfs-primary{font-weight:700}
.sfs-emerg{margin:.4rem 0 0;color:var(--muted)}
@media (prefers-reduced-motion:reduce){.sfs-chev{transition:none}}
@media (max-width:820px){.sfs-body{padding:.9rem .8rem}.sfs-links{grid-template-columns:1fr}}

/* Account > Mobile navigation is the first card on a phone and not shown on a desktop screen (Aaron 2026-10-06). */
@media (min-width:821px){.mobnavcard{display:none}}

/* Who's around: member days use the same three stacked layers as the calendar (morning on top, afternoon, evening below);
   the whole-band row stays one solid colour because it has no part-of-day answer. */
.availtable td.cell.hasthirds{position:relative;background:var(--bg3)}
.availtable td.cell .thirds{position:absolute;inset:0;display:flex;flex-direction:column;overflow:hidden;z-index:0;pointer-events:none}
.availtable td.cell .thirds i{flex:1;background:transparent}
.availtable td.cell .thirds i+i{border-top:1px solid rgba(128,128,128,.22)}
.availtable td.cell.available .thirds i.on{background:rgba(111,206,159,.40)}
.availtable td.cell.unavailable .thirds i.on{background:rgba(226,88,75,.40)}
.availtable td.cell.hasthirds::after{position:relative;z-index:1}
/* The item an alert pointed at (see initAlertTarget in app.js): a ring that fades after a few seconds. Not on :target, so it also works after a page swap. */
.alert-target{outline:3px solid var(--accent);outline-offset:3px;border-radius:10px;scroll-margin-top:calc(var(--topbar-h,64px) + 12px)}
@media (prefers-reduced-motion:no-preference){.alert-target{animation:alertflash 4.5s ease-out 1}@keyframes alertflash{0%,60%{outline-color:var(--accent);background-color:color-mix(in srgb,var(--accent) 18%,transparent)}100%{outline-color:transparent;background-color:transparent}}}
/* Ticket #93: tap/click tooltip on the Who's around icons (birthday, holiday). */
.availtable .tipicon{display:inline;cursor:pointer;border-radius:4px}
.availtable td.bdaycell .tipicon{display:block;width:100%;line-height:24px}
.availtable .tipicon:focus-visible{outline:2px solid var(--accent)}
.icontip{position:fixed;z-index:1000;max-width:min(260px,calc(100vw - 16px));background:var(--bg2);color:var(--text);border:1px solid var(--accent);border-radius:8px;padding:.4rem .6rem;font-size:.8rem;line-height:1.3;box-shadow:0 4px 14px rgba(0,0,0,.35);pointer-events:none}
