/* Dark, minimal: near-black ground, greys for type, one accent for links and focus.
   Every colour is written down once, in a scheme block, and everything the site draws
   reads it back out of a variable, so a scheme is a list of colours and nothing else.
   Which scheme to wear comes from Settings and arrives as data-theme on the html
   element, which is why each block below also carries the name it is chosen by. */

:root {
  /* Midnight: the default, and what anyone who has not chosen yet is shown. */
  color-scheme: dark;
  --bg: #0f1113;
  --text: #e6e8ea;
  --muted: #8b9197;
  --line: #26292d;
  --fill: #16181b;
  /* What an event row and a band button are filled with. Both start out the same as
     everything else the site fills - the note boxes, the form fields, the member rows and
     the ordinary buttons all keep --fill - so a scheme that means only those two
     differently says so and leaves the rest alone. */
  --event-fill: var(--fill);
  --band-fill: var(--fill);
  --accent: #8ab4f8;
  --space: 0.5rem;
  /* The three event types: rehearsal blue, gig red, other green. */
  --rehearsal: #8ab4f8;
  --gig: #f28b82;
  --other: #7eca97;
  /* What a row is filled with when the event it holds belongs to today's date: the same three
     colours, deepened into a fill instead of worn as a badge. Written once, here: no scheme
     block repeats them, so a row saying "today" is the same colour in every scheme, and a
     scheme with its own ground to paint cannot take that marker away or soften it. */
  --today-rehearsal: rgb(27 61 106);
  --today-gig: rgb(106 27 27);
  --today-other: rgb(24 71 29);
  /* Every active member of the band has ticked: the settled green a tick box is
     pressed in. Livelier than the green a type badge wears. */
  --confirmed: #43d17c;
  /* An event's start time. */
  --time: #f2b45c;
  /* A row lit up under the pointer, and a day the calendar shows but will not take. */
  --lift: #1c1f23;
  --wash: rgb(255 255 255 / 0.02);
  /* A button that destroys something and cannot be undone. Its own red rather than
     the gig red, so changing what a gig badge looks like cannot repaint a delete
     button, and so a red ring is not mistaken for a red badge. */
  --danger: #f2766d;
  /* The two typeface stacks every choice is built on top of, and the two the page
     actually uses. A choice from Settings replaces --font or --display by name further
     down; `--display` starts out as whatever the body text is, which is what the
     "same as the body text" option means. */
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font: var(--sans);
  --display: var(--font);
}

/* The other schemes are the same clothes in different colours: an event type keeps
   its hue from one scheme to the next so a rehearsal still reads as a rehearsal, and
   what changes is the ground, the ink and the accent. The two variants of the default
   change nothing but what the event rows and the band buttons are filled with, which is
   the entire difference between them and the scheme they are variants of.

   html[data-theme=...] sits on the very element :root styles, and names an attribute on
   top of it, so it wins the tie and a scheme block only has to say what differs.

   A light scheme would need more than colours here: the header wordmark and the
   sign-in emblem are drawn as light ink on nothing at all, so against a light ground
   they would vanish until dark-ink copies of those two files exist. */
html[data-theme="midnight2"] {
  /* Midnight 2: the default's ground and ink, with the event rows lifted clear of the
     ground and the band buttons lifted further again. Every scheme names the red its own
     destructive buttons wear, even a scheme that takes the very same red as another, so
     that repaint one scheme cannot repaint a second one's delete buttons. */
  --danger: #f2766d;
  --lift: rgb(34 37 42);
  --event-fill: rgb(25 27 31);
  --band-fill: rgb(34 37 42);
}

html[data-theme="midnight_contrast"] {
  /* Midnight contrast: the same ground and ink again, and the event rows and the band
     buttons cut to nothing at all. A row lit up under the pointer has to be a lifted grey
     here: against panels that are black, only something lighter than black registers. */
  --danger: #f2766d;
  --lift: rgb(35 38 43);
  --event-fill: #000000;
  --band-fill: #000000;
}

html[data-theme="slate"] {
  /* Slate: blue-grey ground, cool grey-blue ink, teal accent. */
  --bg: #11161d;
  --text: #dfe6ef;
  --muted: #8b9aad;
  --line: #2a3441;
  --fill: #19202a;
  --accent: #7fd4c1;
  --rehearsal: #93c5fd;
  --gig: #f2938a;
  --other: #8fd6a4;
  --confirmed: #43d17c;
  --time: #f5c26b;
  --lift: #1f2833;
  --danger: #f27f74;
  --wash: rgb(255 255 255 / 0.03);
}

