/* Uses the same semantic palette in Day and Night. */
.notification-button{position:relative;flex:0 0 42px}.notification-button svg{width:23px;height:23px;fill:none;stroke:currentColor;stroke-width:1.8}.notification-button span:not(:empty){position:absolute;right:0;top:0;min-width:16px;border-radius:20px;padding:0 4px;font-size:10px;color:var(--primary-ink);background:var(--accent-fill)}
.add-action{width:auto;min-width:44px;padding:9px 15px;font-size:15px;border-radius:12px}.creation-tabs{margin:0 0 24px;display:grid;grid-template-columns:1fr 1fr}.creation-tabs button{min-height:46px}.caught-up{color:var(--muted);font-size:13px;margin:0 0 15px}.attention-banner{border:1px solid var(--mine-border);background:var(--accent-surface);border-radius:16px;margin:0 0 22px}.attention-link{display:flex;justify-content:space-between;align-items:center;width:100%;text-align:left;padding:16px;background:transparent;border:0;border-radius:16px;gap:12px;color:var(--text)}.attention-link small,.enquiry-card small,.venue-result small,.notification-link small{display:block;font-size:12px;color:var(--muted);margin-top:4px}.attention-link>span:last-child{white-space:nowrap;font-weight:700;color:var(--accent)}
.enquiry-card{display:block;text-align:left;width:100%;margin:0 0 12px;padding:18px;border:1px solid var(--line2);background:var(--panel);color:var(--text);border-radius:16px}.enquiry-card:hover{background:var(--hover)}.enquiry-card-head,.enquiry-card-foot{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}.enquiry-card-head strong{font-size:17px}.enquiry-card-foot{margin-top:14px;font-size:12px;line-height:1.5}.enquiry-badge{display:inline-block;font-size:10px;font-weight:800;letter-spacing:.08em;border:1px solid var(--info);color:var(--info);padding:4px 7px;border-radius:6px;white-space:nowrap}.deadline-row{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0 0}.deadline{font-size:12px;color:var(--muted)}.deadline.due{color:var(--warn);font-weight:600}.enquiry-date{padding:18px 0;border-top:1px solid var(--line)}.enquiry-date-head{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between}.enquiry-date h3{font-size:16px;margin:0}.enquiry-date-summary{font-size:11px;white-space:normal;color:var(--muted)}.enquiry-date-summary.bad{color:var(--bad)}.enquiry-date-summary.good{color:var(--good)}.enquiry-date-summary.wait{color:var(--warn)}.enquiry-date-summary.dep{color:var(--warn)}.enquiry-date-summary.cover{color:var(--cover)}.enquiry-own-row{display:flex;align-items:center;gap:9px;font-size:12px;margin:14px 0 8px}.enquiry-own-row img{border-radius:50%;background:var(--avatar-base);object-fit:cover}.available-after{display:flex;align-items:center;gap:12px;margin:10px 0}.available-after label{font-size:12px;margin:0;flex:1}.available-after input{max-width:140px;min-width:0}.enquiry-save-state{font-size:12px;color:var(--muted);margin:8px 0 0;min-height:18px}.bulk-enquiry{padding:14px 0}.bulk-enquiry summary{cursor:pointer;font-size:13px}.sub-actions:empty,.deadline-row:empty{display:none}.sub-actions .primary{font-size:15px}.stack-actions{display:grid;gap:10px;margin:14px 0}.stack-actions>button,.stack-actions>a{display:block;text-align:left;min-height:46px;white-space:normal;padding:12px 14px;border-radius:10px}.stack-actions>a{border:1px solid var(--line2);color:var(--text);text-decoration:none}.sticky-actions{position:sticky;bottom:-1px;background:var(--panel);padding:12px 0 calc(12px + env(safe-area-inset-bottom));z-index:2}.sticky-actions>button{width:100%}.history-date{display:flex;gap:12px;justify-content:space-between;align-items:center;font-size:12px;padding:10px 0;border-bottom:1px solid var(--line);flex-wrap:wrap}
.venue-result{display:block;width:100%;text-align:left;padding:12px;margin:5px 0;border:1px solid var(--line);border-radius:10px;background:var(--panel2);color:var(--text);min-height:48px}.venue-result strong{display:block}.venue-suggestions:not(:empty){padding:4px 0 14px}.venue-suggestions .section-label{margin:9px 0 4px}.attribution{font-size:10px;color:var(--muted)}.attribution a{color:inherit}.add-date-row{display:grid;grid-template-columns:1fr auto;gap:10px;align-items:end}.add-date-row .field{margin:0}.add-date-row button{min-height:46px;margin-bottom:1px}.candidate-entry{display:flex;align-items:center;gap:10px;padding:12px 0;border-bottom:1px solid var(--line)}.candidate-entry>div{flex:1;min-width:0}.candidate-entry strong{font-size:14px}.candidate-entry input{margin-top:0;font-size:14px}.check-label{display:flex;align-items:center;gap:10px;min-height:44px;font-size:14px;cursor:pointer}.check-label input{width:20px;height:20px;flex:0 0 20px;margin:0}.extras-choices{border:0;margin:14px 0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:2px 12px}.extras-choices legend{font-size:13px;color:var(--muted);margin-bottom:8px}.personal-tools{margin-top:24px}.gig-day{margin:0 0 24px;border-color:var(--good-border);background:var(--good-surface)}.gig-day h2,.gig-day h3{font-size:24px;line-height:1.2;margin:12px 0}.arrival-hero{display:flex;align-items:baseline;gap:14px;font-size:15px;margin:12px 0}.arrival-hero strong{font-size:34px;font-variant-numeric:tabular-nums}.venue-contact,.venue-notes{border-top:1px solid var(--line);padding-top:16px;margin-top:16px}.notification-row{border-bottom:1px solid var(--line);padding:12px 0}.notification-row.urgent{border-left:3px solid var(--bad);padding-left:12px}.notification-link{display:block;border:0;background:transparent;color:var(--text);text-align:left;padding:7px 0;width:100%;min-height:44px}.notification-link strong{font-size:14px}.feedback-item{border-bottom:1px solid var(--line);padding:18px 0}.feedback-item small{display:block;overflow-wrap:anywhere;color:var(--muted);font-size:11px}.gig-notes,.venue-notes dd{white-space:pre-wrap;overflow-wrap:anywhere}select{width:100%;min-height:46px;border:1px solid var(--line2);border-radius:9px;padding:10px;background:var(--input-surface);color:var(--text);font:inherit}.form-grid>div{min-width:0}fieldset{min-width:0}.action-dialog{max-height:calc(100dvh - 24px);padding-bottom:calc(20px + env(safe-area-inset-bottom))}.toast button{min-height:44px;margin-left:8px}
@media(max-width:600px){.topbar{gap:4px}.account-area{gap:4px}.account-area .sync-pill{display:none}.brand{gap:5px}.brand span{font-size:19px}.notification-button{flex-basis:36px;width:36px;min-width:36px}.enquiry-card{padding:15px}.enquiry-card-head strong{font-size:16px}.enquiry-card-foot{display:block}.enquiry-card-foot .ready{display:block;margin-top:5px}.add-date-row{grid-template-columns:1fr}.add-date-row button{width:100%;margin:0 0 4px}.extras-choices{grid-template-columns:1fr}.enquiry-response .quick-controls button{font-size:12px;min-height:54px;padding:8px 3px}.enquiry-date .sub-actions button{font-size:12px}.action-dialog{max-width:calc(100vw - 16px);margin:8px auto}.venue-notes dt{max-width:110px}.gig-details dd{overflow-wrap:anywhere}.enquiry-card-head{gap:6px}}
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}

.creation-tabs button[aria-pressed=true]{background:var(--accent-fill);color:var(--primary-ink)}
@media(max-width:600px){.account-area{display:flex;align-items:center}.topbar{align-items:center;min-height:70px}.account-area .account-button{width:42px;height:42px}.notification-button{padding:6px}}

select:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* Beta 4: consistent member artwork and static form actions. */
.member-mark,.member-avatar,.enquiry-own-row img,#accountIcon .member-mark{border-radius:50%;}
.member-mark{border-style:solid;overflow:visible;}.member-mark img,.member-avatar{border-radius:50%;object-fit:cover;}
.response-symbol{border-radius:50%;}.response-save{position:static;bottom:auto;box-shadow:none;margin-top:18px;}
.owner-response-row{display:flex;gap:10px;align-items:center;padding:10px 0;border-bottom:1px solid var(--line);}.owner-response-row>span{flex:1;}.owner-response-row small{display:block;line-height:1.5;}
.provenance{font-size:12px;color:var(--muted);line-height:1.6;margin-top:12px;}.password-fallback{margin:14px 0;}.password-fallback input{width:100%;margin:6px 0 12px;}.password-fallback summary{cursor:pointer;}
.cell-status{font-size:10px;letter-spacing:0;text-transform:none;}
.action-dialog{max-height:calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 24px);}.action-dialog input,.action-dialog select,.action-dialog textarea{font-size:16px;}@media(max-width:600px){.owner-response-row{flex-wrap:wrap;}.owner-response-row button{min-height:44px;}.action-dialog{width:calc(100% - 16px);}}