html[data-theme="umber"] {
  /* Umber: warm brown-black ground, warm pale ink, amber accent. */
  --bg: #15120e;
  --text: #ece4d8;
  --muted: #a2917c;
  --line: #33291f;
  --fill: #1e1a14;
  --accent: #e3b46b;
  --rehearsal: #9ec5f7;
  --gig: #f2938a;
  --other: #a6d7a8;
  --confirmed: #4fce86;
  --time: #f0b45c;
  --lift: #251f17;
  --danger: #f27a68;
  --wash: rgb(255 255 255 / 0.025);
}

/* The typefaces someone can pick in Settings, chosen the same way a scheme is: by an
   attribute on the html element, whose name is the value stored on their account and
   listed in the core fonts module. Two blocks because two pickers - the body text and the
   headings - and every stack here ends in a generic family, so a page that cannot
   reach Google Fonts is still readable in the fallback while it waits.

   "system" and "same" have no block here because they are what :root already says:
   the system sans, and headings that simply follow it.

   Amarante and Julius Sans One appear only as headings. Both are one weight, neither
   has an italic, and Julius Sans One has no lower case at all - type it and you get
   small capitals. Their strokes are thin enough to break up when reversed out of a
   dark ground, which is survivable in a band name and not in an event row. */
html[data-font="roboto"] {
  --font: "Roboto", var(--sans);
}

html[data-font="roboto-mono"] {
  --font: "Roboto Mono", var(--mono);
}

html[data-font="quantico"] {
  --font: "Quantico", var(--sans);
}

html[data-font="inter"] {
  --font: "Inter", var(--sans);
}

html[data-font="ibm-plex-sans"] {
  --font: "IBM Plex Sans", var(--sans);
}

html[data-font="work-sans"] {
  --font: "Work Sans", var(--sans);
}

html[data-font="ibm-plex-mono"] {
  --font: "IBM Plex Mono", var(--mono);
}

html[data-font="jetbrains-mono"] {
  --font: "JetBrains Mono", var(--mono);
}

html[data-display="julius-sans-one"] {
  --display: "Julius Sans One", var(--sans);
}

html[data-display="amarante"] {
  --display: "Amarante", var(--sans);
}

html[data-display="oswald"] {
  --display: "Oswald", var(--sans);
}

html[data-display="archivo-black"] {
  --display: "Archivo Black", var(--sans);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  color: var(--text);
  font: 16px/1.6 var(--font);
  background: var(--bg);
}

/* What the headings picker changes. Only the words that name something: the page and
   band titles, an event's own title, and the band names in the header strip. Everything
   else keeps the body text, including the badges, whose letters are too small for the
   display faces to survive. The controls do not appear here because they all say
   `font: inherit` and already take the body text. */
h1,
h2,
.band-link,
.event-title {
  font-family: var(--display);
}

/* The width the site is drawn inside, written twice on purpose: once for the page and once
   for the header above it. The header is the same width because its rule line is the edge of
   that column, and a header one width with a page another would leave the line ending short
   of the content under it. With 1.25rem of padding on the sides of each, the pair only binds
   at a window past about 760px: narrower than that every line is whatever the window allows,
   which is why a phone needs nothing of its own here. */
main {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--space) 1.25rem 4rem;
}

.site-header {
  max-width: 720px;
  margin: 0 auto;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  border-bottom: 1px solid var(--line);
}

/* Centred, not baseline-aligned: an image aligns on its bottom edge, which would
   drop the wordmark below the links beside it. */
.header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space);
}

.brand {
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--text);
}

/* The header wordmark, which replaces the name as text. Change mark height to size
   it, and nothing else: the file has 156px of canvas for 65px of drawn wordmark, of
   which the letters are 36px, so the visible wordmark is a little under a quarter of
   this height. At 4.9rem the box is 78px tall, the wordmark reads 199 x 33px, and the
   letters are 18px tall. The colours and the red flourish belong to the image, so they
   are not in the palette above.

   The negative margin cancels the transparent gutter on the left of the file, which is
   40px of the 156px canvas: without it the drawn letters would start about 20px right
   of the strip underneath, and the margin follows the size instead of being a fixed
   guess. The image itself is untouched. */
.brand-mark {
  --mark-height: 4.9rem;
  display: block;
  height: var(--mark-height);
  width: auto;
  margin-left: calc(var(--mark-height) * -0.256);
}

/* Dashboard, Settings and the account pair - the name, a dot, then the way out of it - measure
   under 280px with a short name, which is inside a phone's page column but only just. It is
   a little under what the same four things measured while the name carried an @ and the nav
   row's own gap sat between it and its sign-out. Wrapping is there for the cases that push it
   over: a handle near the twenty-character limit, or a display face with wide letters. The row
   gap is cut in half because a wrapped nav is a second line of links, and the header already
   has its own rhythm between the lines it stacks. */
.site-header nav {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 1rem;
  font-size: 0.9rem;
}

.site-header nav a {
  color: var(--muted);
  text-decoration: none;
  transition: color 150ms;
}

.site-header nav a:hover,
.site-header nav a:focus {
  color: var(--text);
}

.handle {
  color: var(--muted);
}

/* The account's own name and the way out of it are one item of the nav row: the name, a dot,
   then the button. Holding them together is what keeps the 1rem gap between nav items from
   falling between a name and its sign-out, where it could push the two onto separate lines.
   Inside the pair the gap is the 0.35rem the nav row uses between the lines it wraps into,
   which is what keeps the dot nearer to the name than to anything else on the line. */
.nav-account {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
}

/* A screen reader is asked to skip the dot: it holds the two halves apart for the eye, and
   in a spoken list of what the header offers it is only noise. */
.nav-sep {
  color: var(--muted);
}

/* The header's sign-out is a form, so it has to look like the links beside it. */
.inline-form {
  display: inline;
}

.link-button {
  padding: 0;
  font: inherit;
  color: var(--muted);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 150ms;
}

.link-button:hover,
.link-button:focus {
  color: var(--text);
}

h1 {
  font-size: 1.5rem;
  margin: 0 0 0.5rem;
}

h2 {
  font-size: 1.1rem;
  margin: 0 0 0.5rem;
  font-weight: 600;
}

/* The one heading below level two on the site: the month over the booking calendar. It
   had no rule at all, which left the browser in charge of 1.17em bold type with a whole
   em of margin above and below: the month read larger than the card title above it, and
   about 19px of empty space hung over the top of the grid. 1rem at weight 600 puts it
   under the card title (1.1rem) and over the weekday letters (0.7rem), and the margin is
   zero because the head it sits in is stacked, where a gap owns that space instead. */
h3 {
  font-size: 1rem;
  margin: 0;
  font-weight: 600;
  margin: 1rem 0 1rem;
}

a {
  color: var(--accent);
}

.card {
  margin: var(--space) 0;
  padding: var(--space) 0;
  border-bottom: 1px solid var(--line);
}

/* On an event's own page the going card carries the same settled state the rows in a
   list carry, and it carries it in the same two places: the box that finished the set
   is pressed in green, and a green edge down the side of the card keeps the state
   legible even when the tick is out of view. */
.card.confirmed {
  border-left: 2px solid var(--confirmed);
  padding-left: 0.75rem;
}

.card.confirmed input[type='checkbox'] {
  accent-color: var(--confirmed);
}

/* The sign-in card's emblem. Decorative: the heading underneath already names the
   site, so the image carries an empty alt attribute and stays out of the way of a
   screen reader. */
.hero-mark {
  display: block;
  margin: var(--space) 0 0.9rem;
  height: 7.5rem;
  width: auto;
}

.muted {
  color: var(--muted);
  margin: 0 0 var(--space);
}

.empty {
  padding: 1rem 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.note {
  font-size: 0.9rem;
}

code {
  font-family: var(--mono);
  font-size: 0.9em;
  color: var(--text);
}

/* The data list on the privacy page: one thing the site keeps, its name above what it is
   for. A definition list is the element for a name and its explanation, and it needs no
   class of its own - a name and a description inside a card is the only place one is ever
   written, so the card is what selects it. */
.card dl {
  margin: 0 0 var(--space);
}

.card dt {
  font-weight: 600;
  margin-top: 0.9rem;
}

.card dd {
  margin: 0.15rem 0 0;
  color: var(--muted);
}

/* The point-by-point lists on the two legal pages. Every other list on the site is a list
   of controls, which is why it wears no bullets; these are lists of reasons, where a bullet
   is the thing that holds one point apart from the next. A list that nobody gave a class is
   what selects them: a list that has one has already been dressed by its own rule. */
.card ul:not([class]) {
  margin: 0 0 var(--space);
  padding-left: 1.1rem;
}

.card ul:not([class]) li {
  margin: 0.35rem 0;
}

.flashes {
  list-style: none;
  margin: var(--space) 0 0;
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--fill);
}