/* Member identity is the disc; availability is only the outer ring. */
[data-member="steve"]{--member-color:#6478d7;--member-filter:hue-rotate(28deg)}
[data-member="jon"]{--member-color:#ac78cc;--member-filter:hue-rotate(82deg)}
[data-member="colin"]{--member-color:#c19368;--member-filter:hue-rotate(190deg)}
[data-member="nick"]{--member-color:#6b9eb5;--member-filter:hue-rotate(350deg)}
[data-member="emma"]{--member-color:#ce8faf;--member-filter:hue-rotate(125deg)}
.member-mark,.member-mark.mini,.member-mark.small,.month-cell .member-mark.mini,#accountIcon .member-mark,.member-avatar,.enquiry-own-row img{border-radius:50%;background:var(--member-color,#6478d7);}
.member-mark{border:2px solid transparent;padding:1px;overflow:hidden;box-shadow:none;}
.member-mark img{border-radius:50%;object-fit:cover;transform:scale(1.18);filter:var(--member-filter,none);}
.member-avatar,.enquiry-own-row img{filter:var(--member-filter,none);object-fit:cover;}
.member-mark.available{border:2px solid var(--good)}
.member-mark.maybe{border:2px dashed var(--warn)}
.member-mark.unavailable{border:2px solid var(--bad);background:var(--member-color,#6478d7)}
.member-mark.unavailable img{filter:var(--member-filter,none);opacity:1}
/* h44 · A role icon a member picked is shown exactly as it looks in My icon: the per-member hue-rotate above is tuned
   for each member's original photo and would turn a picked icon's ring another colour. Originals keep their tint. */
.member-mark img[data-role-icon],img.member-avatar[data-role-icon],.enquiry-own-row img[data-role-icon]{filter:none}
.member-mark.unknown{border:2px dotted var(--muted)}
.member-mark.conditional{border:3px double var(--warn)}
.member-mark.identity{border:0;padding:0}
.member-mark.unavailable::after{content:none}
.response-symbol{display:none}
.agenda-title,.agenda-venue,.agenda-lifecycle,.agenda-summary{display:block;overflow-wrap:anywhere}
.agenda-venue{font-size:13px;color:var(--muted);margin-top:4px}
.agenda-lifecycle{font-size:11px;color:var(--muted);margin:5px 0 8px}
.agenda-summary{font-size:11px;color:var(--muted);margin-top:7px}
.agenda-body{min-width:0}.agenda-tail:empty{display:none}
.field{margin-bottom:16px}.field>label{display:block;margin-bottom:6px}
.form-grid{gap:16px;align-items:start}.form-section{margin-block:20px}
.dialog-actions,.sub-actions{gap:10px;align-items:center;flex-wrap:wrap}
.inline-error:not([hidden]){margin-block:12px;line-height:1.5}
.action-dialog input:not([type=checkbox]),.action-dialog select{min-height:46px}
#recordResponseForm .field{margin-block:12px}.password-fallback summary{line-height:1.5}
.shell-update{position:fixed;z-index:120;bottom:calc(90px + env(safe-area-inset-bottom));left:16px;right:16px;margin:auto;max-width:580px;display:flex;align-items:center;gap:12px;padding:14px;background:var(--panel);color:var(--text);border:1px solid var(--line2);border-radius:12px;box-shadow:0 4px 20px #0004;font-size:13px}
.shell-update button{flex-shrink:0}
@media(max-width:550px){.shell-update{flex-wrap:wrap}.agenda-row{grid-template-columns:42px minmax(0,1fr) auto}.agenda-tail{font-size:10px}}
/* Keep month summaries inside their date cells on narrow screens. */
@media(max-width:550px){.month-cell .cell-status,.month-cell .cell-life{max-width:100%;white-space:normal;overflow-wrap:anywhere;text-align:center}.month-cell .cell-status{font-size:9px}}

@media(max-width:400px){.month-cell .cell-status{font-size:8px;letter-spacing:0}}
/* D80 · A month square names who can't play. A name is kept whole on one line (one too long for the square ends in
   "…"); with two or more names, "can't play" takes its own line. On a phone the names stand one to a line over "can't"
   and "play" (each word whole; "can't" alone felt unfinished), and the faces of those named are hidden: faces for
   who's in, names for who's out. D80-3: who said maybe is named too ("Emma might play"), as a second group under who
   can't, in the quieter muted colour when both are there, so who can't stays the headline. */
.month-cell .cell-status.out{white-space:normal;overflow-wrap:normal;max-width:100%;text-align:center;text-wrap:balance}
.cell-status.out .out-name,.cell-status.out .out-words{display:inline-block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}
.cell-status.out .out-group{display:block}.cell-status.out .out-group+.out-group{margin-top:3px}
.cell-status.out .out-group.cant+.out-group.maybe{color:var(--muted)}
.cell-status.out .out-group.many .out-words{display:block}
/* D105-2 · "is not available", "might be available" are wider than a tablet-width square (551-800px), where they ended
   in "…": the words wrap between words instead, each word whole. A name still never wraps. */
.cell-status.out .out-words{white-space:normal}
/* D105 · Who can't play now reads "is not available" / "are not available", and D105-2 who said maybe "might be
   available". On a phone "available" (and "might be") is wider than the square, so it shrinks to the square's own
   width (cqi) and is always whole; 10px wherever it fits. */
@media(max-width:550px){.month-cell .member-mark.named-out{display:none}.month-cell .cell-status.out{font-size:10px;line-height:1.15;width:100%;container-type:inline-size}.cell-status.out .out-name,.cell-status.out .out-words{display:block}.cell-status.out .out-sep{display:none}.cell-status.out .out-play{display:block}.cell-status.out .out-group .out-play,.cell-status.out .out-group.maybe .out-words{font-size:min(1em,19cqi)}}
@media(max-width:350px){.month-cell .cell-status.out{font-size:9px}}

/* iOS zooms the page when a focused field has text under 16px, and an installed web app can stay zoomed. Keep touch form text at 16px. */
@media(hover:none) and (pointer:coarse){input,select,textarea,.candidate-entry input{font-size:16px}}

/* Where the sheet sits on the screen is set once, at every width, by the v025 popups rule further down: centred.
   (styles.css draws a phone bottom sheet, and this file's max-width:600px block above sets margin:8px auto; both
   load before that rule and lose to it.) */

/* index.html sets viewport-fit=cover, so the page extends under the notch and the rounded corners and
   the app must inset content itself. The BOTTOM inset was handled from the start (nav, toast, dialog
   padding) but the horizontal ones never were — neither stylesheet referenced safe-area-inset-left or
   -right — so in landscape every container ran under the notch. In-flow content (.topbar, .app) is
   inset once here at body level. Fixed elements do not inherit that, so each is constrained: the nav
   and the update banner could both clip on a narrower landscape, and the sign-in overlay pads its
   gutters. The toast is handled by its own max-width rule in styles.css. */
body{padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right)}
.bottom-nav{width:min(520px,calc(100% - 2*max(env(safe-area-inset-left),env(safe-area-inset-right))))}
.shell-update{left:max(16px,env(safe-area-inset-left));right:max(16px,env(safe-area-inset-right))}
.auth-gate{padding-left:max(23px,env(safe-area-inset-left));padding-right:max(23px,env(safe-area-inset-right))}

/* h16 · Manage enquiry hero, availability colour coding, and one row shape for every notification. */
/* Grid, not wrapped flex: a long title must shrink beside the close button, never push it onto its own row.
   The back control takes a full row of its own above them when it is present, and no space when it is not. */
.dialog-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:10px}
.dialog-head h2{min-width:0}
.dialog-back{grid-column:1/-1;justify-self:start;background:var(--panel2);color:var(--text);font-size:14px;font-weight:650;text-align:left;padding:8px 14px;min-height:44px}
.enquiry-hero{margin:0 0 4px}
.enquiry-hero h3{font-size:21px;line-height:1.25;margin:0 0 8px}
.hero-when{font-size:16px;font-weight:600;margin:0 0 3px}
.hero-time{font-size:14px;margin:0 0 12px}
.hero-time.muted{color:var(--muted)}
.hero-status{font-size:13px;color:var(--muted);margin:0;padding-top:11px;border-top:1px solid var(--line)}
.hero-state{font-size:11px;font-weight:800;letter-spacing:.08em;color:var(--warn);margin:9px 0 0}
.owner-response-row .response-state{display:flex;align-items:center;gap:7px}
.owner-response-row .pip{width:8px;height:8px;border-radius:50%;background:var(--muted);flex:0 0 8px}
.owner-response-row.available .pip{background:var(--available)}
.owner-response-row.maybe .pip{background:var(--maybe)}
.owner-response-row.unavailable .pip{background:var(--unavailable)}
.owner-response-row.available .response-state{color:var(--available)}
.owner-response-row.maybe .response-state{color:var(--maybe)}
.owner-response-row.unavailable .response-state{color:var(--unavailable)}
.notice-list{display:grid;gap:24px}
.notice-group .section-label{margin:0 0 4px}
.notice-group-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.notice-mark-all{flex:0 0 auto;padding:8px 0 8px 10px;font-size:12px;white-space:nowrap}
.notice{display:flex;align-items:center;gap:8px;border-left:3px solid var(--line2);padding-left:13px;border-bottom:1px solid var(--line)}
.notice.action{border-left-color:var(--warn)}
.notice.urgent{border-left-color:var(--bad)}
.notice-link{display:flex;align-items:center;gap:10px;flex:1;min-width:0;border:0;background:transparent;color:var(--text);text-align:left;padding:13px 0;min-height:44px}
.notice-body{display:grid;gap:3px;flex:1;min-width:0}
.notice-title{font-size:15px;font-weight:600;line-height:1.35}
.notice-meta{font-size:12px;color:var(--muted);line-height:1.45}
.notice-tag{flex:0 0 auto;font-size:10px;font-weight:800;letter-spacing:.08em;color:var(--info);border:1px solid var(--info);border-radius:6px;padding:3px 6px}
/* D64 · A Needs action row not yet tapped: the bell's own colour, ringed so it still shows on Day's white. */
.notice-new{flex:0 0 auto;width:9px;height:9px;border-radius:50%;background:var(--accent-fill);box-shadow:0 0 0 1px var(--accent)}
.notice .text-button{flex:0 0 auto}
.delivery-problem{border-left:3px solid var(--bad);padding:2px 0 2px 13px;line-height:1.45}
.identity-card{margin:0 0 4px}
.identity-head{display:flex;align-items:center;gap:14px}
.identity-who{min-width:0}
.identity-who h1{font-size:22px;margin:0 0 2px;line-height:1.2}
.identity-who p{margin:0;font-size:13px}
.identity-email{color:var(--muted);word-break:break-word;margin-top:3px!important}
.identity-card .sub-actions{margin-top:6px}
.settings-group{margin:18px 0 6px}
.settings-group:first-of-type{margin-top:12px}

/* h17 · Gig Day reads as a time ladder; the sign-in card carries one action. */
.gig-day-address{color:var(--muted);font-size:13px;margin:2px 0 14px}
.time-ladder{display:grid;gap:1px;margin:0 0 16px;background:var(--line);border-radius:10px;overflow:hidden}
.time-ladder>div{display:flex;justify-content:space-between;align-items:baseline;gap:12px;background:var(--panel);padding:11px 13px}
.time-ladder dt{font-size:13px;color:var(--muted);margin:0}
.time-ladder dd{margin:0;font-size:19px;font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.gig-day-unset{color:var(--muted);font-size:13px;margin:0 0 14px}
.auth-intro{color:var(--muted);font-size:14px;margin:0 0 20px;text-align:center}
.auth-hint{color:var(--muted);font-size:12px;line-height:1.5;margin:10px 0 0}
/* Steve, 28 Sep: "clear and clean up the login screen UI for an excellent and simple UX. e.g. Sign in with your band
   email can be removed". The status line keeps its place under the button, where Sending…, Check your inbox… and
   every problem appear, but says nothing at rest and takes no room when empty. The hint is one line, centred, and no
   longer says there is no password (Other ways to sign in offers one). A new member's way in, which the member guide
   names, is a full-width outlined button under a hairline (never a second lime one), and the other ways sit last. */
.auth-hint{text-align:center}
.auth-message:empty{min-height:0;margin-top:0}
.auth-message{text-align:center}
.auth-join{margin-top:22px;padding-top:22px;border-top:1px solid var(--line)}
.signed-in-here .auth-join{display:none}
.auth-switch{display:grid;justify-items:center;gap:8px;margin:8px 0 0}
.auth-switch>.secondary{justify-self:stretch}
.auth-switch>.passkey-note{margin:0 0 4px}
/* v025-b12 · D58 · Me → Security in two parts, Face ID sign-in and Password, each under its own heading. */
.security-part{margin:22px 0 6px}
/* v025-b11 · The password box sits in the email form, under the email, only when asked for; a slip in a common
   address is offered back under the box as a one-tap fix. */
.password-field{display:grid}
.email-suggest{color:var(--muted);font-size:13px;margin:-4px 0 10px}
.email-suggest .text-button{display:inline-flex;align-items:center;vertical-align:middle;margin:2px 0;padding:6px 12px;min-height:44px;font-size:13px}
.auth-foot{display:grid;gap:2px;justify-items:start}
.auth-foot:empty{display:none}
/* v025-b10 · The sign-in card's code stage, in the join card's shape: once a code is sent the card asks one thing,
   the 8 digits, so the email form, its hint, the join entry and the other ways step aside until it is done or left. */
.code-form{display:grid}
.code-form .primary{margin-top:4px}
.code-intro{color:var(--muted);font-size:14px;line-height:1.5;text-align:center;margin:0 0 16px;overflow-wrap:anywhere}
.code-intro .nowrap{white-space:nowrap}
.code-alt{display:grid;justify-items:center;gap:2px;margin-top:10px}
.code-stage #loginForm,.code-stage .auth-hint,.code-stage .auth-join,.code-stage .auth-switch,.signed-in-here #codeForm,.signed-in-here #codeAlt{display:none}
.gig-day-times{font-size:15px;margin:0 0 16px;line-height:1.5}
.gig-day-times strong{font-size:17px}
.gig-day-times.muted{color:var(--muted);font-size:13px}
/* h20 · .empty is sized for a whole page; inside an enquiry sheet its 24px padding stacked with the
   disclosure's 18px margin and .history's 27px left a large dead band when nothing needs answering. */
.enquiry-response .empty{padding:12px 0;text-align:left}
.enquiry-response>.more-details:last-of-type{margin-bottom:8px}
/* h21 · The Gig Day banner is Calendar-only and deliberately slight: on the day you want the facts, not a
   billboard. .dialog-actions sticks at bottom:-22px to cancel the dialog's bottom padding, but beta.css
   later changed that padding from 18px to 20px, so the bar no longer sat flush on its own edge. */
.gig-day-banner{padding:14px 16px;margin:0 0 18px}
.gig-day-banner .section-label{margin:0}
.gig-day-line{font-size:15px;line-height:1.5;margin:6px 0 10px}
.gig-day-line strong{font-size:17px}
.gig-day-banner .gig-day-address{margin:0 0 12px}
.gig-day-banner .sub-actions{margin:0}
/* Sticky bottom resolves against the scroller's PADDING edge. styles.css offsets it by a negative value
   meant to cancel the dialog's bottom padding, but beta.css later changed that padding and the two stopped
   agreeing — so the bar sat flush before it stuck and 21px higher after, which is the "floating" Steve saw.
   bottom:0 needs no such bookkeeping: the bar rests on the padding edge in both states. */
/* Steve: "Save gig should only be at the end of the sheet, it's fixed now, on the screen no matter where or
   how I scroll." The submit row was sticky, so it hovered over the form at every scroll position; three
   attempts at making it sit flush were all solving the wrong problem. It is static now, at the end of the
   form, which is what .response-save has done since Beta 3 — that precedent was already in this file. */
.action-dialog .dialog-actions{position:static;bottom:auto;margin-bottom:0;background:transparent;box-shadow:none;padding:16px 0 0;z-index:auto}
/* Declared here so the stylesheet carries the default; app.js overwrites it while a keyboard is open.
   Without this the variable exists only at runtime, which the Day/Night variable guard correctly rejects. */
:root{--keyboard-inset:0px;--keyboard-room:0px}
/* Extra scrollable space at the end of the sheet while a keyboard is open, so the submit row can be scrolled
   above iOS's floating AutoFill pill. Zero when no keyboard is present. */
#dialogBody{padding-bottom:var(--keyboard-room)}
/* v025 popups · Steve, 3 Oct: "Vertically centre (align) every popup page in the app." Every sheet now sits where the
   My icon card (h43) and the confirmation card already do: centred both ways at every width, in the space above the
   keyboard, rounded on all four corners, and only as tall as what it holds. Before this a sheet sat on the bottom edge
   on a phone and on the Mac, and on the top edge between 551 and 600px wide.
   · The gap above and below is the card's own arithmetic (--card-gap-y), so a tall sheet and the card stop at the same
     lines: 56px of air, or 6dvh where that is less, and never under the notch or the home indicator. While a keyboard
     is up the air and the indicator's clearance fall away (the keys cover the indicator) and 16px stays.
   · inset ends the box at the top of the keys, so the sheet is centred in the space the keyboard leaves and lifted
     clear of it, which is the job margin-bottom used to do for a sheet anchored to the bottom edge. */
.action-dialog{
  --sheet-air:max(0px,calc(56px - var(--keyboard-inset,0px)));
  --sheet-gap-y:max(16px,min(6dvh,var(--sheet-air)),env(safe-area-inset-top),min(env(safe-area-inset-bottom),var(--sheet-air)));
  inset:0 0 var(--keyboard-inset,0px);margin:auto;
  max-height:calc(100dvh - var(--keyboard-inset,0px) - 2*var(--sheet-gap-y))
}
@media(max-width:550px){
  /* The phone's bottom sheet had rounded top corners only, the home indicator's inset in its bottom padding, and a
     70dvh floor that held every sheet in one band against the bottom edge. A centred sheet is rounded all round,
     clears the indicator with its gap rather than its padding, and is as tall as what it holds: a floor would only
     leave an empty strip under its last button. */
  .action-dialog{min-height:0;border-radius:22px;padding-bottom:18px}
  .action-dialog{display:flex;flex-direction:column}
  /* An author display beats the browser's own dialog:not([open]){display:none}: without this the closed sheet
     is drawn in the page (below the content on h35, over it on h36). */
  .action-dialog:not([open]){display:none}
  .dialog-head{flex:0 0 auto}
  /* A sheet taller than its content must not stretch that content down the page. */
  #dialogBody{flex:0 0 auto}
}

/* One and done: while this device holds a sign-in, the gate is only ever "Connecting…" or "Can't reach GigLock",
   never an invitation to request another magic link. app.js removes the class when the session truly ends. */
.signed-in-here #loginForm,.signed-in-here .auth-hint,.signed-in-here .auth-switch{display:none}

/* h36 · The gig card. The state is said once; the line-up lists every open task with its own button; then where,
   when and how to get there in the Gig Day sheet's shape, what to know at the venue, notes, the quiet row, Owner
   controls and the small print. One button grammar (14px on 44px) and one lime button per card. Existing tokens only,
   so the Day/Night variable guard and the contrast sweep cover it unchanged. */
.day-gig.conflict{border-color:var(--gig-conflict-border)}
.day-gig.critical{background:var(--gig-conflict-surface)}
.gig-head{flex-wrap:wrap;margin-bottom:8px}
.gig-head h2{font-size:21px;line-height:1.25;overflow-wrap:anywhere}
.gig-status{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin:0 0 16px;font-size:13px;line-height:1.4;color:var(--detail-text)}
.gig-tag{font-size:10px;font-weight:800;letter-spacing:.08em;line-height:1.3;border:1px solid;border-radius:6px;padding:3px 7px;white-space:nowrap;color:var(--muted)}
.gig-tag.booked{color:var(--info)}
.gig-tag.draft{border-style:dashed}
.gig-tag.cancelled,.gig-tag.conflict{color:var(--bad)}
.gig-words{display:inline-flex;align-items:center;gap:7px}
.gig-words::before{content:"";flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--good)}
.gig-status-note,.gig-offline{font-size:13px;line-height:1.45;color:var(--detail-text);margin:-6px 0 16px}
.gig-offline strong{color:var(--warn)}
/* Line-up: the one home for reminders, deps and Jon on vocals. Open tasks share one tinted panel, in core.js's order;
   settled changes follow with the Notifications left rule. */
.gig-crew{margin:0 0 18px}
.gig-crew>.section-label,.gig-block>.section-label{font-size:12px;line-height:1.45;margin:0 0 8px}
.crew-tasks{border-left:3px solid var(--line2);border-radius:0 12px 12px 0;background:var(--panel2);padding:0 13px}
.crew-tasks.warn{border-left-color:var(--warn);background:var(--maybe-surface)}
.crew-tasks.critical{border-left-color:var(--bad);background:var(--conflict-surface)}
.crew-tasks>.crew-row{padding:11px 0 12px}
.crew-tasks>.crew-row+.crew-row{border-top:1px solid var(--line)}
.crew-tasks+.crew-row,.crew-row.good+.crew-row,.crew-row.cover+.crew-row{margin-top:12px}
.crew-row.good,.crew-row.cover{border-left:3px solid var(--good);padding:1px 0 1px 12px}
.crew-row.cover{border-left-color:var(--cover)}
.crew-title{font-size:14px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}
.crew-detail{font-size:13px;line-height:1.45;color:var(--detail-text);margin-top:2px;overflow-wrap:anywhere}
.crew-row .sub-actions{margin-top:10px}
/* Where, when, go: the Gig Day sheet's order, so the two read as one object. */
.gig-venue{font-size:17px;font-weight:700;line-height:1.3;overflow-wrap:anywhere}
.gig-address{font-size:13px;line-height:1.45;color:var(--muted);margin-top:2px;overflow-wrap:anywhere}
.gig-core>.time-ladder,.gig-core>.gig-day-unset{margin:14px 0 0}
.gig-core>:first-child,.gig-core>.sr-only+*{margin-top:0}
.gig-core .time-ladder{border:1px solid var(--line)}
.gig-core .time-ladder>div{background:var(--panel2)}
.is-history .time-ladder dd{font-size:16px;font-weight:600;color:var(--muted)}
.gig-set-line{font-size:13px;line-height:1.45;color:var(--detail-text);margin-top:10px}
.gig-go{margin-top:14px}
.gig-go-alt{display:flex;justify-content:center;margin-top:2px}
.gig-go-alt>.text-button{font-size:13px}
/* One button grammar across the card: 14px labels on 44px targets, links drawn as secondary buttons. */
.gig-body .sub-actions>button,.gig-more>button{min-height:44px;padding:10px 14px;border-radius:11px;font-size:14px}
.gig-block{border-top:1px solid var(--line);margin-top:18px;padding-top:14px}
.gig-block .gig-details,.gig-block .gig-notes{margin:0}
.gig-venue-notes{grid-template-columns:minmax(0,110px) 1fr}
.gig-contact{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 12px}
.gig-venue-notes+.gig-contact{border-top:1px dashed var(--line);margin-top:12px;padding-top:12px}
/* D68 · A venue's second contact sits under the first, divided the same way; on Manage enquiry, Reply to venue closes
   the block. The reply sheet shows the message read-only (it is changed, if at all, in Messages or Mail). */
.gig-contact+.gig-contact{border-top:1px dashed var(--line);margin-top:12px;padding-top:12px}
.gig-venue-info>.enq-reply{margin:12px 0 0}
.venue-contact2-add{margin:2px 0 14px}
.enq-reply-text{display:block;width:100%;min-height:240px;resize:vertical;font:inherit;line-height:1.45}
.enq-reply-send{display:grid;grid-template-columns:1fr;gap:8px;margin-top:12px}
.enq-reply-send>a,.enq-reply-send>button{width:100%;min-height:44px;margin:0;justify-content:center;text-align:center;padding:10px 15px;border:1px solid var(--line);border-radius:11px;font-size:14px;font-weight:650;overflow-wrap:anywhere}
.enq-reply-send>a{background:var(--panel2);color:var(--text);text-decoration:none}
.enq-reply-send>a.primary{background:var(--accent-fill);color:var(--primary-ink)}
.gig-venue-info>.enq-reply>button{flex:1 1 100%}
.gig-contact-who{min-width:0;overflow-wrap:anywhere}
.gig-contact-who strong{display:block;font-size:14px}
.gig-contact-who small{display:block;color:var(--muted)}
.gig-contact>.sub-actions{margin:0}
.gig-contact .sub-actions>a{min-height:44px;min-width:76px;padding:10px 14px;border-radius:11px;justify-content:center;background:var(--panel2);color:var(--text);font-size:14px;font-weight:650}
/* The quiet row. A subscriber's calendar line is a status that opens its sheet; the tick and chevron are generated
   content with empty alternative text, so the button's name stays exactly "In your calendar subscription". */
.gig-more{border-top:1px solid var(--line);margin-top:18px;padding-top:14px}
.gig-more>.text-button.subscribed-note{flex:1 0 100%;display:flex;align-items:center;justify-content:flex-start;gap:8px;text-align:left;padding:10px 14px;font-size:13px;font-weight:650;color:var(--detail-text)}
.gig-more>.subscribed-note::before{content:"\2713";content:"\2713" / "";color:var(--good);font-weight:800}
.gig-more>.subscribed-note.later::before{content:none}
.gig-more>.subscribed-note::after{content:"\203A";content:"\203A" / "";margin-left:auto;color:var(--muted);font-size:19px;font-weight:400;line-height:1}
/* Owner controls: Edit gig and, beside it, Cancel gig (Delete enquiry on a draft) in the danger style. h43 D25: no
   disclosure in front of it any more; one tap opens the confirmation card, which says what it costs. */
.gig-owner>.sub-actions{margin-top:0}
.gig-foot{border-top:1px solid var(--line);margin-top:18px;padding-top:12px}
.gig-foot>.provenance{margin:0;line-height:1.55}
.gig-foot>.attribution{margin-top:4px}
.day-gig>.gig-body+button{margin-top:16px}
@media(max-width:550px){
  .gig-head h2{font-size:20px}
  .gig-venue-notes{grid-template-columns:1fr;gap:2px}
  .gig-venue-notes dd+dt{margin-top:8px}
  .gig-go>button,.gig-more>button,.gig-owner>.sub-actions>button{flex:1 1 auto}
  .gig-contact>.sub-actions{flex:1 1 100%}
  .gig-contact .sub-actions>a{flex:1 1 0}
}
/* h36 review: multi-line venue notes keep their breaks; the open-task panel stays visible on a critical card */
.gig-venue-notes dd{white-space:pre-wrap;overflow-wrap:anywhere}
.day-gig.critical .crew-tasks{background:var(--panel)}
/* h38 · Manage enquiry and the enquiry card. Task first, in the h36 gig card's grammar: the state said once; the dates
   grouped by what can be done with them, each with its own buttons; one lime button per sheet; deadlines in the Gig Day
   ladder with the one control that changes them; At the venue, Notes, Owner controls, small print. New classes are
   prefixed enq-. Existing tokens only. */

/* The enquiry card. A <button> inherits font-weight 650, which made every line of the old card bold. */
.enq-card{font-weight:400;padding:16px 16px 14px}
.enq-card .enquiry-card-head{align-items:center}
.enq-card .enquiry-card-head strong{min-width:0;font-size:17px;font-weight:750;line-height:1.3;overflow-wrap:anywhere}
.enq-card-meta{display:block;margin-top:3px;font-size:13px;line-height:1.45;color:var(--muted);overflow-wrap:anywhere}
.enq-card-meta .deadline{font-size:inherit}
.enq-card-meta .deadline.due{color:var(--warn);font-weight:650}
.enq-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:11px}
.enq-chip{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:3px 10px 3px 8px;border:1px solid var(--line);border-radius:999px;background:var(--panel2);font-size:12px;font-weight:600;line-height:1.2;color:var(--detail-text);white-space:nowrap}
.enq-glyph{font-size:12px;font-weight:800;line-height:1;color:var(--muted)}
.enq-chip.ready .enq-glyph,.enq-chip.available .enq-glyph{color:var(--good)}
.enq-chip.blocked .enq-glyph,.enq-chip.unavailable .enq-glyph{color:var(--bad)}
.enq-chip.maybe .enq-glyph{color:var(--warn)}
.enq-chip.waiting,.enq-chip.unknown{border-style:dashed}
.enq-chip.more{color:var(--muted);font-weight:500}
.enq-next{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:13px;padding-top:11px;border-top:1px solid var(--line);font-size:14px;font-weight:650;line-height:1.4;color:var(--detail-text);overflow-wrap:anywhere}
.enq-next.act{color:var(--accent)}
.enq-go{flex:0 0 auto;font-size:21px;font-weight:400;line-height:1;color:var(--muted)}
.gig-tag.enq-live{color:var(--info);border-style:dashed}
.gig-tag.enq-expired{color:var(--warn)}
.enq-card.enq-history{padding:12px 16px;margin-bottom:8px}
.enq-card.enq-history .enquiry-card-head strong{font-size:15px}

/* Head: venue, when, then the state as a tag and words, the gig card's status row. */
.enq-manage .enq-head{margin:0 0 4px}
.enq-manage .enq-head h3{font-size:21px;line-height:1.25;margin:0 0 3px;overflow-wrap:anywhere}
.enq-manage .hero-when{font-size:14px;font-weight:600;line-height:1.4;color:var(--detail-text);margin:0 0 10px}
.enq-status{margin:0 0 14px}
.enq-status #enquiryProgress{font-weight:600;color:var(--text)}
.enq-due{display:inline-flex;align-items:center;gap:7px;color:var(--warn);font-weight:650}
.enq-due::before{content:"";flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--warn)}
.enq-manage .gig-status-note{margin:-6px 0 14px}
.enq-manage .gig-offline{margin:-6px 0 14px}
.enq-chosen{margin:4px 0 6px}

/* Undo says what happened, at the top of the sheet, where it can be seen. */
.enq-undo{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 14px;padding:2px 4px 2px 14px;border:1px solid var(--line2);border-radius:12px;background:var(--toast-surface);font-size:14px;font-weight:600;line-height:1.35}
.enq-undo .text-button{min-height:44px;font-size:14px}

/* The dates, grouped by what can be done with them. */
.enq-group{margin-top:18px}
.enq-group>.section-label{font-size:12px;line-height:1.45;margin:0 0 2px}
.enq-group .enq-chase{margin:8px 0 6px}
.enq-manage .enq-date{padding:14px 0 4px;border-top:1px solid var(--line)}
.enq-group>.section-label+.enq-date,.enq-lapsed-note+.enq-date{border-top:0;padding-top:8px}
.enq-date h4{font-size:16px;line-height:1.3;margin:0}
.enq-why{display:flex;gap:8px;align-items:baseline;font-size:13px;line-height:1.45;color:var(--detail-text);margin:3px 0 0;overflow-wrap:anywhere}
.enq-why::before{content:"";flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--muted);transform:translateY(-1px)}
.enq-why.good::before{background:var(--good)}
.enq-why.cover::before{background:var(--cover)}
.enq-why.dep::before{background:var(--warn)}
.enq-why.wait::before{background:transparent;border:2px dotted var(--waiting-text);width:5px;height:5px;flex-basis:5px}
.enq-why.bad{color:var(--bad)}
.enq-why.bad::before{background:var(--bad)}
.enq-date-note{font-size:12px;line-height:1.45;color:var(--muted);margin:3px 0 0 16px;overflow-wrap:anywhere}
.enq-lapsed-note{margin:4px 0 0}

/* One button grammar, as on the gig card: 14px labels on 44px targets. Mark not viable is an outlined button set
   apart at the end of the row, so it is never the neighbour of the lime Book. */
.enq-manage .sub-actions>button{min-height:44px;padding:10px 14px;border-radius:11px;font-size:14px}
.enq-acts{margin-top:10px;gap:8px}
.enq-acts>.enq-drop{margin-left:auto}
.enq-acts>button:first-child:not(.text-button){min-width:148px}

/* The line-up behind each date: its face is the calendar's five rings, so who is in reads without opening it. */
.enq-lineup{margin:2px 0 6px;padding-top:0}
.enq-lineup>summary{display:flex;align-items:center;gap:10px;min-height:44px;padding:6px 0;margin:0;font-size:13px;color:var(--muted);list-style:none}
.enq-lineup>summary::-webkit-details-marker{display:none}
.enq-lineup>summary::after{content:"\203A";content:"\203A" / "";margin-left:auto;font-size:20px;line-height:1;color:var(--muted);transform:rotate(90deg)}
.enq-lineup[open]>summary::after{transform:rotate(-90deg)}
.enq-lineup[open]>summary{margin-bottom:2px}
.enq-marks{display:inline-flex;gap:3px;flex:0 0 auto}
.enq-marks .member-mark.mini{width:26px;height:26px}
.enq-lineup .owner-response-row{padding:8px 0}
.enq-lineup .owner-response-row:last-child{border-bottom:0}
.enq-lineup .owner-response-row .member-avatar{width:32px;height:32px}
.enq-lineup .owner-response-row button{min-height:44px;padding:8px 12px;border-radius:11px;font-size:13px}

/* Deadlines in the Gig Day ladder's shape. */
.enq-deadlines .time-ladder{margin:0;border:1px solid var(--line)}
.enq-deadlines .time-ladder>div{align-items:center;background:var(--panel2)}
.enq-ladder dt{display:grid;gap:1px;color:var(--detail-text)}
.enq-ladder dt small{font-size:12px;color:var(--muted)}
.enq-ladder dd{font-size:17px;text-align:right}
.enq-ladder .due dd,.enq-ladder .due dt small{color:var(--warn)}
.enq-ladder .past dd,.enq-ladder .past dt small{color:var(--bad)}
.enq-deadlines>.sub-actions{margin-top:12px}
.enq-deadlines>.gig-day-unset{margin:0}

/* Dates no longer offered, At the venue, Notes. */
.enq-manage .enq-other{margin-top:16px}
.enq-manage .enq-other+.gig-block{margin-top:6px}
.enq-manage .history-date{flex-wrap:nowrap;font-size:14px;min-height:52px;padding:6px 0}
.enq-manage .history-date:last-child{border-bottom:0}
.enq-hist-when{display:grid;gap:1px;min-width:0}
.enq-hist-when small{font-size:12px;color:var(--muted)}
.enq-address{margin:0}
.enq-address+.gig-venue-notes,.enq-address+.inline-note,.enq-address+.gig-contact{margin-top:12px}
.enq-manage .gig-owner{margin-top:18px}

/* Record a member's answers: the respond sheet's three choices, plus No answer, one block per date.
   h40: the date was a floated <legend>, which took itself out of the flow and left the choices free to ride up
   into it — the collision in Steve's screenshot. The block is a labelled group now, so the date is an ordinary
   heading in normal flow and nothing below it can move up. */
.enq-rec-who{display:flex;align-items:center;gap:12px;margin:0 0 10px}
.enq-rec-who .member-avatar{width:44px;height:44px;flex:0 0 44px}
.enq-rec-who strong{display:block;font-size:16px;line-height:1.3}
.enq-rec-who small{display:block;font-size:13px;color:var(--muted)}
.enq-rec-intro{font-size:14px;line-height:1.5;color:var(--detail-text);margin:0 0 4px;overflow-wrap:anywhere}
.enq-rec-date{margin:0;padding:16px 0 12px;border:0;border-top:1px solid var(--line);min-width:0}
.enq-rec-when{margin:0;font-size:16px;font-weight:700;line-height:1.3;overflow-wrap:anywhere}
.enq-rec-by{font-size:12px;color:var(--muted);margin:4px 0 0;overflow-wrap:anywhere}
.enq-rec-kept{font-size:14px;line-height:1.45;color:var(--detail-text);margin:8px 0 0}
/* D71 · Each date's Saving… / Saved line; until a tap it is empty and takes no room. */
.enq-rec-date .enquiry-save-state:empty{display:none}
/* D71 · Select dates: a drag across the month marks a run of days (app.js bulkDrag), so the grid never scrolls the sheet
   under a finger, selects text or raises iOS's callout. The sheet still scrolls from anywhere else on it. */
.bulk-calendar .month-grid{touch-action:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.enq-rec-choices{margin-top:12px}
.enq-rec-choice{position:relative;display:flex;align-items:center;justify-content:center;min-height:50px;margin:0;padding:6px 4px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);font-size:13px;font-weight:650;text-align:center;cursor:pointer}
.enq-rec-choice input{position:absolute;inset:0;width:100%;height:100%;min-height:0;margin:0;padding:0;border:0;opacity:0;cursor:pointer}
.enq-rec-choice[data-status=available]{color:var(--good)}
.enq-rec-choice[data-status=maybe]{color:var(--warn)}
.enq-rec-choice[data-status=unavailable]{color:var(--bad)}
.enq-rec-choice:has(input:checked){border-width:2px;font-weight:800;box-shadow:inset 0 -2px currentColor}
.enq-rec-choice[data-status=available]:has(input:checked){border-color:var(--good);background:var(--good-surface)}
.enq-rec-choice[data-status=maybe]:has(input:checked){border-color:var(--warn);background:var(--maybe-surface)}
.enq-rec-choice[data-status=unavailable]:has(input:checked){border-color:var(--bad);background:var(--bad-surface)}
.enq-rec-choice:has(input:focus-visible){outline:3px solid var(--focus);outline-offset:2px}
/* No answer is the state a date starts in, so it sits under the three answers rather than beside them: the row of
   three keeps its width at 375px, and the choice that clears a date reads as the different thing it is. */
.enq-rec-choice[data-status=unknown]{grid-column:1/-1;min-height:44px;margin-top:5px;border-style:dashed;background:transparent;color:var(--muted)}
.enq-rec-choice[data-status=unknown]:has(input:checked){border-style:solid;border-color:var(--line2);background:var(--panel2);color:var(--text)}
.enq-rec-date .available-after{margin:12px 0 0}

/* Extend deadline says what the two dates do. */
.enq-extend-intro{font-size:14px;line-height:1.5;color:var(--detail-text);margin:0 0 10px}
.enq-extend-gone{display:flex;gap:8px;align-items:baseline;font-size:14px;font-weight:650;line-height:1.45;color:var(--warn);margin:0 0 12px}
.enq-extend-gone::before{content:"";flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--warn)}

@media(max-width:550px){
  .enq-manage .enq-head h3{font-size:20px}
  .enq-chase .sub-actions>button,.enq-deadlines .sub-actions>button,.enq-manage .gig-owner>.sub-actions>button{flex:1 1 auto}
  .enq-manage .gig-contact>.sub-actions{flex:1 1 100%}
  .enq-manage .gig-contact .sub-actions>a{flex:1 1 0}
  .enq-rec-choice{min-height:54px;font-size:12px}
}

/* h38 · The Gigs list, task first. Needs you (a card per item, ending in its one step), In progress (someone else's
   move), All set (booked, nothing open) and one History. Cards and rows share the Calendar list's date column and the
   h36 gig card's grammar: tags said once, open tasks in its tinted panel, settled changes with its green or teal rule,
   where and when in the Gig Day ladder's words. One lime button on the page. New classes are prefixed glist-. Existing
   tokens only. */
.glist-page{max-width:760px;margin:0 auto}
.glist-section>.section-label{margin:0 0 10px}
.add-action.quiet{background:var(--panel2);color:var(--text);border:1px solid var(--line2)}
.add-action.quiet:hover{background:var(--hover)}
.glist-page>.calendar-note{margin:0 1px 4px;font-size:12px}
.glist-clear{display:flex;align-items:center;gap:9px;margin:22px 0 0;font-size:14px;line-height:1.45;color:var(--detail-text)}
.glist-clear::before{content:"";flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--good)}
.glist-empty p+p{margin-top:6px;font-size:14px;line-height:1.5;color:var(--detail-text)}
.glist-empty strong{font-size:16px}
/* The date column, a page off a calendar: the month on its band, the day, the weekday (Today, in accent, on the day),
   and the year when it isn't this one. D87 · The band is coloured by what the date is (glist-t-*, below). */
.glist-date{flex:0 0 52px;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:0;padding:0 0 7px;overflow:hidden;border:1px solid var(--line);border-radius:12px;background:var(--panel2);color:var(--muted);font-size:10px;font-weight:750;letter-spacing:.07em;text-transform:uppercase;line-height:1.2;font-variant-numeric:tabular-nums}
.glist-date>.glist-mon{align-self:stretch;padding:3px 0 2px;background:var(--glist-band);color:var(--glist-band-ink);text-align:center;font-weight:800;letter-spacing:.09em}
.glist-date strong{margin:5px 0 1px;font-size:23px;font-weight:800;letter-spacing:-.02em;line-height:1.05;color:var(--text)}
.glist-dashed{border-style:dashed}
.glist-today{border-color:var(--accent)}
.glist-today>.glist-mon{background:var(--accent-fill);color:var(--selected-ink)}
.glist-today>.glist-dow{color:var(--accent)}
.glist-year{letter-spacing:.02em}
.glist-count{justify-content:center;gap:1px;min-height:66px;padding:6px 0}
.glist-count strong{margin:0}
.glist-count>span{letter-spacing:.04em}
/* Head: title, the state in tags and words, how far off, where, when. */
.glist-head{display:flex;align-items:flex-start;gap:12px}
.glist-what{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:3px}
.glist-title{margin:0;font-size:16px;font-weight:750;line-height:1.3;letter-spacing:-.01em;color:var(--text);overflow-wrap:anywhere}
.glist-status{display:flex;flex-wrap:wrap;align-items:center;gap:5px 8px;margin:2px 0 1px;font-size:13px;line-height:1.4;color:var(--detail-text)}
.glist-rel{font-size:12px;font-weight:650;color:var(--muted)}
.glist-where{font-size:13px;font-weight:600;line-height:1.4;color:var(--detail-text);overflow-wrap:anywhere}
.glist-when,.glist-due{font-size:13px;line-height:1.4;color:var(--muted)}
.glist-when b{font-weight:750;color:var(--text);font-variant-numeric:tabular-nums}
.glist-due .deadline{font-size:inherit}
.glist-warn{color:var(--warn);font-weight:650}
/* The open line-up tasks in the h36 panel, the settled changes with its rule, and one line of who acts. */
.glist-body{margin:12px 0 0}
.glist-tasks{display:block;margin-top:4px;border-left:3px solid var(--line2);border-radius:0 10px 10px 0;background:var(--panel2);padding:1px 12px}
.glist-tasks.warn{border-left-color:var(--warn);background:var(--maybe-surface)}
.glist-tasks.critical{border-left-color:var(--bad);background:var(--conflict-surface)}
.glist-card.critical .glist-tasks,.glist-row.critical .glist-tasks{background:var(--panel)}
.glist-task{display:block;padding:7px 0;font-size:13px;font-weight:600;line-height:1.4;color:var(--text);overflow-wrap:anywhere}
.glist-task+.glist-task{border-top:1px solid var(--line)}
.glist-task.mine{font-weight:800}
.glist-settled{display:block;margin-top:8px;border-left:3px solid var(--good);padding:1px 0 1px 10px;font-size:13px;font-weight:600;line-height:1.4;color:var(--detail-text);overflow-wrap:anywhere}
.glist-settled.cover{border-left-color:var(--cover)}
.glist-line{display:block;margin-top:4px;font-size:13px;line-height:1.45;color:var(--detail-text);overflow-wrap:anywhere}
.glist-chips{margin-top:12px}
/* Needs you: a card, then its one step. The step's target is stretched over the card, so the whole card is that one
   button; nothing else on the card is a control. */
.glist-card{position:relative;margin:0 0 12px;padding:14px;border:1px solid var(--line);border-radius:16px;background:var(--panel)}
.glist-card.conflict{border-color:var(--gig-conflict-border)}
.glist-card.critical{background:var(--gig-conflict-surface)}
.glist-card:hover{border-color:var(--line2)}
.glist-card.conflict:hover{border-color:var(--bad)}
.glist-step{margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
.glist-why{margin:0 0 10px;font-size:13px;line-height:1.45;color:var(--detail-text);overflow-wrap:anywhere}
.glist-go{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;min-height:44px;padding:10px 14px;border-radius:11px;font-size:15px;line-height:1.3}
.glist-go::after{content:"";position:absolute;inset:0;border-radius:16px}
.glist-go>.glist-chev{font-size:20px;font-weight:400;line-height:1;opacity:.7}
/* In progress, All set, History and Me: one row per item, one tap target. */
.glist-row{display:flex;align-items:flex-start;gap:12px;width:100%;margin:0 0 8px;padding:12px;border:1px solid var(--line);border-radius:14px;background:var(--panel);text-align:left;font-weight:400;color:var(--text)}
.glist-row:hover{background:var(--hover)}
.glist-row.conflict{border-color:var(--gig-conflict-border)}
.glist-row.critical{border-color:var(--gig-conflict-border);background:var(--gig-conflict-surface)}
.glist-row .glist-date{min-height:56px}
.glist-row .glist-chips{margin-top:6px}
.glist-past{padding:10px 12px}
.glist-past .glist-title{font-size:15px}
.glist-past .glist-date{min-height:50px}
.glist-past .glist-date strong{font-size:19px;color:var(--detail-text)}
.glist-month{display:flex;align-items:center;gap:10px;margin:16px 0 8px;font-size:13px;font-weight:700;color:var(--muted)}
.glist-month::after{content:"";flex:1;border-top:1px solid var(--line)}
.glist-section>.section-label+.glist-month{margin-top:0}
.glist-history[open]>summary{margin-bottom:10px}
/* The Day card control a Gigs step landed on, for a moment. */
.glist-landed{outline:3px solid var(--focus);outline-offset:3px}
@media(min-width:551px){.glist-go{display:inline-flex;width:auto;min-width:220px}}
@media(max-width:550px){
  .glist-card{padding:13px 12px}
  .glist-head,.glist-row{gap:11px}
  .glist-date{flex-basis:46px}
}

/* D87 (Steve, 18 Oct: "more aesthetically appealing and easy to get the key information") · Every gig and enquiry on
   the Gigs list in three parts, each always in the same place: what and where (title, state, how far off, the venue by
   a pin), the times in their own blocks (beside it on a wide screen, so they line up down the page), then below a rule
   the line-up and who acts, each line with a dot in its tone. A problem keeps a tinted panel; waiting is a plain line.
   The date column's band says what the date is: booked in the calendar's gig blue, draft, enquiry, or gone by. */
:root{--glist-band:#272e36;--glist-band-ink:#c8ced5;--glist-booked:#1d3a5c;--glist-booked-ink:#a9d0ff;--glist-shadow:none}
:root[data-appearance="day"]{--glist-band:#e4e9df;--glist-band-ink:#465147;--glist-booked:#cfe2f6;--glist-booked-ink:#0c3a66;--glist-shadow:0 1px 2px #18241a0f,0 4px 14px #18241a0a}
.glist-t-booked{border-color:var(--glist-booked)}
.glist-t-booked>.glist-mon{background:var(--glist-booked);color:var(--glist-booked-ink)}
.glist-t-enq{border-color:var(--info)}
.glist-t-enq>.glist-mon{background:transparent;color:var(--info);border-bottom:1px dashed var(--info)}
.glist-t-enq.glist-count{color:var(--info)}
.glist-t-past>.glist-mon{color:var(--muted)}
.glist-today.glist-t-booked,.glist-today.glist-t-enq{border-color:var(--accent)}
.glist-today>.glist-mon{background:var(--accent-fill);color:var(--selected-ink);border-bottom:0}
.glist-card,.glist-row{margin:0 0 10px;box-shadow:var(--glist-shadow)}
.glist-card{padding:16px}
.glist-row{padding:14px 16px}
.glist-head,.glist-row{gap:14px}
.glist-title{font-size:17px;line-height:1.28}
/* D87-2 (Steve, 18 Oct; design A) · Two columns: the title, the venue by its pin and the address on the left beside the
   date column; the state, the times and the line-up on the right, behind a thin rule. */
.glist-two{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);column-gap:14px;align-items:start}
.glist-id{display:flex;flex-direction:column;gap:4px;min-width:0}
.glist-side{display:flex;flex-direction:column;align-items:flex-start;gap:10px;min-width:0;padding-left:14px;border-left:1px solid var(--line)}
.glist-side>.glist-status{margin:0}
.glist-addr{padding-left:20px;font-size:13px;line-height:1.4;color:var(--muted);overflow-wrap:anywhere}
.glist-side .enq-chip{max-width:100%;white-space:normal}
.glist-notes{display:flex;flex-direction:column;gap:2px;min-width:0}
.glist-notes>span{display:block}
/* D87-4 (Steve, 18 Oct: "Keep the whole card clickable/tappable, but clicking or tapping on the address opens the maps
   module for instant directions") · A row is a card: its title is its tap, stretched over the whole card (as a
   Needs-you card's step is), so the card's edge is the button's edge. The place is its own outlined button, raised over
   that tap, opening Directions. */
.glist-row{position:relative}
.glist-open{display:inline;min-height:0;margin:0;padding:0;border:0;border-radius:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}
.glist-open:hover{background:none}
.glist-open::after{content:"";position:absolute;inset:0;border-radius:14px}
.glist-open:focus-visible{outline:none}
.glist-open:focus-visible::after{outline:3px solid var(--focus);outline-offset:3px}
.glist-map{position:relative;z-index:1;display:flex;flex-direction:column;align-items:flex-start;align-self:flex-start;gap:3px;max-width:100%;min-height:44px;margin:2px 0 0;padding:7px 30px 7px 10px;border:1px solid var(--line2);border-radius:10px;background:var(--panel2);color:var(--text);font-weight:600;line-height:1.4;text-align:left}
.glist-map:hover{border-color:var(--line2);background:var(--hover)}
.glist-map>.glist-where{color:var(--text)}
.glist-map-go{position:absolute;top:7px;right:10px;font-size:15px;font-weight:400;line-height:1.2;color:var(--muted)}
.glist-status{gap:6px 10px;margin:1px 0 0}
.glist-status .gig-tag{padding:3px 8px;border-radius:7px}
.glist-status .gig-tag.booked{background:var(--glist-booked);border-color:var(--glist-booked);color:var(--glist-booked-ink)}
.glist-rel{font-size:13px;font-weight:700;color:var(--detail-text)}
.glist-where{display:flex;align-items:flex-start;gap:6px;font-size:14px;color:var(--detail-text)}
.glist-pin{flex:0 0 14px;width:14px;height:14px;margin-top:2px;stroke-width:2;color:var(--muted)}
.glist-times{display:flex;flex-direction:column;align-self:stretch;border:1px solid var(--line);border-radius:11px;background:var(--panel2);overflow:hidden}
.glist-time{display:flex;flex-direction:column;gap:2px;padding:6px 12px 7px}
.glist-time+.glist-time{border-top:1px solid var(--line)}
.glist-time-k{font-size:10px;font-weight:750;line-height:1.2;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.glist-time b{font-size:17px;font-weight:800;line-height:1.15;letter-spacing:-.01em;color:var(--text);font-variant-numeric:tabular-nums;white-space:nowrap}
.glist-times.unset{padding:8px 14px;font-size:13px;line-height:1.4;color:var(--muted)}
.glist-foot{display:flex;flex-direction:column;align-self:stretch;gap:8px}
.glist-foot>.glist-line,.glist-foot>.glist-chips{margin:0}
.glist-foot>.glist-line{font-size:13px;color:var(--muted)}
.glist-foot>.glist-tasks{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;border:0;border-radius:0;background:none}
.glist-foot>.glist-tasks.warn,.glist-foot>.glist-tasks.critical{padding:9px 12px;border-radius:10px;background:var(--maybe-surface)}
.glist-foot>.glist-tasks.critical{background:var(--conflict-surface)}
.glist-card.critical .glist-foot>.glist-tasks,.glist-row.critical .glist-foot>.glist-tasks{background:var(--panel)}
.glist-foot .glist-task,.glist-foot>.glist-settled,.glist-foot>.gig-words{display:flex;align-items:flex-start;gap:9px;margin:0;padding:0;border:0;font-size:14px;font-weight:650;line-height:1.4;color:var(--text)}
.glist-foot .glist-task+.glist-task{border-top:0}
.glist-foot .glist-task.mine{font-weight:800}
.glist-foot .glist-task::before,.glist-foot>.glist-settled::before,.glist-foot>.gig-words::before{content:"";flex:0 0 8px;width:8px;height:8px;margin-top:6px;border-radius:50%;background:var(--waiting-text)}
.glist-foot>.glist-tasks.warn .glist-task::before{background:var(--warn)}
.glist-foot>.glist-tasks.critical .glist-task::before{background:var(--bad)}
.glist-foot>.glist-settled::before,.glist-foot>.gig-words::before{background:var(--good)}
.glist-foot>.glist-settled.cover::before{background:var(--cover)}
.glist-past .glist-side{gap:6px}
.glist-past .glist-date strong{font-size:20px}
.glist-section{margin-top:30px}
.glist-section>.section-label{display:flex;align-items:center;gap:8px;margin:0 0 12px}
.glist-n{display:inline-grid;place-items:center;min-width:22px;height:20px;padding:0 7px;border:1px solid var(--line);border-radius:999px;background:var(--panel2);color:var(--detail-text);font-size:11px;font-weight:800;letter-spacing:0}
.glist-clear{margin:20px 0 0;padding:12px 14px;border:1px solid var(--good-border);border-radius:14px;background:var(--good-surface);color:var(--text);font-weight:650}
.glist-clear::before{content:"\2713";content:"\2713" / "";display:grid;place-items:center;flex:0 0 22px;width:22px;height:22px;border-radius:50%;background:var(--good);color:var(--panel);font-size:13px;font-weight:900}
@media(min-width:700px){
  .glist-two{column-gap:20px}
  .glist-side{padding-left:20px}
  .glist-times{flex-direction:row;align-self:flex-start}
  .glist-time{padding:7px 14px 8px}
  .glist-time+.glist-time{border-top:0;border-left:1px solid var(--line)}
}
@media(max-width:550px){
  .glist-card{padding:12px}
  .glist-row{padding:12px}
  .glist-head,.glist-row{gap:10px}
  .glist-date{flex-basis:46px}
  .glist-title{font-size:16px}
  .glist-two{grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:10px}
  .glist-side{padding-left:10px}
  .glist-where{font-size:13px}
  .glist-time{padding:6px 10px 7px}
  .glist-time b{font-size:15px;white-space:normal}
  .glist-map{padding:6px 22px 6px 7px}
  .glist-map-go{top:6px;right:7px}
  .glist-map .glist-where{gap:4px}
  .glist-map .glist-addr{padding-left:18px}
}

/* h38 · The gig form: Add Gig, Repeat gig, Edit draft, Edit gig, Book this date. Top to bottom in the order the task
   happens: what the sheet started from, the date and what it means for the band (the line-up's words and tones), where,
   the times as the card's ladder, the optional details, then one decision and one lime button. Every new class is gform-.
   Existing tokens only, so the Day/Night variable guard and the contrast sweep cover it unchanged. */
/* Sections are headed like the gig card's blocks. A legend floats so its section's hairline runs unbroken. The shared
   venue fieldset and the Date Enquiry side of Add Gig use the same labels, so the two sides read as one form. */
.gform .form-section>legend,.gform-venue>legend,#enquiryForm>.form-section>legend{float:left;width:100%;padding:0;margin:0 0 10px;font-size:12px;font-weight:700;line-height:1.45;color:var(--muted);letter-spacing:.07em;text-transform:uppercase}
.gform .form-section>legend+*,.gform-venue>legend+*,#enquiryForm>.form-section>legend+*{clear:both}
.gform .field>label small,.gform-venue .field>label small{font-size:12px;font-weight:500;color:var(--muted);margin-left:6px}
.gform input[type=checkbox]{accent-color:var(--mine-border)}
/* Add Gig asks one question first. The chosen side is neutral: the submit stays the sheet's one lime button. */
.creation-tabs{margin-bottom:8px}
.creation-tabs button[aria-pressed=true]{background:var(--panel);color:var(--text);box-shadow:0 0 0 1px var(--line2)}
.gform-mode-hint{font-size:13px;line-height:1.45;color:var(--detail-text);margin:0 0 18px}
/* Blocks are hairline-separated, as on the card. */
.gform>.gform-block{min-width:0;border:0;border-top:1px solid var(--line);margin:20px 0 0;padding:14px 0 0}
.gform>.gform-block:first-child{border-top:0;margin-top:0;padding-top:0}
.gform>.gform-block>.section-label{display:block;font-size:12px;line-height:1.45;margin:0 0 10px}
.gform-when>.field{margin-bottom:10px}
.gform-when>.field>label.section-label,.gform-name>.field>label.section-label{display:block;font-size:12px;line-height:1.45;margin:0 0 10px;color:var(--muted)}
/* D89 · The gig's name, the sheet's first box: labelled like the date under it, its Optional in the label's quiet words. */
.gform-name>.field{margin-bottom:0}
.gform-name>.field>label.section-label small{text-transform:none;letter-spacing:0}
/* What the sheet started from: the card's own status tags on an edit, the source of a repeat. */
.gform-status{margin:0}
.gform-status-name{font-size:14px;font-weight:650;color:var(--text);overflow-wrap:anywhere}
.gform-source{font-size:13px;line-height:1.5;color:var(--detail-text);border-left:3px solid var(--line2);padding:2px 0 2px 12px;margin:0;overflow-wrap:anywhere}
.gform-source strong{color:var(--text)}
/* Book this date: the enquiry's facts, read-only, in the time ladder's shape. */
.gform-facts{display:grid;gap:1px;margin:0;background:var(--line);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.gform-facts>div{display:grid;grid-template-columns:124px minmax(0,1fr);gap:12px;align-items:baseline;background:var(--panel2);padding:11px 13px}
.gform-facts dt{font-size:13px;line-height:1.35;color:var(--muted);margin:0}
.gform-facts dd{margin:0;font-size:15px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}
.gform-facts>div:first-child dd{font-size:17px;font-weight:750}
.gform-facts dd small{display:block;font-size:13px;font-weight:500;line-height:1.4;color:var(--detail-text);margin-top:2px}
.gform-facts .gform-due dd small{display:inline;margin:0}
.gform-facts .gform-due.due dd small{color:var(--warn);font-weight:700}
.gform-facts .gform-due.past dd small{color:var(--bad);font-weight:700}
.gform-note{font-size:13px;line-height:1.45;color:var(--detail-text);margin:10px 0 12px}
/* The band check under the date: the line-up panel's shape and tones, so a date reads the same here as on the card. */
.gform-check{border-left:3px solid var(--line2);border-radius:0 12px 12px 0;background:var(--panel2);color:var(--text);padding:11px 13px 12px}
.gform-check.quiet{border-left:0;border-radius:0;background:transparent;padding:0}
.gform-check.good{border-left-color:var(--good);background:var(--good-surface)}
.gform-check.cover{border-left-color:var(--cover);background:var(--cover-surface)}
.gform-check.warn{border-left-color:var(--warn);background:var(--maybe-surface)}
.gform-check.critical{border-left-color:var(--bad);background:var(--conflict-surface)}
.gform-check-day{font-size:11px;font-weight:800;line-height:1.4;letter-spacing:.08em;text-transform:uppercase;color:var(--detail-text);margin:0 0 4px}
.gform-check-title{font-size:14px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}
.gform-check-detail{font-size:13px;line-height:1.45;color:var(--detail-text);margin-top:2px;overflow-wrap:anywhere}
.gform-check.quiet .gform-check-detail{color:var(--muted);margin:0}
.gform-check-marks{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.gform-check-hint{font-size:13px;line-height:1.45;color:var(--detail-text);margin-top:8px;overflow-wrap:anywhere}
.gform-check .sub-actions{margin-top:10px}
.gform-check .sub-actions>button{min-height:44px;padding:10px 14px;border-radius:11px;font-size:14px}
/* Where. The saved-venues note sits under the address it is about. */
.gform-venue-saved{margin:-8px 0 0}
/* Disclosures that say what they hold, on a 48px row with the quiet row's chevron. No flex on summary (older WebKit). */
.gform-more,.gform-venue-more{margin:14px 0 0;padding:0;border:1px solid var(--line);border-radius:12px;background:var(--panel)}
.gform-more>summary,.gform-venue-more>summary{position:relative;display:block;list-style:none;min-height:48px;margin:0;padding:13px 40px 13px 14px;font-size:14px;font-weight:650;line-height:1.5;color:var(--text);cursor:pointer}
.gform-more>summary::-webkit-details-marker,.gform-venue-more>summary::-webkit-details-marker{display:none}
.gform-more>summary::after,.gform-venue-more>summary::after{content:"\203A";content:"\203A" / "";position:absolute;right:15px;top:50%;margin-top:-11px;font-size:19px;font-weight:400;line-height:22px;color:var(--muted);transform:rotate(90deg)}
.gform-more[open]>summary::after,.gform-venue-more[open]>summary::after{transform:rotate(-90deg)}
.gform-more[open]>summary,.gform-venue-more[open]>summary{border-bottom:1px solid var(--line)}
.gform-filled{font-weight:500;font-size:13px;color:var(--muted);overflow-wrap:anywhere}
.gform-more>:not(summary),.gform-venue-more>:not(summary){margin-left:14px;margin-right:14px}
.gform-more>summary+*,.gform-venue-more>summary+*{margin-top:14px}
.gform-more>:last-child,.gform-venue-more>:last-child{margin-bottom:14px}
.gform-venue-more textarea{min-height:64px;field-sizing:content;max-height:200px}
/* Times: the gig card's ladder, with a field on each rung. */
.gform-ladder{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.gform-rung{display:flex;align-items:center;justify-content:space-between;gap:12px;background:var(--panel2);padding:6px 6px 6px 14px;min-height:58px}
.gform-rung>label{margin:0;min-width:0;font-size:15px;font-weight:650;line-height:1.3;color:var(--text)}
.gform-rung>label small{display:block;font-size:12px;font-weight:500;color:var(--muted);margin-top:1px}
.gform-rung>.timefield{flex:0 0 136px;width:136px;min-height:46px;margin:0;padding-right:16px;font-size:17px;font-weight:700;font-variant-numeric:tabular-nums}
.gform-rung.problem{background:var(--conflict-surface);box-shadow:inset 3px 0 var(--bad)}
.gform-rung.problem>.timefield{border-color:var(--bad)}
.gform-times-note{font-size:13px;line-height:1.45;color:var(--detail-text);margin:8px 0 0}
.gform-times-note.problem{color:var(--bad);font-weight:650}
/* Details: the notes (visible, growing with their text), then sets and extras as one-tap choices. */
.gform-details>.field{margin-bottom:14px}
.gform-details textarea{min-height:84px;field-sizing:content;max-height:260px}
.gform-ref{margin:8px 0 0;padding:2px 0 2px 12px;border-left:3px solid var(--line2);font-size:13px;line-height:1.45;color:var(--notes-text);white-space:pre-wrap;overflow-wrap:anywhere}
.gform-ref>span{display:block;font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);white-space:normal}
.gform-options{min-width:0;border:0;padding:0;margin-top:14px}
.gform-options>legend{padding:0;margin:0 0 8px;font-size:12px;font-weight:700;color:var(--notes-text)}
.gform-sets-more{margin-top:12px}
.gform-sets-more .field{margin-bottom:0}
.gform-pills{display:grid;grid-template-columns:1.6fr repeat(4,minmax(0,1fr));gap:6px}
.gform-chips{display:flex;flex-wrap:wrap;gap:8px}
/* The input covers its whole label, invisible but still what is tapped, focused and read out; the span is what is drawn. */
.gform-pill,.gform-chip,.gform-choice{position:relative;display:block;margin:0}
.gform-pill>input,.gform-chip>input,.gform-choice>input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer;z-index:1}
.gform-pill>span,.gform-chip>span{display:flex;align-items:center;justify-content:center;min-height:44px;padding:0 14px;border:1px solid var(--line2);border-radius:22px;background:var(--panel);color:var(--text);font-size:14px;font-weight:600;line-height:1.2;text-align:center}
.gform-pill>span{padding:0 6px}
.gform-pill>input:checked+span,.gform-chip>input:checked+span,.gform-choice>input:checked+span{border-color:var(--mine-border);background:var(--accent-surface);color:var(--text);box-shadow:inset 0 0 0 1px var(--mine-border)}
.gform-pill>input:checked+span,.gform-chip>input:checked+span{font-weight:750}
.gform-chip>input:checked+span::before{content:"\2713";content:"\2713" / "";margin-right:7px;font-weight:800}
.gform-pill>input:focus-visible+span,.gform-chip>input:focus-visible+span,.gform-choice>input:focus-visible+span{outline:3px solid var(--focus);outline-offset:2px}
/* The one decision: has the venue said yes. Chosen reads like a chosen appearance, never a second lime. */
.gform-choice{margin:0 0 8px}
.gform-choice>span{display:block;position:relative;padding:13px 14px 13px 46px;border:1px solid var(--line2);border-radius:12px;background:var(--panel);color:var(--text);font-weight:500}
.gform-choice>span::before{content:"";position:absolute;left:14px;top:15px;width:20px;height:20px;box-sizing:border-box;border:2px solid var(--line2);border-radius:50%;background:var(--panel)}
.gform-choice>input:checked+span::before{border-color:var(--text);background:var(--text);box-shadow:inset 0 0 0 4px var(--panel)}
.gform-choice>input:disabled{cursor:not-allowed}
/* h38 review dimmed only the control, so the reason under "Confirmed by the venue" keeps its contrast. But the input is
   the invisible tap target stretched over the whole card (opacity:0 above): dimming it to .55 drew the browser's own
   radio across the card, a circle as tall as the card on Steve's iPhone (3 Oct, "unusually massive circle"). The
   control that is drawn is the span's circle, so that is what dims; the input stays invisible. */
.gform-choice>input:disabled+span{opacity:1}
.gform-choice>input:disabled+span::before{opacity:.55}
.gform-choice strong{display:block;font-size:15px;line-height:1.35}
.gform-choice small{display:block;font-size:13px;line-height:1.4;color:var(--detail-text);margin-top:2px}
.gform-override{border-left:3px solid var(--warn);border-radius:0 12px 12px 0;background:var(--maybe-surface);color:var(--text);padding:2px 13px 12px;margin:10px 0 0}
.gform-override .check-label{font-size:14px;font-weight:700;color:var(--text)}
.gform-override .inline-note{margin-top:0;font-size:13px;line-height:1.45;color:var(--detail-text)}
/* Book this date says what booking does to the enquiry, date by date. */
.gform-booking-what{font-size:14px;line-height:1.5;color:var(--text);margin:0;overflow-wrap:anywhere}
.gform-released{list-style:none;display:grid;gap:1px;margin:8px 0 0;padding:0;background:var(--line);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.gform-released>li{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:2px 12px;background:var(--panel2);padding:10px 13px;font-size:14px;font-weight:650}
.gform-verdict{font-size:13px;font-weight:650}
.gform-verdict.good{color:var(--good)}
.gform-verdict.cover{color:var(--cover)}
.gform-verdict.warn{color:var(--warn)}
.gform-verdict.wait{color:var(--waiting-text)}
.gform-verdict.bad{color:var(--bad)}
.gform-better{border-left:3px solid var(--warn);border-radius:0 12px 12px 0;background:var(--maybe-surface);color:var(--text);font-size:13px;line-height:1.45;padding:9px 13px;margin:10px 0 0}
.gform-booking-undo{font-size:13px;line-height:1.45;color:var(--detail-text);margin:10px 0 0}
/* Last: what is still missing or why the button is off, then the one button, full width. */
.gform-end{margin-top:18px}
.gform-needed,.gform-why{font-size:13px;line-height:1.45;margin:0 0 6px;overflow-wrap:anywhere}
.gform-needed{color:var(--detail-text)}
.gform-why{color:var(--text);font-weight:650}
.gform .gform-offline{margin:0 0 6px}
.gform>.gform-actions{border-top:0;margin-top:6px;padding-top:6px}
.gform>.gform-actions>button{flex:1 1 100%;min-height:50px;font-size:16px}
/* Save's field errors sit under the field they are about. */
.gform-error{font-size:13px;font-weight:650;line-height:1.4;color:var(--bad);margin:6px 0 0}
.gform input[aria-invalid=true],.gform .timefield[aria-invalid=true]{border-color:var(--bad);box-shadow:0 0 0 1px var(--bad)}
@media(max-width:550px){
  .gform-rung>.timefield{flex-basis:128px;width:128px}
  .gform-facts>div{grid-template-columns:118px minmax(0,1fr)}
}
@media(max-width:350px){
  .gform-rung>.timefield{flex-basis:112px;width:112px}
  .gform-pills{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* h39 · Tapping outside a card closes it, and one scrolling clock sets every time in the app. Existing tokens only
   (--panel, --panel2, --line, --line2, --text, --muted, --accent, --accent-surface, --input-surface), so the Day/Night
   variable guard and the contrast sweep cover this block unchanged, and no text carries opacity. */
/* Without this a backdrop tap can sit behind iOS's 300ms double-tap-zoom wait, which reads as the gesture not working.
   styles.css already sets it on button/a/input/textarea, but not on the sheet itself. */
.action-dialog{touch-action:manipulation}
/* The field shows a time and opens the clock; it is not typed into. Since h43 it is a <button> (see timeInput in
   app.js: iOS opened its own wheel whenever focus came back to an <input type="time">, readonly or not), drawn as
   the time input it replaced — the input box styles.css gives every field, 16px so nothing zooms, the value on the
   left in tabular figures, and the field's own "this opens a chooser" mark on the right, inside the button, so a tap
   on the mark is a tap on the field: one target, one thing that happens. The button's own hover fill is not taken:
   a field does not light up like an action. An empty time shows --:-- in the muted colour, as the native field did. */
.timefield{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-width:0;min-height:47px;margin:0;padding:11px 14px 11px 12px;border:1px solid var(--line2);border-radius:10px;background:var(--input-surface);color:var(--text);font-size:16px;font-weight:500;line-height:1.45;text-align:left;font-variant-numeric:tabular-nums;cursor:pointer;user-select:none;-webkit-user-select:none}
.timefield:hover{background:var(--input-surface);border-color:var(--line2)}
.timefield:disabled{opacity:.65}
.timefield-value{min-width:0;white-space:nowrap}
.timefield[data-empty] .timefield-value{color:var(--muted)}
.timefield[aria-expanded="true"]{border-color:var(--accent)}
.timefield-mark{flex:none;font-size:13px;line-height:1;color:var(--muted)}
/* The sheet is a layer back while the clock is up: inert, and under the veil — one scrim over the whole viewport,
   which also carries the tap that dismisses the clock. A scrim rather than opacity on .dialog-head and #dialogBody:
   the head is sticky over its own content, so making it translucent lets the form scroll visibly through it. The
   literal follows .action-dialog::backdrop in styles.css, which is the same kind of decision. */
/* A modal sheet is in the top layer, above #toast and above every z-index in the page, so anything said to someone
   looking at a sheet is said in the sheet. The head is sticky, so the line is on screen however far the sheet is
   scrolled — unlike #dialogError, which sits after #dialogBody and is below the fold on a tall sheet. It is a note
   in the head's own grid, on the row under the title, like .dialog-back above it. */
.dialog-note{grid-column:1/-1;margin:2px 0 8px;padding:9px 12px;font-size:13px;line-height:1.35;color:var(--notes-text);background:var(--panel2);border:1px solid var(--line2);border-radius:10px;overflow-wrap:anywhere}
.twheel-veil{position:fixed;inset:0;z-index:6;background:#0006}
/* Pinned to the bottom inside edge of the sheet at every width: sticky is what beta.css already endorses for this
   scroller, and it means a sheet that is already scrolled needs no arithmetic. Being in flow, the tray also lengthens
   the scroll, so the last field still clears it. */
.twheel{position:sticky;bottom:0;z-index:7;margin-top:18px;padding:12px 14px;background:var(--panel2);border:1px solid var(--line2);border-radius:14px}
.twheel-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;min-height:22px}
.twheel-head .section-label{margin:0}
.twheel-now{font-size:15px;font-weight:750;font-variant-numeric:tabular-nums;color:var(--text)}
.twheel.pending .twheel-now{font-weight:600;color:var(--muted)}
.twheel-body{position:relative;display:flex;align-items:stretch;justify-content:center;gap:4px;margin:8px 0 4px}
/* 220px of column is five 44px rows; 88px of padding at each end is two more, so the first and last value can still
   reach the middle. The band must agree with that arithmetic or the chosen row sits off centre: row i is at
   88 + 44i, the column shows 220, so centring it is scrollTop = 44i and the band sits at top:88px, height 44px. */
.twheel-band{position:absolute;left:6px;right:6px;top:88px;height:44px;background:var(--accent-surface);border-top:1px solid var(--line2);border-bottom:1px solid var(--line2);pointer-events:none;z-index:0}
.twheel.pending .twheel-band{background:transparent;border:1px dashed var(--line2)}
.twheel-col{position:relative;z-index:1;width:96px;height:220px;overflow-y:scroll;scroll-snap-type:y mandatory;overscroll-behavior:contain;touch-action:pan-y;scrollbar-width:none}
.twheel-col::-webkit-scrollbar{display:none}
/* h39 review · Chrome matches :focus-visible on a programmatic focus that followed a touch, so opening the clock
   with a finger painted a 3px lime frame round the hour column — louder than the band, which is the thing that
   actually says which number is chosen — and a finger's Set left one round the field. data-quiet-focus is the
   one-shot the app sets on those pointer paths only; the first key clears it, so every keyboard ring is untouched.
   var(--focus) rather than var(--accent), which is what every other focus ring in the app uses in both themes. */
.twheel-col:focus-visible{outline:3px solid var(--focus);outline-offset:-3px;border-radius:11px}
.twheel-col[data-quiet-focus]:focus-visible,.timefield[data-quiet-focus]:focus-visible{outline:none}
.twheel-pad{height:88px}
.twheel-item{height:44px;display:grid;place-items:center;scroll-snap-align:center;font-size:21px;font-weight:650;font-variant-numeric:tabular-nums;color:var(--muted);cursor:pointer}
.twheel-item.on{color:var(--text);font-weight:800}
.twheel-colon{position:relative;z-index:1;align-self:center;font-size:21px;font-weight:800;color:var(--text)}
/* h43 · Steve: Clear "needs to be a button with a centered label". Two real buttons, side by side and the same
   size: Clear the quiet one — the sheet's own panel colour inside the tray, a full-strength outline and the text
   colour, so it reads as a button in Day and Night without competing with the lime — and Set the lime primary. Each
   takes half the foot, 48px tall, with its label centred both ways. */
.twheel-foot{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding-top:8px}
.twheel-foot button{display:flex;align-items:center;justify-content:center;min-width:0;min-height:48px;margin:0;padding:10px 14px;font-size:16px;font-weight:750;line-height:1.2;text-align:center}
.twheel-foot .secondary{background:var(--panel);border-color:var(--line2);color:var(--text)}
.twheel-foot .secondary:hover{background:var(--hover);border-color:var(--muted)}
/* v025 popups · The tray no longer adds the home indicator's inset under Clear and Set, at any width. h39 had already
   taken it off the phone's bottom sheet (a 34px dead strip under Set, and 34px off the dials on the narrowest screen in
   the band); above 550px it was what kept Clear and Set off an iPad's indicator. Every sheet is centred now, with a
   gap below it that clears the indicator, so the tray, pinned inside the sheet, can never reach it. The phone's
   margin-top:auto went with the 70dvh floor it filled: there is no spare height in a sheet as tall as what it holds. */
/* h39 review · A phone on its side is 375px tall: the sheet is capped at 100dvh - 24px = 351px and a 330px tray
   covers all of it — the head, the ×, and the very field being set. Three visible rows instead of five brings the
   tray to ~242px, which leaves the head and the field clear and gives openTimeWheel's scroll room to work. Every
   number the clock counts on is kept: rows stay 44px, the pad is (column - 44)/2 so row i still sits at 44 + 44i,
   centring row i is still scrollTop = 44i, and the band still starts one row down. */
@media(max-height:520px){
  .twheel-col{height:132px}
  .twheel-pad{height:44px}
  .twheel-band{top:44px}
  /* Even at 242px the tray leaves only 12px between the sticky head and itself, and a time field is 51px: sideways
     there is no scroll position where the field clears both. The head is inert while the clock is up — the × cannot
     be used, and the tray's own head names the time being set — so it gives up its pin and scrolls with the sheet,
     which leaves the whole 88px above the tray for the field. It sticks again the moment the clock closes. */
  .action-dialog.wheel-open .dialog-head{position:static}
}
@media(max-width:350px){
  .twheel-col{width:84px}
}
/* h41 · Me: Sign out on its own at the foot of the page, and the My icon picker. Existing tokens only (--line,
   --panel2, --text, --muted, --accent, --accent-surface), so the Day/Night variable guard and the contrast sweep cover
   this block unchanged. Tiles are 44px targets and more; the page still has no lime button (Sign out is secondary). */
.me-signout{margin-top:28px;padding-top:20px;border-top:1px solid var(--line)}
.me-signout>button{min-height:48px}
.role-icon-intro{margin:0 0 14px}
.role-icon-stale{margin:0 0 14px}
.role-icon-search{margin:0 0 14px}
.role-icon-group{margin-top:18px}
.role-icon-group>.section-label{margin:0 0 8px}
.role-icon-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px}
.role-icon-tile{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:6px;min-height:44px;padding:10px 2px 8px;border:1px solid var(--line);border-radius:12px;background:var(--panel2);color:var(--text);font-weight:600}
.role-icon-tile .member-mark.identity{width:48px;height:48px}
/* Measured at 375pt: every catalogued word fits a tile's width, Photographer by its soft hyphen (tools/role-icons.mjs).
   A name from a slug Steve adds later may not, so hyphenation, then any break, is the last resort. */
.role-icon-tile{min-width:0}
.role-icon-name{font-size:12px;line-height:1.25;text-align:center;-webkit-hyphens:auto;hyphens:auto;overflow-wrap:anywhere}
/* The icon in use: the accent border and a tick, said once and in the tile's own label for a screen reader. */
.role-icon-tile.chosen{border:2px solid var(--accent);background:var(--accent-surface);padding:9px 1px 7px}
.role-icon-tick{position:absolute;top:4px;right:7px;font-size:13px;line-height:1;font-weight:800;color:var(--accent)}
.role-icon-note{margin-top:14px}
/* h42 · D12 · Joining the band. The join card is the sign-in card's twin: same surface, one stage at a time, one lime
   button per stage, text buttons for the ways out. Band access gains the people asking to join, the join code and a
   line per place, in the sheet's existing grammar. Existing tokens only, so Day and Night follow by themselves. */
.join-entry{display:block;margin:0;color:var(--text);font-weight:650}
.signed-in-here .join-entry{display:none}
.join-brand{font-size:32px;font-weight:800;letter-spacing:-1px}
.join-title{font-size:22px;letter-spacing:-.5px;text-align:center;margin:0 0 8px}
.join-intro{color:var(--muted);font-size:14px;line-height:1.5;text-align:center;margin:0 0 20px;overflow-wrap:anywhere}
.join-intro .nowrap{white-space:nowrap}
.join-form{display:grid}
.join-form .primary{margin-top:4px}
.join-steps{margin:0 0 16px;padding-left:22px;display:grid;gap:8px;font-size:14px;line-height:1.45;color:var(--detail-text)}
.join-code{font-size:30px;font-weight:800;letter-spacing:.12em;text-align:center;font-variant-numeric:tabular-nums;margin:6px 0 8px;-webkit-user-select:all;user-select:all;overflow-wrap:anywhere}
.join-card .inline-note{margin:0 0 16px;text-align:center}
.join-card .join-message:empty{display:none}
.join-alt{margin-top:10px}
.join-places{border:0;padding:0;margin:0 0 16px;display:grid;gap:8px;min-width:0}
.join-place{display:grid;grid-template-columns:auto auto 1fr;align-items:center;gap:10px;margin:0;padding:10px 12px;border:1px solid var(--line);border-radius:14px;background:var(--panel2);color:var(--text);font-size:15px;font-weight:650;cursor:pointer}
.join-place input{width:20px;height:20px;min-height:0;margin:0;padding:0;accent-color:var(--accent)}
.join-place:has(input:checked){border-color:var(--accent);background:var(--accent-surface)}
.join-place.barred{cursor:not-allowed;opacity:.75}
.join-place-name{display:grid;gap:2px;min-width:0}
.join-place-name small{color:var(--muted);font-size:12px;font-weight:500;line-height:1.4}
.acc-section{display:grid;gap:10px;margin:0 0 22px}
.acc-section .section-label{margin:0}
.acc-request{display:grid;gap:6px;padding:12px;border:1px solid var(--line);border-radius:14px;background:var(--panel2)}
.acc-request .sub-actions{margin-top:4px}
.acc-request-head{margin:0;font-size:15px;overflow-wrap:anywhere}
.acc-meta{margin:0;color:var(--muted);font-size:12px}
.acc-warn{margin:0;color:var(--warn);font-size:13px;line-height:1.45}
.acc-place{display:grid;gap:4px;padding:10px 0;border-top:1px solid var(--line)}
.acc-place-head{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:10px}
.acc-who{margin:0;display:grid;gap:2px;min-width:0}
.acc-state{color:var(--muted);font-size:12px;overflow-wrap:anywhere}
.acc-release{color:var(--bad);border-color:var(--danger-border)}
.acc-edit summary{display:flex;align-items:center;min-height:44px;color:var(--muted);font-size:13px;cursor:pointer}
.acc-place .access-row{margin-bottom:6px}
.acc-earlier{margin:6px 0;color:var(--muted);font-size:12px;overflow-wrap:anywhere}
.acc-section .inline-note{margin:0}
.acc-section .sub-actions{margin-top:0}
/* D51 · Edit name and part (Band → Manage access → Places, docs/ROLES_DESIGN.md §2). The two fields stack full width at
   every width, so a 20-character name and a 40-character part fit a 320px phone with room for the thumb; Save sits under
   them at 44px. The note and the boxes wrap rather than push the sheet sideways. Existing tokens only (the fields and the
   secondary button already have their Day and Night looks), so both appearances follow by themselves. */
.place-form{display:grid;margin:0 0 8px;min-width:0}
.place-form .field{margin-bottom:12px;min-width:0}
.place-form input{width:100%;min-width:0}
.place-form .inline-note{margin:0 0 10px;overflow-wrap:anywhere}
.place-actions{display:flex;justify-content:flex-end}
.place-actions button{min-height:44px;min-width:88px}
/* h43 · Change my icon (Me) and Manage access (Band) are controls at rest, not text that only answers a hover a phone
   has not got. Each is a secondary button (its outline and fill) sized for a thumb, 44px and more, with the quiet row's
   chevron for "opens a sheet". The chevron is generated content with empty alternative text, so each button's name is
   exactly its words. button.sheet-button outranks .sub-actions button's 12px. Existing tokens only (--text, --muted),
   so Day and Night follow by themselves. Manage access starts at the page's left edge (styles.css .manage-access). */
button.sheet-button{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 12px 10px 14px;border-radius:11px;font-size:14px;line-height:1.2;color:var(--text);text-align:left}
button.sheet-button::after{content:"\203A";content:"\203A" / "";color:var(--muted);font-size:19px;font-weight:400;line-height:1}
/* On Band it sits under Venue Book and Beta feedback, so it takes their type size, as a sibling rather than a louder one. */
.manage-access>button.sheet-button{font-size:12px}
.manage-access>button.sheet-button::after{font-size:17px}
/* h43 · The confirmation card (confirmCard in app.js): GigLock's own popup in place of the browser's confirm(). A small
   card centred over the sheet's own dimmed backdrop, at every width: it asks one question, so it is never the bottom
   sheet. The question is its heading and what it costs sits under it; then the ranked action (lime, or the danger
   style when the answer loses something) above the way out, each a full-width 48px target. Existing tokens and button
   classes only, so Day and Night follow by themselves and the contrast sweep covers this block unchanged. */
.confirm-card{width:min(360px,calc(100% - 32px));max-height:calc(100dvh - 32px);margin:auto;padding:26px 22px 20px;overflow:auto;overscroll-behavior:contain;border:1px solid var(--line2);border-radius:21px;background:var(--panel);color:var(--text);box-shadow:0 20px 100px #0009;text-align:center;touch-action:manipulation}
/* D74 · No blur behind a card, a sheet (styles.css) or the top bar: on an iPhone a blurred backdrop is drawn again over
   the whole page each time one opens or the page moves. A shade darker instead, so what is behind still recedes. */
.confirm-card::backdrop{background:#000c}
/* h43 D24 · Balanced lines, so a question or its cost never ends on one stranded word ("Colin.", "lost.") at 390px. */
.confirm-title{font-size:19px;line-height:1.3;letter-spacing:-.3px;overflow-wrap:anywhere;text-wrap:balance}
.confirm-message{margin-top:10px;font-size:14px;line-height:1.5;color:var(--detail-text);overflow-wrap:anywhere;text-wrap:balance}
.confirm-actions{display:grid;gap:10px;margin-top:22px}
.confirm-actions>button{width:100%;min-height:48px;font-size:15px}
/* v025 popup outline · Steve, 3 Oct: "Some popups have a thin electric blue outline - I like this. Ensure all popups
   have a thin blue outline app wide." The blue he saw was the browser's own focus ring, drawn round a popup only while
   the popup itself held focus (after a tap on its plain text, say), so it came and went. Now every popup has it, always:
   every sheet, the My icon card and the confirmation card. Placed after .confirm-card, which sets its own border.
   · Nothing moves or changes size. The 1px border every popup already has turns blue, and a 1px ring of the same blue
     is drawn just outside it as a shadow, which takes no room. The drop shadow under the popup is kept.
   · The browser's ring is off on the popup itself, so it never doubles the line where it used to appear. Controls inside
     keep their own focus rings, and the set list's drop outline (.action-dialog.sl-dropping) outranks this and shows.
   · --popup-ring is the system blue of each palette: #0a84ff on Night, #007aff on Day. */
:root{--popup-ring:#0a84ff}
:root[data-appearance="day"]{--popup-ring:#007aff}
.action-dialog,.confirm-card{border-color:var(--popup-ring);box-shadow:0 0 0 1px var(--popup-ring),0 20px 100px #0009}
dialog:focus-visible{outline:none}
/* D39 · The band's name and logo (docs/BAND_IDENTITY_DESIGN.md). In the header the brand shrinks and only the name gives
   way, ending in "…", so the bell and Me always fit at 320px, with "GigLock" small above it. A logo sits on its own
   plate, light or dark in Day and Night alike because it is the logo's background, not the app's, and never in
   .member-mark, which crops, enlarges and tints. Without the band's identity the header keeps h46's markup, and
   nothing here matches it. The preview strips in the sheet draw the phone header in fixed Night and Day colours
   (styles.css :root and :root[data-appearance="day"]), whichever the app is in. */
.brand.band-brand{min-width:0;flex:0 1 auto;gap:9px}
.band-brand~.account-area{flex:none}
.band-pic,.band-card-pic{flex:none;display:flex}
.band-plate{display:grid;place-items:center;flex:none;width:37px;height:37px;padding:3px;border-radius:9px}
.band-plate.light{background:#f7f8f4;box-shadow:inset 0 0 0 1px #0000001f}
.band-plate.dark{background:#15191e;box-shadow:inset 0 0 0 1px #ffffff29}
.band-plate img,.brand .band-plate img{display:block;width:100%;height:100%;object-fit:contain;border-radius:0}
.brand-text{display:flex;flex-direction:column;min-width:0;line-height:1.1}
/* Steve, 28 Sep: GigLock's own line, its mark and name side by side and centred across the top of the bar, above the
   band's row ("Own line at the top"). The bar becomes a two-row grid and grows by the line; nothing else sticks to the
   top of the page, so nothing slides under it. A grid, not a wrapping flex row: the band's row must never wrap (on a
   320 px phone the bell and Me would drop to a third row); its first column shrinks and the name ends in "…" as
   before. .brand's narrow-screen padding-top belonged to the old one-row bar. */
.topbar.has-giglock-line{display:grid;grid-template-columns:minmax(0,1fr) auto;row-gap:2px;align-items:center;padding-top:6px;padding-bottom:8px}
.topbar.has-giglock-line .giglock-line{grid-column:1/-1}
.topbar.has-giglock-line .brand{padding-top:0;justify-self:start;max-width:100%}
.giglock-line{display:flex;align-items:center;justify-content:center;gap:6px;height:20px;font-size:13px;font-weight:750;letter-spacing:.02em;line-height:1;color:var(--muted);white-space:nowrap}
.giglock-line img{flex:none;display:block;width:18px;height:18px}
.band-pic:empty{display:none}
.band-brand .brand-name{font-size:22px;letter-spacing:-.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.band-identity-card{margin:0 0 16px}
.band-identity-head{display:flex;align-items:center;gap:14px;min-width:0}
.band-identity-head h1{font-size:22px;line-height:1.2;margin:0;min-width:0;overflow-wrap:anywhere}
.band-card-pic .band-plate{width:64px;height:64px;padding:5px;border-radius:14px}
.band-identity-card .sub-actions{margin-top:10px}
/* The strips are the header of a 320px phone, the narrowest it is built for, at its own sizes there (a 30px plate or
   mark 9px from the name; the 36px bell and 42px Me, 4px apart and 4px from the brand; 12px in from each edge), so a
   name ends in "…" in the preview exactly when it does in that header. Where the sheet is narrower than 320px (on a
   320px phone), the strip is zoomed down whole, never laid out narrower. */
.band-preview{display:grid;gap:8px;margin:0 0 18px;container-type:inline-size}
.band-strip{border-radius:12px;padding:7px 0 0;overflow:hidden}
.band-strip.night{background:#0b0d10;color:#f4f6f8;box-shadow:inset 0 0 0 1px #2b323a}
.band-strip.day{background:#f2f4ef;color:#242c24;box-shadow:inset 0 0 0 1px #cdd5c8}
.band-strip-label{display:block;padding:0 12px;font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase}
.band-strip-bar{display:flex;align-items:center;justify-content:space-between;gap:4px;width:320px;height:58px;padding:0 12px}
.band-strip .brand{color:inherit;font-size:19px}
.band-strip .band-brand .brand-name{font-size:18px}
/* The small lines are painted on the strip's own colour, said here too so the contrast sweep measures the real pair. */
.band-strip.night .giglock-line,.band-strip.night .band-strip-label{color:#a3adb8;background:#0b0d10}
.band-strip.day .giglock-line,.band-strip.day .band-strip-label{color:#586354;background:#f2f4ef}
/* GigLock's line in the preview, centred over the 320 px bar it sits on, and zoomed with it on a narrower sheet. */
.band-strip .giglock-line{width:320px;margin:4px 0 -4px}
.band-strip .band-brand .band-plate,.band-strip .band-pic>img{width:30px;height:30px}
.band-strip-tools{display:flex;align-items:center;gap:4px;flex:none}
.band-strip-tools span{width:36px;height:36px;border-radius:50%;border:1px solid currentColor;opacity:.3}
.band-strip-tools span+span{width:42px;height:42px}
@container (max-width:319.98px){.band-strip-bar{zoom:.9375}}
@container (max-width:299.98px){.band-strip-bar{zoom:.875}}
@container (max-width:279.98px){.band-strip-bar{zoom:.8125}}
@container (max-width:259.98px){.band-strip-bar{zoom:.75}}
@container (max-width:319.98px){.band-strip .giglock-line{zoom:.9375}}
@container (max-width:299.98px){.band-strip .giglock-line{zoom:.875}}
@container (max-width:279.98px){.band-strip .giglock-line{zoom:.8125}}
@container (max-width:259.98px){.band-strip .giglock-line{zoom:.75}}
.band-logo-actions{display:flex;flex-wrap:wrap;gap:10px}
label.band-file{display:inline-flex;align-items:center;min-height:44px;margin:0;padding:10px 15px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);color:var(--text);font-size:15px;font-weight:650;cursor:pointer}
label.band-file:hover{border-color:var(--line2);background:var(--hover)}
#bandIdentityForm:has(#bandLogoFile:focus-visible) label.band-file{outline:3px solid var(--focus);outline-offset:2px}
.band-plate-choice{margin-top:14px}
.band-plate-choice .section-label{margin:0 0 6px}
.band-plate-pills{display:grid;grid-template-columns:repeat(2,minmax(0,112px));gap:6px}
@media(max-width:600px){.band-brand .brand-name{font-size:18px}.giglock-line{font-size:12px}}
@media(max-width:550px){.band-brand .band-plate{width:34px;height:34px}}
@media(max-width:350px){.band-brand .band-plate{width:30px;height:30px}}
/* v025 · D59 (D23) · Notification settings: this phone, the five alert switches, email, my devices. Tidied on 3 Oct
   (Steve: "clean up the Notification setting page"; the switches "make the haptics function, but does nothing else
   visually"): grouped cards as in iPhone Settings, each section's small heading above its card, every alert a row
   with its switch on the right. The switch is drawn here, not by the browser (Safari's own, squeezed into a small box,
   flipped without showing it): on, it fills with the accent and the knob moves right; off, an outline with the knob on
   the left, in Day and Night alike. The whole row is its label. Existing tokens only; every control 44px or more. */
.push-phone{margin:0 0 18px}
.push-group{margin:0;padding:0 14px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
.push-card{padding:12px 14px}
.push-card p{margin:0}
.push-card .stack-actions,.push-card .sub-actions{margin:10px 0 0}
.push-card .inline-note{margin:8px 0 0}
.push-card>:first-child{margin-top:0}
.push-on{display:flex;align-items:center;gap:8px;font-weight:600}
.push-dot{flex:none;width:10px;height:10px;border-radius:50%;background:var(--accent)}
.push-alerts{border:0;padding:0;margin:0 0 18px;min-width:0}
.push-alerts legend{padding:0;margin:0 0 8px}
.push-alert{display:flex;align-items:center;justify-content:space-between;gap:14px;min-height:56px;padding:10px 0;cursor:pointer}
.push-alert+.push-alert{border-top:1px solid var(--line)}
.push-alert-text{display:flex;flex-direction:column;gap:2px;min-width:0;overflow-wrap:anywhere}
.push-alert-name{font-size:15px;font-weight:650;line-height:1.3;color:var(--text)}
.push-alert-hint{font-size:13px;line-height:1.35;color:var(--muted)}
.push-switch{-webkit-appearance:none;appearance:none;flex:none;box-sizing:border-box;width:52px;height:32px;min-height:0;padding:0;margin:0;border:2px solid var(--muted);border-radius:16px;cursor:pointer;--knob:var(--muted);background:radial-gradient(circle,var(--knob) 0 11px,transparent 11.5px) 0 50%/28px 28px no-repeat var(--panel);transition:background-position .15s ease,background-color .15s ease,border-color .15s ease}
.push-switch:checked{--knob:var(--bg);border-color:var(--accent);background-color:var(--accent);background-position:100% 50%}
.push-switch:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.push-switch:disabled{opacity:.5;cursor:default}
@media (prefers-reduced-motion:reduce){.push-switch{transition:none}}
.push-foot{margin:8px 2px 0;font-size:13px;line-height:1.4;color:var(--muted)}
.push-email{margin:0 0 18px}
.push-email>label{margin:0 0 8px}
.push-devices{list-style:none;margin:0 0 18px}
.push-device{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:48px;padding:6px 0}
.push-device+.push-device{border-top:1px solid var(--line)}
.push-device-name{flex:1 1 auto;min-width:0;font-size:14px;line-height:1.35;overflow-wrap:anywhere}
.push-device .text-button{flex:none;white-space:nowrap}
/* Steve's Email delivery: the Phone alerts lines are their own section, with room above the heading. */
.push-delivery{margin:18px 0 4px}
.push-delivery>.section-label{margin:0 0 6px}
/* v025-sl1 · Set lists (docs/SETLISTS_DESIGN.md §5): the Song Book, a song and its form, the gig card's Set list block,
   the Set list sheet, Edit set list, Add songs and Copy a set list. Existing tokens only, so Night and Day follow by
   themselves and the contrast sweep measures every pair here; every control is 44px or more, and every box 16px (the
   sheet's own rule), so iOS never zooms. On the night the Set list sheet is read at arm's length: big titles, each
   song's number on the left and its length lined up on the right. */
.sl-search{margin:0 0 10px}
.sl-book-add{margin:0 0 12px}
.sl-list{display:grid;gap:6px}
button.sl-row{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;min-height:52px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);color:var(--text);text-align:left;font-weight:500}
.sl-row-main{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.sl-row-main strong{font-size:15px;font-weight:700;line-height:1.3}
.sl-row-main small{font-size:13px;line-height:1.35;color:var(--muted)}
.sl-len{flex:none;font-size:14px;color:var(--muted);font-variant-numeric:tabular-nums}
.sl-empty{padding:16px 2px;text-align:left}
.sl-undo{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 0 12px;padding:2px 2px 2px 12px;border:1px solid var(--line2);border-radius:10px;background:var(--panel2);color:var(--text);font-size:14px}
.sl-facts{margin:0 0 4px}
.sl-none{font-size:14px;line-height:1.45;color:var(--muted)}
.sl-used .venue-result{margin:6px 0 0}
/* The song form: Length is two small boxes, minutes : seconds, under one legend. */
.sl-length{min-width:0;margin:0 0 16px;padding:0;border:0}
.sl-length>legend{margin:0 0 7px;padding:0;font-size:12px;font-weight:700;color:var(--notes-text)}
.sl-form .field>label small,.sl-length>legend small{margin-left:6px;font-size:12px;font-weight:500;color:var(--muted)}
.sl-length-row{display:flex;align-items:flex-end;gap:8px}
.sl-length-row>.field{width:92px;margin:0}
.sl-colon{padding-bottom:11px;font-size:18px;color:var(--muted)}
.sl-form input[aria-invalid=true],.sl-rename input[aria-invalid=true]{border-color:var(--bad);box-shadow:0 0 0 1px var(--bad)}
/* D98 · The gig card's Set list: a tile of its own straight after where and when, its icon and name, the whole of it one
   tap. Outlined like every control that is not the viewer's step (D65); existing tokens only. */
.gig-block.gig-setlist{margin-top:14px;padding-top:0;border-top:0}
.sl-tile{display:flex;align-items:center;gap:12px;width:100%;min-height:68px;margin:0;padding:12px 10px 12px 12px;border:1px solid var(--line2);border-radius:14px;background:var(--panel2);color:var(--text);font-weight:400;text-align:left}
button.sl-tile:hover{border-color:var(--line2);background:var(--hover)}
.sl-tile-icon{display:grid;flex:none;place-items:center;width:44px;height:44px;border:1px solid var(--line2);border-radius:12px;background:var(--bg);color:var(--info)}
.sl-tile-icon svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.sl-tile-body{display:flex;flex:1 1 auto;flex-direction:column;gap:1px;min-width:0}
.sl-tile-name{font-size:17px;font-weight:800;line-height:1.25}
.sl-tile-sum{font-size:14px;font-weight:650;line-height:1.4;overflow-wrap:anywhere}
.sl-tile .sl-none{font-weight:500}
.sl-block-line{font-size:13px;line-height:1.4;color:var(--detail-text);overflow-wrap:anywhere}
.sl-tile-hint{margin-top:3px;font-size:12px;line-height:1.35;color:var(--muted)}
.sl-tile-go{display:flex;flex:none;align-items:center;gap:6px;max-width:44%;font-size:13px;font-weight:700;line-height:1.25;text-align:right}
.sl-tile-go::after{content:"\203A";content:"\203A" / "";color:var(--muted);font-size:26px;font-weight:400;line-height:1}
/* D98-2 · Every gig's Set list button on the Gigs list: under the place, outlined and raised over the card's own tap as
   the place is (.glist-map), the tile's icon smaller, the name over what is on the list. */
.glist-sl{position:relative;z-index:1;display:flex;align-items:center;align-self:flex-start;gap:8px;max-width:100%;min-height:44px;margin:2px 0 0;padding:6px 26px 6px 7px;border:1px solid var(--line2);border-radius:10px;background:var(--panel2);color:var(--text);font-weight:400;line-height:1.3;text-align:left}
.glist-sl:hover{border-color:var(--line2);background:var(--hover)}
.glist-sl::after{content:"\203A";content:"\203A" / "";position:absolute;top:50%;right:9px;transform:translateY(-52%);color:var(--muted);font-size:20px;line-height:1}
.glist-sl>.sl-tile-icon{width:32px;height:32px;border-radius:9px}
.glist-sl>.sl-tile-icon svg{width:19px;height:19px}
.glist-sl-words{display:flex;flex-direction:column;min-width:0}
.glist-sl-name{font-size:14px;font-weight:750}
.glist-sl-sum{font-size:12px;color:var(--muted);overflow-wrap:anywhere}
/* The Set list sheet. D100 · What it is (the gig, the total, the time on stage), one row of tools of equal size with
   their icons in the gig blue (Edit lime for the gig's creator, D65), a quiet Still to add box, then the songs. Existing
   tokens only, so Night and Day follow by themselves; 44px or more. */
.sl-head{display:grid;gap:2px}
.sl-gig,.sl-sent-from{font-size:13px;line-height:1.4;color:var(--muted);overflow-wrap:anywhere}
.sl-summary{font-size:19px;font-weight:800;line-height:1.3}
.sl-gigline{font-size:13px;line-height:1.4;color:var(--detail-text);overflow-wrap:anywhere}
.sl-tools{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:8px;margin:16px 0 0}
button.sl-tool{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-width:0;min-height:72px;padding:10px 6px;border-color:var(--line2);border-radius:14px;font-size:13px;line-height:1.2;text-align:center}
button.sl-tool>svg{flex:none;width:24px;height:24px;stroke-width:1.9}
button.sl-tool.secondary>svg{color:var(--info)}
button.sl-tool>span{overflow-wrap:anywhere}
button.sl-tool:only-child{flex-direction:row;gap:8px;min-height:52px;font-size:15px}
/* D109 (Steve, 1 Nov 2026: "Tidy the formatting of this up") · Still to add is rounded all round like the tools above it,
   with no stripe down its left side, its buttons the same 8px in from the side as from the top and bottom, and the line
   between two rows right across. */
.sl-todo{margin:12px 0 0;border:1px solid var(--line);border-radius:14px;background:var(--panel2)}
.sl-todo-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:60px;padding:8px 8px 8px 16px}
.sl-todo-row+.sl-todo-row{border-top:1px solid var(--line)}
.sl-todo-said{min-width:0;font-size:14px;line-height:1.35;color:var(--detail-text)}
.sl-todo-row>button{flex:none;min-width:112px;min-height:44px;padding:8px 14px;border-radius:9px;font-size:13px}
.sl-set{margin-top:20px}
.sl-set-head{margin:0 0 4px;font-size:15px;line-height:1.35;color:var(--detail-text);overflow-wrap:anywhere}
.sl-view>.sl-none{margin:16px 0 0}
.sl-view>.sl-set{margin-top:22px}
.sl-view .sl-set-head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:0 12px;margin:0 0 6px;font-weight:800;color:var(--text)}
.sl-set-sum{font-size:13px;font-weight:600;color:var(--muted)}
.sl-songs{margin:0;padding:0;list-style:none}
/* D113 (Steve, 1 Nov 2026: "I should be able to click on a song in the set list to find its matched details") · Each song
   is one tap to its own sheet, so it is drawn as the Song Book's rows are (D65: a tappable thing has a button's edge). A
   song not found is not a button: the same box, its edge dashed, no fill. */
.sl-songs>li+li{margin-top:6px}
.sl-song{display:grid;grid-template-columns:2.2ch minmax(0,1fr) auto;align-items:baseline;gap:2px 12px;width:100%;min-height:52px;margin:0;padding:10px 12px 10px 8px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);color:var(--text);text-align:left;font-weight:400}
button.sl-song:hover{background:var(--hover)}
.sl-song.is-gone{border-style:dashed;background:transparent}
/* D115 · The song's cover beside who it's by and its length (not tappable, so no button edge) */
.sl-song-top{display:flex;align-items:flex-start;gap:16px}
.sl-song-top>.sl-facts{flex:1 1 auto;min-width:0}
.sl-art{flex:none;width:96px;height:96px;margin:0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--panel2)}
.sl-art img{display:block;width:100%;height:100%;object-fit:cover}
@media (min-width:480px){.sl-art{width:120px;height:120px}}
.sl-num{font-size:15px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums}
.sl-song-main{display:flex;flex-direction:column;min-width:0;overflow-wrap:anywhere}
.sl-song .sl-title{font-size:20px;font-weight:650;line-height:1.25;color:var(--text)}
.sl-meta{margin-top:2px;font-size:13px;line-height:1.4;color:var(--muted)}
.sl-song>.sl-len{font-size:17px}
.sl-by{margin-top:16px}
/* Edit set list. A lifted row is placed against .sl-edit while the placeholder keeps its place in the list. */
.sl-edit{position:relative}
.sl-eset{margin:0 0 18px;padding:12px 0 0;border-top:1px solid var(--line)}
.sl-eset-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 10px}
.sl-eset-name{margin:0;font-size:17px;line-height:1.3;overflow-wrap:anywhere}
.sl-eset-time{font-size:13px;color:var(--muted)}
.sl-eset-tools{display:flex;gap:2px;margin-left:auto}
.sl-eset-tools>.text-button{padding:8px 12px;font-size:13px}
.sl-rename{margin:6px 0 8px}
.sl-rename-row{display:flex;gap:8px}
.sl-rename-row>input{flex:1 1 auto}
.sl-erows{margin:8px 0;padding:0;list-style:none}
.sl-erows.is-empty{min-height:8px;margin:4px 0}
.sl-erow{display:grid;grid-template-columns:44px minmax(0,1fr) 44px;align-items:center;gap:0 4px;margin:0 0 6px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
button.sl-handle{display:grid;place-items:center;width:44px;min-height:44px;padding:0;border:0;background:transparent;color:var(--muted);cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.sl-handle svg{width:20px;height:20px;fill:currentColor;stroke:none}
button.sl-erow-main{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0;min-height:44px;padding:8px 4px;border:0;background:transparent;text-align:left;font-weight:600}
.sl-erow-main .sl-title{min-width:0;font-size:15px;overflow-wrap:anywhere}
button.sl-take{border:0;background:transparent;color:var(--muted);font-size:22px}
.sl-rowbar{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:6px;padding:0 8px 8px}
.sl-rowbar>button{min-height:44px;padding:8px 12px;font-size:13px}
.sl-rowbar>select{width:auto;min-height:44px}
.sl-eset-empty{margin:0 0 8px;font-size:13px;color:var(--muted)}
button.sl-add{width:100%;border-style:dashed}
.sl-placeholder{margin:0 0 6px;border:2px dashed var(--line2);border-radius:12px;list-style:none}
.sl-erow.sl-lifted{position:absolute;z-index:3;margin:0;box-shadow:0 12px 32px #0006;cursor:grabbing}
.sl-edit.is-dragging{user-select:none;-webkit-user-select:none}
.sl-edit-foot{margin-top:0}
.sl-total{margin:12px 0 0;font-size:15px;font-weight:700}
/* D92 · Add missing lengths: the button under the total, and one song's Minutes and Seconds a row on its sheet */
.sl-lengths-add{margin:8px 0 0}
.sl-lengths>.inline-note{margin:0 0 16px}
.sl-lengths .sl-len-row>legend{font-size:15px;color:var(--text)}
.sl-lengths .sl-len-row>legend small{display:block;margin:2px 0 0}
/* D94 · Change history (site/history.js): the outlined Change history button in an item's foot, under its Created by and
   Last changed lines; the sheet's versions as outlined rows (when, who, what changed; Now on the newest); one version's
   fields with the changed ones marked; and the "Filled in from the version of…" line at the top of a restored edit sheet.
   Existing tokens only, so Night and Day follow by themselves; every control is 44px or more. */
.gig-foot button.history-button,.money-foot button.history-button{display:inline-flex;margin:10px 0 0;min-height:44px}
.gig-foot>.provenance+button.history-button,.money-foot>.provenance+button.history-button{margin-top:8px}
.hx-intro{margin:0 0 12px}
.hx-list{list-style:none;margin:0;padding:0;display:grid;gap:8px}
button.hx-row{display:grid;grid-template-columns:1fr auto;align-items:start;gap:2px 10px;width:100%;min-height:52px;padding:10px 12px;border-radius:10px;text-align:left;font-weight:500}
.hx-when{grid-column:1;font-size:15px;font-weight:700;color:var(--text)}
.hx-who,.hx-what{grid-column:1;font-size:14px;line-height:1.35}
.hx-who{color:var(--muted)}
.hx-what{color:var(--text)}
.hx-now{grid-column:2;grid-row:1;font-size:12px;font-weight:700;color:var(--accent);border:1px solid var(--accent);border-radius:999px;padding:2px 8px}
.hx-by{margin:0 0 12px;color:var(--muted);font-size:14px}
.hx-fields dd{font-weight:600}
.hx-fields .hx-field.is-changed dd{font-weight:700}
.hx-tag{display:inline-block;margin-left:6px;font-size:11px;font-weight:700;color:var(--accent);border:1px solid var(--accent);border-radius:999px;padding:1px 7px;vertical-align:1px}
.hx-note{margin:14px 0 0}
.hx-restore{margin:10px 0 0;border-left:3px solid var(--accent);padding-left:10px}
.sl-by-foot{margin-top:14px}
/* D94-4 · When each answer was given: one quiet line under the member's name (and under an enquiry row's answer). */
.answer-when{color:var(--muted);font-size:12px;line-height:1.45}
.member-info>.answer-when{margin-top:2px}
.money-foot{border-top:1px solid var(--line);margin-top:14px;padding-top:12px}
.money-foot>.provenance{margin:0;line-height:1.55}
.sl-copy{margin:0 0 12px}
/* Add songs: rows that tick; the tick, and "In Set 2" for a song already on the list, sit at either end. */
button.sl-pick-row{justify-content:flex-start}
.sl-tick{flex:none;display:grid;place-items:center;width:24px;height:24px;border:1px solid var(--line2);border-radius:7px;color:var(--accent);font-weight:800}
.sl-pick-row.is-on{border-color:var(--accent)}
.sl-in{flex:none;margin-left:auto;font-size:12px;color:var(--muted)}
/* v025-sl2 · Import songs and song suggestions (docs/SETLISTS_DESIGN.md §8): Import songs beside Add song, the Import
   sheet (a file, a pasted list, or a file dropped on the sheet), Songs found, and Last.fm's suggestions under a song's
   Title. Existing tokens only, so Night and Day follow by themselves and the contrast sweep measures every pair here;
   every control is 44px or more and every box 16px (the sheet's own rule). The file box is the label, as the band logo's
   is; while a file is dragged over the sheet it is outlined, and its head says what dropping does. */
.sl-import-intro{margin:0 0 14px}
.sl-import-pick{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin:0 0 18px}
label.sl-file{display:inline-flex;align-items:center;min-height:44px;margin:0;padding:10px 15px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);color:var(--text);font-size:15px;font-weight:650;cursor:pointer}
label.sl-file:hover{border-color:var(--line2);background:var(--hover)}
.sl-import-pick:has(#songImportFile:focus-visible) label.sl-file{outline:3px solid var(--focus);outline-offset:2px}
.sl-import-pick:has(#songImportFile:disabled) label.sl-file{opacity:.6;cursor:not-allowed}
.sl-drop-hint{margin:0;font-size:13px;color:var(--muted)}
@media(pointer:coarse){.sl-drop-hint{display:none}}
.action-dialog.sl-dropping{outline:3px dashed var(--accent);outline-offset:-6px}
.sl-paste textarea{min-height:150px}
.sl-import-count{margin:0 0 2px;font-size:16px;font-weight:700;line-height:1.35}
.sl-import-skip{margin:0 0 4px;font-size:13px;line-height:1.4;color:var(--muted);overflow-wrap:anywhere}
.sl-import-tools{margin:8px 0 12px}
.sl-import-row.is-off{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:10px 12px;border:1px dashed var(--line2);border-radius:10px;color:var(--muted)}
.sl-import-row.is-off .sl-row-main strong{color:var(--muted)}
.sl-import-row.is-off .sl-tick{visibility:hidden}
/* D110 · Import Song Book: what was looked up for each new song, under its name; the skipped and the not-in-this-file parts set apart from the list. */
.sl-row-main small.sl-import-look{font-size:12px}
#slImportBook:not(:empty),#slImportGone:not(:empty){margin-top:16px}
.sl-why{flex:none;max-width:45%;margin-left:auto;font-size:12px;line-height:1.35;text-align:right;color:var(--muted);overflow-wrap:anywhere}
.sl-suggest{margin:-8px 0 16px}
.sl-suggest-list{display:grid;gap:4px}
button.sl-suggest-item{display:block;width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);color:var(--text);text-align:left;font-size:15px;font-weight:600;line-height:1.3;overflow-wrap:anywhere}
button.sl-suggest-item.is-active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}
.sl-suggest-by{font-weight:500;color:var(--muted)}
.sl-suggest-item small{display:block;margin-top:2px;font-size:12px;font-weight:500;color:var(--muted)}
.sl-suggest-credit{margin:6px 0 0;font-size:12px}
/* D81 · Import a set list (site/setlistimport.js, docs/D81_SETLIST_IMPORT.md): the Import sheet (the Song Book import's
   own look), Check the set list (numbered rows, each saying what it is matched to; × leaves one out), Choose the song,
   and a gig's card outlined while a file is dragged over it. Existing tokens only; 44px targets. "Check this" is said in
   words as well as in the warning tone. */
.slx-pick:has(#setListImportFile:focus-visible) label.sl-file{outline:3px solid var(--focus);outline-offset:2px}
.slx-pick:has(#setListImportFile:disabled) label.sl-file{opacity:.6;cursor:not-allowed}
.slx-hint{margin:6px 0 0}
.slx-rows{margin:6px 0 0;padding:0;list-style:none}
.slx-row{display:grid;grid-template-columns:2.4ch minmax(0,1fr) auto;align-items:center;gap:0 8px;margin:0 0 6px;padding-left:6px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
.slx-row.is-out{border-style:dashed;background:transparent}
.slx-row.is-out .sl-row-main strong{color:var(--muted);text-decoration:line-through}
.slx-row.is-finding .slx-tag{font-style:italic}
button.slx-row-main{display:flex;align-items:center;min-width:0;min-height:52px;padding:8px 4px;border:0;background:transparent;color:var(--text);text-align:left;font-weight:500}
.slx-tag{margin-top:2px;font-size:12px;color:var(--muted)}
.slx-tag.is-check{color:var(--warn);font-weight:650}
button.slx-in{min-height:44px;padding:8px 12px;font-size:13px}
.slx-credit{margin:14px 0 0}
.slx-search{margin:8px 0 14px}
.slx-keep{margin:10px 0 4px} /* D84 · Don’t match it, first on Choose the song */
.slx-search>label{display:block;margin:0 0 6px;font-weight:650}
.slx-search .sl-rename-row>input{min-width:0}
.slx-search .sl-rename-row>button{flex:none;white-space:nowrap}
#slxOptions{display:grid;gap:6px;margin:0 0 14px}
.day-gig.slx-dropping{outline:3px dashed var(--accent);outline-offset:3px}
/* D61 · Gig money (site/money.js, docs/D61_GIG_MONEY_DESIGN.md): the Money part of a gig, Edit money and Band › Money.
   Amounts sit in their own column with tabular figures, so a list of shares reads straight down; "paid" is said in
   words and in the good tone, never by colour alone. Fields keep the app's own sizes (16px on a touch screen, above). */
.gig-money .money-lines{margin:0;display:grid;gap:6px}
.gig-money .money-lines>div{display:flex;justify-content:space-between;gap:12px;align-items:baseline}
.gig-money .money-lines dt{color:var(--muted);font-size:14px;min-width:0;overflow-wrap:anywhere}
.gig-money .money-lines dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}
.money-split{margin:12px 0 6px;font-size:13px;color:var(--muted)}
.money-shares{list-style:none;margin:0;padding:0;display:grid;gap:4px}
.money-shares li{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(88px,auto);gap:10px;align-items:baseline;font-size:14px}
.money-shares .money-who{min-width:0;overflow-wrap:anywhere}
.money-amount,.money-row-amount{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.money-state{font-size:12px;color:var(--muted);text-align:right}
.money-state.good{color:var(--good)}
.money-state.bad{color:var(--bad)}
.money-check{margin:10px 0 0;font-size:13px;color:var(--muted);min-height:1.2em}
.money-check.warn{color:var(--warn)}
.money-check.good{color:var(--good)}
.money-note{margin:0 0 6px;font-size:14px;color:var(--muted)}
.money-mine{margin:0;font-size:15px}
.money-mine strong{font-variant-numeric:tabular-nums}
/* v025-gm5 · Steve, 3 Oct: "Make Money a smooth dropdown collapsable box". The admin's Money part is a box drawn like the
   gig's time ladder above it: a 48px top row (Money, where the money stands, a chevron that turns) over the money
   itself. Opening and shutting slides: the one grid row grows from 0fr to 1fr, which WebKit, Blink and Gecko all
   animate, and the app's reduced-motion rule makes it instant. Shut, what is inside is hidden from taps, Tab and
   VoiceOver once the slide has ended (visibility waits for it); open, at once. The wrapper that clips the slide keeps
   the money 13px in from its edges, clear of the 6px focus ring. */
.money-box{margin:18px 0 0;border:1px solid var(--line);border-radius:10px;background:var(--panel)}
.money-box>.money-head{margin:0}
button.money-toggle{display:flex;align-items:center;gap:10px;width:100%;min-height:48px;margin:0;padding:11px 13px;border:0;border-radius:9px;background:transparent;color:var(--text);text-align:left;line-height:1.3}
.money-title{flex:0 0 auto;margin-right:auto;font-size:15px;font-weight:650}
.money-brief{min-width:0;font-size:13px;font-weight:500;color:var(--muted);text-align:right;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.money-brief strong{font-size:15px;font-weight:650;color:var(--text)}
.money-brief .money-state{font-size:13px}
button.money-toggle::after{content:"\203A";content:"\203A" / "";flex:0 0 auto;width:14px;font-size:19px;font-weight:400;line-height:22px;text-align:center;color:var(--muted);transform:rotate(90deg);transition:transform .26s ease}
.money-box.is-open button.money-toggle::after{transform:rotate(-90deg)}
.money-fold{display:grid;grid-template-rows:0fr;transition:grid-template-rows .26s ease}
.money-box.is-open>.money-fold{grid-template-rows:1fr}
.money-fold-inner{min-height:0;overflow:hidden;visibility:hidden;transition:visibility 0s linear .26s}
.money-box.is-open .money-fold-inner{visibility:visible;transition-delay:0s}
.money-fold-body{margin:0 13px;padding:12px 0 13px;border-top:1px solid var(--line)}
.money-entry{margin-top:18px}
.money-entry .money-button{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}
.money-entry-text{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:0}
.money-entry-title{font-weight:700}
.money-entry-line{font-size:13px;color:var(--muted)}
.money-form .section-label{margin:20px 0 8px}
.money-gig{margin:0 0 12px;color:var(--muted);font-size:14px}
.money-amount-field{display:flex;align-items:center;gap:6px}
.money-amount-field input{flex:1 1 auto;min-width:0}
.money-pound{color:var(--muted)}
.money-cost{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(72px,96px) 44px;gap:6px;align-items:center;margin-bottom:8px}
.money-cost input,.money-share input[type=text]{min-width:0;width:100%}
/* Who played (Steve, 3 Oct: "each band member, fee owed, date and paid tick box on one row"): one row a person, in four
   columns that the small headings above them share; the paid date sits in its own column, empty until Paid is ticked. */
.money-who-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:20px 0 0}
.money-form .money-who-head .section-label{margin:0}
#moneyAllPaidRow[hidden]{display:none}
button.money-all-paid{min-height:44px;padding:6px 12px;border:1px solid var(--line2);border-radius:999px;background:transparent;color:var(--text);font-size:13px;font-weight:650;line-height:1.2}
.money-share-cols,.money-share{display:grid;grid-template-columns:minmax(0,1fr) 72px 112px 44px;gap:4px;align-items:center}
.money-share-cols{padding:2px 0 4px;font-size:12px;color:var(--muted)}
.money-share-cols span:last-child{text-align:center}
.money-share{padding:4px 0;border-top:1px solid var(--line)}
.money-share .money-played{min-width:0}
.money-share .money-played{gap:6px}
.money-share .money-played span{overflow-wrap:break-word;min-width:0}
.money-share-field{display:flex;align-items:center;gap:4px;min-width:0}
.money-paid-cell{min-width:0}
.money-paid-cell .money-paid-on{width:100%;min-width:0;padding-inline:4px}
.money-share .money-paid{display:grid;place-items:center;min-width:44px;min-height:44px;cursor:pointer}
.money-share .money-paid input{width:20px;height:20px;margin:0}
.money-share.is-out .money-pound,.money-share.is-out .money-share-amount{opacity:.45}
.money-page .money-group+.money-group{margin-top:20px}
.money-rows{display:grid;gap:6px}
.money-row{display:grid;grid-template-columns:minmax(0,1fr) auto 14px;gap:10px;align-items:center;width:100%;text-align:left;min-height:44px;padding:10px 12px;border-radius:11px}
.money-row .money-row-what{min-width:0;overflow-wrap:anywhere}
.money-row small{color:var(--muted);font-weight:500}
/* D69 · a deposit: its note under an owed gig's name in Band › Money, and its fields in Edit money. */
.money-row .money-row-note{display:block;margin-top:2px;font-size:12px}
.money-deposit{margin:10px 0 4px}
.money-deposit .money-check{margin:0 0 8px;min-height:0}
.money-person summary{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:10px;align-items:center;min-height:44px;cursor:pointer}
.money-person summary small{color:var(--muted);font-size:12px}
.money-person .money-rows{margin:6px 0 10px}
/* D65 (Steve, 3 Oct) · One look for every control. Lime is "your next step", one to a card or popup; every other control
   is the outlined button, and no tappable words sit outside a button's edge. styles.css draws .text-button and the
   "Available after…" and "Clear response" buttons outlined; the Back links above. Here: the fold-outs (with the
   Money page's people) and the Notifications rows. Left as they are on purpose: the ✕ close, the bottom tabs, a set list's drag handle and ×, the
   toggles inside a framed group (Day/Week/Month/List, Night/Day/System, Gig/Date Enquiry), a row inside a box that
   already draws the edge (Add Gig's "More" fold-outs, the Money box's top row, the attention banner, a set list row),
   the band name in the header, and the Last.fm credit, whose words and link Last.fm's terms fix. A chosen toggle is
   not a step either, so the calendar's Day/Week/Month/List and the List filters mark the chosen one the way Add Gig's
   Gig/Date Enquiry switch does: the panel colour and a ring, never lime. tests/buttons-outlined.test.cjs holds it. */
.history>summary,.more-details:not(.enq-lineup)>summary,.acc-edit>summary{position:relative;display:block;min-height:44px;padding:11px 40px 11px 14px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);color:var(--text);font-size:14px;font-weight:650;line-height:1.45;list-style:none;cursor:pointer}
.history>summary::-webkit-details-marker,.more-details:not(.enq-lineup)>summary::-webkit-details-marker,.acc-edit>summary::-webkit-details-marker{display:none}
.history>summary::after,.more-details:not(.enq-lineup)>summary::after,.acc-edit>summary::after{content:"\203A";content:"\203A" / "";position:absolute;right:15px;top:50%;margin-top:-11px;font-size:19px;font-weight:400;line-height:22px;color:var(--muted);transform:rotate(90deg)}
.history[open]>summary::after,.more-details:not(.enq-lineup)[open]>summary::after,.acc-edit[open]>summary::after{transform:rotate(-90deg)}
.enq-lineup{margin-top:8px}
.enq-lineup>summary{padding:6px 12px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);color:var(--text);cursor:pointer}
.money-person>summary{grid-template-columns:minmax(0,1fr) auto auto 14px;padding:10px 12px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);list-style:none}
.money-person>summary::-webkit-details-marker{display:none}
.money-person>summary::after{content:"\203A";content:"\203A" / "";font-size:19px;font-weight:400;line-height:1;color:var(--muted);transform:rotate(90deg)}
.money-person[open]>summary::after{transform:rotate(-90deg)}
.money-person+.money-person{margin-top:6px}
.history>summary:hover,.more-details:not(.enq-lineup)>summary:hover,.acc-edit>summary:hover,.enq-lineup>summary:hover,.money-person>summary:hover{background:var(--hover);border-color:var(--line2)}
.notice{border:1px solid var(--line);border-left:3px solid var(--line2);border-radius:12px;padding:0 12px 0 13px;background:var(--panel2)}
.notice+.notice{margin-top:8px}
.notice-mark-all{padding:8px 12px}
.segmented button[aria-checked=true],.filter-row button[aria-pressed=true]{background:var(--panel);color:var(--text);box-shadow:0 0 0 1px var(--line2)}
.auth-switch>.text-button{justify-self:stretch}

/* D70 · Preview as a member (docs/D70_PREVIEW.md). The banner is the top bar's last row, so it is on screen on every page
   at any scroll: "Previewing as Nick · read-only" and Stop, the outlined button (D65: lime is only ever the next step of
   the member being previewed). In the amber of a Maybe, so it never reads as part of the band's own data. */
.topbar.previewing{flex-wrap:wrap;row-gap:8px}
.preview-banner{flex:1 0 100%;grid-column:1/-1;display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;padding:4px 4px 4px 14px;border:1px solid var(--maybe-border);background:var(--maybe-surface);border-radius:14px;color:var(--text);font-size:14px;line-height:1.3}
.preview-words{min-width:0;overflow-wrap:anywhere}
.preview-banner .preview-stop{flex:none;padding:8px 18px}
.preview-private,.preview-hint{margin:10px 0 0}
/* D72 · A tapped button whose work is still going after a moment says so: it dims and breathes until the work is done
   (app.js, tapPaint), and a second tap on it waits for the first. Only the look's strength changes: no edge, fill or
   size, so every button keeps D65's look; with Reduce Motion it stays dimmed instead of breathing. */
button.tap-busy{cursor:progress;animation:tap-busy .9s ease-in-out infinite alternate}
@keyframes tap-busy{from{opacity:.45}to{opacity:.8}}
@media (prefers-reduced-motion:reduce){button.tap-busy{animation:none;opacity:.6}}
/* D75 · Rehearsals (site/practices.js, docs/D75_REHEARSALS.md). Steve: "Find a space on the calendar tab and ensure
   pristine formatting". The Calendar tab's Rehearsals card sits under the calendar (outside its turning pages) on Month,
   Week and List: the Gigs list's own date column, title, tags, times and one step a row, rows divided by hairlines inside
   one card, and the Gigs page's quiet ＋ Add. The rehearsal sheet is Manage enquiry's grammar (enq-manage); the form is
   the gig form's (gform). New classes are prefixed rh-. Existing tokens only. */
.rh-section{margin-top:26px}
.rh-head{margin:0 0 12px}
.rh-list{display:grid}
.rh-row .rh-chips{margin-top:10px}
/* On a Mac the rehearsals sit two a row under the calendar, so a card is never a wide strip with its words at one end. */
@media(min-width:900px){.rh-list{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:start}.rh-list>.glist-card{margin:0}}
.rh-empty{margin:0;font-size:14px;line-height:1.45;color:var(--detail-text)}
.rh-history{margin-top:18px}
.rh-history[open]>summary{margin-bottom:10px}
.rh-history .glist-row:last-child{margin-bottom:0}
.rh-who{margin-top:2px}
.rh-gig{color:var(--warn);font-weight:650}
/* H1 (Steve, 8 Oct 2026): ＋ Add Rehearsal sits in the calendar's header, just before Today and outlined like it. On a
   phone the month takes its own line and the buttons sit under it, Add Rehearsal on the left, Today and the arrows on the
   right; wider, it is all one line. */
.period-nav .period-add{width:auto;min-height:40px;padding:0 12px;font-size:12px;white-space:nowrap}
@media(max-width:550px){.period-nav.has-add{flex-wrap:wrap;row-gap:8px}.period-nav.has-add .period-title{flex:0 0 100%}
  .period-nav.has-add .period-add{margin-right:auto;padding:7px 10px;font-size:11px}}
/* M3 (Steve, 8 Oct 2026): a confirmed gig (blue, as its BOOKED tag) and a booked rehearsal (violet) are chips with the
   time each starts, at the foot of a month square, under a week's day and at the end of a List row (app.js dayChips).
   The chip replaces the BOOKED line and the top bar a booked square had; a conflict keeps both its word and its bar. */
:root{--chip-gig:#79b8ff;--chip-gig-ink:#0b2340;--chip-rh:#b69cff;--chip-rh-ink:#211442}
:root[data-appearance="day"]{--chip-gig:#b9d6f5;--chip-gig-ink:#0c3a66;--chip-rh:#d8cdfa;--chip-rh-ink:#3b2a7a}
.cal-chips{display:flex;flex-direction:column;align-items:center;gap:2px;width:100%}
.cal-chip{display:block;width:100%;max-width:58px;border-radius:5px;font-size:10px;font-weight:750;line-height:15px;text-align:center;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:clip}
.cal-chip.gig{background:var(--chip-gig);color:var(--chip-gig-ink)}
.cal-chip.rh{background:var(--chip-rh);color:var(--chip-rh-ink)}
.month-cell .cal-chips{margin-top:2px}
.month-cell.booked:not(.conflict){box-shadow:none}
.week-heading .cal-chips{margin-top:4px}
.week-card-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%}
.week-card-foot .cal-chips{flex-direction:column;align-items:flex-end;width:auto;flex:none}
.week-card-foot .cal-chip{width:auto;min-width:46px;padding:0 7px}
.agenda-tail .cal-chips{flex-direction:column;align-items:flex-end;width:auto}
.agenda-tail .cal-chip{width:auto;min-width:44px;padding:0 7px}
.cal-key{display:flex;gap:16px;margin:10px 2px 0;font-size:12px;color:var(--muted)}
.cal-key>span{display:inline-flex;align-items:center;gap:6px}
.cal-key-swatch{width:11px;height:11px;border-radius:3px;display:inline-block}
.cal-key-swatch.gig{background:var(--chip-gig)}.cal-key-swatch.rh{background:var(--chip-rh)}
@media(max-width:550px){.cal-chip{font-size:9px;line-height:14px}}
@media(min-width:950px){.month-cell .cal-chip{max-width:84px;font-size:11px;line-height:18px}}
/* D103 (Steve, 25 Oct 2026) · Month squares. Today is always pale yellow, whatever the day's answers; its words keep the
   Day palette's inks so they read in Night too. No faces on any square, so the words sit in the middle. A confirmed
   gig's day is blue and a booked rehearsal's violet; under the date their label, a deeper shade, fills the square: the
   name and the time, and at its top a strip for what needs doing (yellow a dep to arrange, red a gig that
   can't run, grey who might play or hasn't answered). A gig on today keeps its blue inside a yellow ring, its date on
   yellow. On a phone "Rehearsal" won't fit, so a metronome stands for it, and "Dep needed for" says "Dep for".
   D103 colours (Steve: "more in-fitting with the design language of the app"; he chose the Gigs page colours): a gig is
   the navy and pale blue of a booked gig's date on the Gigs page (--glist-booked), a rehearsal the app's rehearsal
   violet (--chip-rh-ink); in Day a pale square under a navy or violet label, in Night a deep square over a deeper one. */
:root{--sq-gig:#1d3a5c;--sq-gig-line:#1d3a5c;--sq-gig-date:#a9d0ff;--sq-gig-label:#10243b;--sq-gig-ink:#e6f0ff;--sq-rh:#2e2456;--sq-rh-line:#2e2456;--sq-rh-date:#cbb9ff;--sq-rh-label:#1d163b;--sq-rh-ink:#efe9ff;--sq-today:#fff8b5;--sq-today-line:#d9b500;--sq-today-ink:#5c4a00;--sq-ring:#ffe14d;--sq-dep:#ffd166;--sq-dep-ink:#3d2a00}
:root[data-appearance="day"]{--sq-gig:#cfe2f6;--sq-gig-line:#9fc0e4;--sq-gig-date:#0c3a66;--sq-gig-label:#1d3a5c;--sq-gig-ink:#fff;--sq-rh:#e2dafa;--sq-rh-line:#bba9ea;--sq-rh-date:#3b2a7a;--sq-rh-label:#3b2a7a;--sq-rh-ink:#fff}
.month-cell .cell-status{margin:auto 0}
.month-cell.today:not(.selected){background:var(--sq-today);border:2px solid var(--sq-today-line);color:#242c24;--bad:#a42d3b;--warn:#795200;--good:#186533;--cover:#176b60;--info:#235f9c;--muted:#586354;--waiting-text:#495969}
.month-cell.today:not(.selected) .day-number{box-shadow:none;color:var(--sq-today-ink);background:var(--sq-today)}
.month-cell.sq-gig,.month-cell.sq-rh{padding-left:0;padding-right:0;padding-bottom:0;gap:0;overflow:hidden;box-shadow:none}
.month-cell.sq-gig{background:var(--sq-gig);border-color:var(--sq-gig-line);color:var(--sq-gig-date)}
.month-cell.sq-rh{background:var(--sq-rh);border-color:var(--sq-rh-line);color:var(--sq-rh-date)}
.month-cell.sq-gig .day-number{color:var(--sq-gig-date);box-shadow:none;background:var(--sq-gig)}.month-cell.sq-rh .day-number{color:var(--sq-rh-date);box-shadow:none;background:var(--sq-rh)}
.month-cell.today.sq-gig:not(.selected){background:var(--sq-gig);border:1px solid var(--sq-gig-line)}
.month-cell.today.sq-rh:not(.selected){background:var(--sq-rh);border:1px solid var(--sq-rh-line)}
.month-cell.today.sq-gig:not(.selected),.month-cell.today.sq-rh:not(.selected){box-shadow:inset 0 0 0 3px var(--sq-ring);padding:3px 3px 3px}
.month-cell.today.sq-gig:not(.selected) .day-number,.month-cell.today.sq-rh:not(.selected) .day-number{background:var(--sq-ring);color:#3d3000}
.month-cell.today:not(.selected) .sq-label{border-radius:0 0 6px 6px}
.month-cell .sq-label{flex:1;align-self:stretch;min-height:0;margin-top:3px;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;padding:4px 2px;text-align:center;color:var(--sq-gig-ink);background:var(--sq-gig-label);overflow:hidden;-webkit-hyphens:auto;hyphens:auto;overflow-wrap:break-word}
.month-cell.sq-rh .sq-label{background:var(--sq-rh-label);color:var(--sq-rh-ink)}
@media(hover:hover){.month-cell .sq-label:hover{filter:brightness(1.18)}}
.sq-main{margin:auto 0;max-width:100%;display:flex;flex-direction:column;align-items:center;gap:3px}
.sq-name{max-width:100%;font-size:12px;font-weight:800;line-height:14px;display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.sq-kind{opacity:.8}
.sq-time{font-size:11px;font-weight:750;line-height:13px;opacity:.9;font-variant-numeric:tabular-nums}
.sq-icon{display:block;width:20px;height:20px}
.sq-strip{flex:none;align-self:stretch;margin:-4px -2px 0;padding:3px 2px;font-size:10px;font-weight:850;line-height:12px}
.sq-strip.dep{background:var(--sq-dep);color:var(--sq-dep-ink)}
.sq-strip.cant{background:#fbe4e6;color:#8a1f2c}
.sq-strip.maybe{background:#edf0f3;color:#33404d}
.month-cell .sq-label .cell-status.out{margin:0;font-size:inherit;line-height:inherit;color:inherit}
.month-cell .sq-label .out-group.maybe{color:inherit}
.month-cell.sq-rh .sq-label .cell-status.out{font-size:10px;line-height:12px;font-weight:800}
.sq-also{flex:none;align-self:stretch;margin:0 -2px -4px;padding:2px;background:var(--sq-rh);color:var(--sq-rh-date);display:flex;align-items:center;justify-content:center;gap:3px;font-size:10px;font-weight:750}
.sq-also .sq-icon{width:13px;height:13px}
.sq-narrow{display:none}
@media(max-width:550px){.sq-wide{display:none}.sq-narrow{display:block}.month-cell .sq-label{padding:3px 1px}.sq-strip{margin:-3px -1px 0;font-size:9px;line-height:11px}
  .sq-name{font-size:10px;line-height:12px;-webkit-line-clamp:5}.sq-time{font-size:9px;line-height:11px}.sq-main{gap:2px}.sq-also{margin:0 -1px -3px}
  .month-cell.sq-rh .sq-label .cell-status.out{font-size:9px;line-height:11px}}
@media(min-width:950px){.sq-name{font-size:14px;line-height:17px}.sq-time{font-size:12px;line-height:15px}.sq-strip{font-size:11px;line-height:13px}}
.sq-key .cal-key-swatch.gig{background:var(--sq-gig-label);box-shadow:inset 0 0 0 1.5px var(--sq-gig-date)}.sq-key .cal-key-swatch.rh{background:var(--sq-rh-label);box-shadow:inset 0 0 0 1.5px var(--sq-rh-date)}
.cal-key-swatch.today{background:var(--sq-today);box-shadow:inset 0 0 0 1.5px var(--sq-today-line)}
/* The List's four filters fit one row from 320px: a little less room either side of the words on a narrow phone. */
.filter-row button{white-space:nowrap}
@media(max-width:400px){.filter-row{gap:4px}.filter-row button{padding:8px 10px}}
/* A Day page: the day's rehearsal above the date's own card, and Add Rehearsal beside Add Gig. */
.rh-day{margin:0 0 16px}
.rh-day-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 8px}
.rh-day-head>.section-label{margin:0}
.rh-day-place{font-size:17px;font-weight:750;line-height:1.3;overflow-wrap:anywhere}
.rh-day .glist-when{display:block;margin-top:3px}
.rh-day .glist-line{margin-top:3px}
.rh-day .sub-actions>button{min-height:44px;padding:10px 18px;font-size:14px}
.day-add{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}
.day-add>button{width:100%;min-width:0}
.rh-gig-note{margin:-6px 0 16px}
/* The rehearsal sheet. */
.rh-sheet .rh-when{font-size:17px;font-weight:750;line-height:1.35;color:var(--text);margin:0 0 8px;overflow-wrap:anywhere}
.rh-time{font-weight:650;color:var(--text);font-variant-numeric:tabular-nums}
.rh-sheet .rh-hero .gig-status{margin-bottom:12px}
.rh-sheet .rh-hero .gig-status-note{margin:-4px 0 12px}
.rh-sheet .gig-go{margin-top:12px}
.rh-sheet .rh-dates{margin-top:18px}
.rh-standing{display:flex;align-items:center;gap:10px;margin:8px 0 0;min-width:0}
.rh-marks{flex:0 0 auto}
.rh-said{min-width:0;font-size:13px;line-height:1.4;color:var(--detail-text);overflow-wrap:anywhere}
.rh-gig-line{font-size:13px;font-weight:650;line-height:1.45;color:var(--warn);margin:3px 0 0;overflow-wrap:anywhere}
/* The answer buttons are the Day page's own (styles.css .inline-response): the symbol over the word, all three alike. */
.rh-answer{margin-top:10px}
.rh-answer button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:58px;padding:8px 2px;line-height:1.25;letter-spacing:-.15px;font-size:13px}
.rh-answer .choice-symbol{font-size:16px;line-height:1}
.rh-save{margin:6px 0 0}
.rh-save:empty{display:none}
.rh-sheet .enq-date{padding-bottom:12px}
.rh-sheet .rh-chase{margin:12px 0 2px}
.rh-going .rh-gig-line{margin:0 0 4px}
.rh-going .member-row.mine .inline-response .quick-controls{margin-top:2px}
.rh-going .inline-response .rh-save{margin-top:6px}
.rh-more{margin-top:16px}
/* The form: the gig form's blocks; the dates as the enquiry form lists them; places used before as one-tap chips. */
.rh-date-list:empty{display:none}
.rh-date-list .candidate-entry:last-child{border-bottom:0}
.rh-dates-hint{margin:8px 0 0}
.rh-dates-hint:empty,.rh-dates-hint[hidden]{display:none}
.rh-places{display:flex;flex-wrap:wrap;gap:6px;margin:-6px 0 16px}
.rh-places-label{flex:1 0 100%;margin:0 0 2px;font-size:12px;color:var(--muted)}
.rh-place{min-height:36px;padding:6px 13px;border:1px solid var(--line2);border-radius:999px;background:var(--panel2);color:var(--text);font-size:13px;font-weight:600;line-height:1.3;max-width:100%;overflow-wrap:anywhere;text-align:left}
.rh-place:hover{background:var(--hover)}
/* D77 · Admin override and Change type (docs/D77_ADMIN_OVERRIDE.md). On someone else's entry the admin's controls are
   the Owner controls block, headed Admin controls, with one quiet line under the heading saying whose it is. Change type
   opens a small sheet: the entry in one line, then the two other kinds as full-width outlined buttons, the kind's name
   over one line saying what it becomes. History says what an entry became, with an outlined Open to the new one. */
.gig-owner-note{font-size:13px;line-height:1.45;color:var(--detail-text);margin:-2px 0 10px;overflow-wrap:anywhere}
.type-sheet{display:grid;gap:14px}
.type-from{margin:0;font-size:14px;line-height:1.45;color:var(--detail-text);overflow-wrap:anywhere}
.type-choices{display:grid;gap:10px}
.type-choices>.type-choice{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:3px;width:100%;min-height:66px;padding:12px 16px;text-align:left;border-radius:12px}
.type-choice-name{font-size:16px;font-weight:750;line-height:1.25;color:var(--text)}
.type-choice-what{font-size:13px;font-weight:500;line-height:1.4;color:var(--detail-text)}
.type-changed{margin:0 0 16px}
.type-changed-line{margin:0;font-size:14px;line-height:1.45;font-weight:650;color:var(--text);overflow-wrap:anywhere}
.type-changed>.sub-actions{margin-top:8px}
.enq-manage>.type-changed{margin:2px 0 18px}
.enquiry-response>.type-changed{margin:10px 0 14px}
/* Change to a gig from an entry with several dates: the dates are choices, as Sets are, as many to a row as fit. */
.type-dates{margin-top:0}
.type-dates>.gform-pills{grid-template-columns:repeat(auto-fill,minmax(118px,1fr))}
.type-cut{margin:10px 0 0}
/* D75-10..12 · The early set-up. On the rehearsal (card, Day card, sheet) a line under the time; in the form a rung before
   Start and, once it has a time, who comes for it: the band's members as toggles, outlined, the chosen ones in the form's
   own chosen look (Ask the band first's) with a tick, never lime (D65). */
.rh-setup{font-weight:600;color:var(--detail-text)}
.rh-sheet .rh-setup-line{margin:-6px 0 12px;font-size:14px;font-weight:600;line-height:1.45;color:var(--detail-text);overflow-wrap:anywhere}
.rh-setup-who{background:var(--panel2);padding:10px 12px 12px 14px}
.rh-setup-who[hidden]{display:none}
.rh-who-label{margin:0 0 8px;font-size:13px;font-weight:650;color:var(--detail-text)}
.rh-who-chips{display:flex;flex-wrap:wrap;gap:6px}
.rh-who-chip{display:inline-flex;align-items:center;gap:6px;min-height:40px;padding:7px 13px;border:1px solid var(--line2);border-radius:999px;background:var(--panel);color:var(--text);font-size:14px;font-weight:600;line-height:1.2;max-width:100%;overflow-wrap:anywhere}
.rh-who-tick{display:none;font-weight:800;line-height:1}
.rh-who-chip[aria-pressed=true]{border-color:var(--mine-border);background:var(--accent-surface);box-shadow:inset 0 0 0 1px var(--mine-border)}
.rh-who-chip[aria-pressed=true] .rh-who-tick{display:inline}
.rh-setup-who .gform-error{margin-top:8px}
/* D78 · The date picker (beta-ui.js datePicker): an enquiry's offered dates and a rehearsal's suggested dates are tapped
   on a small month, in place of a date box and an Add button (Steve, 9 Oct 2026: "I've always found this confusing").
   A picked day reads as a chosen option (the Select dates calendar's accent edge and tick), never lime (D65). Days the
   band already has a gig or a rehearsal on carry a bar in the Calendar's colours, drawn darker by day so it shows. */
:root{--pick-gig:var(--chip-gig);--pick-rh:var(--chip-rh)}
:root[data-appearance="day"]{--pick-gig:var(--chip-gig-ink);--pick-rh:var(--chip-rh-ink)}
.pick-hint{margin:0 0 10px;font-size:13px;line-height:1.4;color:var(--muted)}
.pick{border:1px solid var(--line);border-radius:14px;background:var(--panel2);padding:8px 10px 12px}
.pick-nav{display:flex;align-items:center;gap:8px;margin:0 0 6px}
.pick-nav .icon-button{width:44px;height:44px;min-height:44px;flex:0 0 44px;font-size:22px;line-height:1}
.pick-nav .icon-button:disabled{opacity:.3}
.pick-title{flex:1;min-width:0;margin:0;text-align:center;font-size:16px;font-weight:800}
.pick-weekdays{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;margin:0 0 4px;text-align:center;font-size:11px;color:var(--muted)}
.pick-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.pick-day{touch-action:manipulation}
.pick-gap{min-height:44px}
.pick-day{position:relative;display:flex;align-items:center;justify-content:center;min-width:0;min-height:44px;margin:0;padding:0;border:1px solid var(--cell-border);border-radius:10px;background:var(--panel);color:var(--text);font:inherit;font-variant-numeric:tabular-nums;cursor:pointer}
.pick-num{font-size:15px;font-weight:700;line-height:1.2;padding:1px 4px;border-radius:6px}
.pick-day.today .pick-num{box-shadow:0 0 0 1px var(--accent);color:var(--accent)}
.pick-day.on{border-color:var(--accent);background:var(--accent-surface);box-shadow:inset 0 0 0 1px var(--accent)}
.pick-day.on .pick-num{color:var(--text);font-weight:800}
.pick-tick{position:absolute;top:1px;right:4px;font-size:10px;font-weight:800;color:var(--accent)}
.pick-day.past{opacity:.35;background:transparent;cursor:default}
.pick-marks{position:absolute;left:7px;right:7px;bottom:4px;display:flex;gap:2px}
.pick-marks i{display:block;flex:1;height:3px;border-radius:2px}
.pick-marks i.gig,.pick-key i.gig{background:var(--pick-gig)}
.pick-marks i.rh,.pick-key i.rh{background:var(--pick-rh)}
.pick-key{display:flex;flex-wrap:wrap;gap:6px 16px;margin:8px 2px 0;font-size:12px;color:var(--muted)}
.pick-key span{display:inline-flex;align-items:center;gap:6px}
.pick-key i{display:block;width:14px;height:3px;border-radius:2px}
.pick-count{margin:14px 0 0;font-size:13px;font-weight:700;color:var(--notes-text)}
.pick-section .candidate-entry,.rh-date-entry{display:block}
.candidate-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.candidate-head strong{font-size:15px}
.candidate-remove{min-height:40px;padding:6px 14px;font-size:13px;flex:none}
.candidate-note-label{margin:10px 0 6px}
.candidate-note-label small{margin-left:4px;font-weight:500;color:var(--muted)}
/* D95 · Print or share a set list, and Change the look (site/setlistprint.js; docs/D95_SETLIST_PRINT.md). The looks are
   a row of outlined choices, the chosen one ringed (never lime: lime is the next step, Share as PDF); the pages are a
   strip that scrolls sideways, each drawn as it will come out. */
.sp-block{margin:0 0 18px}
.sp-look-row{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px}
button.sp-look{min-height:44px;padding:8px 14px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);color:var(--text);font-size:14px;font-weight:600}
button.sp-look.is-on{background:var(--panel);border-color:var(--line2);box-shadow:0 0 0 2px var(--mine-border)}
.sp-look small{margin-left:4px;font-size:11px;font-weight:600;color:var(--muted)}
.sp-preview{display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;padding:4px 2px 12px;-webkit-overflow-scrolling:touch}
.sp-page{flex:none;scroll-snap-align:start;border-radius:3px;box-shadow:0 0 0 1px var(--line2),0 4px 14px #00000040}
.sp-preview-one{position:sticky;z-index:1;justify-content:center;margin:0 -2px 14px;padding:4px 2px 10px;background:var(--panel)}
.extras-choices.sp-sets{display:flex;flex-wrap:wrap;gap:0 22px;margin:0 0 16px}
.sp-pages{margin:0;font-size:13px;color:var(--muted)}
.sp-outs{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 8px}
.sp-outs>button{min-height:44px}
.sp-ready{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin:0 0 12px;padding:10px 12px;border:1px solid var(--line2);border-radius:11px;background:var(--panel2)}
.sp-ready p{margin:0;font-size:14px;font-weight:650}
.sp-choice{margin:0 0 14px}
.sp-label{display:block;margin:0 0 7px;font-size:12px;font-weight:700;color:var(--notes-text)}
.sp-seg{flex-wrap:wrap}
.sp-seg button{flex:1 1 auto;min-height:40px}
.sp-group{margin:0 0 10px}
.sp-group-body{padding:12px 2px 4px}
.sp-colours{display:flex;flex-wrap:wrap;gap:10px 18px;margin:0 0 12px}
.sp-colour{display:flex;align-items:center;gap:8px;min-height:44px;font-size:14px}
.sp-colour input{width:46px;height:36px;padding:2px;border:1px solid var(--line);border-radius:8px;background:var(--panel2)}
.sp-themes{flex-wrap:wrap}
.sp-save{margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
/* ─── D96 · Lyrics for rehearsal and on stage (site/lyrics.js; docs/D96_LYRICS.md) ───────────────────────────────────
   The words screen is a layer over the whole app, not a sheet: black with large white words (.ly-dark) or, D114, white
   with black words (.ly-light), the member's pick for each mode. The words' size is one custom property (A− / A+); chords sit over the words they
   were typed above, in their own colour; a part's name (Chorus, Verse 2) is a label. */
html.ly-open,html.ly-open body{overflow:hidden}
.ly-stage{position:fixed;inset:0;z-index:1000;display:flex;flex-direction:column;background:var(--bg);color:var(--text);--ly-chord:var(--info);--ly-size:30px;--ly-part:var(--accent);--ly-part-fill:var(--accent-surface);
  padding:env(safe-area-inset-top,0) env(safe-area-inset-right,0) 0 env(safe-area-inset-left,0)}
.ly-stage[hidden]{display:none}
.ly-stage.ly-dark{color-scheme:dark;--bg:#000;--panel:#0d0f10;--panel2:#151719;--line:#2c3034;--line2:#3c4248;--text:#fff;--muted:#a7adb3;--detail-text:#d3d7db;--accent:#d9ff5c;--accent-surface:#2a331a;
  --primary-ink:#10140b;--ly-chord:#ffcf5a;--ly-part:#d9ff5c;--ly-part-fill:#1f2614;--focus:#d9ff5c;--hover:#1c2024}
.ly-bar{flex:0 0 auto;padding:8px 12px 10px;border-bottom:1px solid var(--line);background:var(--panel2)}
.ly-bar[hidden]{display:none}
.ly-bar-row{display:flex;align-items:center;gap:10px}
.ly-where{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.ly-count{font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums}
.ly-title{font-size:17px;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ly-close{min-width:44px;padding:8px 12px;font-size:18px}
.ly-tools{display:flex;flex-wrap:nowrap;align-items:center;gap:12px;margin:8px -12px 0;padding:0 12px 2px;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none}
.ly-tools::-webkit-scrollbar{display:none}
.ly-group{display:inline-flex;flex:0 0 auto;align-items:center;gap:6px}
.ly-tool{flex:0 0 auto;min-height:42px;padding:8px 13px;white-space:nowrap}
.ly-tool[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-surface);color:var(--text)}
.ly-tool:disabled{opacity:.45;cursor:default}
.ly-pace{min-width:3em;font-size:13px;text-align:center;color:var(--muted);font-variant-numeric:tabular-nums}
.ly-lead-note{font-size:14px;font-weight:700;white-space:nowrap;color:var(--accent)}
.ly-status{margin:8px 0 0;font-size:14px;line-height:1.4;color:var(--detail-text)}
.ly-status[hidden]{display:none}
.ly-body{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;touch-action:pan-y;-webkit-overflow-scrolling:touch;outline:none;
  padding:18px max(16px,env(safe-area-inset-right,0)) calc(32vh + env(safe-area-inset-bottom,0)) max(16px,env(safe-area-inset-left,0));font-size:var(--ly-size,30px);line-height:1.35}
.ly-song,.ly-end{max-width:46em;margin:0 auto}
.ly-head{margin:0 0 .5em}
.ly-name{margin:0;font-size:.8em;line-height:1.2}
.ly-facts{margin:.2em 0 0;font-size:max(14px,.45em);color:var(--muted)}
.ly-part{display:inline-block;margin:.7em 0 .3em;padding:.12em .55em;border-radius:8px;font-size:max(13px,.55em);font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--ly-part);background:var(--ly-part-fill)}
.ly-line{margin:0 0 .12em;white-space:pre-wrap;overflow-wrap:anywhere}
.ly-with-chords{margin-bottom:.3em;line-height:1.15}
.ly-unit{display:inline-flex;white-space:nowrap;vertical-align:bottom}
.ly-seg{display:inline-flex;flex-direction:column}
.ly-words{white-space:pre}
.ly-chord{min-height:1.2em;font-size:.62em;font-weight:800;line-height:1.2;color:var(--ly-chord);white-space:pre}
.ly-chords-only .ly-chord{display:inline-block;margin-right:.5em}
.ly-gap{height:.65em}
.ly-none{font-size:max(16px,.6em);color:var(--muted)}
.ly-none .sub-actions{margin-top:12px}
.ly-end{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;margin-top:1.4em;padding-top:1em;border-top:1px solid var(--line);font-size:max(16px,.5em)}
.ly-end p{margin:0}
.ly-end small{color:var(--muted)}
.ly-list{position:absolute;top:0;right:0;bottom:0;z-index:2;width:min(380px,100%);overflow-y:auto;overscroll-behavior:contain;padding:calc(12px + env(safe-area-inset-top,0)) 14px calc(20px + env(safe-area-inset-bottom,0));
  background:var(--panel);border-left:1px solid var(--line);box-shadow:-8px 0 30px #0007}
.ly-list[hidden]{display:none}
.ly-list-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:6px}
.ly-list-set{margin:14px 0 4px;font-size:13px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.ly-list-song{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;margin:0 0 6px;text-align:left}
.ly-list-song small{color:var(--muted);font-weight:500}
.ly-list-song[aria-current="true"]{border-color:var(--accent)}
/* On a song, a set list, and in the sheets. */
.ly-peek{margin:4px 0 10px;color:var(--detail-text);font-style:italic;line-height:1.45}
.ly-for{margin:0 0 10px}
.ly-for small{color:var(--muted)}
.ly-find{margin:0 0 6px}
.ly-box{width:100%;min-height:42vh;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:16px;line-height:1.45;white-space:pre;overflow-wrap:normal;overflow-x:auto;tab-size:8}
a.ly-link{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:10px 15px;border:1px solid var(--line);border-radius:11px;background:var(--panel2);color:var(--text);font-weight:650;text-decoration:none}
.ly-find-row{padding:12px 0;border-top:1px solid var(--line)}
.ly-find-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin:0}
.ly-find-head small{color:var(--muted)}
.ly-find-state{margin-left:auto;font-size:13px;font-weight:700;color:var(--muted)}
.ly-st-found{color:var(--good)}
.ly-st-none,.ly-st-instrumental{color:var(--warn)}
.ly-find-down{margin:12px 0;padding:12px 14px;border:1px solid var(--line);border-left:3px solid var(--warn);border-radius:11px}
.ly-find-down p{margin:0 0 10px}
.ly-finder .sub-actions{margin-top:6px}
/* D111 · Try another name, in Edit lyrics: the name boxes and LRCLIB's copies to pick from. */
.ly-other{margin:0 0 14px;padding:12px 14px;border:1px solid var(--line);border-radius:11px}
.ly-other[hidden]{display:none}
.ly-other .inline-note{margin:10px 0 0}
.ly-other .ly-other-hint{margin:0 0 10px}
.ly-choices .sub-actions{margin-top:6px}
.ly-choices .ly-find-row:last-child{padding-bottom:0}
@media(max-width:550px){
  .ly-bar{padding:6px 8px 8px}
  .ly-tools{gap:10px;margin:6px -8px 0;padding:0 8px 2px}
  .ly-tool{min-height:40px;padding:7px 11px}
}
/* A phone on its side: the bar's two lines become one, so the words keep most of the screen. */
@media(max-height:520px) and (min-width:600px){
  .ly-bar{display:flex;align-items:center;gap:12px;padding-top:6px;padding-bottom:6px}
  .ly-bar-row{flex:0 0 auto;min-width:0}
  .ly-where{width:min(24ch,28vw)}
  .ly-count{white-space:nowrap}
  .ly-tools{flex:1 1 auto;min-width:0;margin:0;padding:0 0 2px}
  .ly-status{position:absolute;left:12px;right:12px;top:100%;z-index:1;margin:0;padding:6px 10px;border-radius:0 0 10px 10px;background:var(--panel2);border:1px solid var(--line);border-top:0}
  .ly-bar{position:relative}
  .ly-body{padding-top:10px}
}
/* D97 · A song's timing (docs/D97_SONG_TIMING.md): each part is a block of its own; while a timing is recorded, the
   part just tapped and the one to tap next are marked by a bar at their side (a shadow, so nothing moves). */
.ly-block{border-radius:6px}
.ly-block.ly-now{box-shadow:-8px 0 0 var(--line2)}
.ly-block.ly-next{box-shadow:-8px 0 0 var(--accent)}
.ly-rec .ly-lead-note{color:var(--text)}
/* D114 · Light or Dark, and the controls hidden (docs/D114_LYRICS_CONTROLS.md). Dark is the black stage look above;
   Light is white with near-black words, easy to read in daylight. With the controls hidden (.ly-full) the bar's two
   lines go and the words have the whole screen; a small button stays in the corner to bring them back, and what the
   bar says shows at the foot of the screen for its few seconds. */
.ly-stage.ly-light{color-scheme:light;--bg:#fff;--panel:#fff;--panel2:#f3f5f0;--line:#cdd5c8;--line2:#9da998;--text:#111511;--muted:#525c4f;--detail-text:#3b453c;--accent:#486400;--accent-surface:#e2efbc;
  --hover:#e8ede3;--primary-ink:#17200a;--ly-chord:#0b4f9c;--ly-part:#3b5200;--ly-part-fill:#e6f2c5;--focus:#5b7600}
.ly-icon{display:inline-grid;place-items:center;min-width:44px;padding:8px 10px}
.ly-icon svg{width:20px;height:20px;stroke-width:2}
.ly-full .ly-bar{position:absolute;left:0;right:0;bottom:0;z-index:3;padding:0;border:0;background:none;pointer-events:none}
.ly-full .ly-bar-row,.ly-full .ly-tools{display:none}
.ly-full .ly-status{position:fixed;top:auto;left:max(12px,env(safe-area-inset-left,0));right:calc(70px + env(safe-area-inset-right,0));bottom:calc(12px + env(safe-area-inset-bottom,0));z-index:3;margin:0;padding:8px 12px;
  border:1px solid var(--line);border-radius:10px;background:var(--panel2)}
.ly-show{position:absolute;right:calc(12px + env(safe-area-inset-right,0));bottom:calc(12px + env(safe-area-inset-bottom,0));z-index:3;opacity:.6}
.ly-show:hover,.ly-show:focus-visible{opacity:1}
.ly-show[hidden]{display:none}

/* D93 · Share with family (Me › Calendar subscription, docs/D93_FAMILY_CALENDAR.md): under the member's own link, set
   apart by a rule; each person a row of a grouped card, as My devices is, with their name and since-date over New link
   and Stop sharing. A long name wraps rather than push the sheet sideways; every control 44px. Existing tokens only, so
   Day and Night follow by themselves. */
.family-shares{margin:22px 0 4px;padding-top:18px;border-top:1px solid var(--line)}
.family-shares .section-label{margin:0}
.family-shares>.inline-note{margin:6px 0 0}
.family-list{list-style:none;margin:12px 0 0;padding:0 14px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
.family-share{padding:12px 0;min-width:0}
.family-share+.family-share{border-top:1px solid var(--line)}
.family-share-who{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;margin:0;font-size:15px;overflow-wrap:anywhere;min-width:0}
.family-share-who small{color:var(--muted)}
.family-share .sub-actions{margin-top:8px}
.family-shares .sub-actions>button{min-height:44px;padding:10px 14px;border-radius:11px;font-size:14px}
.family-link-intro{margin:0 0 14px}
/* D106 · Connected apps (docs/D106_SET_LIST_ARCHITECT.md §5.2, §8; site/connect.js). The Connect sheet: what the app will
   be able to do as a short list, then Connect (lime, the next step) and Don't connect (outlined). Me › Connected apps:
   each app in the boxed rows Share with family uses, its dates muted, Disconnect in the danger tone (as Stop sharing). A
   long name wraps; every control 44px. The Set list's "Sent from" line takes the quiet look of the gig's name at the top
   of the sheet (.sl-gig). Existing tokens only, so Day and Night follow by themselves. */
.app-connect>p{margin:0 0 10px}
.app-connect-can{margin:0 0 12px;padding-left:20px}
.app-connect-can li{margin:4px 0}
.app-connect .inline-note{margin:0}
.app-connect-bad{margin:0}
.connected-apps{list-style:none;margin:0;padding:0 14px;border:1px solid var(--line);border-radius:12px;background:var(--panel2)}
.connected-app{padding:12px 0;min-width:0}
.connected-app+.connected-app{border-top:1px solid var(--line)}
.connected-app-what{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;margin:0;font-size:15px;overflow-wrap:anywhere;min-width:0}
.connected-app-what small{color:var(--muted)}
/* D108 · Alerts sent (site/alertlog.js): the admin's list of every alert sent to the band. One block per thing that
   happened: when, then the words the member was shown, then one line per member, the name first. Lines wrap rather than
   run off a phone; nothing in it is tappable but Show older. */
.alert-log-item{padding:14px 0;border-bottom:1px solid var(--line);min-width:0}
.alert-log-item:focus{outline:none}
.alert-log-when{margin:0;font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.02em}
.alert-log-what{margin:4px 0 8px;font-size:15px;overflow-wrap:anywhere}
.alert-log-members{list-style:none;margin:0;padding:0;display:grid;gap:4px}
.alert-log-members li{font-size:14px;line-height:1.35;overflow-wrap:anywhere;min-width:0}
.alert-log-members li span{color:var(--muted)}
.alert-log-foot{margin-top:14px}
/* D108 · Steve, 1 Nov: WhatsApp's ticks. Two grey ticks: sent. Two blue ticks: seen. The blue is the popup ring's on
   Night; on Day the ring's #007aff is 4.0:1 on white, so the ticks take a deeper blue that reads at 4.5:1 or better. */
:root{--tick-seen:#0a84ff}
:root[data-appearance="day"]{--tick-seen:#0066cc}
.alert-log-key{margin:8px 0 2px;font-size:13px;color:var(--muted);display:flex;flex-wrap:wrap;align-items:center;gap:4px}
.alert-log-key-gap{display:inline-block;width:10px}
.alert-log-ticks,.alert-log-members .alert-log-ticks{display:inline-block;vertical-align:-1px;color:var(--muted);line-height:0}
.alert-log-ticks.seen,.alert-log-members .alert-log-ticks.seen{color:var(--tick-seen)}
.alert-log-ticks svg{width:18px;height:12px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.connected-app .sub-actions{margin-top:8px}
.connected-app .sub-actions>button{min-height:44px;padding:10px 14px;border-radius:11px;font-size:14px}
.family-link-actions>button{flex:1 1 auto;min-height:48px;padding:10px 16px;border-radius:11px;font-size:15px}
/* h43 · My icon is a card, not a sheet. Steve: "The My icon popup card should not be attached to the bottom of the app
   on Mac or iPhone." openDialog marks the one dialog that asks for it (context.presentation 'card') with .centred-card
   and nothing else changes: every other sheet is still a bottom sheet on a phone. Two classes outrank every
   .action-dialog rule above, whatever its media query, so this one block undoes the bottom sheet's margins, square
   corners, 70dvh floor and home-indicator padding for this card alone.
   · Centred both ways at every width: margin:auto inside the fixed box a modal dialog is given. The box ends above the
     keyboard, so the keyboard the search brings up lifts and shrinks the card rather than covering it.
   · Even margins: the same gap either side on each axis, never under 16px and never under the larger safe-area inset
     on that axis (the notch, the Dynamic Island, the home indicator), so it is centred on the screen and clear of
     all of them. A taller window gives it a little more air, up to 56px, and a large screen a card of at most 780px.
     While a keyboard is up that air, and the home indicator's clearance (the indicator is behind the keys then), go
     back to the card: --card-air is 56px with no keyboard and 0 once one is showing, so a phone on its side keeps
     16px above and below and gives the rest to the search and the grid.
   · A head that never moves and a body that scrolls: the card is a column, the head across the top over a hairline,
     and #dialogBody the one scroller under it, so the scroll bar starts below the hairline and stays inside the
     rounded corners. The page behind is locked (lockPage) and overscroll stays in the card.
   · How tall: with the search (a catalogue long enough to need one) the card is as tall as it may be, whatever the
     search leaves in it, so typing never moves the card, the field or the ×, and the results fill from the top.
     Without it (no icons yet), the card is only as tall as what it holds, and still centred.
   Existing tokens only, so the Day/Night variable guard and the contrast sweep cover it unchanged. */
.action-dialog.centred-card{
  --card-air:max(0px,calc(56px - var(--keyboard-inset,0px)));
  --card-gap-x:max(16px,env(safe-area-inset-left),env(safe-area-inset-right));
  --card-gap-y:max(16px,min(6dvh,var(--card-air)),env(safe-area-inset-top),min(env(safe-area-inset-bottom),var(--card-air)));
  --card-height:min(780px,calc(100dvh - var(--keyboard-inset,0px) - 2*var(--card-gap-y)));
  inset:0 0 var(--keyboard-inset,0px);margin:auto;
  width:min(480px,calc(100% - 2*var(--card-gap-x)));max-width:none;
  min-height:0;max-height:var(--card-height);
  display:flex;flex-direction:column;overflow:hidden;
  border-radius:22px;padding:0
}
.action-dialog.centred-card:not([open]){display:none}
.action-dialog.centred-card:has(#roleIconSearch){height:var(--card-height)}
.action-dialog.centred-card .dialog-head{flex:0 0 auto;margin:0;padding:10px 10px 10px 20px;border-bottom:1px solid var(--line)}
.action-dialog.centred-card .dialog-head h2{font-size:20px}
/* Steve, 28 Sep, on his iPhone: the green ring around the card's × "seems to fall off the edge of the viewable screen".
   The card opens with the × focused, and the focus ring (3px wide, 3px outside the button) reached past the card's
   edge, 4px from the × on a phone, where the card clips it (overflow:hidden). The card's × draws its ring just inside
   its own edge instead: the same ring, never cut, upright or sideways. (A bottom sheet's × has the sheet's padding
   around it, so its ring was never cut.) */
.action-dialog.centred-card .dialog-head .icon-button:focus-visible{outline-offset:-3px}
/* --keyboard-room is the end-of-form room every sheet gets while a keyboard is up (#dialogBody, above); the card's own
   padding would otherwise replace it. */
.action-dialog.centred-card #dialogBody{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;padding:16px 20px calc(20px + var(--keyboard-room,0px))}
.action-dialog.centred-card #dialogError{flex:0 0 auto;margin:0 20px 16px}
/* A tile narrower than 76px breaks Microphone, Tambourine and Megaphone mid-word (measured, 12px names), so the card's
   grid never goes under it: where four do not fit, it takes three. On a phone the card gives its width to the grid,
   12px inside and a 4px gap, which keeps four a row from 375pt up — as the sheet had — with even gutters outside. */
.action-dialog.centred-card .role-icon-grid{grid-template-columns:repeat(auto-fill,minmax(76px,1fr))}
@media(max-width:550px){
  .action-dialog.centred-card .dialog-head{padding:8px 4px 8px 12px}
  .action-dialog.centred-card #dialogBody{padding:14px 12px calc(12px + var(--keyboard-room,0px))}
  .action-dialog.centred-card #dialogError{margin:0 12px 12px}
  .action-dialog.centred-card .role-icon-grid{gap:4px}
}
/* A phone on its side: the head gives up its air above and below the 44px ×, and the body its first 6px, which is the
   room a keyboard leaves for the search and a row of results. */
@media(max-height:520px){
  .action-dialog.centred-card .dialog-head{padding-top:2px;padding-bottom:2px}
  .action-dialog.centred-card #dialogBody{padding-top:10px}
}

.acceptance-label{background:#ffe7a8;color:#30230a;text-align:center;padding:7px 12px;font:600 12px system-ui;position:relative;z-index:100;}