.flashes li {
  margin: 0;
}

form {
  margin: 0;
}

label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.9rem;
  color: var(--muted);
}

/* The three Settings pickers apply themselves, so their labels are the only thing on that
   page saying a choice can be made. They wear the amber a scheme already names for event
   times, plus a weight the muted prose around them does not carry: a class reaching an
   element wins over the plain element rule above, which is what makes them stand out. The
   event type picker's pills wear a different class, and keep their own colours. */
.pick-label {
  font-weight: 600;
  color: var(--time);
}

input {
  width: 100%;
  max-width: 20rem;
  padding: 0.6rem 0.75rem;
  font: inherit;
  color: var(--text);
  background: var(--fill);
  border: 1px solid var(--line);
  border-radius: 4px;
  transition: border-color 150ms, box-shadow 150ms;
}

/* A field lights up in the accent: the line turns to it and a ring of it, thinned out,
   grows around the field. The thinning is done where it is used rather than being
   written down as a paler colour, so a scheme only has to name the accent once. */
input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

/* The note box reads as the same kind of field as the text inputs above, but it is
   the one field worth making as wide as the page: a note is the part of an event you
   actually write. */
textarea {
  display: block;
  width: 100%;
  max-width: none;
  padding: 0.6rem 0.75rem;
  font: inherit;
  color: var(--text);
  background: var(--fill);
  border: 1px solid var(--line);
  border-radius: 4px;
  transition: border-color 150ms, box-shadow 150ms;
}

textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

::selection {
  background: var(--accent);
  color: var(--bg);
}

.button {
  display: inline-block;
  margin-top: 0.75rem;
  padding: 0.6rem 1.1rem;
  font: inherit;
  font-size: 0.95rem;
  color: var(--text);
  text-decoration: none;
  background: var(--fill);
  border: 1px solid var(--line);
  border-radius: 4px;
  cursor: pointer;
  transition: border-color 150ms, color 150ms;
}

.button:hover,
.button:focus {
  border-color: var(--accent);
  color: var(--accent);
}

.button.primary {
  color: var(--bg);
  background: var(--text);
  border-color: var(--text);
}

.button.primary:hover,
.button.primary:focus {
  color: var(--bg);
  background: var(--accent);
  border-color: var(--accent);
}

.button.subtle {
  color: var(--muted);
}

/* Wearing the scheme's danger red as a ring, so the button that cannot be undone is
   the one thing on the page with a red edge. The fill stays the plain one until the
   pointer is on it, which is when the ring is a warning rather than decoration. */
.button.danger {
  color: var(--danger);
  border-color: var(--danger);
}

.button.danger:hover,
.button.danger:focus {
  color: var(--danger);
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}

/* A row is a line of things meant to be read together: the three notification buttons,
   a band name with the buttons beside it, a save and a cancel. None of them fit on one
   line inside a phone's 320px of usable page, and a flex row that is not allowed to wrap
   answers that by squeezing every button down to its longest word, which reads as three
   tall skinny ones and on the narrowest phones still spills past the edge of the card.
   Wrapping belongs here rather than in the narrow-screen block at the end because the
   squeeze begins at any window under about 600px, not at 480px: a small laptop window
   needs it just as much as a phone does. */
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}

input[type="date"] {
  max-width: 12rem;
}

input[type="time"] {
  max-width: 8rem;
}

select {
  display: block;
  width: 100%;
  max-width: 20rem;
  padding: 0.6rem 0.75rem;
  font: inherit;
  color: var(--text);
  background: var(--fill);
  border: 1px solid var(--line);
  border-radius: 4px;
  transition: border-color 150ms, box-shadow 150ms;
}

select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

/* --- Bands, in the header and on their own pages ----------------------------- */
.band-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.band-link {
  padding: 0.5rem 0.75rem;
  font-size: 1.2rem;
  color: var(--text);
  text-decoration: none;
  background: var(--band-fill);
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: border-color 150ms, color 150ms;
}

.band-link:hover,
.band-link:focus {
  color: var(--accent);
  border-color: var(--accent);
}

.band-link.add {
  color: var(--muted);
  border-style: dashed;
}

/* The first button in the strip is not a band: it is the way back to the page that
   shows every band at once, so it is drawn in the quieter colour to tell it apart from
   the names beside it. */
.band-link.all {
  color: var(--muted);
}

.tag {
  margin-left: 0.4rem;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.band-head h1 {
  margin: 0;
}

/* A .row is flex and centres its items, and a button's margin-top is the space it
   wants when it sits under a form field. In a band's head it is beside a title instead,
   and that margin is what pushed the buttons below the name: the flex box centred the
   whole margin, not just the button. Only this head needs the margin gone - the rows
   under a field on the event pages still want it. */
.band-head .button {
  margin-top: 0;
}

/* --- The members page: one row per person, one below the next ------------------- */
.member-list {
  list-style: none;
  margin: 0 0 var(--space);
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.member-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem 0.75rem;
  padding: 0.55rem 0.9rem;
  background: var(--fill);
  border: 1px solid var(--line);
  border-radius: 8px;
}

/* Somebody switched off is quieter, but still a person in the band. */
.member-row.inactive {
  border-style: dashed;
}

.member-row.inactive .handle {
  color: var(--muted);
}

.member-list .button {
  margin-top: 0;
}

/* The tick box and the Remove button belong at the far end of a member row. */
.member-row .tick {
  margin-left: auto;
}

/* --- Tick boxes: the box you press to say something ----------------------------- */
.tick {
  display: flex;
  align-items: center;
}

.tick-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
  cursor: pointer;
}

/* x out of y: how many of the band's active members are coming, out of how many there
   are to convince. The same quiet type whether or not a tick box sits next to it.
   Tabular digits keep the two numbers lined up down a cluster. */
.tick-count {
  font-size: 0.85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The general input rule is written for text fields, so a tick box has to undo most
   of it, keep its own little square, and be twice as wide as a plain one so it is
   easy to hit. */
input[type='checkbox'] {
  width: 1.6rem;
  height: 1.6rem;
  max-width: none;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Once everybody active in the band has ticked, the box that completed the set is
   pressed in the settled green rather than the accent blue: the outline of the row
   still says what kind of event it is, the box says the counting is finished. */
.event-row.confirmed input[type='checkbox'] {
  accent-color: var(--confirmed);
}

/* --- Events and their colours ------------------------------------------------ */
/* One rounded rectangle per event. Events on the same day form a cluster that has no
   gap inside it; a different day is a new cluster, so it gets the space around it. */
.cluster {
  display: flex;
  flex-direction: column;
  margin: 0 0 1.5rem;
}

.event-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  color: var(--text);
  text-decoration: none;
  background: var(--event-fill);
  border: 1px solid var(--line);
}

/* Only the ends of a cluster are round, so rows sharing a day sit flush. */
.event-row:first-child {
  border-radius: 8px 8px 0 0;
}

.event-row:last-child {
  border-radius: 0 0 8px 8px;
}

.event-row:only-child {
  border-radius: 8px;
}

/* Overlap the two borders a cluster shares into one line. */
.event-row + .event-row {
  margin-top: -1px;
}

/* A row is both a link to the event it represents and a place to leave a tick. The
   link holds the badge, the names and the date; the tick stays outside it, at the far
   end of the row, so pressing a box is never the same as opening a page. */
.event-row-link {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  color: inherit;
  text-decoration: none;
}

.event-row > .tick,
.event-row > .tick-count {
  margin-left: auto;
}

/* Only a row that links somewhere lights up when you hover it, and the whole of it
   lights up, tick box included. */
.event-row:has(.event-row-link):hover,
.event-row:has(.event-row-link):focus-within {
  position: relative;
  z-index: 1;
  background: var(--lift);
}

/* Confirmed: every active member of the band has ticked "Going", so the row wears the
   colour of its own badge. A cluster overlaps the line two rows share, so a confirmed
   row has to sit above the neighbour that would otherwise paint over it. */
.event-row.confirmed {
  position: relative;
  z-index: 1;
}

.event-row.rehearsal.confirmed {
  border-color: var(--rehearsal);
}

.event-row.gig.confirmed {
  border-color: var(--gig);
}

.event-row.other.confirmed {
  border-color: var(--other);
}

/* Today: a row whose event belongs to this date is filled with a deep version of its own type
   colour, so which day something is on shows without reading any of the words on it. Only the
   day decides this: a row from tomorrow keeps the ordinary fill, and a row everybody has ticked
   keeps the edge its type gives it, because the day changes what is behind the words and a tick
   changes only the line around them. A cluster holds rows sharing one date, so a cluster is
   filled in all today or not at all, and clusters never sit flush against one another, so a
   today fill never runs into another day's fill. */
.event-row.rehearsal.today {
  --today-fill: var(--today-rehearsal);
}

.event-row.gig.today {
  --today-fill: var(--today-gig);
}

.event-row.other.today {
  --today-fill: var(--today-other);
}

.event-row.today {
  background: var(--today-fill);
}

/* Under the pointer a today row steps up the same way every other row does, to a lighter
   version of what it is already filled with, instead of being painted back to the neutral grey
   that would make the one row this page is pointing at look ordinary for as long as the pointer
   is on it. Naming the fill once for each type is what lets this single rule do it for all
   three colours. */
.event-row.today:has(.event-row-link):hover,
.event-row.today:has(.event-row-link):focus-within {
  background: color-mix(in srgb, var(--today-fill) 85%, white);
}

/* The middle of a row: the band page stacks the title over its note, the dashboard
   holds the band name. */
.event-main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.event-title,
.event-band {
  font-weight: 600;
}

.event-date {
  font-size: 1rem;
  white-space: nowrap;
  color: var(--muted);
}

/* On an event's own page the same line is a paragraph of its own, and a paragraph
   brings a browser default margin that would sit badly under a heading. */
p.event-date {
  margin: 0 0 0.5rem;
}

/* The "today" / "tomorrow" / "in 3 days" that leads a date. */
.event-rel {
  font-weight: 600;
  color: var(--text);
}

/* The time trails the date, so its digits line up down a cluster. */
.event-time {
  font-variant-numeric: tabular-nums;
  color: var(--time);
}

.event-note {
  font-size: 0.9rem;
  color: var(--muted);
}

.small {
  font-size: 0.85rem;
}

.tiny {
  font-size: 0.85rem;
  color: var(--muted);
}

.button.tiny {
  padding: 0.35rem 0.7rem;
  font-size: 0.85rem;
}

/* A badge is its type colour worn three ways: the word, a ring of the same colour
   thinned out, and a wash of it as the fill. Naming only the colour is what lets a
   scheme change it without anyone hunting for the pale copies of it. */
.badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid;
  border-radius: 999px;
}

.badge.rehearsal {
  color: var(--rehearsal);
  border-color: color-mix(in srgb, var(--rehearsal) 35%, transparent);
  background: color-mix(in srgb, var(--rehearsal) 12%, transparent);
}

.badge.gig {
  color: var(--gig);
  border-color: color-mix(in srgb, var(--gig) 35%, transparent);
  background: color-mix(in srgb, var(--gig) 12%, transparent);
}

.badge.other {
  color: var(--other);
  border-color: color-mix(in srgb, var(--other) 35%, transparent);
  background: color-mix(in srgb, var(--other) 12%, transparent);
}

/* One event's own page. The band name leads at the top, and it is the way back down
   to the band, so it is drawn like the links in the strip rather than as a heading. */
.band-crumb {
  display: inline-block;
  font-size: 0.9rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 150ms;
}

.band-crumb:hover,
.band-crumb:focus {
  color: var(--accent);
}

/* The badge and the one thing you may still change on an event sit on one line. */
.type-line {
  margin-bottom: 0.5rem;
}

/* --- One event's own page: who is coming --------------------------------------- */
/* The names run straight down, one below the next, because the point of this list is
   to read a set of people, not to act on any of them. They are in the order of their
   handles, so the same crowd reads the same way on every page it is shown on. */
.going-list {
  list-style: none;
  margin: 0 0 var(--space);
  padding: 0;
}

.going-list li {
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--line);
}

.going-list li:last-child {
  border-bottom: 0;
}

/* The buttons that book and change an event. */
.add-event {
  margin-top: 1rem;
}

/* --- The type picker: the three colours as buttons you click ------------------ */
fieldset {
  margin: 0 0 1rem;
  padding: 0;
  border: 0;
}

fieldset legend {
  margin-bottom: 0.35rem;
  font-size: 0.9rem;
  color: var(--muted);
}

.type-pick {
  display: flex;
  flex-wrap: wrap;
  margin: 1.5rem 0 1.5rem;
  gap: 0.5rem;
}

/* The real radio button is kept, just hidden behind the pill, so the picker works
   with no JavaScript and stays selectable by keyboard. */
.pick {
  position: relative;
  margin: 0;
}

.pick input {
  position: absolute;
  width: auto;
  max-width: none;
  padding: 0;
  opacity: 0;
}

.pick span {
  display: inline-block;
  padding: 0.4rem 0.9rem;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  background: var(--fill);
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: color 150ms, border-color 150ms, background 150ms;
}

.pick.rehearsal span {
  color: var(--rehearsal);
  border-color: color-mix(in srgb, var(--rehearsal) 35%, transparent);
}

.pick.gig span {
  color: var(--gig);
  border-color: color-mix(in srgb, var(--gig) 35%, transparent);
}

.pick.other span {
  color: var(--other);
  border-color: color-mix(in srgb, var(--other) 35%, transparent);
}

/* A picked pill is the same colour again, only fuller: the ring goes solid and a wash
   of the colour fills the pill, so the choice you made is the loudest thing on the row. */
.pick.rehearsal input:checked + span {
  background: color-mix(in srgb, var(--rehearsal) 16%, transparent);
  border-color: var(--rehearsal);
}

.pick.gig input:checked + span {
  background: color-mix(in srgb, var(--gig) 16%, transparent);
  border-color: var(--gig);
}

.pick.other input:checked + span {
  background: color-mix(in srgb, var(--other) 16%, transparent);
  border-color: var(--other);
}

/* The keyboard focus ring, since the control you can actually see is the span. */
.pick input:focus-visible + span {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

/* --- The calendar: a link per day, bigger numbers, seven equal columns --------- */
/* The month label leads, and the three month links sit below it, lined up with its left
   edge, rather than being shoved to the far end of the same line. */
.calendar-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin: 1rem 0 1rem;
  gap: 0.45rem;
}

/* The grid used to shrink-wrap to the widest thing a day cell holds, which is a
   two-digit number or three six-pixel dots: about 17rem in practice, so any cap
   written here was never reached. Fixed layout and an explicit width make the width a
   number that is obeyed instead, and divide it between the columns evenly rather than
   handing each column whatever its contents happen to want. 22rem is that 17rem plus
   about 28 per cent: roomier days, and still inside the page column, so nothing else
   on the booking page moves. An explicit width also means the grid is the same size
   whichever typeface someone chose in Settings, because the columns are no longer
   sized by their type. max-width leaves a narrow screen in charge of it. */
.calendar {
  table-layout: fixed;
  width: 22rem;
  max-width: 100%;
  margin-top: 0.5rem;
  border-collapse: collapse;
}

.calendar th {
  padding: 0.35rem 0;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.calendar td {
  padding: 0.2rem;
  text-align: center;
}

/* Days outside the month being shown: a ground very slightly raised out of the page,
   which is why it belongs to the scheme rather than being a wash of white. */
.calendar td.off {
  background: var(--wash);
}

.calendar a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.15rem;
  color: var(--text);
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 4px;
  transition: border-color 150ms;
}

.calendar a:hover,
.calendar a:focus {
  border-color: var(--line);
}

.day-num {
  font-size: 1.1rem;
  font-variant-numeric: tabular-nums;
}

.past .day-num {
  color: var(--muted);
}

/* Today's number is the one your eye looks for first. */
.today .day-num {
  font-size: 1.45rem;
  font-weight: 700;
}

.today a {
  padding-top: 0.15rem;
  border-color: var(--line);
}

.selected a {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}

.dots {
  display: flex;
  gap: 0.2rem;
  min-height: 6px;
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

.dot.rehearsal {
  background: var(--rehearsal);
}

.dot.gig {
  background: var(--gig);
}

.dot.other {
  background: var(--other);
}

/* Prev, today and next cut to the same shape an event badge is cut from: 0.75rem
   uppercase letters, 0.04em of tracking, a 1px edge and a 999px radius, which makes each
   one 27px tall, exactly as tall as a badge. What they do not take is any of the colour,
   because these are controls and not the label of an event type: the resting edge is the
   plain hairline every card and row already uses. Under the pointer the edge and the ink
   each step one shade up towards white instead of taking the accent, so the only colour
   left anywhere on the calendar is the colour of an event. Three pills measure 185px
   between them, which is well inside the 352px grid, and wrapping is there for a narrow
   screen rather than because they need it. */
.calendar-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.calendar-nav a {
  padding: 0.2rem 0.7rem;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: color 150ms, border-color 150ms;
}

.calendar-nav a:hover,
.calendar-nav a:focus {
  color: var(--text);
  border-color: var(--muted);
}

#google-button {
  margin: var(--space) 0;
}

/* The dev sign-in buttons sit side by side and wrap on a narrow screen. */
.dev-login {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.75rem;
}

.dev-login .button {
  margin-top: 0;
}

@media (max-width: 480px) {
  /* The page column is what is left after the padding on both sides, so on a 360px phone
     the usable line is 320px here and 328px when the padding is 1rem instead of 1.25rem.
     Those 8px are what an event's whole date line needs in order to stay on one line
     inside a row, and the header gives the same room back to the links. */
  main,
  .site-header {
    padding-left: 1rem;
    padding-right: 1rem;
  }

  /* At this width the header makes two lines, the wordmark and then the links, and each of
     them is the only item on its own line. A lone item in a space-between row sits at the
     left edge, which is where the wordmark was: centring is what brings both lines into the
     middle of the column instead. */
  .header-top {
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem 1rem;
  }

  /* The negative margin on the wordmark exists to pull the drawn letters flush with the band
     strip underneath them. Here nothing is underneath them, and keeping it would leave them
     about 10px left of the middle: the file holds 473px of canvas around 395px of drawn
     wordmark, a 40px transparent gutter on its left and 38px on its right, so centring the
     box is not the same as centring the letters in it. */
  .brand-mark {
    margin-left: 0;
  }

  /* The band buttons are the line below these, and they wrap the same way. Centring is what
     makes each line of pills read as a line of its own in the middle of the column, rather
     than a row that starts hard at the left edge and trails off before the last one. */
  .band-strip {
    justify-content: center;
  }

  /* A band's own head - its name and the buttons that lead to its members and its settings -
     is one of the shared rows, so it borrows their arrangement and starts hard at the left end
     of every line it wraps into. A band name beside two buttons measures well past a phone's
     line, so what arrives here is two lines, and centring is what brings both of them into the
     middle of the column. The name is centred as words as well, because a name long enough to
     break inside its own box would otherwise trail off to the left above buttons that are
     centred. */
  .band-head {
    justify-content: center;
  }

  .band-head h1 {
    text-align: center;
  }

  /* The emblem at the top of the sign-in card is a block with a plain left margin, so it sits
     hard at the left edge of the card. At this width the card is the whole page and the emblem
     is the first thing on it, so it reads better in the middle, and auto margins on both sides
     are what put it there. The file holds 313px of canvas around 268px of drawn art, 24px of it
     transparent on the left and 21px on the right, and the rule above draws the mark 120px tall:
     a scale that turns those 3px of uneven gutter into about half a pixel on the page, so the
     box can simply be centred here, with no correction the way the wordmark needs one. */
  .hero-mark {
    margin-left: auto;
    margin-right: auto;
  }

  /* The Add event button on a band page is the last thing in the card, so it has a line to
     itself, which is what makes where it sits a question of centring rather than of what it
     shares a line with. The button style it inherits draws it as an inline box sized to its own
     words, and auto margins do nothing to an inline box: they divide up the room left on a line
     only for a box that owns the whole of it. So the box becomes a block, and max-content is
     what stops that block from stretching across the column - the same box and the same size as
     on a wide window, brought into the middle. The room it is given above is left as it is, and
     two words of button sit well inside a phone's line. */
  .add-event {
    display: block;
    width: max-content;
    margin-left: auto;
    margin-right: auto;
  }

  /* A field is as wide as the page and the button that submits it sits inline after it, so
     the two share a line only if the field gives up room for the button. This reserves that
     room - measured from the widest button that follows one of these fields, "Create band"
     at about 130px - and relaxes back towards the full width on a wide phone. */
  #username,
  #name {
    max-width: calc(100% - 9rem);
  }

  .calendar th,
  .calendar td {
    padding: 0.1rem;
  }

  /* A narrow screen has room for a date that leads with "tomorrow" and trails with a
     time, but only just: the whole line measures about 283px and the room inside an event
     row is about 299px. Breaking is the safety net for what pushes past that, an unusually
     wide display face or a longer relative day, where the time moves onto a line of its
     own instead of shoving the tick box out of the row. */
  .event-date {
    font-size: 0.9rem;
    white-space: normal;
  }

  /* A thumb is a far worse pointer than a mouse, so on a phone the controls cut for a
     mouse are made taller. Heights measured in this typeface: the month links were 26px
     and are now about 39, the type pills 35 and now about 43, the small buttons 35 and
     now about 41, the tick box 26 and now about 38, the header links and the edit-note
     link 23 and now about 36. The calendar grid is left as it is, because at this width
     each day cell already measures about 47 tall by 44 wide. */
  .calendar-nav a {
    padding: 0.55rem 0.9rem;
  }

  .pick span {
    padding: 0.65rem 1rem;
  }

  .button.tiny {
    padding: 0.55rem 0.9rem;
  }

  input[type='checkbox'] {
    width: 2.4rem;
    height: 2.4rem;
  }

  .site-header nav a,
  .link-button,
  .tiny {
    padding: 0.4rem 0;
  }
}
