/* =============================================================================
   THE GUS BAND — SITE STYLES
   Brand: Heritage Scarlet #BE1D2E · Royal Red #A50E0E · Sovereign Gold #F1C532
   Type:  Noverion Sans. Headings CAPS · sub-heads Title Case · body sentence case
   ============================================================================= */

/* WOFF2, WHICH IS THE SAME THREE FACES AT LESS THAN HALF THE WEIGHT — 108KB of
   TrueType became 48KB, on the first visit to every page. Nothing is lost: the
   format is the web's own, every browser this site supports has read it for
   the best part of a decade, and the .ttf masters are in the folder the fonts
   came from rather than in the site. */
@font-face{font-family:'Noverion';src:url('../fonts/NoverionMedium.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'Noverion';src:url('../fonts/NoverionBold.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'Noverion';src:url('../fonts/NoverionBlack.woff2') format('woff2');font-weight:900;font-display:swap}

:root{
  --scarlet:#BE1D2E; --royal:#A50E0E; --gold:#F1C532;
  --ink:#14100F; --ink-2:#241B1A;
  --paper:#fff; --tint:#FAF6F3; --line:#E6DDD8; --mute:#6B5F5B;
  --wrap:1180px;
  --f:'Noverion',system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
}

*{box-sizing:border-box}
/* The hidden attribute applies display:none at the lowest priority, so any later
   rule setting display:flex/grid would silently un-hide the element. */
[hidden]{display:none !important}
html{scroll-behavior:smooth}
/* Smooth scrolling is movement the reader did not ask for, and the one setting
   on this page that ignored their preference: every reveal and rotator already
   stops under reduced motion, and a jump down the page should simply arrive. */
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
/* FOCUS IS NEVER HIDDEN UNDER THE HEADER (WCAG 2.4.11). Tab forwards and the
   browser scrolls the next control up from the bottom, which is fine; Shift+Tab
   backwards and it scrolls the control down only as far as the top edge of the
   window, which is under the sticky header, so the ring and the field were both
   out of sight. On the buy page at 1280 the Name box sat at -16px with the
   header's foot at 75. Telling the root that its top --hdr-h (measured by
   site.js, gold rule included) is covered makes every scroll the browser does
   for focus, an anchor or scrollIntoView stop below it, with 16px of air. The
   admin uses the same header and the same measured value, so this covers it
   too. --hdr-h is declared just under the header rule below; custom properties
   do not care about order. */
html{scroll-padding-top:calc(var(--hdr-h) + 16px)}

/* Set on <html> while the biography panel is open, so the page behind can't be
   scrolled under it. On the root rather than on <body>: the root is the element
   that actually scrolls, and locking it leaves the scroll position alone.
   Locking <body> instead is what used to throw the page back to the top every
   time a player was opened. */
/* THE PAGE BEHIND A PANEL, HELD STILL WITHOUT MOVING IT.

   overflow:hidden alone is what made clicking a player jump the page to the
   top. The root is the thing that scrolls; take its ability to scroll away and
   the browser clamps it to zero, and the backdrop is see-through enough that
   you watch it happen.

   So the body is pinned instead, at minus the distance already scrolled — which
   leaves it looking exactly where it was while the root has nothing left to
   scroll. site.js sets --page-y and --bar before adding the class.

   --bar is the width the scrollbar took up. A pinned body has no scrollbar, and
   without putting that width back as padding the whole page slides sideways by
   about fifteen pixels as the panel opens. */
html.dlg-open{overflow:hidden}
html.dlg-open body{position:fixed;top:var(--page-y,0);left:0;right:0;width:100%;
  padding-right:var(--bar,0)}
body{margin:0;font-family:var(--f);font-weight:500;font-size:17px;line-height:1.65;
  color:var(--ink);background:var(--paper);-webkit-font-smoothing:antialiased}
img{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3,h4{margin:0;line-height:1.05;font-weight:900}
/* .ad-welcome-who is the name on the admin's welcome. It is listed here rather
   than given a heading style of its own next to it: the first version had
   Title Case and negative tracking, which is not how this band sets a heading,
   and the only reliable way to keep type in step is to have one declaration of
   it. */
h1,.ad-welcome-who{font-size:clamp(40px,7vw,84px);text-transform:uppercase;
  letter-spacing:.005em}
h2{font-size:clamp(28px,4.2vw,48px);text-transform:uppercase;letter-spacing:.01em}
h3{font-size:22px}
p{margin:0 0 1em}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 24px}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.skip{position:absolute;left:-9999px;background:var(--gold);color:var(--ink);
  padding:12px 18px;z-index:200;font-weight:700}
.skip:focus{left:12px;top:12px}
/* THE RING HAS TO BE SEEN AGAINST WHAT IT IS ON. Sovereign Gold is 1.64:1
   against paper and 1.23:1 against the resting border — so on every white
   ground on this site, a keyboard user had no usable indication of where they
   were. WCAG asks for 3:1. Heritage Scarlet on white is 6.17:1.

   Gold keeps the rings that sit on ink or on scarlet, where it is the legible
   choice and the brand's own. The stylesheet had already worked this out once,
   for the admin's half of a shared selector; the public half was left behind. */
:focus-visible{outline:3px solid var(--scarlet);outline-offset:3px}
.dark :focus-visible,.red :focus-visible,.foot :focus-visible,
.ad-gate :focus-visible,.page-head :focus-visible{outline-color:var(--gold)}

/* ---------- type helpers ---------- */
.kicker{font-weight:700;text-transform:uppercase;letter-spacing:.18em;
  font-size:12px;color:var(--scarlet);margin:0 0 12px}
/* The gap under a kicker has to grow with the heading beneath it. A flat 12px
   reads as generous under a 28px heading and cramped under a 48px one, which is
   why "COME AND HEAR US" looked tighter than everything else on the site. The em
   resolves against the heading's own size, so every kicker/heading pair now has
   the same optical gap with nobody tuning it page by page. */
.kicker + h1,.kicker + h2,.kicker + h3,.kicker + p{margin-top:.16em}
.dark .kicker{color:var(--gold)}
.lede{font-size:clamp(17px,1.9vw,21px);line-height:1.6}
.txtlink{font-weight:700;font-size:14px;letter-spacing:.05em;text-decoration:none;
  color:var(--scarlet);border-bottom:2px solid transparent;white-space:nowrap}
.txtlink:hover{border-color:var(--gold)}
.dark .txtlink{color:var(--gold)}

/* ---------- buttons ---------- */
/* ---- THE TRAILING LETTER-SPACE, which affects every label on this site ----
   CSS puts the tracking AFTER the last letter as well as between letters, so a
   letter-spaced word is always carrying an invisible gap on its right. Centre
   that word and you centre the gap with it, which leaves the visible letters
   sitting half the tracking to the LEFT of true centre. Every uppercase label
   here is letter-spaced, so every one of them has it.

   The header lockup already compensates for this in script when it measures the
   band name. These are the CSS equivalents, and there are two, because the fix
   depends on how the text is aligned:

     CENTRED text  ->  text-indent equal to the tracking. The browser centres
                       the line in the width left after the indent and then
                       offsets it by the indent, so the line moves right by half
                       of it — exactly the correction needed.

     LEFT-aligned  ->  take the tracking off the right padding. A shrink-to-fit
     chips            box would otherwise look like it had more air on the right
                       than the left, because it has.

   Both are written in em so they stay correct if the type size changes.        */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-weight:700;
  font-size:14px;letter-spacing:.09em;text-indent:.09em;text-transform:uppercase;
  text-decoration:none;
  padding:16px 30px;border:2px solid transparent;border-radius:0;cursor:pointer;
  font-family:inherit;transition:.18s}
/* A finger needs 44px whatever the button says — the admin worked that out and
   then said it in a rule of its own that beat this one everywhere. It belongs
   here, once. */
.btn-sm{min-height:44px;padding:11px 20px;font-size:12.5px}
.btn-gold{background:var(--gold);color:var(--ink);border-color:var(--gold)}
.btn-gold:hover{background:#ffdf5e;border-color:#ffdf5e}
.btn-red{background:var(--scarlet);color:#fff;border-color:var(--scarlet)}
.btn-red:hover{background:var(--royal);border-color:var(--royal)}
/* Royal Red on Heritage Scarlet — the accent doing what it's for, sitting on
   the primary without competing with it. Hovers to ink rather than to a lighter
   red, since there is no red darker than royal to move to. */
.btn-royal{background:var(--royal);color:#fff;border-color:var(--royal)}
.btn-royal:hover{background:var(--ink);border-color:var(--ink)}
.btn-ghost{background:rgba(255,255,255,.07);color:#fff;border-color:rgba(255,255,255,.6)}
.btn-ghost:hover{background:#fff;color:var(--ink);border-color:#fff}
.btn-outline{background:none;color:var(--ink);border-color:var(--line)}
.btn-outline:hover{border-color:var(--scarlet);color:var(--scarlet)}

/* ---------- header ----------
   Heritage Scarlet is the primary brand colour and leads every major surface.
   Royal Red is the accent: gradient ends, dividing rules, hover states.
   Gold on Scarlet is 3.75:1 — fine for large display text, so small text
   (this sub-line, nav links, kickers) is white and gold does the rules. */
/* Full-width gold rule, flush to the bottom of the header. 7px rather than the
   original 5px — the extra weight was the part of the experiments worth keeping.
   Tried at 12px since; too heavy, and 7px is settled.
   Even padding top and bottom: the tallest thing in here is the Tickets button,
   and a button is a box with no overhang, so equal padding reads as equal. */
/* --hdr-h is measured and published by site.js — the real height of this bar,
   gold rule included. Everything that has to clear the header reads it rather
   than carrying its own copy of the number. 73px is only the value used before
   the script has run and on a page with no script at all. */
:root{--hdr-h:73px}
.site{position:sticky;top:0;z-index:100;background:var(--scarlet);
  border-bottom:7px solid var(--gold)}

/* Going down the page on a phone the header leaves; coming back up it returns.
   The class is put on and taken off by site.js, which only ever does so on a
   touch layout, never above the first screenful, and never while the menu is
   open. transform rather than top, so it costs no layout and cannot shift the
   page as it moves. */
.site{transition:transform .28s ease}
.site.gone{transform:translateY(-100%)}
@media(prefers-reduced-motion:reduce){
  /* Asked for less movement, so it does not slide — it is simply there or not,
     which is still the behaviour, without the travel. */
  .site{transition:none}
}
.hdr{display:flex;align-items:center;gap:24px;padding:11px 24px}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:#fff;flex:0 0 auto}
/* LOGO VARIANTS — gus-logo.png is the FLAT mark, for small sizes. The shadowed
   mark (gus-logo-shadow.png) is for large reproductions; below roughly 120px the
   offset shadow closes up and reads as dirt rather than depth.
   Use .logo-lg on any logo rendered at 120px or more. */
.brand img{height:44px;width:auto}
.logo-lg{content:url('../img/gus-logo-shadow.png')}
/* Nothing carries .logo-lg at the moment — the footer logo went back to 54px.
   The rule stays because it is the brand rule, not a leftover: the day anything
   is rendered at 120px or more it needs this, and the rule is where the
   instruction above it can be found. */
/* The name is scaled by site.js to exactly match the sub-line's width — the two
   are measured in the browser, because estimating from font metrics gets it
   wrong by enough to notice. 20px is only the starting point; the script
   overwrites it. --lockup is the resolved size. */
.brand span{display:block}
.brand b{font-weight:900;font-size:var(--lockup,20px);letter-spacing:.06em;display:block;
  line-height:1;white-space:nowrap}
.brand i{font-style:normal;font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:#fff;opacity:.92;display:block;margin-top:3px;white-space:nowrap}
/* The current-page underline runs down to meet the gold rule, so the two join
   into a T rather than the underline floating above it. For that the links have
   to reach the very bottom of the header: the nav stretches to the full content
   height, then eats the header's 11px bottom padding with a negative margin,
   which puts each link's bottom border flush against the gold. The link's own
   11px bottom padding puts the text back on the optical centre it had before.
   The Tickets button opts out of the stretch — it's a box, not a tab. */
.nav{display:flex;gap:20px;margin-left:auto;align-items:stretch;
  align-self:stretch;margin-bottom:-11px}
/* The highlight is 4px against the rule's 7px. Tried at 7px so the two strokes
   of the T matched; it read as heavy, and 4px is right. */
.nav a{font-weight:700;font-size:13px;letter-spacing:.05em;text-transform:uppercase;
  color:#fff;text-decoration:none;display:flex;align-items:center;
  padding:0 0 11px;border-bottom:4px solid transparent}
.nav a:hover,.nav a[aria-current=page]{border-color:var(--gold);color:#fff}
/* .nav a sets white for the links, and it out-specifies .btn-gold's own colour —
   so the Tickets button has to claim ink back explicitly, resting AND hover.
   Without this it renders white on gold, which is 1.7:1 and close to illegible. */
.nav .btn,.nav .btn:hover{color:var(--ink)}
.nav .btn{align-self:center;margin-left:6px;margin-bottom:11px;padding:11px 20px;
  font-size:12px;border-bottom:2px solid var(--gold)}
/* Each link stays on one line. With the brand, six links, Tickets and the social
   icons the row was about 30px too full even at full width, so "What's on", "The band"
   and "Book us" broke onto two lines. A slightly smaller gap fits it at full width, and
   between the phone menu and full width the social icons step out (they are in the
   footer too). */
.nav a{white-space:nowrap}
.nav{gap:16px}
@media(min-width:1001px) and (max-width:1199px){.nav .social{display:none}}

/* NO OPTICAL NUDGE HERE, and it is worth saying why not.
   The Tickets button and the icons were once pushed down 3px on the theory that
   the 7px gold rule reads as part of the same block, so centring on the scarlet
   alone leaves things 3.5px high. It was a nice argument and it was wrong: on
   screen the button then sat visibly low, worse than what it replaced.
   The measurement was right all along — the scarlet runs 71.1px and the
   button's centre is at 35.5px, which is exactly half. Leave it alone. */

/* ---- social links in the header ----
   Deliberately quieter than everything else up here. The nav takes people
   through the site and the Tickets button is the one thing we want pressed;
   three icons at 80% white are a way out to somewhere else, and should not
   compete with either. They come up to full white on hover.

   Marked out from the nav by a hairline rather than by extra space, because
   space alone at this size reads as a gap rather than a division. They opt out
   of the nav's full-height stretch — these are icons, not tabs, so they take no
   underline and centre on the row like the button does. */
.social{display:flex;align-items:center;gap:2px;align-self:center;
  margin-bottom:11px;margin-left:14px;padding-left:14px;
  border-left:1px solid rgba(255,255,255,.22)}
/* These are inside .nav, so `.nav a` matches them too — and that rule turns a
   link into a full-height tab: 11px of bottom padding and a 4px bottom border
   for the current-page underline. Both selectors are one class and one element,
   so they have equal specificity and .social a only wins on the properties it
   actually names. It named neither of those.

   The result: everything is border-box, so a 34px button with 11px of padding
   and a 4px border had 19px of content area left, and the icon centred in that
   — 7.5px above the middle of the button. The hover rule would also have drawn
   a gold underline beneath each icon. Both are undone explicitly here. */
.social a{display:grid;place-items:center;width:34px;height:34px;
  padding:0;border-bottom:0;
  color:rgba(255,255,255,.8);transition:color .15s}
.social a:hover{color:#fff;border-color:transparent}
.social svg{width:19px;height:19px;display:block}
/* 44 by 44. The three bars occupy only 24 by 16 of it; the rest is padding,
   which is invisible and is exactly the point — a target the size of a
   fingertip rather than the size of the drawing on it. */
.burger{display:none;background:none;border:0;cursor:pointer;flex-direction:column;
  justify-content:center;align-items:center;
  gap:5px;width:44px;height:44px;padding:0;margin-left:auto}
.burger span{display:block;width:24px;height:2px;background:#fff}

/* ---------- hero ---------- */
/* overflow:hidden is load-bearing, not tidiness. .hero-img is deliberately taller
   than this box so it can drift for the parallax; without clipping, that extra
   9% top and bottom simply paints outside the hero — and since .sec has no
   background of its own, the spill below showed as a strip of photograph between
   the gold "next performance" bar and What's On. .quote had this from the start;
   the hero didn't, because until the parallax nothing overflowed it. */
.hero{position:relative;color:#fff;isolation:isolate;background:var(--ink-2);
  overflow:hidden}
/* Overhangs top and bottom so it can drift against the scroll without ever
   showing an edge — the same trick as the quote photograph, gentler, because
   this one is on screen the moment the page opens. */
.hero-img{position:absolute;inset:-9% 0;z-index:-2;background-size:cover;
  background-position:center 40%;background-repeat:no-repeat}
/* Two layers, so the photograph still reads:
   1. a neutral scrim, strongest behind the text on the left, fading off to the
      right — this is what carries the legibility, not the colour;
   2. a light Heritage Scarlet wash, deepening to Royal Red at the base where it
      meets the gold bar. Kept well under a third so the image shows through. */
.hero::after{content:'';position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(90deg,
      rgba(20,16,15,.72) 0%,
      rgba(20,16,15,.58) 40%,
      rgba(20,16,15,.30) 75%,
      rgba(20,16,15,.14) 100%),
    linear-gradient(180deg,
      rgba(190,29,46,.20) 0%,
      rgba(190,29,46,.28) 55%,
      rgba(165,14,14,.48) 100%)}
/* safety net for the body line, which sits lower over unpredictable image areas */
.hero .lede{text-shadow:0 1px 12px rgba(20,16,15,.55)}
/* No max-width of its own, so it keeps .wrap's 1180px and starts on the same
   left edge as every other section — including the gold "next performance" bar
   immediately beneath it, which is also a .wrap. It used to be capped at 880px,
   which centred it and pushed the headline 150px to the right of everything
   else on the page. The reading measure is still controlled, just not here:
   .hero .lede caps itself at 600px, which is what that 880 was really for. */
.hero-in{padding:96px 24px 104px}
.hero h1{text-shadow:0 4px 34px rgba(0,0,0,.45)}
/* The whole headline is white — the gold bar underneath is the only gold here,
   which keeps the accent doing one job rather than two. */
.hero h1 em{font-style:normal;color:inherit}
.hero .lede{max-width:600px;margin:22px 0 34px;color:rgba(255,255,255,.93)}
.hero-cta{display:flex;gap:14px;flex-wrap:wrap}
/* White, not gold: this is 12px text on Heritage Scarlet, where gold is 3.75:1. */
/* column-gap MUST stay 0. The gold divider is a ::before inside the following
   span, so any column gap is added on its left only — the pipe then sits that
   much nearer the word on its right. With the gap at zero the spacing comes
   entirely from the divider's own symmetric 12px margins, and the .16em
   letter-space that trails both the previous word and the pipe itself falls on
   each side equally. Row gap still applies when the strip wraps on a phone. */
.proof{display:flex;column-gap:0;row-gap:8px;flex-wrap:wrap;align-items:center;
  margin:0 0 26px;font-weight:700;font-size:12px;letter-spacing:.16em;
  text-transform:uppercase;color:#fff}
.proof span{display:inline-flex;align-items:center}
.proof span+span::before{content:'|';margin:0 12px;color:var(--gold);opacity:1;font-weight:500}

/* The rotating honour. Every entry is stacked in one grid cell, so the strip is
   sized by the longest and nothing shifts as they change — a chip that resized
   itself would nudge the whole line every few seconds. Only the current one is
   visible; the rest stay in the document for screen readers, which get the
   complete list rather than whichever happened to be on screen. */
/* The stacking goes on an inner .cycle, NOT on the .proof-cycle span itself.
   `.proof span+span::before` draws the gold divider as a pseudo-element inside
   that span — make the span a grid and the divider becomes a grid item, lands
   in row two, and drags the text out of line. Leaving the span as an ordinary
   flex item keeps the divider beside the text where it belongs. */
.proof-cycle .cycle{display:inline-grid;align-items:center}
.cycle b{grid-area:1/1;font-weight:700;opacity:0;transition:opacity .45s ease;
  white-space:nowrap;text-align:left}
.cycle b.on{opacity:1}
/* The longest honour is about 280px once letter-spaced, which overflows the
   narrowest phones. Below that, let it wrap — the grid still stacks them, so
   the strip becomes two lines tall rather than running off the screen. */
@media(max-width:480px){.cycle b{white-space:normal}}

/* The rotating occasion above BOOK THE BAND. Same stacking device as the hero
   chip: every line in one grid cell, so the block is as tall as the tallest and
   the heading beneath it never moves as they change. Centred, because the CTA
   section is. */
.cta-cycle .cycle{display:inline-grid;align-items:center;text-align:center}
.cta-cycle .cycle b{text-align:center}
@media(max-width:560px){.cta-cycle .cycle b{white-space:normal}}
@media(prefers-reduced-motion:reduce){
  /* Shown one after another as ordinary text rather than fading. */
  .cta-cycle .cycle{display:inline}
  .cta-cycle .cycle b{opacity:1}
  .cta-cycle .cycle b+b{display:none}
}
/* Nothing should move by itself for anyone who has asked it not to. All of them
   are then shown in sequence, which the strip can carry. */
@media(prefers-reduced-motion:reduce){
  .proof-cycle .cycle{display:inline}
  .cycle b{opacity:1;transition:none}
  .cycle b+b::before{content:'|';margin:0 10px;color:var(--gold);font-weight:500}
}

/* Heritage Scarlet across the body, Royal Red only in the far corner. */
/* Ink, the same treatment as the enquiry panel on Book Us: flat black ground,
   white heading, gold kicker, and the black crest reading as a shade rather
   than a shape. Deliberately not scarlet — the header above is already scarlet,
   so a scarlet banner directly beneath it stacked two reds with only the gold
   rule between them. */
.page-head{background:var(--ink);
  color:#fff;padding:64px 0 58px;border-bottom:5px solid var(--gold)}
.page-head h1{font-size:clamp(34px,5.5vw,60px)}
/* THE THREE LINES ARE ONE LOCKUP. The gold bar sits under the heading at
   exactly its own thickness — 8px under an 8px bar, which is the rule the whole
   site is set to — while the kicker floated nineteen pixels above it, so the
   pair read as two separate things that happened to be stacked. The air above
   the capitals is now the air below them.

   Nineteen became eight by taking eleven off the box, not off the eye: seven of
   those pixels are the leading under the kicker's own line — the space its
   descenders would use if it had any, and it is capitals, so it never does. The
   correction is in the kicker's em rather than in pixels, so it still holds if
   the kicker is ever set at another size. */
.page-head .kicker{color:var(--gold);margin-bottom:calc(8px - .58em)}
.page-head .kicker + h1{margin-top:0}
.page-head .lede{max-width:660px;margin-top:18px;color:rgba(255,255,255,.94)}

/* THE FRONT PAGE'S OWN TITLE, in the white under the banner. The banner is
   addressed to the person — good evening, DANIEL — so the page itself would
   otherwise go unnamed, and a front page with no title reads as the middle of
   something. The same heading device as every other screen in here, sitting on
   the same left edge as the strip and the tiles below it. */
.ad-intro-home{margin:0 0 26px}
/* AND AT FULL SIZE, because it is the page's heading and not a caption on the
   way to one. Deliberately the same clamp as the banner's own h1, so the two
   titles on this screen track each other at every width — the ink says who is
   here, the white says what this is, in the same voice. */
.ad-intro-home h2{font-size:clamp(34px,5.5vw,60px)}
/* And the bar under it is the banner's, not the section pages': the thickness
   goes with the size of the word it is under, and this word is now the same
   size as the one in the ink above it. */

/* ---------- next performance bar ---------- */
.nextbar{background:var(--gold);color:var(--ink)}
.nextbar-in{display:flex;align-items:center;gap:18px;padding:14px 24px;flex-wrap:wrap}
/* The black tag looked to be sitting high in its own box, and it was.
   The label inherited the body's 1.65 line-height, so an 11px capital sat in an
   18px line box. Capitals have no descenders, so all the ink is in the top part
   of that box and the empty descender space below it pushes the visible block
   above centre — the padding was even, but the thing inside it wasn't.

   line-height:1 takes the leading out, then 1px more above than below corrects
   for capitals sitting slightly high in the em itself. The letter-spacing also
   adds a trailing gap after the final letter, which shifts the label left of
   centre; padding-right carries 1px less to take that back out. */
.nb-tag{font-weight:900;font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  background:var(--ink);color:var(--gold);border-radius:0;
  line-height:1;padding:9px calc(12px - .16em) 8px 12px}
.nb-body{font-weight:700;font-size:15px;flex:1 1 auto}
.nb-link{font-weight:700;font-size:13px;letter-spacing:.06em;text-transform:uppercase;
  text-decoration:none;border-bottom:2px solid var(--ink);white-space:nowrap}

/* ---------- sections ---------- */
.sec{padding:84px 0}
.sec-tint{background:var(--tint)}
.dark{background:var(--ink);color:#fff}
.dark h2,.dark h3{color:#fff}
.dark p{color:rgba(255,255,255,.82)}

/* Heritage Scarlet section. White text only — gold small text fails here. */
.red{background:var(--scarlet);color:#fff}
.red h2,.red h3{color:#fff}
.red p{color:rgba(255,255,255,.94)}
.red .kicker{color:#fff}
.red .txtlink{color:#fff;border-bottom-color:rgba(255,255,255,.5)}
.red .txtlink:hover{border-bottom-color:var(--gold)}
.red .venues span{border-color:rgba(255,255,255,.45);background:rgba(0,0,0,.16)}
.red .btn-outline{color:#fff;border-color:rgba(255,255,255,.6)}
.red .btn-outline:hover{background:#fff;color:var(--scarlet);border-color:#fff}
.sec-head{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;
  margin-bottom:36px;flex-wrap:wrap}
/* :not(.kicker), and that is the whole point of it. `.sec-head p` is a class
   plus an element, so it outranks the bare `.kicker` class and was painting the
   little heading above the title mute grey — but only inside a .sec-head. Seven
   of them across three pages were grey while every other kicker on the site was
   scarlet, which is why they looked arbitrary: the rule that greyed them was
   meant for the sentence underneath, and caught the kicker on the way past. */
.sec-head p:not(.kicker){margin:10px 0 0;color:var(--mute);max-width:56ch}
.dark .sec-head p{color:rgba(255,255,255,.75)}

/* The .prod / .prods rules that used to live here styled the three numbered
   production cards on Book Us. That menu is gone — the band doesn't sell a fixed
   set of productions — and nothing else on the site used them, so they have gone
   with it rather than sitting here waiting to be wondered about. See .offers. */

/* ---------- record / proof strip ---------- */
/* Heritage Scarlet panels divided by Royal Red rules — the accent doing its job.
   Gold numerals are 42px display text, so 3.75:1 clears the AA-large threshold. */
.record{display:grid;grid-template-columns:repeat(4,1fr);gap:2px;background:var(--royal)}
.rec{background:var(--scarlet);padding:32px 24px}
.rec b{display:block;font-weight:900;font-size:42px;color:var(--gold);line-height:1}
.rec i{font-style:normal;display:block;font-size:13.5px;color:rgba(255,255,255,.94);
  margin-top:8px;line-height:1.4}

/* The two cycling panels. Every honour is stacked in the same grid cell, so the
   panel is as tall as the longest one and the row never changes height as they
   turn over — a panel that resized itself would shunt the whole strip. */
.rec-cycle{display:grid;align-items:start}
/* One out, then the next in — not a crossfade. Overlapping them leaves two
   honours half-visible over the same pixels, which reads as a smudge rather than
   a change. The gap between the two is timed in site.js, which reads this
   duration back off the element so the two can't fall out of step.
   Same treatment as the rotating chip in the hero. */
.rec-cycle .stat{grid-area:1/1;opacity:0;transition:opacity .85s ease}
.rec-cycle .stat.on{opacity:1}
@media(prefers-reduced-motion:reduce){
  /* No movement: each panel shows its opening honour and stays there. */
  .rec-cycle .stat{transition:none}
}

/* ---------- events ---------- */
.tag{display:inline-block;font-weight:700;font-size:10.5px;letter-spacing:.13em;
  text-transform:uppercase;padding:4px calc(10px - .13em) 4px 10px;margin-bottom:8px}
.tag-contest{background:#FFF6D9;color:#8A6A00}
.tag-concert{background:#FDEBED;color:var(--royal)}
.ev-note{font-size:13px;color:var(--mute);font-style:italic;text-align:center;padding:8px}

/* ---------- cards ---------- */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:26px}
.card{background:#fff;border:1px solid var(--line);text-decoration:none;color:inherit;
  display:flex;flex-direction:column;transition:.18s}
.card:hover{transform:translateY(-3px);box-shadow:0 14px 34px rgba(20,16,15,.1)}
/* A news item with no story and no address is drawn as an <article>, not a
   link (site.js), and does not lift: lifting is how a card says "press me". */
.card.card-still:hover{transform:none;box-shadow:none}
.card-img{aspect-ratio:16/10;background:var(--tint) center/cover no-repeat}
.card-body{padding:22px 24px 26px}

/* A small scarlet line on a card. News puts it under the title as the date;
   Listen puts it above as a label ("Over 100,000 views", "Whit Friday") — which
   is why the name is only half right, and why the spacing is set per position
   rather than baked into the class. */
.card-date{font-weight:700;font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--scarlet)}
.card h3,.card h2{font-size:20px;margin-bottom:9px}
/* A card's title is an h2 where nothing on the page sits between it and the
   h1 (the News page, the 404's three ways on), so headings go down one level
   at a time. It is set exactly as the h3 it was: the h2 rule's capitals and
   letter-spacing are handed back to whatever the card itself has. */
.card h2{text-transform:inherit;letter-spacing:inherit}

/* Above a title (Listen): space below it, separating it from the heading.
   Under a title (News): the heading's own 9px is already there, so it only
   needs space beneath, before the blurb. Tighter above than a paragraph would
   be, so it reads as belonging to the title rather than starting the text. */
.card-date + h3,.card-date + h2{margin-top:0}
.card h3 + .card-date,.card h2 + .card-date{margin:-3px 0 9px}
.card-body > .card-date:first-child{margin-bottom:8px}
.card p{font-size:14.5px;color:var(--mute);margin:0}
/* A pinned story says so on its date line, in the small capitals the site
   labels things with. */
.card-pin{margin-left:8px;font-size:10.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--scarlet)}
.news-pick{margin:-16px 0 26px}
.news-pick .pick-one span{min-height:44px;padding:0 18px;font-size:14px}

/* ---------- a story on its own page ----------
   Read at a measure, not across the whole wrap: 68 characters a line is where
   a paragraph is comfortable, and a photograph or a film takes the same
   column. Square corners, one weight of rule, the site's type. */
.story-wrap .story,.story-wrap .story-cover,.story-wrap .story-back{max-width:760px}
.story-cover{margin:0 0 34px}
.story-cover img{display:block;width:100%;height:auto}
.story{font-size:17.5px;line-height:1.68}
.story p{margin:0 0 1.15em}
/* A heading inside a story is the writer's words as written — not the site's
   display capitals, which are for the names of pages and sections.

   Two levels, and they have to look like two levels or there was no point
   having them: the second is smaller, set in the small-capital letterspacing
   the rest of the site uses for a label, and sits closer to the paragraph it
   introduces than to the one it follows — which is what says it belongs to the
   heading above rather than standing beside it. */
.story h2{font-size:23px;font-weight:900;letter-spacing:-.01em;line-height:1.15;
  text-transform:none;margin:1.6em 0 .55em}
/* THE BAND'S OWN RULE DECIDES THIS ONE. The Branding Pack sets sub-headings in
   Bold, Title Case — and says in as many words that capitals are for headings
   only. The first attempt at this was scarlet small capitals, which looked
   smart and broke both halves of that. Bold at 18px against Black at 23px is a
   clear step down without borrowing a device from somewhere it does not
   belong. */
.story h3{font-size:18px;font-weight:700;letter-spacing:0;line-height:1.3;
  text-transform:none;margin:1.8em 0 .4em}
/* A subheading straight after its heading belongs to it, and sits closer. */
.story h2 + h3{margin-top:.8em}
.story figure{margin:1.6em 0}
.story figure img{display:block;width:100%;height:auto}
.story figcaption{margin-top:9px;font-size:13.5px;color:var(--mute)}
.story-film iframe{display:block;width:100%;aspect-ratio:16/9;border:0;background:var(--ink)}
.story-more{margin-top:1.6em}
.story-back{margin:44px 0 0}

/* ---------- split ---------- */
.split{display:grid;grid-template-columns:1.15fr 1fr;gap:60px;align-items:center}
.split-2{display:grid;grid-template-columns:1fr 1fr;gap:56px}

/* ---------- book us: what we do ----------
   Deliberately not cards. Cards look like products with prices behind them, and
   the whole point of this section is that these are examples of what the band
   has done rather than a catalogue to choose from.

   THE SUB-HEADINGS ARE THE BAND'S OWN DEVICE, lifted from the social media plan,
   where a Royal Red strip of white Bold text heads forty-one blocks. The plan's
   brand note is explicit about the colour: Royal Red #A50E0E for on-page
   elements — badges, boxes and rules — "since none sit on a coloured
   background", which is exactly the case here. Heritage Scarlet leads whole
   surfaces; Royal Red does the small furniture on white. 7.87:1.

   TWO THINGS TAKEN FROM THE DOCUMENT ITSELF RATHER THAN FROM ITS BRAND NOTE.

   The strip is as wide as its words, not as wide as the column. Every strip in
   the plan is its own single-cell table sized to its contents: measured across
   them, the width holds at 110–134 twentieths of a point per character from a
   thirteen-character heading to a forty-seven-character one, and the widest
   never reaches two thirds of the page. Hence inline-block.

   And the text is sentence case. The brand note says Title Case for
   sub-headings; the document says otherwise forty times out of forty-one —
   "Our headline targets", not "Our Headline Targets". Not one is in caps.
   Where the note and the practice disagree, the practice is what the band
   actually looks like.

   THE INSET IS TIGHT, AND TIGHTER STILL AT THE SIDES. Measured from the cell
   margins: 36 twentieths of a point top and bottom against 6 at the sides — the
   fill is drawn almost exactly round the words, and it is closer at the left and
   right than above and below, which is the reverse of how a button is padded.
   The leading is tight with it, at 0.96 of single spacing.

   Translated rather than copied. Literally 6 twentieths of a point is 0.4px at
   this size, which would have the letters touching the red; 5px keeps a hair of
   air without loosening the shape. Everything else follows the original: 4px
   above and below, and the leading pulled in to 1.2 so the strip sits on the
   text rather than around it. */
/* Two columns, not three. Six small items across a white field read as a list of
   minor points; the same six at half the count per row read as six things the
   band does. Nothing has been added to make this stronger — no boxes, no ground,
   no rules. It is bigger, there is more air between, and the body text is ink
   rather than grey. Confidence rather than decoration.

   The measure is capped: a two-column layout at this width would otherwise run
   to ninety characters a line, which is where prose stops being read. */
.offers{display:grid;grid-template-columns:repeat(2,1fr);gap:40px 56px;margin-top:42px}
/* THE INSET IS THE DOCUMENT'S: 4px above and below against 5px at the sides,
   the fill drawn almost exactly round the words, which is the reverse of how a
   button is padded. This said 5px 7px and the Analytics cards said 4px 7px —
   the same device, drawn three slightly different ways in one stylesheet, none
   of them the one the brand document specifies. See the check in
   verify-site.js, which now holds the three of them together. */
.offer h3{display:inline-block;background:var(--royal);color:#fff;font-weight:700;
  font-size:20px;line-height:1.2;letter-spacing:.01em;text-transform:none;
  padding:4px 5px;margin:0 0 15px}
.offer p{margin:0;font-size:16.5px;line-height:1.62;color:var(--ink);max-width:50ch}
@media(max-width:760px){
  .offers{grid-template-columns:1fr;gap:30px}
  .offer h3{font-size:18px}
}

/* ---------- book us: the collage ----------
   EVERY PICTURE IS THE SAME HEIGHT; THE WIDTHS DO WHATEVER THE PICTURE WANTS.
   That is the whole idea. A grid of fixed cells forces every photograph into the
   same shape and gives ragged rows when the shapes differ; here the height is
   the constant, each picture is as wide as its own proportions make it, and the
   row stretches to fill the line. Uneven widths, dead-level rows.

   HOW IT WORKS. Each figure declares --ar, its width divided by its height.
   flex-basis starts it at --ar × the row height, which is its true width, and
   flex-grow shares out whatever is left over in the same proportion, so wider
   pictures take more of the slack. Nothing has to be measured in JavaScript and
   nothing needs to know how many photographs there are.

   ADDING ONE: copy a <figure>, set --ar from the file's own dimensions —
   300x169 is 1.78, 2048x1363 is 1.50 — and drop it anywhere in the list. The
   rows re-justify on their own. If --ar is left off it falls back to 3:2, which
   is right for most photographs and wrong only in a way nobody notices.

   The caption sits on the picture rather than under it. Underneath, a one-line
   caption and a two-line caption make the row ragged again at the bottom, and
   the whole block was taking too much of the page. */
.photo-set{display:flex;flex-wrap:wrap;gap:8px;--h:210px}
.photo-set figure{margin:0;position:relative;overflow:hidden;
  flex:var(--ar,1.5) 1 calc(var(--ar,1.5) * var(--h))}
.photo-set .photo{height:var(--h);background-size:cover;background-position:center 40%;
  background-repeat:no-repeat;background-color:var(--ink-2)}
/* The last row would otherwise stretch a lone picture across the full width. */
.photo-set::after{content:'';flex-grow:1e6}
.photo-set figcaption{position:absolute;left:0;right:0;bottom:0;
  padding:26px 13px 10px;color:#fff;font-size:12.5px;line-height:1.35;
  background:linear-gradient(180deg,rgba(20,16,15,0) 0%,rgba(20,16,15,.55) 45%,
                                    rgba(20,16,15,.88) 100%)}
@media(max-width:900px){.photo-set{--h:170px}}
@media(max-width:560px){
  /* One at a time, at their own shapes — justifying two per row at this width
     leaves slivers. */
  .photo-set{--h:auto;display:block}
  .photo-set figure{margin-bottom:8px}
  .photo-set .photo{height:auto;aspect-ratio:var(--ar,1.5)}
}

/* ---------- book us: what it involves ---------- */

/* This section was briefly a two-column head — heading one side, prose the
   other. It measured badly. The heading column stacked to about 145px and the
   prose beside it to about 239px, so whichever way they were aligned one of
   them was left hanging: top-aligned put a 94px hole in the bottom left, right
   where the panel starts, and bottom-aligned dropped the heading to nothing.
   Two columns only balance when the two things in them are a similar size, and
   a heading is never the size of three paragraphs.

   So the head is one full-width block, and the two remarks that used to pad the
   right column have gone below the panel as a matched pair, where they are the
   same size as each other and do balance. */
.spec-lede{max-width:62ch;margin:18px 0 0}

/* The six answers a promoter actually rings up to ask.
   These were previously laid two-across inside the narrow half of a .split:
   190px of label against what worked out at a 20px value column, so every
   answer wrapped to roughly one word per line. They now take the full wrap and
   read three across, which is the measure the copy was written for.

   The rules between them are drawn by a 1px grid gap over a --line ground
   rather than by a border on each cell. One continuous table, no doubled
   hairlines where cells meet, and nothing to special-case at the edges. */
.specs{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);margin-top:40px}
.spec{background:var(--paper);padding:26px 28px 30px}

/* Royal red, not mute grey. These are the labels on a specification sheet and
   they are meant to be found at a glance — 7.87:1 on paper, and it ties the
   panel to the red strips further up the page. */
.spec dt{font-weight:700;font-size:12px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--royal);margin:0 0 13px}
/* No max-width here: the cell is 321px at full size, which is about a
   40-character measure on its own. A ch cap on top of that would only leave a
   ragged strip of empty card down the right of every answer. */
.spec dd{margin:0;font-size:16px;line-height:1.58;color:var(--ink)}

/* The same device used again in the Sponsor section, where it sits in the
   narrow half of a .split and carries four short figures rather than six
   sentences. Two across, not three. It had the identical squashed-value
   problem before this change and simply wasn't as obvious, because "4,900
   followers" survives a narrow column better than a full sentence does. */
.specs-narrow{grid-template-columns:repeat(2,1fr)}

/* The two remarks under the panel. Equal columns, equal size, equal colour —
   the balance is doing the work here, so neither may be emphasised over the
   other.

   They are 225 and 204 characters, which at this measure comes to four lines
   and three. Matching the lengths to make them bottom out level would mean
   padding a sentence to fit a column, which is the wrong way round. Instead
   each gets a short rule across the top, so the pair is anchored at the head
   where they are exactly level and the ragged foot stops signifying. Two
   separate rules with the column gap between them, not one continuous line —
   that would read as a second border under the panel. */
.spec-notes{display:grid;grid-template-columns:1fr 1fr;gap:22px 56px;margin-top:34px}
.spec-notes p{margin:0;padding-top:18px;border-top:2px solid var(--line);
  font-size:15.5px;line-height:1.66;color:var(--mute)}
.spec-notes b{color:var(--ink);font-weight:700}

/* Still used on its own by the Sponsor panel, which has one remark, not two. */
.spec-note{margin:24px 0 0;font-size:14.5px;line-height:1.6;color:var(--mute);max-width:74ch}

/* Two across once the third column would drop below about 300px, one across on
   a phone — a definition list is the one layout that loses nothing by stacking. */
@media(max-width:980px){
  .specs{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:620px){
  .specs,.specs-narrow{grid-template-columns:1fr}
  .spec{padding:22px 22px 24px}
  /* Side by side is the whole point of the pair; once they'd be 40 characters
     wide it isn't, so they stack. */
  .spec-notes{grid-template-columns:1fr}
}

.venues{display:flex;flex-wrap:wrap;gap:10px;margin-top:8px}
.venues span{border:1px solid var(--line);padding:8px 16px;font-size:14px;background:#fff}
.dark .venues span{border-color:rgba(255,255,255,.25);background:rgba(255,255,255,.05)}

/* ---------- steps ---------- */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;counter-reset:s}
.step{counter-increment:s;position:relative;padding-top:56px}
.step::before{content:counter(s,decimal-leading-zero);position:absolute;top:0;left:0;
  font-weight:900;font-size:34px;color:var(--gold)}
.step h3{font-size:18px;text-transform:uppercase;letter-spacing:.03em;margin-bottom:8px}
.step p{font-size:15px;color:var(--mute);margin:0}
.dark .step p{color:rgba(255,255,255,.78)}

/* ---------- roster ---------- */
/* One click to any section. Twenty-nine players is a long scroll however it's
   laid out; this is what stops it being a slog, without hiding anybody. */
.roster-jump{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 38px;
  padding-bottom:26px;border-bottom:1px solid var(--line)}
.roster-jump a{font-weight:700;font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;color:var(--ink);background:var(--tint);
  border:1px solid var(--line);padding:9px calc(15px - .1em) 9px 15px;transition:.18s}
.roster-jump a:hover{background:var(--ink);border-color:var(--ink);color:#fff}

/* scroll-margin keeps a jumped-to heading clear of the sticky header. */
/* scroll-margin keeps a jumped-to heading clear of the sticky header — the real
   height of it plus a little air, rather than a number typed in and left to
   drift when the header changes.
   The header's height now lives once, on html as scroll-padding-top (see the
   top of this file), and the two ADD: left at calc(var(--hdr-h) + 22px) this
   would have landed a jumped-to section a whole header lower than before. So
   only the difference stays here, 6px on top of the root's 16px, and a section
   lands exactly where it always did: header, then 22px. */
.section-block{margin-bottom:44px;scroll-margin-top:6px}
.section-block h3{margin-bottom:22px}

/* The heading IS the control, so it takes the whole width — a section is folded
   by clicking its name, not by hunting for a small arrow at one end. The scarlet
   rule that was on the h3 moves onto the button, which is the thing being
   pressed. */
.sec-toggle{width:100%;display:flex;align-items:center;gap:12px;
  background:none;border:0;border-bottom:2px solid var(--scarlet);
  padding:0 0 10px;margin:0;cursor:pointer;text-align:left;color:inherit;
  font:inherit;font-size:15px;font-weight:900;text-transform:uppercase;
  letter-spacing:.16em}
.sec-toggle:hover{border-bottom-color:var(--gold)}
.sec-name{flex:1 1 auto}

/* How many players are in there. Reads as information when the section is open
   and as a reason to open it when it isn't. */
.sec-count{font-size:12px;font-weight:700;letter-spacing:.08em;color:var(--mute)}

/* The open/shut mark. A triangle rotated rather than two different characters,
   so it turns rather than jumps — and the transition is on transform only, which
   the compositor handles without touching layout.
   Marked aria-hidden by being CSS content: generated content is not in the
   accessibility tree, and aria-expanded on the button already says the same
   thing properly. */
.sec-toggle::after{content:'';width:0;height:0;flex:0 0 auto;
  border-left:6px solid transparent;border-right:6px solid transparent;
  border-top:7px solid var(--scarlet);transition:transform .2s ease}
.sec-toggle[aria-expanded=false]::after{transform:rotate(-90deg)}
.sec-toggle[aria-expanded=false]{border-bottom-color:var(--line)}
/* Five across rather than four, and a squarer crop. Same photographs, roughly a
   third less page to get through. */
.players{display:grid;grid-template-columns:repeat(5,1fr);gap:18px}

/* .player is a <button> for anyone with a biography and a <div> for anyone
   without, so everything a button brings with it has to be unset: buttons come
   with their own font, a border, a background, centred text and a fixed width
   that ignores the grid. */
.player{text-align:left;font:inherit;color:inherit;background:none;border:0;
  padding:0;margin:0;width:100%;display:block}
.player-img{display:block;aspect-ratio:4/5;background:var(--tint) center/cover no-repeat;
  margin-bottom:10px;position:relative;overflow:hidden}
.player-img.blank{background:repeating-linear-gradient(45deg,#F3EEEA,#F3EEEA 10px,#FAF6F3 10px,#FAF6F3 20px)}
.player b{display:block;font-weight:700;font-size:16px}
.player .seat{display:block;font-size:13.5px;color:var(--mute)}

/* ---- a player you can open ----
   The cue sits inside the photograph, along its bottom edge, and slides up on
   hover and focus. It stays in the accessibility tree whether or not it is
   showing, so the button never announces itself as nothing but a name — and it
   only exists on the cards that actually lead somewhere. */
.player-open{cursor:pointer}
.player-cue{position:absolute;left:0;right:0;bottom:0;
  background:var(--scarlet);color:#fff;                 /* 6.17:1 */
  font-size:11px;font-weight:700;letter-spacing:.12em;text-indent:.12em;
  text-transform:uppercase;
  padding:4px 8px;text-align:center;line-height:1.35;
  transform:translateY(100%);transition:transform .22s ease}
.player-open:hover .player-cue,
.player-open:focus-visible .player-cue{transform:translateY(0)}

/* The name underlines in gold under the cursor, which together with the cue
   sliding up is enough to say the card does something.
   The photograph deliberately does NOT scale on hover, tempting as it is: these
   are tight portrait crops, and growing one inside a fixed frame trims a few
   per cent off the top and bottom — which on a head-shot means shaving the top
   of somebody's head. Not worth it for a flourish. */
.player-open:hover b{text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:3px;text-decoration-color:var(--gold)}

@media(prefers-reduced-motion:reduce){
  .player-cue,.sec-toggle::after{transition:none}
}

.player.tbc .player-img{border:2px dashed var(--line)}
.player.tbc b{color:var(--mute);font-style:italic}
/* Dormant on purpose, paired with the commented-out "Play with us" section in
   book-us.html. The roster filters vacant seats out, so nothing carries these
   today; both come back together the day a seat is advertised. */
.player.vacancy .player-img{border:2px dashed var(--scarlet);background:#FFF8F8}
.player.vacancy b{color:var(--scarlet)}

/* ---------- the biography panel ----------
   This used to be a <details> opening inside its own cell of a five-column grid.
   That cell is about 212px, so a 1,750-character biography set at roughly
   twenty-six characters a line and ran to sixty-seven of them, in a column the
   width of a thumb, shoving the rest of the row down the page as it went.

   A native <dialog>, so the browser handles the focus trap, Escape, the inert
   background and returning focus to the card afterwards. What is styled here is
   only how it looks. */
/* The panel itself never scrolls — overflow:hidden, not auto. Only the column
   of words inside it does, so the photograph stays put however long somebody's
   career has been. A flex column with the inner row set to min-height:0 is what
   lets that row be shorter than its contents and hand the overflow down;
   without it the row grows to fit and the panel scrolls as one piece again. */
/* SIZED IN dvh, NOT vh — this matters on a phone and nowhere else.
   vh is the height of the screen with the address bar HIDDEN. While the bar is
   showing, which is most of the time, that is taller than what can actually be
   seen — so a panel sized to 100vh minus a margin still runs off the bottom by
   the height of the bar, and the close button goes with it. dvh is the space
   there is at this moment. The vh line stays first as the fallback for anything
   too old to know dvh, where the old behaviour is no worse than it was. */
.bio-dlg{width:min(1020px,calc(100vw - 48px));max-height:min(760px,calc(100vh - 64px));
  padding:0;border:0;background:var(--paper);color:var(--ink);
  overflow:hidden;position:relative;display:flex;flex-direction:column}
.bio-dlg{max-height:min(760px,calc(100dvh - 64px))}
/* THE PAGE BEHIND IS DARKENED AND BLURRED, and the two numbers are set
   together on purpose.

   The darkening was .72 on its own. A blur behind ink that opaque does almost
   nothing you can see — there is not enough of the page left showing for
   anything to be soft. So the ink comes down to .58 and the blur does the rest
   of the work: still plainly dark, but the roster behind now reads as an
   out-of-focus background rather than a dim one. Together they separate the
   panel from the page more completely than .72 flat did.

   8px, which is soft rather than frosted. Enough that no face behind is
   recognisable and no name readable, not so much that the page looks broken.

   Nothing here affects the words in the panel — the dialog has its own paper
   background — so there is no contrast question to answer. */
.bio-dlg::backdrop{background:rgba(12,9,8,.58);
  -webkit-backdrop-filter:blur(8px);
  backdrop-filter:blur(8px)}

/* Anything that cannot blur keeps the old, heavier darkening, so it separates
   the panel by the one means it has. Both spellings are asked about: Safari
   supported only the -webkit- one for years, and testing the plain name alone
   would send those versions here and give them the blur AND the heavier ink. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))) {
  .bio-dlg::backdrop{background:rgba(12,9,8,.72)}
}

/* ---- how it arrives ----
   The panel used to appear whole, in one frame, which reads as a jolt rather
   than as something opening — and made the click feel like a page change.
   It rises a little and fades, and the page behind goes out of focus with it,
   so the two halves of the effect belong to the same movement.

   ON [open] RATHER THAN A CLASS. The attribute appears the moment showModal()
   runs, so the animation starts with no second frame to wait for and no
   JavaScript to keep in step with the stylesheet.

   Nothing on the way out. Closing a dialog with an animation needs the browser
   to keep it painted after it stops being open, and getting that wrong leaves a
   panel that cannot be shut — a much worse fault than a brisk exit.

   .28s: long enough to read as a movement, short enough that somebody working
   down a roster opening one player after another is never waiting for it.

   Switched off for reduced motion rather than on for no-preference — the way
   the other thirteen movement rules in this file are written, and the way that
   fails safe: it runs unless somebody has asked it not to. */
.bio-dlg[open]{animation:bio-rise .28s cubic-bezier(.2,.75,.3,1) both}
.bio-dlg[open]::backdrop{animation:bio-veil .28s ease both}

@media(prefers-reduced-motion:reduce){
  .bio-dlg[open],.bio-dlg[open]::backdrop{animation:none}
}
@keyframes bio-rise{
  from{opacity:0;transform:translateY(16px) scale(.985)}
}
@keyframes bio-veil{
  from{opacity:0;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0)}
}

/* A closed dialog is hidden by the browser's own stylesheet, which says
   dialog:not([open]){display:none}. Author rules beat browser rules whatever
   their specificity, so the display:flex above quietly switched that off: the
   panel sat at the foot of the roster page, permanently visible, and the
   autofocus inside it sent the page straight to the bottom on load.

   Any rule that sets display on a <dialog> has to put this back. It is not
   optional and it is not belt and braces. */
.bio-dlg:not([open]){display:none}

.bio-in{flex:1 1 auto;min-height:0;
  display:grid;grid-template-columns:360px 1fr;gap:0;align-items:stretch}

/* The photograph fills its half however tall the biography turns out to be —
   these are portrait crops of wildly different sizes, so cover is the only thing
   that behaves. */
/* ---- the left column: who this is ----
   The photograph used to fill a 1:2 slot on its own, which left the choice
   between cropping a square portrait to a strip of its middle and leaving a
   dead white block underneath. The column carries the identity instead — the
   whole picture, then the seat, the name and the facts — on ink. The words fill
   what the picture does not. The crest watermark is not here: it stays in the
   white column behind the biography, where it has always been.

   Ink AROUND the photograph rather than white: a picture mounted on a dark
   ground reads as framed, where the same gap in white reads as something
   missing. That is the whole difference between the two versions of this. */
.bio-side{background:var(--ink);color:#fff;
  display:flex;flex-direction:column;min-height:100%}

/* FLUSH TO THE TOP AND BOTH SIDES. It had a margin around it, which made the
   picture look like something laid ON the column rather than the top of it.

   9:10, and that shape was measured rather than picked. The roster is square
   and 3:4 in roughly equal numbers, so any one slot costs something; across the
   nineteen photographs whose size is known:

     1:1    worst 25%   average 9.1%
     9:10   worst 17%   average 8.8%     <- this
     6:7    worst 21%   average 11.0%
     4:5    worst 26%   average 15.0%
     3:4    worst 31%   average 18.8%

   9:10 is the best of them on the worst case by eight points and the best on
   average as well, which is unusual enough to be worth writing down.

   Anchored to the top, so what a tall picture loses is the bottom of somebody's
   instrument rather than the top of their head. Centred across, because the one
   thing every one of these photographs has in the middle is a face. */
.bio-side .bio-photo{flex:0 0 auto;margin:0;height:auto;min-height:0;
  aspect-ratio:9/10;background-color:var(--ink);
  background-position:center top;background-size:cover}

.bio-id{flex:1 1 auto;min-height:0;padding:20px 30px 30px}
.bio-id .kicker{color:var(--gold)}
.bio-id h2{color:#fff;font-size:clamp(26px,3.4vw,38px)}

/* Label and answer on one line, ruled off from each other. Small caps for the
   label so the answer is what the eye lands on. */
.bio-facts{margin:26px 0 0;display:grid;gap:0}
.bio-facts>div{display:flex;justify-content:space-between;align-items:baseline;
  gap:16px;padding:10px 0;border-top:1px solid rgba(255,255,255,.16)}
.bio-facts dt{font-size:11px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.6)}
.bio-facts dd{margin:0;font-weight:700;font-size:15px;color:#fff;text-align:right}

/* THE WHOLE PHOTOGRAPH, NOT A CROP OF IT.

   This was center/cover. The column is 360 wide by up to 760 tall — about 1:2.1
   — and the photographs are square or near it. Filling a slot that shape from a
   square source throws away 52% of the width: measured across the roster, every
   picture was blown up between 2.5 and 2.7 times and showed about 140px of its
   300. Faces arrived cropped to the middle and enlarged, and the euphonium the
   player is holding was mostly outside the panel.

   The slot is nearly square now instead, which is the shape the photographs
   actually are — see the measured comparison above .bio-side .bio-photo. The
   worst any picture loses is 17% and the average is under 9%, against 52% for
   every single one of them before.

   NOT SOLVED BY BIGGER ORIGINALS. A 2000px source cropped to 1:2.1 loses the
   same 52% — it would be sharper and just as cut off. Resolution and framing
   are different faults, and this is the framing one. */
.bio-photo{background:var(--tint) center top/contain no-repeat;min-height:100%}
/* Hiding it needs no rule of its own: [hidden]{display:none !important} at the
   top of this file already outranks anything set here, which is the whole reason
   that rule carries an !important. The folding grids rely on it too. */

/* The left column stays whether or not there is a photograph. It used to
   collapse to one column when there was none, because the column WAS the
   photograph and an empty one was just a grey rectangle. It now carries the
   seat, the name and the facts as well, so with no picture it is a name plate
   rather than a gap — and a panel that changed shape depending on whether
   somebody had sent a photograph in was drawing attention to exactly the thing
   it should not. */

/* .bio-text holds the crest and does not move; .bio-scroll inside it carries the
   words and the padding. Splitting them is what keeps the watermark pinned to
   the bottom-left corner of the panel — an absolutely positioned crest inside a
   scrolling box would slide up the page along with the text.
   .mark supplies position:relative, overflow:hidden, and lifts .bio-scroll above
   the watermark, so none of that is repeated here. */
.bio-text{min-height:0;display:flex;flex-direction:column;position:relative}

/* The crest, bottom left, exactly as on every section elsewhere: no size
   override here at all, so it takes the standard 'auto 100%' and fills the full
   height of the panel — top edge flush with the top, bottom flush with the
   bottom, width falling out of that. At this panel's proportions that comes to
   about 599px across a 660px column, so it very nearly reaches the right edge
   too. It was briefly held back to 58%, which left it sitting in the corner
   looking like a small graphic rather than the watermark it is.

   The brand note says once per page and this is technically a third; it is on a
   surface that covers the page rather than sitting in it, so it is never seen at
   the same time as the other two. */

.bio-scroll{flex:1 1 auto;min-height:0;overflow-y:auto;padding:44px 48px 46px}

/* Focus lands here when the panel opens, so the biography is what gets
   announced rather than the close button. Programmatic focus on a tabindex=-1
   container doesn't match :focus-visible, so no ring is drawn — but belt and
   braces, because a ring round the whole text column would look like a fault. */
.bio-scroll:focus{outline:none}

/* ---- the panel's own scrollbar ----
   Recolouring the system scrollbar was the first attempt and it still looked
   like a system scrollbar, because that is exactly what it was. So the native
   one is taken out and we draw our own, the same device already sitting under
   the homepage reel — turned on its side, and inset from the edges top and
   bottom so it reads as part of the panel rather than as the browser's furniture
   bolted to the side of it.

   The bar is a sibling of the scrolling box, not inside it, so it stays put
   while the words move. .mark>* would otherwise force position:relative onto it
   — hence the two-class selector, which outranks that. */
.bio-scroll{scrollbar-width:none;-ms-overflow-style:none}
.bio-scroll::-webkit-scrollbar{display:none}

/* Top starts at 62px, not 44px. The close button is 44px square in that same
   corner, so a bar starting at 44 began exactly where the button ended and the
   two ran together into a single vertical shape. 18px of clear air separates
   them, which is the same gap the bar keeps from the foot of the panel. */
.bio-text .bio-bar{position:absolute;top:62px;bottom:46px;right:18px;width:4px;
  background:var(--line);z-index:2;cursor:pointer}

/* The thumb is wider than the track it runs in, so it reads as the moving part
   rather than as a filled portion of a tube — and it gives the pointer a little
   more to catch hold of. */
.bio-text .bio-thumb{position:absolute;left:-2px;right:-2px;top:0;
  background:var(--gold);will-change:transform;transition:background .15s}
.bio-bar:hover .bio-thumb,.bio-bar.dragging .bio-thumb{background:#ffdf5e}

.bio-text .kicker{margin-bottom:10px}
.bio-body{margin-top:22px}
.bio-body p{margin:0 0 1em;font-size:16.5px;line-height:1.68}
.bio-body p:last-child{margin-bottom:0}

/* Square, scarlet, and pinned to the corner of the panel rather than floating
   over the photograph, where it would land on somebody's face. 44px so it clears
   the 24px minimum for a touch target with room to spare. */
.bio-close{position:absolute;top:0;right:0;width:44px;height:44px;
  display:flex;align-items:center;justify-content:center;
  background:var(--scarlet);color:#fff;border:0;cursor:pointer;
  line-height:1;padding:0;z-index:2}
.bio-close .pico{width:18px;height:18px;display:block}
.bio-close:hover{background:var(--royal)}

@media(max-width:820px){
  /* On a phone the panel takes nearly the whole screen. 48px of margin is right
     on a desktop, where the page behind is worth seeing; on a 390px screen it
     is 12% of the width spent on showing a blurred page nobody is reading. */
  .bio-dlg{width:calc(100vw - 20px);max-height:calc(100dvh - 28px)}

  /* Photograph on top, words beneath, and the whole panel scrolls as one — on a
     phone there isn't the height to give the text its own scrolling box without
     it becoming a letterbox two lines deep. The photograph is a fixed band
     across the top rather than a portrait column, which would otherwise push
     the words below the fold before they had started. */
  .bio-in{grid-template-columns:1fr;grid-template-rows:auto 1fr}
  /* On a phone the photo is a band across the top rather than a column beside
     the words, and 3/2 is a shape a square nearly fills — so here it still
     covers. Told to contain, a square in a 3/2 band would leave a bar of tint
     down each side of every player. */
  /* On a phone the column becomes a band across the top, so the photograph is
     a 3/2 strip and the seat, name and facts sit under it. cover here, not
     contain: 3/2 is a shape a square nearly fills, and contain would put ink
     down both sides of every player. The fixed height from the two-column
     layout has to be undone or it fights the aspect ratio. */
  .bio-side .bio-photo{height:auto;margin:0;aspect-ratio:3/2;
    background-size:cover;background-position:center}
  .bio-id{padding:18px 22px 24px}
  .bio-scroll{padding:30px 26px 34px}
  .bio-body p{font-size:16px}
  /* The bar follows the tighter padding in, so it doesn't end up sitting on the
     words. No allowance for the close button here — at this width the
     photograph is a band across the top and the button sits on that, well clear
     of the text pane, so the bar can start at the top of the words.
     It stays visible rather than being hidden for touch: with the native
     scrollbar gone there would otherwise be nothing at all to say the biography
     carries on below the fold. */
  .bio-text .bio-bar{top:30px;bottom:34px;right:11px}
}

/* ---------- history timeline ---------- */
/* ---------- timeline ----------
   Tightened throughout. Nine decades laid out at the old spacing ran to a very
   long page for something most visitors skim, so the era headings are smaller,
   the rows are closer together and the prose is a size down. The years and the
   headlines — the two things people actually scan — are untouched.

   THE RAIL AND THE DOTS
   Three measurements used to be typed in separately: the rule's position, the
   width of the year column, and each dot's offset. They disagreed, which is why
   the dots sat almost against the years and slightly off the rule. They now all
   derive from --rail and --col, and the dots are centred on the rail with a
   translate rather than by a hand-worked offset, so a dot cannot drift off the
   line and the gap after the year is whatever --rail minus --col says it is. */
.era{margin-bottom:40px}
.era-head{margin-bottom:18px}

/* The heading IS the control, so it takes the whole width — a decade is folded
   by pressing its name, not by finding a small arrow at one end. The rule that
   was on .era-head moves onto the button, which is the thing being pressed. */
.era-toggle{width:100%;display:flex;align-items:baseline;gap:16px;
  background:none;border:0;border-bottom:2px solid var(--line);
  padding:0 0 11px;margin:0;cursor:pointer;text-align:left;color:inherit;
  font:inherit}
.era-toggle:hover{border-bottom-color:var(--gold)}
.era-head b{font-weight:900;font-size:clamp(25px,3.2vw,34px);color:var(--scarlet);line-height:1}
.era-head span{font-weight:700;font-size:12px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mute);flex:1 1 auto}

/* The open/shut mark. A triangle turned rather than two different characters,
   so it rotates instead of jumping, and the transition is on transform alone,
   which costs no layout. Generated content is not in the accessibility tree,
   and aria-expanded on the button already says this properly. */
.era-toggle::after{content:'';width:0;height:0;flex:0 0 auto;align-self:center;
  border-left:6px solid transparent;border-right:6px solid transparent;
  border-top:7px solid var(--scarlet);transition:transform .2s ease}
.era-toggle[aria-expanded=false]::after{transform:rotate(-90deg)}
.era-toggle[aria-expanded=false]{border-bottom-color:var(--line)}
@media(prefers-reduced-motion:reduce){.era-toggle::after{transition:none}}

/* ---------- the timeline's own scrolling box ----------
   HOW TALL, AND WHY
   clamp(360px, 62vh, 640px). The floor stops the box collapsing to a slot on a
   short laptop screen; 360px is four rows, which is enough to read as a list
   rather than a peephole. The ceiling stops it swallowing a tall monitor, where
   62vh would be most of a metre of timeline and we are back to the problem this
   solves. In between, roughly two thirds of the screen, so the honours board
   below is always in sight and the reader can tell there is more page.

   SCROLL CHAINING IS LEFT ALONE
   No overscroll-behavior here, on purpose. The default chains: the wheel scrolls
   the box until it reaches the end, then carries on scrolling the page. Setting
   `contain` would seal the box and strand anyone whose pointer happened to be
   over it. Setting `none` does the same. The default is the behaviour we want.

   PADDING
   Room on the right for our scrollbar, and a little at the foot so the last
   entry does not sit hard against the edge. The left padding is only there to
   stop a focus ring being clipped by overflow. */
.tl-box{position:relative}
.tl-scroll{max-height:clamp(360px,62vh,640px);overflow-y:auto;
  padding:2px 40px 8px 2px;scroll-behavior:smooth}
.tl-scroll:focus{outline:none}
.tl-scroll:focus-visible{outline:2px solid var(--scarlet);outline-offset:3px}
@media(prefers-reduced-motion:reduce){.tl-scroll{scroll-behavior:auto}}

/* The native bar is hidden only once site.js has drawn ours — the attribute is
   set by the script. With scripts off the ordinary scrollbar stays, because a
   box that scrolls with nothing to show for it is a trap. */
.tl-scroll[data-own-bar]{scrollbar-width:none;-ms-overflow-style:none}
.tl-scroll[data-own-bar]::-webkit-scrollbar{display:none}

/* Same bar as the biography panel, same measurements, drawn by the same
   function. Inset 2px top and bottom so it reads as a bar in the box rather
   than a border on it. */
.tl-box .tl-bar{position:absolute;top:2px;bottom:8px;right:8px;width:4px;
  background:var(--line);z-index:4;cursor:pointer}
.tl-box .tl-thumb{position:absolute;left:-2px;right:-2px;top:0;
  background:var(--scarlet);will-change:transform;transition:background .15s}
.tl-bar:hover .tl-thumb,.tl-bar.dragging .tl-thumb{background:var(--gold)}

/* The decade heading pins to the top of the box as its entries pass beneath, so
   you always know which decade you are reading. It needs an opaque background to
   do that — the section is sec-tint, hence --tint — and it has to sit above the
   rail and the squares, which are z-index 1. The negative top margin and the
   matching padding give the heading something to cover the rail with as a row
   slides under it. */
.tl-box .era-head{position:sticky;top:0;z-index:3;background:var(--tint);
  margin:-2px 0 18px;padding:2px 0 0}
.tl-box .era{margin-bottom:34px}
.tl-box .era:last-child{margin-bottom:0}

/* ---- the timeline on a phone ----
   The box comes off entirely. A box that scrolls inside a page that also scrolls
   is a fight on a touch screen: a swipe meant for the page gets eaten by the
   timeline, and the reader has to find somewhere else on the screen to push. On
   a mouse this never comes up, because a wheel over a box is unambiguous.

   What replaces it is better anyway. site.js starts every decade SHUT on a
   phone, so the timeline arrives as eight short rows — more compact than the box
   ever was — and a tap opens the one you want. Nothing is hidden: the control
   above still opens the lot.

   The sticky decade heading goes too. It has nothing to stick to now, and left
   in it would pin itself to the top of the screen underneath the header.

   THE CONDITION IS TOUCH, NOT WIDTH
   hover:none as well as a width, because the reason is the gesture and not the
   screen. A phone turned sideways is 844px wide — past any sensible phone
   breakpoint — and still has exactly the same problem. hover:none asks the right
   question: can the thing pointing at this page hover? If it cannot, it is a
   finger, and a finger cannot tell two scrolling areas apart. */
@media(max-width:700px),(hover:none){
  .tl-scroll{max-height:none;overflow:visible;padding:0}
  .tl-box .tl-bar{display:none}
  .tl-box .era-head{position:static;margin:0 0 18px;padding:0}
  .tl-box .era{margin-bottom:26px}
}

/* One control for all eight, above the timeline. */
.tl-tools{margin:0 0 30px}
.tl-toggle{font:inherit;font-weight:700;font-size:12px;letter-spacing:.1em;
  text-transform:uppercase;text-indent:.1em;
  color:var(--ink);background:var(--tint);
  border:1px solid var(--line);padding:10px calc(16px - .1em) 10px 16px;
  cursor:pointer;transition:.18s}
.tl-toggle:hover{background:var(--ink);border-color:var(--ink);color:#fff}
/* --col  width of the year column
   --rail  distance from the left edge to the vertical rule
   --pad   clear space between the rail and the start of the text
   The gap after the year is therefore --rail minus --col: 34px on desktop,
   where it used to be a negative number, which is why the dots looked stuck to
   the dates. */
.tl{--col:62px;--rail:96px;--pad:22px;list-style:none;margin:0;padding:0;position:relative}
.tl::before{content:'';position:absolute;left:var(--rail);top:5px;bottom:5px;width:2px;
  background:var(--line);transform:translateX(-50%)}
.tl li{position:relative;display:grid;
  grid-template-columns:var(--col) 1fr;
  column-gap:calc(var(--rail) - var(--col) + var(--pad));
  padding:0 0 17px}
.tl li:last-child{padding-bottom:0}
.tl .yr{font-weight:900;font-size:17px;color:var(--ink);text-align:right;padding-top:1px}
.tl .ev{position:relative}
/* The text starts --pad to the right of the rail, so the rail is --pad to the
   left of the text — and the dot centres on it. One number, no drift. */
/* SQUARES, and two of them rather than two colours.

   These were circles, gold for an ordinary entry and scarlet for a turning
   point. Two problems with that. Round corners are against the brand, which is
   square throughout. And gold against scarlet reads as two CATEGORIES of thing —
   both are brand colours, both are saturated, neither looks subordinate to the
   other — when what is actually being said is that one matters more than the
   other. Fourteen of the twenty-eight are turning points and nothing told the
   reader that, so the pattern looked arbitrary.

   Gold for an ordinary entry, scarlet and larger for a turning point. The pale
   rail colour was tried for the ordinary ones — quieter, and it made the
   hierarchy unarguable — but it drains the rail of the brand and reads as
   unfinished. Gold against scarlet with a size difference carries the same
   meaning and looks like the rest of the site. */
.tl .ev::before{content:'';position:absolute;left:calc(var(--pad) * -1);
  top:9px;width:9px;height:9px;transform:translateX(-50%);
  border-radius:0;background:var(--gold);z-index:1}
.tl .ev.major::before{background:var(--scarlet);width:14px;height:14px;top:6px}
.tl .ev b{display:block;font-weight:700;font-size:15.5px;margin-bottom:2px}
.tl .ev p{margin:0;font-size:14px;line-height:1.55;color:var(--mute);max-width:66ch}
.tl .ev cite{font-style:normal;display:block;font-size:13px;color:var(--mute);margin-top:4px}

/* ---------- honours board ---------- */
.honours{display:grid;grid-template-columns:repeat(2,1fr);gap:2px;background:rgba(255,255,255,.28)}
.hon{background:var(--scarlet);padding:26px 28px}
.hon b{display:block;font-weight:900;font-size:15px;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;margin-bottom:12px}
.hon .yrs{display:flex;flex-wrap:wrap;gap:8px}
.hon .yrs span{font-weight:700;font-size:14px;background:rgba(0,0,0,.2);color:#fff;
  padding:5px 11px;border-radius:0}
.hon i{font-style:normal;display:block;font-size:13.5px;color:rgba(255,255,255,.85);margin-top:10px}

/* ---------- the names ---------- */
.names{display:grid;grid-template-columns:repeat(3,1fr);gap:2px;background:var(--line)}
.nm{background:#fff;padding:22px 24px}
.nm b{display:block;font-weight:700;font-size:16px;margin-bottom:4px}
.nm span{font-size:13.5px;color:var(--mute);letter-spacing:.04em}

/* ---------- the team ----------
   THREE FIXED COLUMNS FOR THREE GROUPS OF UNEQUAL LENGTH. Six names, then
   four, then three, in a grid whose row is as tall as its tallest cell — so the
   third column stopped two thirds of the way up and the page ended on a
   rectangle of nothing the size of a small photograph. It read as something
   that had failed to load. And it was fixed at three, so a fourth group would
   have gone onto a second row of its own with the same void beside it, and a
   band with one committee would have had two empty thirds.

   Columns rather than a grid, so the number of them follows how many there are
   to put in them and how much room there is: at most three, each at least
   300px, which is the browser choosing — four groups pack into three columns by
   height rather than starting a row nobody asked for, and two groups take two
   columns rather than leaving one empty. One group takes one, said below,
   because `columns` on its own would still make three of them and leave two
   blank.

   AND A GROUP IS DRAWN AS A BLOCK that visibly ends. That is the other half of
   why the short column read as a fault: with no edge anywhere, a column that
   stopped early looked like a column that had given up rather than a list that
   had finished. The scarlet rule over the heading is the same device the
   honours board uses, and the last name in a group keeps its closing line. */
.teams{columns:3 300px;column-gap:34px}
.teams[data-groups="1"]{columns:1}
.teams[data-groups="2"]{columns:2 300px}
.team-group{break-inside:avoid;-webkit-column-break-inside:avoid;
  page-break-inside:avoid;margin:0 0 38px}
.team-group h3{font-size:14px;text-transform:uppercase;letter-spacing:.14em;
  color:var(--scarlet);margin:0 0 6px;padding-top:12px;
  border-top:3px solid var(--scarlet)}
.team-group .cond{grid-template-columns:1fr;gap:2px;padding:14px 0}
.team-group .cond dt{font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute)}
.team-group .cond dd{font-weight:700;font-size:16px}
.team-group .cond dd span{font-weight:500}
.team-group .cond dd a{color:var(--scarlet);text-decoration:none;font-size:13px}
.team-group .cond dd a:hover{text-decoration:underline}
/* ---------- what's on reel ----------
   The homepage shows dates as a horizontal reel of picture cards; What's On keeps
   the plain list, which is better for scanning twenty dates. Scroll-snap does the
   paging, so there's no carousel library and it still works with the script off.
   Square corners throughout, per the brand. */
.reel-wrap{position:relative}
.reel{display:flex;gap:22px;overflow-x:auto;scroll-snap-type:x mandatory;
  scroll-behavior:smooth;padding:4px 0 20px;
  scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.reel::-webkit-scrollbar{height:6px}
.reel::-webkit-scrollbar-thumb{background:var(--line)}
.reel-card{flex:0 0 316px;scroll-snap-align:start;display:flex;flex-direction:column;
  text-decoration:none;color:var(--ink);background:var(--paper);
  border:1px solid var(--line);transition:.18s}
.reel-card:hover{transform:translateY(-3px);box-shadow:0 14px 34px rgba(20,16,15,.12);
  border-color:var(--scarlet)}
.reel-img{position:relative;height:186px;background-size:cover;background-position:center;
  background-color:var(--ink-2)}
/* Date block sits on the image, scarlet so it reads over any photograph. */
.reel-date{position:absolute;left:0;bottom:0;background:var(--scarlet);color:#fff;
  padding:9px 14px 8px;text-align:center;border-top:4px solid var(--gold)}
.reel-date b{display:block;font-weight:900;font-size:26px;line-height:1}
.reel-date i{font-style:normal;display:block;font-weight:700;font-size:11px;
  letter-spacing:.14em;text-indent:.14em;text-transform:uppercase;margin-top:2px}
.reel-body{padding:20px 22px 22px;display:flex;flex-direction:column;flex:1}
.reel-body h3{font-size:19px;line-height:1.2;margin:10px 0 8px}
/* When and where are two different facts and now look like it: the date in ink
   and bold, the address grey and lighter underneath, with air between them.
   Previously both were the same 14px grey with no gap and they read as one
   run-on line. */
.reel-meta{font-size:14px;margin:0 0 16px}
.reel-meta span{display:block}
.reel-meta .when{font-weight:700;color:var(--ink);letter-spacing:.01em}
.reel-meta .where{color:var(--mute);font-size:13.5px;margin-top:4px;line-height:1.45}
.reel-body .more{margin-top:auto;font-weight:700;font-size:12.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--scarlet)}
.reel-card .ev-note{margin-top:auto;font-size:13.5px;color:var(--mute)}
/* ---- reel controls ----
   The native scrollbar is hidden and replaced with our own, so the track and
   thumb can be square-cornered and in brand colours like everything else. */
.reel{scrollbar-width:none;-ms-overflow-style:none}
.reel::-webkit-scrollbar{display:none}
/* While the thumb is being dragged the snap points have to come off. Left on,
   the browser re-snaps to a card boundary on every pointer move and the reel
   stutters instead of following the cursor. Snap returns on release, so it
   still settles neatly on a card. */
.reel.dragging{scroll-snap-type:none;scroll-behavior:auto;cursor:grabbing}

/* This was gold and 7px, matching the rule under the header, on the theory that
   it would read as the brand mark rather than browser furniture. It did — and
   that was the problem. A 7px bar in the header's exact weight, carrying a gold
   segment, looks like a brand rule that has failed to finish drawing rather than
   something you can drag.

   The thumb stays Sovereign Gold. It is the band's colour and this is the band's
   scrollbar; that was the original intent and it stands.

   NOTE, left as it is on purpose: gold on this track measures 1.23:1, where
   WCAG 1.4.11 asks 3:1 for the visible boundary of a control. It is recorded
   here rather than silently "fixed", because the row does not depend on the bar
   — arrows, wheel, touch, keyboard and the cards themselves all work without it,
   so it reports position rather than granting access. If it ever has to pass,
   darken the TRACK; the thumb stays gold. */
/* No margin of its own. The reel above already carries 20px of bottom padding —
   room for the shadow a card casts when it lifts on hover, which would otherwise
   be clipped by the scroller. That padding is invisible, so adding a further
   12px here set the scrollbar 32px adrift from the row it belongs to while
   reading in the stylesheet as though it were 12. */
/* Scrollbar and arrows on one line — the two controls for the row, together.
   The bar takes whatever width is left; the arrows are a fixed size at the end
   of it. */
.reel-foot{margin-top:0;display:flex;align-items:center;gap:20px}
.reel-track{flex:1 1 auto;height:4px;background:var(--line);position:relative;cursor:pointer}
.reel-thumb{position:absolute;top:0;bottom:0;left:0;min-width:44px;
  background:var(--gold);will-change:transform;transition:background .15s}
.reel-track:hover .reel-thumb,.reel-thumb:active{background:#ffdf5e}

/* Arrows live in the section header, top right, beside the "all dates" link.
   That's what Reuters and Spotify do for a row of cards, and it's better than
   floating them over the artwork: they never cover a picture, never sit at an
   arbitrary height, and read as controls for the row rather than as something
   attached to one card. */
.reel-nav{display:flex;gap:8px;flex:0 0 auto}
.reel-nav button{width:42px;height:42px;padding:0;display:grid;place-items:center;
  border:1px solid var(--line);background:var(--paper);color:var(--ink);
  cursor:pointer;transition:.15s}
.reel-nav button svg{width:13px;height:13px;display:block}
.reel-nav button:hover:not(:disabled){background:var(--scarlet);
  border-color:var(--scarlet);color:#fff}
/* Dimmed rather than hidden at the ends — removing them would shift the link
   beside them sideways every time you reached an edge. */
.reel-nav button:disabled{opacity:.25;cursor:default}

@media(max-width:640px){.reel-card{flex-basis:82%}.reel-nav{display:none}}

/* The 900px rule that forced one column is gone: `columns:3 300px` already
   drops to two and then to one as the room runs out, at the width the content
   itself needs rather than at a number typed here. */

/* ---------- conductors ---------- */
.conductors{border-top:1px solid var(--line)}
.cond{display:grid;grid-template-columns:170px 1fr;gap:24px;padding:18px 0;
  border-bottom:1px solid var(--line);align-items:baseline}
.cond dt{font-weight:700;font-size:14px;letter-spacing:.06em;color:var(--scarlet)}
.cond dd{margin:0;font-size:16px}
.cond dd span{display:block;font-size:13.5px;color:var(--mute);margin-top:2px}

@media(max-width:900px){
  .honours,.names{grid-template-columns:1fr}
}
@media(max-width:640px){
  /* Everything follows from the three variables now — no separate offsets to
     keep in step. */
  .tl{--col:46px;--rail:70px;--pad:17px}
  .tl .yr{font-size:15px}
  .cond{grid-template-columns:1fr;gap:2px}
}

/* ---------- quote ----------
   BRAND RULE: two scarlet surfaces never sit next to each other. This band sits
   between the honours board and the closing ask, both scarlet, so it must not be
   a third. It used to be flat tint, which did the job but looked like nothing at
   all. A photograph does the same job and earns its place.

   The photograph is the background; the words sit on a solid panel over it. Not
   straight on the picture, because white text on a stage shot is legible with
   THIS image and a gamble with the next one anybody swaps in. The panel keeps
   the contrast fixed at 17:1 whatever the photograph does. */
.quote{position:relative;background:var(--ink-2);color:var(--ink);overflow:hidden}
/* Deliberately taller than its contents, and overhanging top and bottom, so the
   photograph can drift against the scroll without ever showing an edge. The
   overhang is what makes the parallax possible; 14% of a 560px section is about
   78px of slack each way, and site.js never moves it more than 54px. */
.quote-photo{position:absolute;inset:-14% 0;background-size:cover;
  background-position:center 38%;background-repeat:no-repeat;
  will-change:transform}
/* An even wash now the panel is centred: weighting it to one side only made
   sense when the panel sat on that side. Slightly deeper top and bottom so the
   photograph settles behind the card rather than competing with it. */
.quote-photo::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(20,16,15,.50) 0%,rgba(20,16,15,.34) 40%,
                                    rgba(20,16,15,.34) 60%,rgba(20,16,15,.52) 100%)}
.quote-in{position:relative;display:flex;align-items:center;justify-content:center;
  min-height:600px;padding:88px 24px}
/* Centred, and built like the rest of the site: square, gold rule across the
   top, kicker and heading in the house order. */
.quote-card{background:var(--tint);max-width:640px;margin:0 auto;text-align:center;
  padding:44px 52px 38px;border-top:7px solid var(--gold);
  box-shadow:0 24px 60px rgba(20,16,15,.30)}
/* The crest, bottom left, exactly as on every other surface: no size override,
   so it takes the standard 'auto 100%' and fills the card top to bottom.
   It was held back to 72% on the argument that a full-height crest would be more
   than half the width of the card and stop being a watermark. That was wrong on
   both counts — it is a watermark because of its colour, not its size, and
   holding it back is what made it read as a small graphic parked in the corner
   rather than part of the surface. The card's children are lifted above it by
   the .mark rule, so nothing about the text has to change. */
.quote-card .kicker{margin-bottom:10px}
.quote-card h2{font-size:clamp(24px,3vw,34px);margin-bottom:30px}
/* An oversized opening mark, in gold, above the words. */
.qmark{font-weight:900;font-size:58px;line-height:.7;color:var(--gold);
  margin:0 0 14px}

/* All the quotes occupy the same grid cell, so the section is as tall as the
   longest one and nothing jumps as they change. Only the current one is visible. */
.quote-stack{display:grid}
.quote-stack>figure{grid-area:1/1;margin:0;opacity:0;visibility:hidden;
  transition:opacity .5s ease}
.quote-stack>figure.on{opacity:1;visibility:visible}
/* Bold rather than Black — a spoken sentence, not a headline. */
/* Ink, not scarlet. Someone else's words carry themselves; setting them in the
   brand colour made the band look like it was shouting its own praise, and put
   a third red surface into the lower third of the homepage. Grey does the
   attribution underneath, so the whole element is black-and-grey. */
/* A size down from before: the panel is narrower than the old full-width band,
   and 33px in a 600px box gives four words a line. */
.quote blockquote{font-weight:700;font-size:clamp(19px,2.1vw,26px);line-height:1.35;
  margin:0 0 20px;color:var(--ink)}
/* A short gold rule between the words and whoever said them. inline-block so the
   rule is only as wide as the name it sits above, and centres with the card. */
.quote figcaption{font-weight:700;font-size:13px;letter-spacing:.1em;
  text-transform:uppercase;padding-top:16px;border-top:3px solid var(--gold);
  display:inline-block}
.quote figcaption span{display:block;font-weight:500;text-transform:none;
  letter-spacing:0;font-size:13.5px;color:var(--mute);margin-top:4px}

/* THE DOT IS 9PX; WHAT YOU PRESS IS 24. The buttons were the dots, 9px square
   with their centres 18px apart, which is under the 24px WCAG 2.5.8 asks for a
   mouse as well as a finger. Each button is now a 24px square with the 9px dot
   drawn in its middle, the same way the touch layout further down draws its 44px
   ones. The dots are exactly the size and colour they were; their centres are
   24px apart instead of 18, the least they can be for neither target to sit on
   the next. The -7.5px top and bottom take the extra height back out, so the
   row is still 9px tall to whatever is around it and nothing above or below
   moves. */
.quote-dots{display:flex;gap:0;justify-content:center;margin-top:26px}
.quote-dots button{width:24px;height:24px;margin:-7.5px 0;padding:0;border:0;background:none;
  cursor:pointer;display:grid;place-items:center}
.quote-dots button::before{content:'';width:9px;height:9px;background:var(--line);
  transition:background .2s}
.quote-dots button[aria-current=true]::before{background:var(--ink)}
.quote-dots button:hover::before{background:var(--mute)}

/* Anyone who has asked for less movement gets the quotes without the crossfade;
   site.js also stops advancing them on its own. */
@media(prefers-reduced-motion:reduce){.quote-stack>figure{transition:none}}

/* On a narrow screen there isn't room to sit a readable panel on top of a
   photograph, so the two stop overlapping and stack: picture, then words. The
   photograph comes out of absolute positioning and becomes a band of its own. */
@media(max-width:820px){
  .quote-photo{position:relative;height:230px}
  .quote-photo::after{background:linear-gradient(180deg,rgba(20,16,15,.20),rgba(20,16,15,.35))}
  .quote-in{min-height:0;padding:0}
  .quote-card{max-width:none;width:100%;padding:32px 26px 28px;box-shadow:none}
  .qmark{font-size:48px}
}

/* ---------- reveal on scroll ----------
   THE ONE RULE HERE: nothing is ever hidden unless JavaScript is definitely
   running AND the reader hasn't asked for less movement. Every rule below is
   behind .js-anim, which is added to <html> by a one-line script in the head of
   the page. Scripts off, script failed, reduced motion — the class is never
   added and the whole file below does nothing. The page is simply visible,
   which is the only acceptable failure mode: content that needs JavaScript to
   appear is content that sometimes doesn't.

   The class goes on in the HEAD rather than from site.js at the end of the body.
   From the end of the body you get a frame of visible content that then vanishes
   and fades back in — a flicker on every load. */
.js-anim [data-rise]{opacity:0;transform:translateY(24px);
  transition:opacity .75s cubic-bezier(.22,.61,.36,1),
             transform .75s cubic-bezier(.22,.61,.36,1)}
.js-anim [data-rise].in{opacity:1;transform:none}

/* A group whose children come in one after another. site.js writes the delay
   onto each child; the CSS just has to not fight it. */
.js-anim [data-rise-stagger]>*{opacity:0;transform:translateY(24px);
  transition:opacity .7s cubic-bezier(.22,.61,.36,1),
             transform .7s cubic-bezier(.22,.61,.36,1)}
.js-anim [data-rise-stagger].in>*{opacity:1;transform:none}

/* ---- the hero, on load ------------------------------------------------------
   The one part of the page that moves without being scrolled to, because it is
   already there when the page opens. Each line follows the one above it, so the
   band's name arrives before the sentence explaining it, which arrives before
   the buttons. That order is the point: it's the reading order, drawn.

   .hero-in is given .in by site.js on the first painted frame — not by an
   observer, which would be answering a question we already know the answer to. */
.js-anim .hero-in>*{opacity:0;transform:translateY(28px);
  transition:opacity .8s ease,transform .9s cubic-bezier(.22,.61,.36,1)}
.js-anim .hero-in.in>*{opacity:1;transform:none}
.js-anim .hero-in>*:nth-child(1){transition-delay:.10s}
.js-anim .hero-in>*:nth-child(2){transition-delay:.22s}
.js-anim .hero-in>*:nth-child(3){transition-delay:.34s}
.js-anim .hero-in>*:nth-child(4){transition-delay:.46s}
/* The gold bar under the headline draws itself once the words are up. */
.js-anim .hero .rule::after{transform:scaleX(0);transform-origin:left;
  transition:transform .9s cubic-bezier(.22,.61,.36,1) .5s}
.js-anim .hero-in.in .rule::after{transform:scaleX(1)}

/* ---- the detailed reveal ----------------------------------------------------
   [data-reveal] is a trigger, not an effect: it has no appearance of its own and
   never moves. It simply gains .in when it arrives, and the parts inside it —
   the kicker, the heading word by word, the gold bar drawing itself, then the
   line underneath — come in one after another off that single class.

   One observer per block rather than one per word. Forty separate observers for
   the words of five headings would be forty callbacks on every scroll for no
   visible gain.

   EASING: everything here uses the same curve as the block reveals, so the page
   has one sense of movement rather than several competing ones. */
.js-anim [data-reveal] .kicker{opacity:0;transform:translateY(12px);
  transition:opacity .5s ease,transform .5s cubic-bezier(.22,.61,.36,1)}
.js-anim [data-reveal].in .kicker{opacity:1;transform:none}

/* One word at a time. The rise is in em, so it scales with the heading — a
   48px headline and a 22px one lift by the same proportion, not the same pixels. */
.js-anim [data-reveal] .w{display:inline-block;opacity:0;transform:translateY(.6em);
  transition:opacity .5s ease,transform .6s cubic-bezier(.22,.61,.36,1)}
.js-anim [data-reveal].in .w{opacity:1;transform:none}

/* The gold bar draws itself from the left, after the words have landed. scaleX
   rather than width: a transform doesn't touch layout, so nothing round it
   reflows sixty times a second while it grows. Centred headings draw from the
   middle outwards, or the bar would slide off its own centre. */
.js-anim [data-reveal] .rule::after{transform:scaleX(0);transform-origin:left;
  transition:transform .75s cubic-bezier(.22,.61,.36,1) .38s}
.js-anim [data-reveal].in .rule::after{transform:scaleX(1)}

/* The line under the heading, last of all — and on the quote card, the mark,
   the words and the dots follow the same beat.

   Direct-child paragraphs are included so the standard kicker / heading / line
   block works everywhere without hand-marking each one. The kicker is itself a
   <p>, so it has to be excluded or it would be caught twice and take the later
   rule's delay, arriving after the heading instead of before it. */
.js-anim [data-reveal] > p:not(.kicker),
.js-anim [data-reveal] .after,
.js-anim [data-reveal] .qmark,
.js-anim [data-reveal] .quote-stack,
.js-anim [data-reveal] .quote-dots{opacity:0;transform:translateY(14px);
  transition:opacity .55s ease .42s,transform .55s cubic-bezier(.22,.61,.36,1) .42s}
.js-anim [data-reveal].in > p:not(.kicker),
.js-anim [data-reveal].in .after,
.js-anim [data-reveal].in .qmark,
.js-anim [data-reveal].in .quote-stack,
.js-anim [data-reveal].in .quote-dots{opacity:1;transform:none}
.js-anim [data-reveal] .quote-stack{transition-delay:.5s}
.js-anim [data-reveal] .quote-dots{transition-delay:.58s}

/* Photographs settle rather than simply appear: a shade over-size to begin with,
   easing back to true as the card arrives. Slower than everything else on
   purpose — a picture that snaps looks cheap. The parent must clip, or the
   oversized image spills past the card's border while it settles. */
.card,.reel-card{overflow:hidden}
.js-anim [data-rise] .card-img,.js-anim [data-rise-stagger] .card-img,
.js-anim [data-rise] .reel-img,.js-anim [data-rise-stagger] .reel-img{
  transform:scale(1.07);transition:transform 1.2s cubic-bezier(.22,.61,.36,1)}
.js-anim [data-rise].in .card-img,.js-anim [data-rise-stagger].in .card-img,
.js-anim [data-rise].in .reel-img,.js-anim [data-rise-stagger].in .reel-img{
  transform:none}

/* Belt and braces. If .js-anim ever gets added on a machine that has since been
   told to reduce motion, this still stops the movement. */
@media(prefers-reduced-motion:reduce){
  .js-anim [data-rise],.js-anim [data-rise-stagger]>*,
  .js-anim [data-reveal] .kicker,.js-anim [data-reveal] .w,
  .js-anim [data-reveal] > p,
  .js-anim [data-reveal] .after,.js-anim [data-reveal] .qmark,
  .js-anim [data-reveal] .quote-stack,.js-anim [data-reveal] .quote-dots,
  .js-anim .card-img,.js-anim .reel-img,.js-anim .hero-in>*{
    opacity:1;transform:none;transition:none}
  .js-anim [data-reveal] .rule::after{transform:none;transition:none}
  .quote-photo,.hero-img{transform:none!important}
}

/* ---------- one menu -------------------------------------------------------
   THE SITE HAD FIVE. A menu is one act — pick one of these — and it was drawn
   five different ways: 16px in a form and on a card, 15px on the contest
   filters, 14px on Analytics, 14.5px on the People screen; a 2px edge in three
   of them and a 1px hairline in the other two; a gold edge on focus in three
   and nothing at all in two. Measured, not guessed: the People picker came out
   44px tall with a 1px edge beside a 2px button in the same row, and it was
   the faintest thing in a group where it does the actual work.

   None of that is a decision anybody made. It is five people answering the
   same question on five different afternoons, which is the state this
   stylesheet's note about capitals already describes and already has a rule
   for. So: one menu, drawn like every other box on the site, and the only
   thing that varies is how wide it is.

   16px IS NOT A STYLE CHOICE. Below it, iOS zooms the page in when a menu is
   opened and does not zoom back out — so three of these screens left somebody
   stranded at 150% on a phone, the People screen included.

   AND THE ARROW IS OURS. Every other mark on this site is drawn by it: the
   chevron on a row, the arrow on a back link. The one on a menu was Windows's
   own grey button, sitting in the middle of a page that draws everything
   itself. This is the same chevron as .ad-head::after — scarlet, 2px, square
   ends — as a picture rather than a rotated square, because a background image
   is the only thing that reaches inside a control the browser owns. */
/* MEDIUM, SAID RATHER THAN INHERITED. A control inherits nothing from the page
   — the browser draws it at 400, a weight this site does not own — so the
   weight has to be asked for. Asked for as `inherit` it came out Black on the
   People screen, where the menu sits inside its own small-capital label and so
   inherited 900. The site's own weight is Medium; a menu is set in it wherever
   it happens to stand. */
select{appearance:none;-webkit-appearance:none;
  font-family:inherit;font-weight:500;font-size:16px;letter-spacing:0;
  text-transform:none;color:var(--ink);
  border:2px solid var(--line);border-radius:0;min-height:48px;
  padding:13px 40px 13px 15px;
  background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5l6 6 6-6' fill='none' stroke='%23BE1D2E' stroke-width='2'/%3E%3C/svg%3E")
    no-repeat right 15px center;
  background-size:14px 9px}
select:focus{border-color:var(--ink);outline:3px solid var(--scarlet);
  outline-offset:1px}
/* A menu nobody is allowed to touch says so by going quiet, rather than by the
   browser's own grey — which, now that the box is ours, would not have come. */
select:disabled{color:var(--mute);background-color:var(--tint);cursor:not-allowed}

/* ---------- forms ---------- */
.form{display:grid;gap:14px}
.form label{font-weight:700;font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--mute);margin-bottom:-8px}
.dark .form label{color:rgba(255,255,255,.65)}
.form input,.form textarea{padding:14px 16px;border:2px solid var(--line);
  background:#fff;font-family:inherit;font-size:16px;border-radius:0;color:var(--ink)}
/* The menu takes all of this from the one menu rule above, including the room
   its arrow needs on the right — which a padding shorthand here would close. */
.dark .form input,.dark .form select,.dark .form textarea{
  background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.24);color:#fff}
/* The line above sets `background`, which takes the arrow off with it — and
   scarlet on ink is 3.07:1 in any case, which is under the 3:1 a mark like
   this is held to once anti-aliasing is allowed for. Gold on ink is 9.9:1. */
.dark .form select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5l6 6 6-6' fill='none' stroke='%23F1C532' stroke-width='2'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 15px center;
  background-size:14px 9px}
.dark .form input::placeholder,.dark .form textarea::placeholder{color:rgba(255,255,255,.5)}
/* NOT outline:none. This beat the global ring on specificity, and what it put
   in its place was a two-pixel border going from pale warm grey to pale gold —
   the same value, to the eye. Tabbing Name, Email, Telephone, HOLD THESE
   TICKETS gave no indication of where you were, on the one form on this site
   that takes somebody's money. */
.form input:focus,.form textarea:focus{border-color:var(--ink);
  outline:3px solid var(--scarlet);outline-offset:1px}
/* A box that is filled in for you and cannot be changed — the address on the
   choose-a-password page, which the emailed link decides. It has to be a real
   field rather than a sentence, because that is where a password manager looks
   to find out whose password it is being offered; it should not look like one
   waiting to be typed in. */
.form input[readonly]{background:var(--tint);color:var(--mute);cursor:default}
.form input[readonly]:focus{border-color:var(--line)}
.form .row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.form-ok{background:var(--gold);color:var(--ink);padding:18px 20px;font-weight:700}

/* ---------- tracks ---------- */
.tracks{border:1px solid var(--line);padding:26px}
.track{display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:center;padding:14px 0;
  border-bottom:1px solid var(--line)}
.track:last-child{border-bottom:0}
/* Royal Red, matching the button beside them. Changed everywhere rather than
   only on the scarlet section — the player should look the same on every page.
   Hover goes to ink for the same reason .btn-royal does: royal has nowhere
   redder to move to. Gold still marks the one that's playing. */
/* The mark inside is a drawn SVG, not a character — see ICON_PLAY in site.js for
   why. Sized here rather than by font-size, which no longer has anything to act
   on. */
.play{width:44px;height:44px;border-radius:50%;border:0;background:var(--royal);color:#fff;
  cursor:pointer;display:grid;place-items:center;transition:.15s}
.play .pico{width:17px;height:17px;display:block}
.play-lg .pico{width:27px;height:27px}
.play:hover{background:var(--ink);transform:scale(1.07)}
.play.on{background:var(--gold);color:var(--ink)}
.track b{display:block;font-weight:700;font-size:15.5px}
.track span{font-size:13px;color:var(--mute)}

/* On a scarlet section the track list becomes a white panel rather than being
   restyled piece by piece. Everything inside then falls back to its normal
   colours — ink titles, muted credits, the scarlet play button — so there is
   one override here instead of six, and the player looks the same wherever it
   appears. color has to be reset too: .red sets white on the whole section. */
.red .tracks{background:var(--paper);color:var(--ink);border-color:var(--paper)}

/* ---------- our music: the featured listen ----------
   The page's first job is to answer "what do they sound like?", so one track
   is played large before anything is asked of the visitor. It reuses .track so
   the markup and the audio wiring stay identical to the list underneath — only
   the scale changes. */

.feature{grid-template-columns:auto 1fr;gap:26px;padding:30px;border:1px solid var(--line);
  background:var(--tint);align-items:center}
.feature b{font-size:clamp(21px,2.6vw,30px);font-weight:900;letter-spacing:.01em;
  line-height:1.1;margin-bottom:6px}
.feature span{font-size:15px}
.play-lg{width:74px;height:74px}
@media(max-width:560px){
  .feature{padding:22px;gap:18px}
  .play-lg{width:56px;height:56px}
  .play-lg .pico{width:21px;height:21px}
}

/* The list sits directly beneath the feature, so it loses its own top border
   and reads as a continuation of it rather than a second, separate panel. */
.after-feature{border-top:0;margin-top:0}

/* ---------- our music: records ----------
   Works in both states. While the record is unreleased the card is an
   announcement; once it's out the same card carries a price and a button. */

.albums{display:grid;gap:30px}
.album{display:grid;grid-template-columns:230px 1fr;gap:34px;align-items:center}
.album h3{font-size:clamp(22px,2.6vw,31px);font-weight:900;line-height:1.1;margin:6px 0 12px}
.album-in p{margin:0}
.album-buy{display:flex;align-items:center;gap:18px;margin-top:20px}
.album-buy b{font-size:23px;font-weight:900}
.album-soon{margin-top:18px;font-size:14px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--gold)}
@media(max-width:720px){
  .album{grid-template-columns:1fr;gap:22px}
}

/* A built sleeve for records with no artwork yet — square, scarlet, gold rule.
   Deliberately not a mock CD case: it reads as a placeholder that happens to
   be handsome, rather than pretending to be a photograph of a product. */
.sleeve{display:grid;align-content:center;gap:10px;aspect-ratio:1;padding:26px;
  background:var(--scarlet);border-bottom:6px solid var(--gold);container-type:inline-size}
/* White, not gold: at this size the label is small text, and gold on scarlet
   only reaches 3.75:1. White clears AA at 6.17:1. The gold stays on the rule
   and the base edge, where contrast rules don't apply. */
.sleeve em{font-style:normal;font-weight:700;font-size:4.6cqw;letter-spacing:.16em;
  text-transform:uppercase;color:#fff}
.sleeve b{font-weight:900;font-size:11cqw;line-height:1.02;color:#fff;text-transform:uppercase}
.sleeve i{display:block;width:26%;height:5px;background:var(--gold);margin-top:4px}
.sleeve-art{width:100%;aspect-ratio:1;object-fit:cover;display:block}

/* ---------- what's on: the poster wall ----------
   The frame is 4:5. The band's exports vary — 900x1300 (1:1.444) and 945x1181
   (1:1.250) have both turned up — so posters are MOUNTED in it rather than
   cropped to it. On a concert poster the date, venue and ticket line ARE the
   artwork, and cropping takes the scarlet foot carrying all three.

   Where there's no poster the card builds one from the fixture data in the same
   layout — masthead, title, scarlet footer — so the wall reads evenly whether
   the artwork exists or not. A built poster has one advantage over a real one:
   it's text, so it can be read aloud and indexed. A supplied poster is a
   picture, which is why those carry a full alt description instead.

   Sizes are in cqw — a percentage of the CARD's width, not the viewport — so a
   built poster keeps its proportions at any column count. */
/* A line of orientation between the next-performance bar and the wall, so the
   posters don't start cold. Two columns: what's coming, and how tickets work. */
.wall-intro{display:grid;grid-template-columns:1.15fr 1fr;gap:52px;
  margin-bottom:46px;align-items:start}
.wall-intro p{margin:0}
.wall-intro p+p{font-size:15.5px;color:var(--mute);line-height:1.65}
.wall-intro p+p b{color:var(--ink);font-weight:700}
/* The summary sits under the lede in the same column, a size down from it and a
   size up from the running text on the right — it is the second thing read on
   the page, not the third. Empty until site.js writes it, and an empty paragraph
   would otherwise leave a hole where its margin is. */
/* The summary of the season. It used to sit under the lede in the left column,
   with a paragraph about how to buy tickets alongside it. That paragraph has
   gone, so this now takes the right-hand column on its own — which suits it:
   the lede states the shape of the season and this fills it in.

   The selector names .wall-intro deliberately. Without it, `.wall-intro p+p`
   wins on specificity and greys this down to the size the departed paragraph
   used — small print. It is not small print: it is what the page is about, and
   the only thing on the page telling anybody what is actually coming up. */
.season-sum{margin:14px 0 0;font-size:16.5px;line-height:1.55;color:var(--ink);
  text-align:justify;-webkit-hyphens:auto;hyphens:auto;hyphenate-limit-chars:8 4 4}
.wall-intro p.season-sum{margin:0;font-size:16.5px;color:var(--ink)}
.season-sum:empty{display:none}

@media(max-width:820px){.wall-intro{grid-template-columns:1fr;gap:22px}}

.wall{display:grid;grid-template-columns:repeat(3,1fr);gap:26px}
/* The concerts-or-contests choice, above the wall, only when both are in the
   season. The buttons are the site's pick control, at the wall's size. */
.wall-pick{margin:-16px 0 26px}
.wall-pick .pick-one span{min-height:44px;padding:0 18px;font-size:14px}

/* Month headings run the full width of the grid and break the wall into a
   season rather than a pile. The gold rule stretches to fill whatever is left
   after the month name, so it sets its own length — the same device as the
   underlines, but earning its keep as a divider. */
.wall-head{grid-column:1/-1;display:flex;align-items:center;gap:18px;margin-top:24px}
.wall-head:first-child{margin-top:0}
.wall-head b{font-weight:900;font-size:clamp(22px,2.7vw,32px);line-height:1;
  text-transform:uppercase;white-space:nowrap}
.wall-head u{text-decoration:none;font-weight:700;font-size:15px;color:var(--mute);
  white-space:nowrap}
/* The gold rule now runs to the end of the row — there is nothing after it to
   leave room for, since the date count that used to sit there has gone. */
.wall-head em{flex:1;height:4px;background:var(--gold);font-style:normal;min-width:20px}

/* The next fixture gets a flag. One per page, so it reads as "this is the one
   coming up" rather than as decoration. */
.poster-next{position:absolute;top:0;left:0;z-index:2;background:var(--gold);
  color:var(--ink);font-weight:900;font-size:3cqw;letter-spacing:.16em;
  text-transform:uppercase;padding:2.4cqw 4.4cqw;line-height:1}

@media(max-width:560px){.wall-head b{font-size:24px}}

.poster{container-type:inline-size;display:block;text-decoration:none;color:inherit;
  position:relative;aspect-ratio:4/5;overflow:hidden;background:var(--ink);
  transition:.18s}
.poster:hover{transform:translateY(-3px);box-shadow:0 16px 40px rgba(20,16,15,.22)}

/* A supplied poster is MOUNTED, not cropped. The band's exports aren't a single
   ratio — two of the three seen so far are 900x1300 (1:1.444), the third is
   945x1181 (1:1.250) — so any fixed frame would trim something. object-fit:cover
   would crop, and on a concert poster the first thing lost is the scarlet foot
   carrying the date and the ticket URL. contain keeps every poster whole and
   lets the ink show as a mount around it, which reads as framing rather than as
   a mistake. */
.poster-art{width:100%;height:100%;object-fit:contain;display:block;background:var(--ink)}

/* A built one, echoing the house layout. */
.poster-photo{position:absolute;inset:0;background-size:cover;background-position:center;
  background-color:var(--ink-2)}
.poster-scrim{position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(20,16,15,.78) 0%,rgba(20,16,15,.30) 32%,
                                    rgba(20,16,15,.35) 58%,rgba(20,16,15,.88) 78%)}
.poster-in{position:relative;height:100%;display:flex;flex-direction:column;
  color:#fff;text-align:center}

.poster-mast{padding:5cqw 5cqw 0}
.poster-mast u{text-decoration:none;display:block;font-weight:500;font-size:4.4cqw;
  letter-spacing:.02em}
.poster-mast b{display:block;font-weight:900;font-size:10cqw;line-height:1;
  color:var(--gold);letter-spacing:.01em}
.poster-mast i{font-style:normal;display:block;font-weight:900;font-size:3.7cqw;
  letter-spacing:.1em;margin-top:1cqw}

.poster-title{margin-top:auto;padding:0 5cqw 4cqw;font-weight:900;font-size:8.4cqw;
  line-height:.98;text-transform:uppercase;text-wrap:balance}

/* The scarlet foot, as on the printed posters: crest, gold rule, then details.

   ITS HEIGHT IS FIXED, and that is the point of this block. It used to be
   whatever its contents came to, so a card for "Holy Trinity Parish Church, High
   St, Rothwell" carried a visibly deeper red band than one for "Northampton &
   County Club" — same wall, same size cards, different proportions. Set to
   32cqw, which on a 4:5 card is a touch over a quarter of its height, and every
   poster on the wall now cuts at the same line.

   The text has to fit that, so each line is held to one line and clipped with an
   ellipsis if it will not. Nothing is lost by it: the venue and the date are
   both repeated in full in the caption under the card and again in the panel
   that appears over it. The poster is a poster, not the record.

   26cqw, which is 21% of a 4:5 card. That figure is not chosen, it is measured:
   the David Read card is a poster the band supplied, its red band is part of the
   artwork, and it comes to 20.7% of the card. A built poster sitting next to a
   real one should cut at the same line. It was 34cqw and looked visibly deeper.

   Getting there meant the type had to come down with it — the four lines and
   their padding measured 31.7cqw, which will not fit in 26. Everything in here
   is scaled to 0.84 and the padding to 3cqw, which lands at 25.9. Slack is thin
   by design at that size, so overflow:hidden below is doing real work rather
   than sitting there as a formality.

   min-width:0 on the text column because a grid item will not shrink below its
   content by default, and without it the ellipsis never triggers — the column
   just pushes the card wider instead. */
.poster-foot{background:var(--scarlet);display:grid;grid-template-columns:auto 1.2cqw 1fr;
  gap:3cqw;align-items:center;padding:3cqw 5cqw;text-align:left;
  height:26cqw;box-sizing:border-box;overflow:hidden}
.poster-foot img{width:13cqw;height:auto}
.poster-foot > span:last-child{min-width:0}
.poster-bar{background:var(--gold);align-self:stretch}
.poster-town,.poster-when,.poster-where,.poster-tix{
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.poster-town{display:block;font-weight:900;font-size:6.2cqw;line-height:1;
  text-transform:uppercase}
.poster-when{display:block;font-weight:700;font-size:3.1cqw;margin-top:1.2cqw}
.poster-where{display:block;font-weight:500;font-size:2.6cqw;opacity:.9;margin-top:.5cqw}
.poster-tix{display:block;font-weight:700;font-size:2.5cqw;color:var(--gold);margin-top:1.3cqw}

/* Hover: the poster falls back and the detail comes forward.
   The blurred layer is scaled up 6% because a blur samples past the element's
   edge — without the overscan you get a soft, pale rim where there's nothing
   left to sample from. */
.poster-art,.poster-photo{transition:filter .25s ease,transform .25s ease}
.poster-in{transition:opacity .2s ease}

.poster:hover .poster-art,.poster:focus-visible .poster-art,
.poster:hover .poster-photo,.poster:focus-visible .poster-photo{
  filter:blur(7px) brightness(.5);transform:scale(1.06)}
/* A built poster carries its own type, which would show through the blur and
   collide with the overlay — so it steps aside. */
.poster:hover .poster-in,.poster:focus-visible .poster-in{opacity:0}

.poster-over{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;
  padding:8cqw 7cqw;color:#fff;opacity:0;transition:opacity .25s ease;
  pointer-events:none}
.poster:hover .poster-over,.poster:focus-visible .poster-over{opacity:1}
.poster-over u{text-decoration:none;font-weight:700;font-size:3.6cqw;
  letter-spacing:.18em;text-transform:uppercase;color:var(--gold)}
/* An h2 since What's On has no other heading between its h1 and the wall; it
   was an h3, and the letter-spacing the h2 rule adds is handed back here so it
   is set exactly as before. */
.poster-over h2{font-size:8.8cqw;line-height:1.04;margin:3.2cqw 0;text-transform:uppercase;
  letter-spacing:inherit;text-wrap:balance}
.poster-over p{margin:0;font-size:4.8cqw;line-height:1.45}
.poster-over p b{display:block;font-weight:700}
.poster-over .btn{margin-top:6cqw;font-size:4cqw;padding:4cqw 7cqw;letter-spacing:.08em}
.poster-over .ev-note{margin-top:5cqw;font-size:4cqw;color:rgba(255,255,255,.85);
  font-style:italic}

/* Caption stays as plain text under every card. It is the selectable, indexable
   copy of the details on a supplied poster — a poster is a picture, and neither
   Google nor a screen reader can read one — and it's what a touch device sees,
   since there is no hover there. No button: the whole card is the link. */
.poster-cap{padding:14px 2px 0}
.poster-cap b{display:block;font-size:15px;font-weight:700}
.poster-cap span{display:block;font-size:13.5px;color:var(--mute);font-weight:500}

/* No pointer, no hover — so on touch the detail layer never appears and the
   caption does all the work. Nothing is lost; it just isn't decorated. */
@media(hover:none){
  .poster-over{display:none}
}
@media(prefers-reduced-motion:reduce){
  .poster-art,.poster-photo,.poster-in,.poster-over{transition:none}
  .poster:hover .poster-art,.poster:hover .poster-photo{transform:none}
}

@media(max-width:900px){.wall{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.wall{grid-template-columns:1fr}}

/* ---------- live contest record ----------
   Built by record.js from the results feed. Square corners, scarlet rules,
   wins picked out in Royal Red so the eye can find them down a long column. */
/* ---------- the full contest record: filters ---------- */
.rt-tools{display:flex;flex-wrap:wrap;gap:16px 22px;align-items:flex-end;
  padding-bottom:20px;border-bottom:2px solid var(--ink);margin-bottom:14px}
.rt-tools label{display:flex;flex-direction:column;gap:6px;font-weight:700;font-size:11.5px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--mute)}
/* Only how wide. Everything else is the one menu rule. */
.rt-tools select{min-width:200px}
.rt-check{flex-direction:row!important;align-items:center;gap:9px!important;
  color:var(--ink)!important;font-size:13px!important;letter-spacing:.06em!important;
  padding-bottom:9px;cursor:pointer}
.rt-check input{width:18px;height:18px;accent-color:var(--scarlet);cursor:pointer}
.rt-clear{margin-bottom:9px;background:none;border:0;padding:0;cursor:pointer;
  font:inherit;font-weight:700;font-size:12.5px;letter-spacing:.06em;
  color:var(--scarlet);border-bottom:2px solid transparent}
.rt-clear:hover{border-color:var(--gold)}
.rt-count{margin:0 0 16px;font-size:13.5px;color:var(--mute)}
.rt-none{padding:26px 0!important;color:var(--mute);text-align:center}
.rt-foot{margin-top:22px}

.rec-table{width:100%;border-collapse:collapse;font-size:15px}
.rec-table th{text-align:left;font-weight:900;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--scarlet);padding:0 16px 12px 0;
  border-bottom:2px solid var(--scarlet)}
.rec-table td{padding:12px 16px 12px 0;border-bottom:1px solid var(--line);
  vertical-align:top}
.rec-table tr:last-child td{border-bottom:0}
.rec-table td:first-child{font-weight:700;white-space:nowrap;width:64px}
.rec-table td:nth-child(3){white-space:nowrap;width:74px}
.rec-table td:last-child{color:var(--mute);white-space:nowrap}
.rt-win{color:var(--royal);font-weight:900}
@media(max-width:640px){
  .rec-table td:last-child,.rec-table th:last-child{display:none}
  .rec-table{font-size:14px}
  .rt-tools{gap:14px}
  .rt-tools label{flex:1 1 100%}
  .rt-tools select{min-width:0;width:100%}
}

/* ---------- brand mark watermark ----------
   The supplied mark, always bottom-left, bleeding off that corner.
   Solid brand colours — no opacity — exactly as the reference artwork:
       white  #FFFFFF  →  mark #F2F2F2   (light grey)
       scarlet#BE1D2E  →  mark #A50E0E   (Royal Red)
       black  #0D0D0D  →  mark #000000
   Mark is 373 × 417, so every height below is width × 1.118.
   USE IT ONCE PER PAGE. It's punctuation, not wallpaper — on the page banner
   for inner pages, and on a single chosen section for the homepage.
   Opt in with class="mark"; .page-head carries it automatically. */
.mark,.page-head{position:relative;overflow:hidden}
.mark>*,.page-head>*{position:relative;z-index:1}

/* The mark fills the section's full height — top edge flush with the top of the
   section, bottom flush with the bottom — and its width follows from that.
   'auto 100%' scales to the height and lets the width fall out proportionally,
   so it can never be short of the frame however tall the section grows. */
.mark::before,.page-head::before{
  content:'';position:absolute;pointer-events:none;z-index:0;
  inset:0;
  background-position:left bottom;
  background-size:auto 100%;
  background-repeat:no-repeat}

/* The colour follows the surface it sits on */
.mark::before                             {background-image:url('../img/gus-crest-light.png')}  /* on white   */
.red.mark::before                         {background-image:url('../img/gus-crest-red.png')}    /* on scarlet */
/* The page banners take the BLACK mark rather than the royal one. On scarlet it
   reads as a shadow in the corner instead of a second red, which is closer to
   how the crest is used elsewhere in the brand. It's a much stronger contrast
   than royal-on-scarlet, so it's held back with opacity to keep it a watermark
   rather than a graphic. */
.dark.mark::before,.foot.mark::before     {background-image:url('../img/gus-crest-dark.png')}      /* on black   */
.page-head::before{background-image:url('../img/gus-crest-dark.png')}

/* On narrow screens a full-height mark would span most of the width, so it
   backs off to three-quarters height while staying anchored bottom-left. */
@media(max-width:700px){
  .mark::before,.page-head::before{background-size:auto 75%}
}

/* ---------- gold rule under headings ----------
   The device used across the band's artwork: a Sovereign Gold bar
   sitting under the heading, the width of the text. */
/* BRAND RULE: the visible gap above the bar must equal the bar's own thickness.
   Both read from one variable so they can't drift apart.
   The -0.19em pulls out the dead space every line box carries below the cap
   baseline — Noverion's descender plus leading measures 0.189em, and without
   this correction the gap looks roughly twice the bar on a 48px heading.
   Width is measured by site.js and written to --bar-w: the bar spans the first
   word of the last line, or its first 5 characters if the word is longer, so it
   never runs across a space. The clamp is only a fallback if JS doesn't run.

   --bar-x is where that word starts, also measured by site.js. The bar is drawn
   from the first word, so it is drawn UNDER the first word — on every heading,
   whatever its text alignment. Centred headings used to get margin:auto here,
   which put the bar in the middle of the line while its width still came from
   the word at the start of it: the bar then underlined nothing in particular. */
.rule::after{
  /* THE BAR IS A FRACTION OF ITS OWN HEADING, not a number of pixels. It was
     six, with three exceptions bolted on for the sizes where six was wrong —
     and the exceptions only covered the places somebody had noticed. Measured
     across the whole site, the good ones all sat between 0.119 and 0.133 of
     the type they were under, and the two that looked wrong were the two that
     had fallen outside it: a 34px heading on the front page carrying the same
     six as a 48px one, and the ticketing page's 84px heading carrying six
     where the hero's 84px carried ten. One eighth of the heading puts every
     bar within a pixel of the ones nobody has ever complained about, and there
     is nothing left to keep in step by hand.

     The gap above it follows automatically: it is the bar's own thickness,
     less the dead space under the cap baseline, and both are now in em. */
  --bar:0.125em;
  content:'';display:block;
  width:var(--bar-w, clamp(120px,26%,260px));
  height:var(--bar);
  margin-top:calc(var(--bar) - 0.19em);
  margin-left:var(--bar-x, 0px);
  background:var(--gold)}

/* AND A BAR NOBODY HAS MEASURED IS NOT DRAWN AT A GUESS.
   The width above falls back to a share of the COLUMN, which is the one thing
   the bar is not a fraction of: under WHAT'S ON at 1132px wide that guess is
   260px against a word 217px wide, so the bar covered the word, the space
   after it, and the first letter of the next one — and then snapped back when
   the measure arrived. It was seen on any fresh draw: a card closing rebuilds
   the heading, and the new element carries no measurement at all.

   So with site.js running (it sets .has-bars before the first paint) an
   unmeasured bar has no width, and appears at its true width the moment it is
   measured — a beat late at worst, never wrong. Without site.js the guess is
   still better than nothing, which is what the class is for. */
.has-bars .rule:not([data-barred])::after{width:0}

/* (There is nothing to set for the larger headings any more: a bar measured
   off its own type is already in proportion at every size.) */

/* A SCREEN OF THE ADMIN THAT LIVES AT ITS OWN ADDRESS. Ticketing, the door
   list and the scanner are separate pages, and an <h1> is the right tag for a
   page — but they are screens of the admin to the person using them, and a
   screen heading in here is 48px. Left as a plain h1 it came out at 84,
   half again the size of the heading on the screen it was opened from. */
/* ONLY THE SIZE. The capitals and the letter-spacing are already on h1, and
   setting them again here would be a third way of writing capitals in an admin
   that has two — which verify-site.js watches for, and rightly. */
.ad-intro h1{font-size:clamp(28px,4.2vw,48px)}

/* ---------- cta band ---------- */
.cta{background:var(--scarlet);color:#fff;padding:66px 0;text-align:center;
  border-top:5px solid var(--gold)}
.cta h2{margin-bottom:14px;color:#fff}
.cta .kicker{color:#fff}
.cta p{max-width:620px;margin:0 auto 28px;color:rgba(255,255,255,.94)}

/* A LINK ON THE BAND'S OWN RED IS WHITE, AND UNDERLINED.
   Three of them were set in gold with an inline style, and measured against
   the scarlet behind them they came out at 2.84:1 and 3.75:1 against the 4.5:1
   that text this size has to meet. Gold on scarlet is a shade under 3.6:1 at
   its very best, before anything is faded — it is a colour for a rule, a mark
   or a heading on that ground, and the Branding Pack says as much: gold is not
   for body text.

   White on scarlet is 5.5:1. The underline is not decoration either: on a
   surface where the surrounding words are also white, it is the only thing
   left saying which of them can be pressed. */
.cta a:not(.btn),.sec.red a:not(.btn){
  color:#fff;text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px}
.cta a:not(.btn):hover,.sec.red a:not(.btn):hover{
  text-decoration-color:var(--gold);text-decoration-thickness:2px}

/* ---------- prose: privacy, accessibility ----------
   A single measured column. Legal and policy text is read, not scanned, so the
   line length is deliberately shorter than the rest of the site. */

.prose{max-width:720px}
.prose h2{font-size:clamp(20px,2.3vw,26px);font-weight:900;margin:44px 0 14px;
  text-transform:uppercase;letter-spacing:.01em}
.prose h2:first-child{margin-top:0}
.prose p,.prose li,.prose dd{line-height:1.72}
.prose p{margin:0 0 16px}
.prose ul{margin:0 0 16px;padding-left:22px}
.prose li{margin-bottom:9px}
.prose dl{margin:0 0 16px}
.prose dt{font-weight:700;margin-top:16px}
.prose dd{margin:4px 0 0;padding-left:18px;border-left:3px solid var(--gold)}
.prose a{color:var(--scarlet);font-weight:700}
.prose a:hover{border-bottom:2px solid var(--gold)}
.prose .stamp{margin-top:44px;padding-top:20px;border-top:1px solid var(--line);
  font-size:14px;color:var(--mute)}

/* ---------- footer ---------- */
.foot{background:#0C0908;color:rgba(255,255,255,.72);padding:56px 0 0}
/* Even gaps between the four blocks, which a column grid cannot give you.
   The columns were 2fr 1fr 1fr 1fr, so the COLUMNS were evenly sized — but the
   text inside them is not. "What's On" is 74px in a 202px column and "Promoter
   pack" is 98px, so the space left over differed in each, and the gaps you
   could actually see came out at 105px, 168px and 166px.

   Laid out as a row instead, with each block only as wide as it needs and the
   leftover shared out equally between them. The gaps are then equal by
   construction and stay equal if a link is renamed. */
.foot-in{display:flex;flex-wrap:wrap;justify-content:space-between;
  gap:40px;padding-bottom:40px}
.foot-brand{flex:0 1 var(--brand-measure)}
.f-col{flex:0 0 auto}
/* The logo floats top-left and the blurb wraps round it, at 54px.

   It does NOT fill the height of the row, and that is a deliberate trade rather
   than an oversight. The row is 189px, set by the Explore list; this block comes
   to 140px, so about 50px is left over and the gold rule floats in the middle of
   it. Both ways of closing that gap cost more than the gap does:

     narrow the column until the text wraps further — the logo already takes
     70px off the width, so this ends at about 21 characters a line, and
     justified text at 21 characters is nothing but holes;

     grow the logo until it fills the height itself — needs 140px, which is
     far too big for a footer.

   So the measure stays at 340px, about 38 characters, which justifies cleanly,
   and the leftover height is simply leftover. If it ever wants closing, the
   lever is the Explore list rather than this block: tightening the footer link
   spacing would bring the row down to meet it, and shorten the whole footer at
   the same time. */
/* A column, so the block can fill the height the footer row gives it — which is
   set by the tallest thing in that row, the Explore list. The blurb sits at the
   top, the credit at the bottom, and the gold rule takes what is left.

   .foot-blurb keeps the logo and the blurb together as one flex item, so the
   two move as a unit and only the rule and the credit below take a share of the
   spare height. */
.foot-brand{display:flex;flex-direction:column}
/* flow-root so the float is contained — otherwise the logo, being taller than
   the text beside it, hangs out of the bottom and lands on the gold rule. */
.foot-blurb{display:flow-root}
.foot img{float:left;height:54px;width:auto;margin:3px 16px 2px 0}

/* margin:auto 0 is what centres it. An auto margin in a flex column swallows
   the free space, and one on each side swallows an equal share — so the rule
   sits exactly halfway between the blurb above and the credit below, whatever
   that distance turns out to be. It is the answer to "halfway between the two"
   that does not need a number, and it stays right if the blurb rewraps at a
   different window width.
   The minimum gaps are set on the neighbours rather than on the rule, because
   an auto margin cannot also carry a floor. 12 above and 10 below, keeping the
   2px difference that cancels the leading: the blurb ends with a few pixels of
   space below its last line and the credit begins with a few above its
   capitals, so equal numbers would leave the rule looking closer to the blurb.
   On a narrow screen, where there is no spare height to share out, those
   minimums are the whole gap. */
.foot-rule{display:block;flex:0 0 2px;background:var(--gold);
  width:100%;max-width:var(--brand-measure);margin:auto 0}
.foot-blurb{margin-bottom:12px}
/* One measure, shared by the blurb and the credit beneath it, and given in px
   rather than ch on purpose. A `ch` is the width of the digit zero in the
   element's OWN font-size, so the same `32ch` on a 14.5px paragraph and a 12px
   credit produced two different widths — 232px and 192px. The gold rule spans
   the credit, so it came out 40px shorter than the text it was dividing, and
   the credit line no longer fitted on one line either. */
.foot-brand{--brand-measure:340px}

/* Justified, to match the project's documents — both of them set their body
   paragraphs to justified and neither sets one to left.

   Hyphenation is switched on with it, and that is not optional at this measure.
   The column is about 36 characters, so a line holds six or seven words and
   there are only five or six gaps to absorb whatever space is left over. Take a
   long word down to the next line without hyphens and the remaining words on
   the line stretch far enough apart to leave a visible river of white running
   down the paragraph. Hyphenation breaks the word instead, so the leftover is
   small and the spacing stays even. It needs the lang attribute on <html> to
   know the rules; every page here carries lang="en-GB".

   The credit line underneath opts out — it is a single line, and the last line
   of justified text is never justified anyway, so it would only be a trap for
   the day somebody lengthens it. */
/* 15.5px, up from 14.5. The credit line beneath is sized by measurement to fill
   the gold rule and lands around 15.45px, so the blurb was the smaller of the
   two and the maker's credit was quietly the largest text in the footer. Both
   are 15.5 now — the credit is capped at that figure in sizeCredit(), so it can
   reach the rule but never overtake the band's own words. */
.foot-brand p{font-size:15.5px;max-width:var(--brand-measure);margin:0;
  text-align:justify;-webkit-hyphens:auto;hyphens:auto}

/* Left to itself a browser will break a word with two letters before the hyphen,
   which is how "future" came out as "fu-ture". These are the limits: only words
   of eight letters or more, and never fewer than four letters on either side of
   the break.

   In this paragraph that leaves exactly four words that could break at all —
   Creating, exciting, Kettering and Northampton — and of those only Northampton
   has a break that satisfies the four-either-side rule, at North-ampton. Every
   short word, "future" included, is now off limits entirely.

   -webkit- for Safari, which named these separately and earlier. Where neither
   is understood the browser falls back to its own loose defaults, so this is an
   improvement rather than a guarantee; if a bad break ever shows up somewhere
   unexpected, the certain fix is hyphens:manual and slightly looser word
   spacing. */
.foot-brand p{
  -webkit-hyphenate-limit-before:4;
  -webkit-hyphenate-limit-after:4;
  hyphenate-limit-chars:8 4 4}
.f-col{display:flex;flex-direction:column;gap:9px}
.f-col b{font-weight:700;font-size:11.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--gold);margin-bottom:5px}
.f-col a{font-size:14.5px;text-decoration:none}
.f-col a:hover{color:var(--gold)}
/* The last line on the page, and it had 20px above and 20px below — the same
   spacing as any strip in the middle of a document, which left it sitting on the
   bottom edge of the window with nothing under it.

   More below than above, deliberately: a footer wants the page to end, not to
   stop. And when these two lines wrap onto separate rows on a narrow screen,
   row-gap keeps them apart instead of letting them close up into one block. */
/* Equal above and below. It was 22px above the small print and 40px beneath,
   which reads as the page having failed to finish — the eye measures the gap
   against the rule above it, and a bottom nearly twice the top looks like
   something was meant to be there. */
.foot-btm{display:flex;justify-content:space-between;gap:12px 18px;padding:22px 24px;
  border-top:1px solid rgba(255,255,255,.1);font-size:13px;flex-wrap:wrap}
.foot-btm a{text-decoration:none}
/* The maker's credit, in the brand column above the dividing rule rather than
   down in the small print with the charity number.

   Set apart rather than merely spaced. As a third paragraph in the same column
   it read as another sentence about the band, which it isn't — so it gets its
   own short gold rule above it and is stepped down in size and weight. The rule
   is the same device the headings use, at the width of a word rather than a
   heading, so it reads as house furniture rather than a new idea. */
/* The rule spans the column rather than being a 40px stub at the left of it.
   As a stub it read as a fragment — something that had been cut off, or the
   start of an underline that never finished. Full width it does the job it was
   there to do: it divides the band's description from the maker's credit, and
   the two read as two things rather than one paragraph with a mark above it.

   The column is set by .foot-brand p{max-width:32ch}, so the rule is given the
   same measure and lines up with the text it is dividing rather than with the
   grid column, which is wider. */
/* Equal air above and below, because it is a divider and a divider that sits
   closer to one of the two things it separates has picked a side. It was 26px
   above and 18px below.

   2px rather than 3px. The only other rule in this footer is the hairline over
   the copyright line; 3px of gold between a 14.5px text and a 12px one was
   shouting where it only needed to speak. */
/* .foot-brand p.credit, not .credit. `.foot-brand p` is a class plus an element
   and so outranks a bare class, whatever the order in the file — and this is a
   <p> inside .foot-brand. It was therefore silently taking font-size:14.5px and
   margin:0 from that rule and ignoring what is asked for here: the credit
   rendered at the same size as the blurb, too wide for its column so it wrapped
   to two lines, with NO gap above the gold rule at all. Only the colour and the
   letter-spacing were getting through, which is why it still looked different
   enough to seem deliberate.

   12 above and 10 below — a 24px divider, down from 46. The 16px reference it
   used to take from the logo gap has gone, because the logo no longer sits on a
   line of its own; the column's remaining rhythm is the 9px between the footer
   links, and 12 sits just above that.

   12 and 10, not 11 and 11. Equal numbers do not give equal gaps here: the
   paragraph above ends with roughly 3px of leading below its last line, and the
   credit below starts with roughly 5px above its capitals, so matched padding
   leaves the rule looking closer to the blurb than to the credit. The 2px
   difference cancels that out.

   No rule drawn here any more — .foot-rule is a real element between the two
   paragraphs, because only an element of its own can take an equal share of the
   leftover height above and below itself. A border or a pseudo-element is
   welded to one side or the other and can only ever sit at a fixed distance
   from it. */
/* Sized to reach the width of the gold rule above it, rather than stretched to
   it — justifying a single line was tried and looked like exactly what it was,
   a short line pulled apart.

   The 12px here is a floor, not the intended size. sizeCredit() in site.js
   measures the line and scales it up to meet the rule, the same way the header
   lockup is matched to its sub-line. It is done by measurement because it was
   twice done by arithmetic and was twice wrong: once leaving the line well
   short, once making it wide enough to wrap onto a second line.

   12px is what shows if that script never runs. It is under the size that fits
   in every case, so with scripts off the line is a little short of the rule and
   never wrapped, which is the right way round to fail. */
.foot-brand p.credit{margin:10px 0 0;
  max-width:var(--brand-measure);text-align:left;hyphens:manual;
  font-size:12px;letter-spacing:.06em;color:rgba(255,255,255,.55)}

/* ==========================================================================
   JUSTIFIED BODY TEXT
   ==========================================================================
   Applied to the running prose across the site, to match the project's
   documents, which set their body paragraphs justified.

   NOT applied to everything with words in it, and the line is drawn by
   measure. Justification works by stretching the spaces between words to fill
   the line: give it forty-five characters or more and there are enough gaps to
   absorb the slack invisibly, give it thirty and one long word wrapping leaves
   a hole you can see. So:

     justified          prose pages           100 characters
                        page ledes             90 or more
                        split columns          64 to 73
                        Book Us offers         53
                        biography panel        71

     left as they were  a spec answer          42
                        a news card blurb      36
                        a poster card's meta   40

   Hyphenation comes with it, on the same limits as the footer: eight-letter
   words minimum, four letters either side of the break. Without that a browser
   will break "future" as "fu-ture", which is how this was found in the footer.
   With it, the hyphen only ever lands somewhere a person would put it.

   The last line of a justified paragraph is never stretched, so ragged endings
   are correct and not a fault. */
.prose p, .prose li,
.lede,
.split p, .wall-intro p,
.offer p,
.bio-body p,
.spec-notes p,
.sec-head p:not(.kicker){
  text-align:justify;
  -webkit-hyphens:auto;hyphens:auto;
  -webkit-hyphenate-limit-before:4;
  -webkit-hyphenate-limit-after:4;
  hyphenate-limit-chars:8 4 4}

/* Anything that is a label, a caption or a note stays ranged left, whatever it
   sits inside — these are short and justification would only pull them apart. */
/* NOT a bare `figcaption`, which is what this said at first. There are two kinds
   on this site and they want opposite things. The captions under the Book Us
   collage are labels beneath a picture, and range left. The one on a quote is the
   attribution under a centred card, and belongs on the centre line with
   everything else in it.

   The bare selector caught both — and because justify aligns its LAST line to the
   start, and these are one line each, the speaker's name and their role both slid
   to the left edge of the block while the card around them stayed centred. It
   read as a centring bug rather than an alignment one, which is why it survived
   a look. Named by where they are now, so the two cannot be confused again. */
/* NOT .ev-note. This block is about hyphenation, and text-align:left came along
   for the ride — which silently un-centred every "Sold out", every "Nothing is
   on sale here at the moment", and "This phone cannot use the camera for
   scanning", all of which are centred by design three lines below where they
   are declared. Same specificity, later rule, so nobody could see why. */
.prose .stamp, .hint, .card-date, .credit,
.photo-set figcaption, .cond, .spec dd{
  text-align:left;-webkit-hyphens:manual;hyphens:manual}
.ev-note{-webkit-hyphens:manual;hyphens:manual}

/* ---- the timeline arriving as you scroll ----
   Each entry rises as it reaches the viewport, a beat after the one above it,
   so a decade assembles itself rather than appearing whole. The same reveal
   machinery the rest of the site uses — data-rise-stagger on each decade's
   list — with one difference worth stating: the delay is capped further down
   the list than elsewhere, because a decade can hold five entries and a linear
   delay would leave the last arriving long after a reader has got to it.

   Movement is small and vertical only. A timeline is a vertical thing and
   anything sideways would fight the rail. */
.js-anim .tl[data-rise-stagger] > li{opacity:0;transform:translateY(14px);
  transition:opacity .5s ease, transform .5s cubic-bezier(.2,.7,.3,1)}
.js-anim .tl[data-rise-stagger].in > li{opacity:1;transform:none}

/* The square arrives after the words it belongs to, which reads as the entry
   being pinned to the rail rather than the two sliding in together. */
.js-anim .tl[data-rise-stagger] > li .ev::before{transform:translateX(-50%) scale(0);
  transition:transform .34s cubic-bezier(.2,.9,.3,1.4) .18s}
.js-anim .tl[data-rise-stagger].in > li .ev::before{transform:translateX(-50%) scale(1)}

@media(prefers-reduced-motion:reduce){
  .js-anim .tl[data-rise-stagger] > li,
  .js-anim .tl[data-rise-stagger] > li .ev::before{
    opacity:1;transform:none;transition:none}
  .js-anim .tl[data-rise-stagger] > li .ev::before{transform:translateX(-50%)}
}

/* ==========================================================================
   TOUCH
   ==========================================================================
   Everything here answers one of two questions a phone asks that a mouse never
   does.

   HOW BIG IS A FINGER?
   About 9mm across, which on a phone screen is roughly 44px. Anything smaller
   than that is a target you have to aim at, and aiming is what makes a site feel
   fiddly. Note that the target does not have to LOOK 44px — padding is invisible
   — so nothing below gets visually heavier, it just gets easier to hit.

   WHAT IF IT CANNOT HOVER?
   A finger has no hover state, so anything a mouse reveals by hovering is simply
   invisible on a phone. Every such thing needs either a touch equivalent or an
   honest admission that it is decoration and can go.

   Keyed on (hover:none) rather than a width, because both questions are about
   the thing doing the pointing, not the size of the screen it is pointing at. A
   tablet is wide and still has fingers. A small window on a laptop is narrow and
   still has a mouse.                                                          */
@media(hover:none){

  /* ---- the roster ----
     The cue that says a player can be opened slides up on hover, so on a phone
     it never appeared at all and twenty-nine portraits looked like twenty-nine
     photographs. It now sits where it lands, permanently, on every card that
     leads somewhere — which is also the only visible difference between a player
     with a biography and one without. */
  .player-cue{transform:translateY(0)}
  /* Hover underlines the name to reinforce the same message; with the cue always
     showing, the name would be permanently underlined for no reason. */
  .player-open:hover b{text-decoration:none}

  /* ---- targets ----
     The jump links are the worst of them: 12px type in 9px of padding is a 32px
     row, and there are eleven of them side by side. */
  .roster-jump a{min-height:44px;display:flex;align-items:center}
  .tl-toggle,.rt-clear,.txtlink,.nb-link,.reel-body .more{min-height:44px;
    display:inline-flex;align-items:center}
  /* The decade and section headings are already full-width rows; this only makes
     sure a short one is still a comfortable height. */
  .era-toggle,.sec-toggle{min-height:48px}
  /* The dots under the quotes are 9px of ink each. The ink stays at 9px — they
     are markers, and a bigger dot would read as a button — but each now sits in
     the middle of a 44px square that can actually be pressed. */
  .quote-dots{gap:0}
  .quote-dots button{width:44px;height:44px;margin:0;background:none;
    display:grid;place-items:center}
  .quote-dots button::before{content:'';width:9px;height:9px;background:var(--line)}
  .quote-dots button[aria-current=true]::before{background:var(--ink)}
  .quote-dots button:hover{background:none}
  /* The record's filter checkbox: the input is 18px, the label beside it is the
     rest of the target, so the row is what has to be tall enough. */
  .rt-check{min-height:44px}
  .rec-table td,.rec-table th{padding-top:14px;padding-bottom:14px}

  /* ---- the biography panel's own scrollbar ----
     A 4px track is a mouse target, not a thumb one. It stays visible, because
     with the native bar hidden there would otherwise be nothing at all to say
     the biography carries on below the fold — but it widens to something that
     can actually be caught hold of, and moves further from the words so a
     scrolling finger does not land on it by accident.

     Dragging it is not the point. Scrolling the panel with a finger already
     works and always did; this is a signpost that happens to be draggable. */
  .bio-text .bio-bar{width:8px;right:8px}
  .bio-text .bio-thumb{left:-3px;right:-3px}

  /* ---- the highlight on a press ----
     Left alone, a tap flashes a translucent grey-blue box over the element —
     an Android default that belongs to no brand and least of all to this one.
     Scarlet at a tenth, so a press is acknowledged in the band's own colour. */
  a,button,[role=button],summary,label{-webkit-tap-highlight-color:rgba(190,29,46,.10)}

  /* Stops a double tap zooming instead of pressing, which on a page of small
     links is the difference between a site that responds and one that argues. */
  a,button,[role=button],input,select,textarea,summary{touch-action:manipulation}
}

/* Held at 100 so a phone turned sideways does not inflate the type to fill the
   wider screen — Safari does this by default, and it silently undoes every
   measurement on the page. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}

/* ==========================================================================
   THE BOX OFFICE
   ==========================================================================
   Written for a phone first and widened afterwards, which is the opposite way
   round from the rest of this stylesheet — and deliberately. Somebody browsing
   the band's history is at a desk with a cup of tea. Somebody buying a ticket
   is on a phone, on a train, having seen a post about a concert, and will give
   up if it is fiddly. So the phone layout is the design and the desk is the
   variation.

   Everything below inherits the site's own type, colour and spacing. Nothing
   here is a second design system for a corner of the site; a ticket page that
   looks like a different website is a ticket page people abandon, because the
   moment a payment stops looking like the thing you clicked from is the moment
   you wonder whether it is real.                                             */

/* ---- choosing how many ---- */
.tk-row{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 0;border-bottom:1px solid var(--line)}
.tk-row:first-child{border-top:1px solid var(--line)}
.tk-row b{display:block;font-weight:700;font-size:16px}
.tk-row span{display:block;font-size:13.5px;color:var(--mute);margin-top:2px}

/* The stepper. The number field stays, and stays typeable, for anyone who would
   rather — but on a phone changing a 1 to a 2 by hand means summoning a
   keyboard to press one key, and these are 44px targets that do not. */
.tk-count{display:flex;align-items:center;gap:0;flex:0 0 auto}
.tk-step{width:44px;height:44px;padding:0;font:inherit;font-size:20px;
  line-height:1;background:var(--tint);color:var(--ink);
  border:1px solid var(--line);cursor:pointer;transition:.15s}
.tk-step:hover{background:var(--ink);border-color:var(--ink);color:#fff}
.tk-count input{width:56px;height:44px;text-align:center;font:inherit;
  font-weight:700;font-size:17px;border:1px solid var(--line);border-left:0;
  border-right:0;border-radius:0;background:#fff;color:var(--ink);
  -moz-appearance:textfield}
/* The browser's own up/down arrows are about 12px tall and sit on top of each
   other. They are worse than useless beside a 44px button that does the job. */
.tk-count input::-webkit-outer-spin-button,
.tk-count input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.tk-count input:focus{border-color:var(--ink);outline:3px solid var(--scarlet);
  outline-offset:1px}

/* ---- what it comes to ---- */
.tk-summary{background:var(--tint);border:1px solid var(--line);padding:24px 26px}
.tk-summary h3{font-size:14px;font-weight:900;letter-spacing:.16em;
  text-transform:uppercase;margin:0 0 14px}
.tk-lines{list-style:none;margin:0;padding:0}
.tk-lines li{display:flex;justify-content:space-between;gap:14px;
  padding:7px 0;font-size:15px}
.tk-total{display:flex;justify-content:space-between;align-items:baseline;
  margin:12px 0 0;padding-top:12px;border-top:2px solid var(--ink);
  font-weight:700}
.tk-total b{font-size:24px;font-weight:900}

/* The reminder on the checkout page of what is being bought. Quiet: the clock
   beside it is the thing that needs the attention. */
.tk-sum-title{font-size:19px;font-weight:900;line-height:1.2;margin:0 0 6px;
  text-transform:uppercase;letter-spacing:.01em}
.tk-sum-when{margin:0;font-size:14px;font-weight:700}
.tk-sum-where{margin:2px 0 0;font-size:14px;color:var(--mute)}

.tk-left{display:inline-block;font-weight:700;font-size:12px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--royal);margin:0 0 10px}
.tk-left.gone{color:var(--mute)}

/* ---- the clock on the checkout ----
   Prominent because it is the only thing on that page that is running out, and
   a hold that expires while somebody is looking for their card, with no warning
   they were on the clock, is the single most annoying thing a box office can
   do. */
/* THE CLOCK IS A PANEL, NOT A STRIP. It carries the crest now (see the note in
   tickets.js on why the class is rewritten every second), and a watermark
   anchored to the foot of an 86px box shows as a faint arc at the left edge
   rather than as the band's crest — there is not enough height for the shape to
   become a shape. Given the room, it reads as what it is.

   It is also the thing on this page somebody looks at longest, and it was the
   smallest block on it. */
.tk-clock{background:var(--ink);color:#fff;padding:30px 30px 32px;
  margin-bottom:24px}
.tk-clock b{display:block;font-size:30px;font-weight:900;line-height:1;
  font-variant-numeric:tabular-nums}
.tk-clock span{display:block;font-size:13.5px;color:rgba(255,255,255,.72);
  margin-top:6px}
.tk-clock.soon{background:var(--scarlet)}
.tk-clock.gone{background:var(--mute)}

/* ---- test mode ----
   Loud on purpose. This appears only while there is no way to take a real
   payment, and the one thing that must never happen is somebody believing they
   have paid when nothing was taken. */
.tk-test{border:3px dashed var(--gold);background:#FFFBF0;padding:22px 24px}
.tk-test b{display:block;font-weight:900;font-size:15px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--royal);margin-bottom:8px}

/* ---- the ticket ---- */
.tk-head{margin-bottom:26px}
.tk-head h1{font-size:clamp(26px,5vw,36px);line-height:1.1;margin:0 0 8px}
/* The heading that stands in while the tickets load. Sized like the real one so
   nothing jumps when it is replaced. */
.tk-loading{font-size:clamp(26px,5vw,36px);line-height:1.1;margin:0 0 8px;
  color:var(--mute)}
.tk-when{font-weight:700;font-size:17px;margin:0 0 2px}

.tk-pass{border:2px solid var(--ink);background:#fff;padding:22px;
  margin-bottom:20px;text-align:center}
.tk-qr{display:flex;justify-content:center;margin-bottom:14px}
.tk-qr svg{width:min(260px,70vw);height:auto;display:block}
.tk-pass-foot b{display:block;font-weight:900;font-size:13px;letter-spacing:.12em;
  text-transform:uppercase}
/* The typed fallback, deliberately big and spaced: it gets read off a screen in
   the dark by somebody who has already given up on the camera. */
.tk-short{display:block;font-weight:900;font-size:26px;letter-spacing:.22em;
  text-indent:.22em;margin:8px 0 4px;font-variant-numeric:tabular-nums}
.tk-used{display:block;font-weight:700;font-size:13px;color:var(--royal)}
.tk-pass.used{border-color:var(--line);background:var(--tint);opacity:.72}

.tk-terms{font-size:12.5px;color:var(--mute);margin-top:26px;
  padding-top:16px;border-top:1px solid var(--line)}
.tk-legal{font-size:11.5px;color:var(--mute)}

.tk-done h2{font-size:22px;margin:0 0 6px;text-transform:inherit;letter-spacing:inherit}

/* ---- the door scanner ----
   The verdict is enormous because it is read at arm's length, in the dark, by
   somebody with a queue in front of them. Colour alone never carries it: every
   state also says what it is in words, for anyone who cannot tell scarlet from
   green and for the far more common case of a phone screen washed out by a
   floodlight. */
.scan-verdict{padding:22px 24px;margin-bottom:18px;background:var(--tint);
  border:2px solid var(--line);text-align:center}
.scan-verdict b{display:block;font-size:clamp(26px,7vw,40px);font-weight:900;
  letter-spacing:.06em;line-height:1.1}
.scan-verdict span{display:block;font-size:14px;margin-top:6px}
.scan-verdict.admit{background:#0B6B3A;border-color:#0B6B3A;color:#fff}
.scan-verdict.again{background:var(--gold);border-color:var(--gold);color:var(--ink)}
.scan-verdict.unpaid,
.scan-verdict.unknown,
.scan-verdict.err{background:var(--scarlet);border-color:var(--scarlet);color:#fff}

.scan-cam{background:var(--ink);margin-bottom:18px;aspect-ratio:4/3;
  display:grid;place-items:center;overflow:hidden}
.scan-cam video{width:100%;height:100%;object-fit:cover;display:block}
.scan-cam .ev-note{color:rgba(255,255,255,.8);padding:20px}

.form-err{background:#FFF4F4;border-left:4px solid var(--scarlet);
  padding:14px 16px;margin:14px 0;font-size:15px;color:var(--ink)}

.wrap-narrow{max-width:620px}

/* ---- on a wider screen ---- */
@media(min-width:820px){
  .tk-summary{position:sticky;top:calc(var(--hdr-h) + 24px)}
}
@media(max-width:560px){
  /* The summary belongs above the form on a phone: it is what they came to
     check, and below the form it is under the fold behind a keyboard. */
  .tk-row{padding:14px 0}
  .tk-summary{padding:20px}
  .tk-pass{padding:18px 14px}
}

/* ==========================================================================
   THE ADMIN
   ==========================================================================
   Used by volunteers who did not ask to be webmasters, often on a phone, often
   months apart. So it is built round three things.

   NOTHING LOOKS TECHNICAL. It uses the site's own type and colour, so it feels
   like the website rather than like software. No monospace, no grey panels of
   settings, nothing labelled "record" or "field".

   THE LIST IS SCANNABLE AND THE FORMS ARE SHUT. Twenty-nine players all open at
   once is a page nobody can find anything in. Shut, it is a list you read.

   IT WORKS WITH A THUMB. Every row is a target, the save button is always
   reachable, and nothing depends on hovering.                                */

/* The admin's heading block now sits inside .page-head — the same ink banner
   What's On, Listen and History open with, which brings the crest watermark and
   the gold edge with it. This only lays the two halves out; everything that
   makes it look the way it does comes from that rule. */
.ad-head-in{display:flex;flex-wrap:wrap;align-items:flex-end;
  justify-content:space-between;gap:20px}
.ad-head-in h1{margin-bottom:6px}

/* The right-hand column of the banner: who you are, and the one action this
   screen has. Stacked, right-aligned, and level with the heading rather than
   under a rule at the foot of the band. */
/* THE TWO BLOCKS ARE ONE BLOCK. Right-aligned but self-sized, the account row
   and the save button were two different widths stacked at an angle to each
   other, which is what "unbalanced" looks like when you cannot name it: the
   column has no edge on the left, only a ragged one. Stretching both to the
   width of the wider of them gives the stack two straight sides, and the
   button — the thing this screen is FOR — becomes the largest object in the
   corner rather than a smaller shape hanging off the row above it. */
.ad-head-side{display:flex;flex-direction:column;align-items:stretch;gap:12px;
  width:max-content;margin-left:auto}
.ad-save{text-align:right}
.ad-head-side .ad-save .btn{width:100%}
.ad-save .hint{margin:8px 0 0;max-width:280px}

/* ---- whose account this is ----
   BESIDE THE HEADING, WITH THE SAVE BUTTON, on every screen but the front page.
   It was a row of its own across the foot of the banner with a rule above it,
   which put a line across a black band for no reason anybody could name and
   left the two things a person reaches for — who am I, and save — a hand's
   width apart. They are one column now, right-hand side, level with the words
   they belong to.

   THE ADDRESS IS SHOWN RATHER THAN HIDDEN BEHIND A HOVER. It is one line, it
   fits, and the account IS the address on this site — a card that appears on
   hover is a card nobody on a phone can open. */
.ad-you{display:flex;align-items:center;justify-content:flex-end;
  gap:12px;margin:0;text-align:left}
.ad-you-text{display:flex;flex-direction:column;min-width:0;gap:1px}
.ad-you-text b{font-weight:700;font-size:14px;line-height:1.25}
.ad-you-text span{font-size:12.5px;line-height:1.3;color:rgba(255,255,255,.72);
  overflow-wrap:anywhere}
/* Gold on ink, like every other accent on a dark surface here — 11.50:1, and
   11.50:1 the other way round when it fills on hover. */
.ad-you-out{font:inherit;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;min-height:44px;padding:0 13px;cursor:pointer;
  background:none;border:1px solid rgba(255,255,255,.4);color:var(--gold);
  transition:.15s}
.ad-you-out:hover{background:var(--gold);border-color:var(--gold);color:var(--ink)}
.ad-you-out:focus-visible{outline:3px solid var(--gold);outline-offset:3px}

@media(max-width:820px){
  /* Flush left with the heading above it, once there is no right-hand column
     for it to line up under. */
  .ad-head-side{align-items:flex-start;width:100%}
  .ad-you{justify-content:flex-start}
}

/* ---- THE GOLD BAR DRAWS ITSELF HERE TOO ----
   The one animation this site is recognisable by: the gold rule under a heading
   grows from the left after the words have landed. Every public page does it as
   the section scrolls in; the admin did not do it at all, so moving from the
   site to the admin was a small change of world.

   The same movement and the same timing as the public pages — 0.75s on the same
   curve, after a 0.38s beat — copied deliberately rather than approximated, so
   the two halves look like one thing.

   AN ANIMATION RATHER THAN A TRANSITION, because the admin does not scroll its
   headings into view: it replaces them. A heading drawn into the page runs this
   once as it arrives, and the banner's heading — which is rewritten in place on
   every screen — is made to run it again by taking the class off and putting it
   back. scaleX, not width: a transform does not touch layout, so nothing round
   it reflows while it grows. */
.ad-rule-draw::after{animation:ad-rule-draw .75s cubic-bezier(.22,.61,.36,1) .38s both}
@keyframes ad-rule-draw{from{transform:scaleX(0)}}
.ad-rule-draw::after{transform-origin:left}

@media(prefers-reduced-motion:reduce){
  .ad-rule-draw::after{animation:none}
}

/* ---- moving between the admin's screens ----
   They are not pages — one element is emptied and refilled — so without this a
   press changes everything on screen in the same frame, which reads as a jolt
   rather than as having gone somewhere.

   Sideways, and the direction means something: deeper in from the right, back
   out from the left, the way every phone moves between a list and the thing on
   it. It matches how the front page is arranged, which is the one arrangement
   everybody can already read.

   .2s is short. This is on the path between somebody and the correction they
   came to make, possibly at ten to eight on a concert night, and a transition
   that has to be waited for is worse than none. Fading only the opacity would
   be safer still, but it says nothing about which way you went.

   Nothing on the way out — the old screen is gone the instant the new HTML is
   written, and keeping it to animate would mean holding two copies of a form
   in the page with the same ids in both.

   NAMED ad-slide-*, NOT ad-fwd/ad-back. .ad-back is already the "← ADMIN"
   button, and putting that class on #adminBody dressed the whole screen as one
   — small capitals, letter-spacing, and the button's own ← turning up in front
   of the page. Nothing in the file doing it looked wrong.

   SWITCHED OFF FOR REDUCED MOTION, NOT ON FOR NO-PREFERENCE. This was written
   the other way round — inside @media(prefers-reduced-motion:no-preference) —
   which is the only place in this file that asks the question that way, against
   thirteen that turn things off under `reduce`. It also fails in the wrong
   direction: anything that does not answer the question gets no animation at
   all, where the whole rest of the site would animate and then be told to stop.
   Written like everything else, it works unless somebody has asked it not to. */
/* ONE VOCABULARY, NOT FOUR EFFECTS. Everything that moves in the admin uses the
   same easing and one of two durations, so the whole thing reads as one piece
   of software rather than as four people's ideas. --ad-ease overshoots very
   slightly at the end, which is what stops a movement feeling mechanical.

   Depth is carried by scale and a little blur rather than by distance alone: a
   screen arriving comes from very slightly too small and slightly out of
   focus, the way something does when it is settling into place. Going back it
   arrives from slightly too large, as though stepping out of the thing just
   left. That is the difference between "the content changed" and "I went
   somewhere".

   THE BLUR IS 3px AND LASTS 0.2s. Blurring a whole screen is the most
   expensive thing here, and on a slow laptop an over-generous one turns a
   transition into a stutter. Three pixels is enough to read as focus pulling
   in and cheap enough not to be noticed as work. */
.ad-work{--ad-ease:cubic-bezier(.22,.9,.28,1.06);--ad-quick:.18s;--ad-calm:.26s}

/* IT GROWS FROM WHAT WAS PRESSED. transform-origin defaults to the middle of
   the element, and #adminBody is as tall as the page — so the pivot sat a long
   way down and the zoom looked like it came from the bottom left. admin.js
   measures the pressed tile and writes --from-x and --from-y here.

   The fallback is top centre, not the middle: with nothing to measure — the
   browser's Back button, a reload — a page should start from where its first
   line is, which is the top. */
#adminBody.ad-slide-fwd,#adminBody.ad-slide-back{
  transform-origin:var(--from-x,50%) var(--from-y,0px)}

/* Going in, the scale does the work: the screen opens out of the tile, and the
   sideways nudge that used to say "forward" would now fight the origin.
   Coming back there is nothing to grow from — you are returning to a page, not
   opening a thing — so that one keeps the drift from the left. */
#adminBody.ad-slide-fwd {animation:ad-slide-fwd  var(--ad-calm,.26s) var(--ad-ease) backwards}
#adminBody.ad-slide-back{animation:ad-slide-back var(--ad-calm,.26s) var(--ad-ease) backwards}
@keyframes ad-slide-fwd {
  from{opacity:0;transform:scale(.94);filter:blur(3px)}
}
@keyframes ad-slide-back{
  from{opacity:0;transform:translateX(-14px) scale(1.02);filter:blur(3px)}
}

/* Whatever stands above the tiles — the strip of figures and the jobs list on
   the front page, the back button and the sentence on a hub — moves with them
   rather than being there already. It was the fixed point everything else
   arrived around, which is what made the tiles feel late rather than staggered. */
.ad-status,.ad-todo,.ad-intro{
  animation:ad-pop var(--ad-calm,.26s) var(--ad-ease) backwards}

/* ---- the tiles arrive in the order they are read ----
   They used to appear in one frame, all nine at once, which is a lot of
   identical squares landing simultaneously. Forty-five milliseconds apart they
   assemble instead, top row before bottom — the stagger says the reading order
   out loud without anybody having to be told it.

   --in is written onto each tile by admin.js as it counts them out, because the
   number of tiles depends on what the person is ticked for. Nine fixed classes
   would be nine chances to be wrong. */
/* BACKWARDS, NOT BOTH — this one matters. A filled animation keeps its final
   value in force for the properties it animates, and it outranks ordinary
   declarations: with `both`, every tile would hold transform:none afterwards
   and .ad-tile:hover{transform:translateY(-3px)} would silently stop lifting.
   `backwards` applies the opening frame during the stagger delay, which is what
   keeps a tile invisible until its turn, and then gets out of the way. */
.ad-tile{animation:ad-pop var(--ad-calm,.26s) var(--ad-ease) backwards;
  animation-delay:var(--in,0ms)}
@keyframes ad-pop{
  from{opacity:0;transform:translateY(10px) scale(.965);filter:blur(2px)}
}

/* ---- a row opening ----
   Nothing had to change in the JavaScript for this: the fold sets and clears
   the hidden attribute, and :not([hidden]) matches the moment it is cleared.
   So the opening animates and the closing stays instant, which is the right
   way round — you watch something open, you do not watch it shut. */
.ad-entry .ad-body:not([hidden]){
  animation:ad-unfold var(--ad-quick,.18s) var(--ad-ease) backwards}
@keyframes ad-unfold{
  from{opacity:0;transform:translateY(-6px) scale(.995);filter:blur(2px)}
}

/* ---- the save says so ----
   A gold sweep straight across the button, once. The most important press in
   the admin used to change a word and move nothing. */
#adSave{position:relative;overflow:hidden}
#adSave.ad-swept::after{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,transparent 20%,var(--gold) 50%,transparent 80%);
  transform:translateX(-100%);
  animation:ad-sweep .6s var(--ad-ease) both}
@keyframes ad-sweep{ to{transform:translateX(100%)} }

/* And the sentence underneath arrives rather than appearing. */
.ad-note:not([hidden]){
  animation:ad-unfold var(--ad-quick,.18s) var(--ad-ease) backwards}

@media(prefers-reduced-motion:reduce){
  #adminBody.ad-slide-fwd,#adminBody.ad-slide-back,
  .ad-tile,.ad-status,.ad-todo,.ad-intro,
  .ad-entry .ad-body:not([hidden]),.ad-note:not([hidden]),
  #adSave.ad-swept::after{animation:none}
}

/* The sign-out tile. Same shape as its neighbours — it is a way out, not an
   alarm — but marked differently so it does not read as one more place to go.
   A different-coloured tile among navigation would look like a warning; a
   different MARK reads as "this one is not like the others".

   GOLD, NOT SCARLET, BECAUSE THE PLATE IS INK. The foot tiles carry
   .ad-tile.away, whose plate is ink. Scarlet on ink measures 3.07:1 — the bare
   floor for a graphic, and it looks like the floor: a dark red shape on a
   near-black square. Gold on ink is 11.50:1, and gold is the accent this site
   already uses on ink everywhere else — the kicker, the bar under every
   heading, the rule on the welcome.

   Scarlet leads on white. On ink it is gold. */
.ad-tile[data-key="signout"] .ad-plate{color:var(--gold)}

/* HOVER GOES SCARLET, LIKE ITS NEIGHBOURS, and the mark stays white.

   It inverted to a gold plate with an ink mark, which measures 11.50:1 and is
   perfectly legible — but it turned the mark black at the moment of pressing,
   which reads as the icon changing rather than the tile lighting up.

   Keeping the plate gold and making the mark white is not the fix: white on
   gold is 1.64:1, which is no mark at all. So the plate changes instead, to the
   same scarlet the other away tiles use, where white sits at 6.17:1.

   Gold at rest is what marks this tile out. The hover is only feedback, and
   feedback that matches everything else is one less thing to explain. */
.ad-tile[data-key="signout"]:hover .ad-plate,
.ad-tile[data-key="signout"]:focus-visible .ad-plate{
  background:var(--scarlet);color:#fff}

/* The tick on the sign-in box. .ad-tick already gives it a 44px row; this only
   places it in the form and keeps the wording beside it rather than under. */
.ad-stay{margin-top:18px}
.ad-stay + .hint{margin-top:2px}

/* On ink, the muted grey the hints use everywhere else is barely there. */
.page-head .hint{color:rgba(255,255,255,.7)}

/* The banner is flush with the header, and the work below it starts where a
   section normally would. */
.ad-work{padding-top:34px;padding-bottom:64px}

/* The save button follows you down the page. On a phone the sections are long
   and the button would otherwise be a scroll away from wherever you were
   typing — which is how somebody edits four things and saves none of them. */
@media(max-width:820px){
  .ad-top{display:block}
  .ad-save{position:sticky;bottom:0;z-index:20;text-align:left;
    background:#fff;border-top:2px solid var(--ink);
    margin:0 -24px;padding:12px 24px calc(12px + env(safe-area-inset-bottom));
    display:flex;align-items:center;gap:14px}
  .ad-save .btn{flex:0 0 auto}
  .ad-save .hint{margin:0;max-width:none;font-size:12.5px}
}

/* ---- the sections across the top ----
   A scrolling row rather than a stack, so the page does not open with a
   screenful of navigation before any content. */
/* THE STRIP WRAPS. IT DOES NOT SCROLL.
   It used to scroll sideways with a fade at the right-hand edge, on the
   reasoning that a tab sliced in half reads as a broken page while a tab fading
   out reads as "there is more this way". The fade is honest about that. It is
   not honest about how much: at 1280px the strip is 1,415px of tabs in 1,132px
   of room, so Music Player, Albums and Homepage banner are all off the end
   behind a 34px smudge, and nothing on the screen says they exist. Sideways
   scrolling inside a page is also the one gesture a trackpad, a mouse wheel and
   a keyboard are each bad at in a different way — and this is the control for
   moving around the whole admin.

   Wrapped, every section is on the screen at once, at every width, and the
   order the eye reads is the order the Tab key goes. It costs a second row.

   The row gap is larger than the gap along a row, because two chips side by
   side are one list and two chips above each other are two rows of it — equal
   gaps in both directions read as a block of tiles rather than as a strip that
   has wrapped. */
.ad-tabs{display:flex;flex-wrap:wrap;gap:10px 6px;padding-bottom:14px;
  margin-bottom:24px;border-bottom:2px solid var(--ink)}
.ad-tab{flex:0 0 auto;font:inherit;font-weight:700;font-size:12.5px;
  letter-spacing:.09em;text-indent:.09em;text-transform:uppercase;
  min-height:44px;padding:0 16px;cursor:pointer;
  background:var(--tint);color:var(--ink);border:1px solid var(--line);
  transition:.15s}
.ad-tab:hover{background:var(--ink);border-color:var(--ink);color:#fff}
.ad-tab.on{background:var(--scarlet);border-color:var(--scarlet);color:#fff}

/* Home is the way back, not a tenth section, so it is drawn as one: a gold
   edge that reads as a marker rather than another equal choice, and it keeps
   that edge when it is the tab you are on. */
.ad-tab-home{border-left:4px solid var(--gold)}

/* The phone's version of the same strip — see the note on it in index.html.
   Hidden across a desk, where the chips are better; the only control below
   700px, where they are not. The browser's own select, deliberately: on a
   phone it opens as a full-screen list the operating system draws, which is
   the most legible menu available on that screen and the one the person
   already knows how to use. */
.ad-jump{display:none;align-items:center;gap:12px;
  padding-bottom:14px;margin-bottom:24px;border-bottom:2px solid var(--ink)}
.ad-jump label{font-weight:900;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute);flex:0 0 auto}
/* Only how wide it is. What a menu is made of — the weight, the box, the
   band's own chevron and the room that chevron needs — is the one `select`
   rule near the top of this file, and a padding or a background written here
   would take the arrow off with it. */
.ad-jump select{flex:1 1 auto;min-width:0}
@media(max-width:700px){
  .ad-tabs{display:none}
  .ad-jump{display:flex}
}

.ad-intro{margin-bottom:26px}

/* The lede on a section page runs the width of the column, because everything
   under it does: the count, the find box, the add button and every row in the
   list all reach the right-hand edge. Held at 62ch it stopped a couple of
   hundred pixels short of all of them and read as a mistake rather than a
   measure — the eye takes the list's edge as the page's edge and the text
   looks broken off. At the widths this page is used at that is around 75
   characters, which is inside the limit prose pages are set at and well past
   the 45 justification needs. */
.ad-intro .lede{max-width:none;margin-top:14px}
/* EXCEPT THE ONE DIRECTLY UNDER THE HEADING, which is a paragraph somebody
   reads rather than a caption they glance at. Told it could have the whole
   window it took it — seventeen words across 1200px on the ticketing screen,
   which is a line nobody tracks back from. The hub screens already hold theirs
   to 56ch and this is the same sentence doing the same job. */
.ad-intro > .lede{max-width:56ch}

/* ---- the tiles ----
   The first screen is two choices, so they are large: half the width each, and
   a plate big enough to be the thing you aim at rather than a decoration beside
   the words. Inside a choice the tiles are smaller but still substantial — nine
   across one row made each one narrow, small-marked and surrounded by white
   space, which is the arrangement the screenshot showed and the reason for
   this. Three across, three rows down, fills the same space with bigger things. */
/* --gap is declared rather than typed twice: the sign-out's offset below is
   worked out from the column width, and a gap changed in one place and not the
   other would put it a few pixels out — which is exactly the fault it is there
   to fix. */
.ad-home{--gap:14px;--pad:20px;
  display:grid;gap:var(--gap);grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.ad-home-top{grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px}
/* ONE THING TO DO IS DRAWN AS ONE THING. Somebody ticked only for ticketing had
   a half-width tile and a screen's worth of white beside it, which reads as a
   page that failed to finish loading rather than as a page with one job on it.
   Laid out along its own length instead: the mark at the left, the words beside
   it, the way the wide tiles at the foot already are. */
.ad-home-top.one{grid-template-columns:1fr}
.ad-home-top.one .ad-tile{flex-direction:row;align-items:center;text-align:left;
  flex-wrap:wrap;gap:6px 24px;padding:24px 26px}
/* .ad-tile.big is named in these because it is declared LATER in this file and
   would otherwise tie on specificity and win — the plate stayed 104px and the
   bar stayed 178px tall with sixty of them empty. */
.ad-home-top.one .ad-tile.big .ad-plate{width:76px;height:76px;margin:0}
.ad-home-top.one .ad-tile.big .ad-icon{width:38px;height:38px}
/* The name and the line under it sit side by side along the bar rather than
   stacked in the middle of it: stacked, the tile was 180px tall with 60 of them
   empty. */
.ad-home-top.one .ad-tile.big .ad-tile-name{font-size:21px}
.ad-home-top.one .ad-tile.big .ad-tile-sub{margin:0;font-size:14.5px;max-width:none}
/* THE THREE THAT ARE NOT EDITING, IN A ROW, with the way out on the row below.
   Stacked full-width they each centred their own contents, so the three marks
   sat at three different distances from the left — the eye reads that as
   crooked before it reads any of the words.

   auto-fit rather than a fixed three, because People is only there for somebody
   ticked for it. With two the row is two, evenly; with a fixed three it would
   be two and a gap.

   Where the way out goes is set further down, next to how it is drawn. */
.ad-home-foot{margin-top:16px;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
@media(min-width:820px){
  /* Nine tiles want three rows of three, not one row of nine. auto-fit would
     give five and four, which reads as an accident. */
  .ad-home{grid-template-columns:repeat(3,1fr)}
  .ad-home-top{grid-template-columns:repeat(2,1fr)}
  /* THREE IS THREE ACROSS. Website, Social and Ticketing — the account with
     both ticks — was two tiles and a straggler on its own row, which is the
     one arrangement this row must never make. */
  .ad-home-top.three{grid-template-columns:repeat(3,1fr)}
  /* AND THE FOOT ROW KEEPS ITS OWN COUNT, said again here because the line
     above would otherwise take it: .ad-home-foot is a .ad-home, this rule comes
     later in the file, and three fixed columns is right for nine section tiles
     and wrong for the two or three things at the foot. An account without the
     people tick has two of them, and in a row built for three that is two tiles
     and a hole — which is exactly how it looked. */
  .ad-home-foot{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
}

.ad-tile{display:flex;flex-direction:column;align-items:center;text-align:center;
  padding:30px 16px 26px;background:var(--tint);color:var(--ink);
  border:1px solid var(--line);font:inherit;cursor:pointer;text-decoration:none;
  transition:.15s}
.ad-tile:hover,.ad-tile:focus-visible{background:#fff;border-color:var(--ink);
  transform:translateY(-3px)}

/* The plate is the app icon: one flat shade, the mark knocked out of it in
   white, corners rounded enough to read as a tile without becoming a pill.
   Scarlet leads. */
/* SQUARE. Every corner on this site is square on purpose — the stylesheet
   writes border-radius:0 in a dozen places purely to overrule the browser's own
   ideas. The crest has no rounded corner in it, and neither should anything
   standing next to it. A rounded plate is the single detail that would have
   made the admin look like a different product bolted on. */
.ad-plate{position:relative;display:grid;place-items:center;width:76px;height:76px;
  margin-bottom:18px;border-radius:0;background:var(--scarlet);color:#fff;
  transition:.15s}
/* THE BADGE, on the corner of the plate the way a phone puts it: how many of
   the front page's jobs are in this section. Ink on white, edged in the tile's
   own tint so it stands off the plate whatever colour the plate is — scarlet,
   the gold of unsaved, the royal of a hover. Square, like everything else. */
.ad-tile-jobs{position:absolute;top:-9px;right:-9px;min-width:24px;height:24px;
  padding:0 5px;display:grid;place-items:center;box-sizing:border-box;
  background:var(--ink);color:#fff;border:2px solid var(--tint);
  font-size:12px;font-weight:900;line-height:1;letter-spacing:0}
.ad-tile:hover .ad-tile-jobs,.ad-tile:focus-visible .ad-tile-jobs{border-color:#fff}
.ad-icon{width:38px;height:38px;flex:0 0 auto}
.ad-tile:hover .ad-plate,.ad-tile:focus-visible .ad-plate{background:var(--royal)}

.ad-tile-name{font-weight:700;font-size:17px;line-height:1.25}
.ad-tile-sub{margin-top:7px;font-size:13px;line-height:1.4;color:var(--mute);
  max-width:26ch;text-wrap:balance}

/* The two on the first screen. Bigger again, because there are only two of them
   and the screen is otherwise empty — a large target is easier to hit on a
   phone and easier to believe on a laptop. */
.ad-tile.big{padding:46px 24px 40px}
.ad-tile.big .ad-plate{width:104px;height:104px;border-radius:0;
  margin-bottom:24px}
.ad-tile.big .ad-icon{width:52px;height:52px}
.ad-tile.big .ad-tile-name{font-size:24px;letter-spacing:-.01em}
.ad-tile.big .ad-tile-sub{font-size:14.5px}

/* Unsaved work, said in gold where you would go looking for it rather than only
   in the line beside the save button. Ink on gold, because white on gold is not
   readable and never has been. */
.ad-tile.unsaved .ad-plate{background:var(--gold);color:var(--ink)}
.ad-tile.unsaved .ad-tile-sub{color:var(--scarlet);font-weight:700}

/* Things that are not a list you change and save: the scanner, the box office,
   the live site. The plate says so before the words do. */
.ad-tile.away .ad-plate{background:var(--ink)}
.ad-tile.away:hover .ad-plate{background:var(--scarlet)}

/* THE LAST ROW HAS NO INK ON IT. The three tiles above it are the admin — the
   people in it, the post, the log — and they are drawn in ink because they are
   the work. Under them sit the two that are not: going out to the public site,
   and going out altogether. The way out already carries somebody's face, which
   is a photograph and therefore in colour, so an ink plate beside it left that
   row looking like one black square and one person.

   Gold, and the same gold as the bar under the heading at the top of the
   screen — the page then opens and closes on the same colour. The mark inside
   it goes to ink, because a white line on gold is barely a line. */
.ad-tile.public .ad-plate{background:var(--gold);color:var(--ink)}
/* AND IT TURNS OVER RATHER THAN CHANGING COLOUR. The rest of this row goes
   scarlet under the pointer, which is the right answer for a black square:
   something has to happen to it and scarlet is what happens. This one is
   already the brightest thing on the screen, so making it brighter says
   nothing — the two colours it is made of simply swap places. Same pair, same
   tile, unmistakably touched. */
.ad-tile.public:hover .ad-plate,
.ad-tile.public:focus-visible .ad-plate{background:var(--ink);color:var(--gold)}

/* The live site is not something you administer, so it goes underneath and lies
   down rather than standing up beside the two that are. */
/* Left, not centred. Centred, every tile put its mark wherever its own words
   happened to end, so no two lined up. */
.ad-tile.wide{flex-direction:row;justify-content:flex-start;gap:18px;
  padding:18px 20px;text-align:left}
.ad-tile.wide .ad-plate{width:52px;height:52px;border-radius:0;margin:0}
.ad-tile.wide .ad-icon{width:26px;height:26px}
.ad-tile.wide .ad-tile-name{font-size:15px}
.ad-tile.wide .ad-tile-sub{margin:2px 0 0;font-size:13px}

/* THE FOOT ROW IS A SMALL GRID, NOT A ROW OF THREE THINGS.

   As a flex row the mark, the name and the description were three siblings
   competing for one line, and in a third of the width the name lost: "What
   changed" and "View the site" each broke across two lines while the
   description sat beside them, so the tile had two ragged columns of text and
   no obvious reading order.

   Two columns instead — the mark, then the words — with the name above its
   description in the second. The mark spans both rows so it stays centred
   against the pair however tall they are. Nothing has to fit on one line, so
   nothing breaks in an odd place.

   Written after .ad-tile.wide rather than before it: both selectors are two
   classes, so specificity ties and source order is what decides. */
.ad-home-foot .ad-tile{display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:16px;row-gap:1px;align-items:center;justify-content:start;
  text-align:left;padding:16px 20px}
.ad-home-foot .ad-plate{grid-row:1/3;align-self:center}
.ad-home-foot .ad-tile-name{grid-column:2;align-self:end;margin:0}
.ad-home-foot .ad-tile-sub{grid-column:2;align-self:start;margin:0;max-width:none}

/* THE BAR IS FULL WIDTH, THE CONTENTS LINE UP WITH THE MIDDLE COLUMN. Those are
   separate decisions, and it took getting each of them wrong on its own to see
   that.

   Full width says this is not a fourth place to go — it is the line under the
   three. But merely centring the contents inside it put the mark at a position
   nothing else on the page shares, a few pixels off the one above it, which
   reads as a near-miss rather than as a choice.

   So the contents are pushed to where the middle tile's contents start: one
   column, plus the gap, plus the padding every tile has. The mark then sits
   directly under the mark on What changed.

   THE OFFSET ASSUMES THREE ACROSS, so it is only applied at a width where the
   row really is three — 820px, where 3 x 230 + 2 gaps fits with room to spare.
   Narrower than that the row is two columns or one, and an offset of a third of
   the width would push the mark into the middle of nothing. There it simply
   starts at the left like every other tile.

   The one case it still gets wrong: an account with no people tick sees two
   tiles up there, and this lands to the right of the second. The arithmetic
   cannot know — the row is auto-fit, so how many columns there are is settled
   by the browser long after this stylesheet has had its say. */
/* ONE COLUMN, WHOEVER IS LOOKING. The way out used to be the last cell of the
   row above, spanning it — which forced that row to have as many columns as the
   widest account needs, so somebody with two tiles up there got two tiles and a
   hole. And its own words were pushed towards the middle by an arithmetic that
   assumed three columns and could not know: the row is auto-fit, and how many
   columns there are is settled by the browser long after this stylesheet has
   had its say.

   Its own row cannot be got wrong. The words start where every other tile's
   words start.

   IT SHARES THAT ROW WITH ONE THING: viewing the site. They are the two tiles
   that are not work — leaving for the public side, and leaving altogether — and
   the row above them is the admin itself, three of it. Both are drawn for
   everybody, whatever they are ticked for, so this pair is always a pair and
   the row is never one tile and a hole. auto-fit rather than a fixed two, so a
   narrow window stacks them instead of squeezing.

   Said once, unlike the foot row above, and the difference is worth knowing:
   .ad-home-foot is written BEFORE the rule that gives every .ad-home three
   columns on a wide screen, so it has to say its count again inside that query
   to win. This comes after it, so it wins by being later and needs no repeat.
   A second copy here would be a line that could only ever fall out of step. */
.ad-home-out{margin-top:var(--gap);
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}

/* Nothing between the back link and the tiles since the lede went, so the gap
   under it is the gap it was holding open for two lines of type that are no
   longer there. */
.ad-intro-hub{margin-bottom:6px}

/* TEN THINGS IN THREES LEFT ONE ON ITS OWN, with two tiles' worth of nothing
   beside it at the bottom of the page — the hole that made this screen read as
   empty however much was on it. Nine of them are lists somebody edits; the
   tenth only reports. So the nine make a square, and the odd one out runs the
   width underneath as a bar, which is both a tidier page and a truer one. */
.ad-home .ad-tile-span{grid-column:1/-1}

/* ---- the two hubs that are not nine equal things ---------------------------
   A grid that fits as many 190px columns as it can is right for nine lists
   that are all the same kind of thing. It is wrong for five tools of two
   different sizes: it put all five on one line, so the two large ones read as
   a mistake beside the three small, and at the width where it dropped to four
   columns the fifth stretched across a whole row on its own.

   Six columns instead, which both shapes divide into: the two you come here to
   use take three each and make the top line, the three smaller ones take two
   each and make the second. Nothing stretches and nothing is left over. */
/* SIX TILES: the two big ones on the first row, the four small ones in a
   line under them. Twelve columns rather than six because four small tiles
   over three columns was three and a straggler. */
.ad-home-social{grid-template-columns:repeat(12,1fr)}
.ad-home-social .ad-tile.big{grid-column:span 6}
.ad-home-social .ad-tile.away{grid-column:span 3}

/* Ticketing is two doors and, when there is a concert on sale, the guest list
   for it across the bottom. Two columns rather than auto-fit, so the doors stay
   a pair at every width instead of becoming a row of four small plates on a
   wide screen. */
.ad-home-ticketing{grid-template-columns:repeat(2,1fr)}

@media(max-width:860px){
  /* THREE, NOT TWO. Two columns leaves the third small tile alone on a row
     with a hole beside it — the same fault this rule exists to cure, moved to
     a narrower screen. Three puts the small ones in a line and gives each big
     one a row of its own, which is the right emphasis anyway. */
  .ad-home-social{grid-template-columns:repeat(2,1fr)}
  .ad-home-social .ad-tile.big{grid-column:span 2}
  .ad-home-social .ad-tile.away{grid-column:auto}
}
@media(max-width:620px){
  /* One thing at a time, and nothing spanning a column that is not there —
     span 3 in a single-column grid invents two more columns and most of the
     tile hangs off the screen. */
  .ad-home-social,.ad-home-ticketing{grid-template-columns:1fr}
  .ad-home-social .ad-tile.big{grid-column:auto}
}
.ad-intro-hub .lede{max-width:56ch}
/* NOT JUSTIFIED IN THE ADMIN. The site's ledes are set justified, which is
   right for a paragraph of running text on a page and wrong for two lines
   over a list — the review saw "What  the  diary  says" with a river down
   it. Ragged right, and the last line kept from being a single word. */
.ad-intro .lede{text-align:left;-webkit-hyphens:manual;hyphens:manual;text-wrap:pretty}

.ad-back{display:inline-flex;align-items:center;gap:7px;margin-bottom:14px;
  min-height:44px;padding:0 2px;background:none;border:0;cursor:pointer;
  font:inherit;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--mute)}
.ad-back::before{content:'←';font-size:15px}
.ad-back:hover{color:var(--scarlet)}
/* The three ticketing screens are separate pages, so their way back is a link
   rather than a button. Same mark, same words, no underline. */
a.ad-back{text-decoration:none}

@media(hover:none){
  /* Nothing lifts on a touch screen — the pointer that would have lifted it is
     a finger already covering it. */
  .ad-tile:hover{transform:none}
  .ad-tile:hover .ad-plate{background:var(--scarlet)}
  .ad-tile.away:hover .ad-plate{background:var(--ink)}
}

/* ---- the list ---- */
/* ---- the bar above a list ----
   How many there are, a box to find one in, and a way to add without scrolling
   to the foot of forty-four of them. */
/* ---- the strip across the top of the admin's front page ----
   What a person opening this actually wants to know before choosing anything:
   when it was last touched, what is coming, and whether anything needs doing.
   Without it the front page is a menu; with it, it is a desk. */
/* A RAIL, NOT FURNITURE. It was three tinted cells in a bordered grid with a
   second bordered bar beneath them, and together they took a hundred and fifty
   pixels above the two things this page is for — drawn heavily enough to be
   read first, when all four are things you glance at on the way past.

   Now they are four facts on one line: label, answer, hairline, next. The only
   border left is the one under the whole thing, which separates the rail from
   the choices instead of drawing a box round every fact in it. Nothing is
   tinted, because nothing here is a surface — it is type on the page. */
/* ---- the rail is set on a line, like anything else that is typeset --------
   Every line in it — each fact, the label over the jobs, a fact that has
   wrapped — sits 26px below the one before it, and nothing in it is allowed to
   grow its own line: the faces are pulled in at the margins so a row of squares
   takes the same height as a row of words. Breaks between the parts are half a
   line, which is the only measurement here that is not 26 or a multiple of it.

   That is what stops the stacked rail reading as three unrelated rows with
   different amounts of air around them, which is what it did while each row
   was as tall as whatever happened to be in it: 55px, then 32, then 31. */
.ad-rail{--rail-line:26px;
  padding:0 0 13px;margin:0 0 26px;border-bottom:1px solid var(--line)}

/* THE THREE FACTS ARE SPREAD ACROSS THE PAGE, not bunched at the left of it.
   Set as a row they took the width of their own words and left a third of the
   line empty, which reads as a row that ran out rather than one that was laid
   out. Three equal columns put each answer at a third of the way along and the
   dividers on the thirds, so the line is as wide as everything under it. */
/* THE AIR IS SHARED, NOT ALLOTTED. Equal columns gave each fact a third of the
   line whether it needed it or not, and the short answers left holes; putting
   the outer two on the page's edges and the middle one in the middle only moved
   the holes about — a hand's width after ONLINE and a mile before SAVED.

   The facts take the width of their own words and the room left over is split
   equally between them. Three gaps of the same size, both ends on the margins
   the page is set to, and it stays true as the words change: a longer concert
   title takes its space out of the gaps rather than out of the next fact. */
.ad-status{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:4px 28px;padding:0;margin:0}
/* THE LABEL SITS ON THE ANSWER'S OWN LINE. Centred, a 11.5px capital and a
   15px word are two boxes of different heights lined up through their middles,
   which puts the small capitals a pixel or so below where the eye expects them
   — SAVED sat low against "Never". Baselines are what the eye actually reads a
   line by, so that is what they are lined up on. */
.ad-status div{display:flex;align-items:baseline;gap:8px;
  min-height:var(--rail-line);padding:0;background:none;min-width:0}
/* THE MIDDLE FACT HAS FACES IN IT, and they were setting its baseline — a
   flex row takes its baseline from its first item, and its first item is a
   square with a letter in the middle. So ONLINE sat six pixels below NEXT and
   SAVED on the same line. The faces are drawn as type instead: an inline box
   on the line rather than a flex item in front of it, dropped so its middle
   sits on the middle of the lower-case, and pulled in at top and bottom so it
   cannot make its own line any taller than a line of words. The sentence after
   it is then what the whole fact is aligned by, like the other two.

   (The cell's answer also has to stop hiding its overflow, or the browser
   stops looking for a baseline in it at all and uses the bottom edge.) */
.ad-status #adHere{overflow:visible}
.ad-status div > b{flex:0 0 auto}

/* The two states, and the frame in between where the row is asked how wide it
   would rather be. Nothing is painted while it is measuring: it is set, read
   and unset without the browser drawing anything in between. */
.ad-status.is-measuring{flex-wrap:nowrap}
.ad-status.is-measuring div{flex:0 0 auto;min-width:auto}
.ad-status.is-measuring span,
.ad-status.is-measuring em{overflow:visible;text-overflow:clip}
/* Stacked, the three labels are three different lengths, so three answers
   started in three different places down the left of the page. Two columns
   instead — the labels in one, as wide as the longest of them, and every
   answer beginning on the same line as the others. */
/* No gap between the rows, because the line is the gap: every line of type in
   here is 26px below the last whether it is the next fact or the second line
   of the one above. */
.ad-status.is-stacked{display:grid;grid-template-columns:max-content 1fr;
  align-items:baseline;gap:0 10px}
.ad-status.is-stacked > div{display:contents}
/* And once they are stacked there is no reason left to cut anything: the line
   is no longer holding three facts, so a long answer takes a second line of
   its own rather than an ellipsis. Cutting is for the one-line state, where
   the alternative is a rail that is not a rail. */
.ad-status.is-stacked span,
.ad-status.is-stacked .ad-here em{white-space:normal;overflow:visible;
  text-overflow:clip}

/* AND WHEN THE WORDS ARE TOO LONG FOR THE LINE, the answer is cut rather than
   the line broken. "National Brass Band Championships of Great Britain" is a
   real concert title and there is nothing to stop a longer one; a rail that
   becomes three lines because of it is no longer a rail. Whatever is cut is
   still there in full on the title of the element, and every one of these
   facts is one press away from the page that says it properly. */
.ad-status div > span{min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.ad-status .ad-here{min-width:0;overflow:visible}
.ad-status .ad-here em{min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
/* NO DIVIDERS. They were hairlines on the thirds, which was where the columns
   divided and not where the words did — with the facts set to the edges they
   pointed at nothing. Three labels in small capitals separate three answers
   perfectly well on their own. */
.ad-status b{display:inline;font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute);margin:0;white-space:nowrap;
  line-height:var(--rail-line)}
.ad-status span{display:inline;font-size:15px;line-height:var(--rail-line);
  color:var(--ink)}
.ad-status em{font-style:normal;color:var(--mute)}

/* Things worth doing, each one a way straight to the place it is done. Listed
   only when there is something in them — an empty "nothing needs attention"
   panel is a panel that has to be read to learn it says nothing. */
/* ---- what wants doing ----
   One list, and everything feeds into it: work somebody started and did not
   finish, and information old enough to be worth looking at again. Both are a
   minute of somebody's time and a press away from where the minute is spent.

   BEHIND ONE LINE, CLOSED TO BEGIN WITH. Six chips across the top of the front
   page is a hedge in front of the door: every one of them is worth knowing and
   none of them is worth reading before somebody has decided what they came to
   do. The count is the nag; the list is the answer to it. */
/* THE COUNT RIDES ON THE END OF THE RAIL. It had a plate and a gold edge of
   its own, on a line of its own, under a grid of boxes — three separate ways of
   saying "look here" stacked on top of each other in front of the door. It is a
   line of type among the other three now, pushed to the far end, and the only
   one of them anybody can press, which the scarlet says on its own. */
/* THE JOBS THEMSELVES, ON THE LINES UNDER THE FACTS. The label reads as one
   of the rail's other labels, because that is what it is: NEXT, ONLINE, SAVED,
   WANTS DOING. What follows it is the work rather than a count of the work —
   all of it, on as many lines as it takes, and the label stays level with the
   first of them rather than floating halfway down the stack. */
.ad-jobs{display:flex;align-items:flex-start;gap:12px;
  margin-top:calc(var(--rail-line) / 2)}
.ad-jobs > b{flex:0 0 auto;font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute);white-space:nowrap;
  line-height:34px}
/* The jobs share the room left over, so every line ends where the page ends. */
.ad-jobs .ad-todo{flex:1 1 auto;margin:0;gap:7px}
/* Never squeezed: min-width:max-content means a job is on the line at its
   full length. Without it the four that fit became four that fitted badly —
   "The committee and staff has nev…" — and a job you cannot read is not on the
   page in any sense that matters. The width each one is drawn at is set by
   stackJobs(), which measures them first with the row told not to stretch. */
.ad-jobs .ad-todo > li{flex:1 1 auto;min-width:max-content}
.ad-jobs .ad-todo.is-measuring > li{flex:0 0 auto}
/* The one that is wider than the window — a reminder with its Still right
   button, on a phone — is let wrap rather than run off the edge. */
.ad-jobs .ad-todo > li.is-wide{min-width:0}
.ad-jobs .ad-todo > li.is-wide > button,
.ad-jobs .ad-todo > li.is-wide .ad-job-say{white-space:normal;min-width:0}
.ad-jobs .ad-todo > li.is-wide > button:first-child{padding-top:6px;padding-bottom:6px}
.ad-jobs .ad-todo > li > button{flex:1 1 auto}
.ad-jobs .ad-todo .ad-still{flex:0 0 auto}
/* ON A PHONE IT IS A SENTENCE, NOT A ROW. Laid out as a row of parts it broke
   into three columns of two words each with the figure stranded on the left,
   which is what a flex row does to a sentence when there is no room for it.
   Set as ordinary running text it simply wraps, the way the words were written
   to. The facts above it lose their dividers at the same width, because a
   hairline between two lines that are already on separate lines is a rule
   pointing at nothing. */
/* ON A PHONE THERE ARE NO COLUMNS AND NO ROW. A third of a phone is not wide
   enough to say "Sun 6 Sep, in 9 days" in, and a line of jobs across it holds
   one job and a figure — so the facts stack a line each, and the jobs wrap as
   a small block with the label above them rather than beside them. */
@media(max-width:640px){
  .ad-rail{padding-bottom:13px;margin-bottom:20px}
  .ad-jobs{display:block}
  .ad-jobs > b{display:block}
  .ad-jobs .ad-todo > li{flex:0 1 auto}
}

#adJobs .ad-todo{animation:ad-unfold var(--ad-quick,.18s) var(--ad-ease,ease) backwards}

.ad-todo{margin:0 0 22px;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:8px}
.ad-todo li{display:flex;align-items:stretch}
.ad-todo button{display:inline-flex;align-items:center;gap:7px;min-height:34px;
  padding:0 11px 0 6px;background:#fff;border:1px solid var(--line);
  border-left:3px solid var(--gold);font:inherit;font-size:13px;
  color:var(--ink);cursor:pointer;transition:.15s;text-align:left;
  white-space:nowrap}
.ad-todo button:hover{border-color:var(--ink);border-left-color:var(--scarlet)}
.ad-todo b{font-weight:900}
/* The words are one run, so that where they have to wrap they wrap as words
   do, not as a figure on one line and its noun on the next. */
.ad-job-say{white-space:nowrap}
.ad-job-say b{margin-right:3px}
/* THE APP'S OWN MARK ON THE JOB — the plate from the tile, at the size of the
   line, so "5 players with no photograph" is seen to belong to Players before
   it is read. Square, like every plate here. */
.ad-job-mark{display:grid;place-items:center;flex:0 0 auto;width:22px;height:22px;
  background:var(--scarlet);color:#fff;transition:.15s}
.ad-job-mark .ad-icon{width:14px;height:14px;stroke-width:2.1}
.ad-todo button:hover .ad-job-mark{background:var(--royal)}

/* A THIRD KIND OF JOB, MARKED AS ONE. The gold edge on the others says
   unfinished — a photograph nobody has uploaded, a start time nobody has
   typed — and every one of them is the website being untidy. These are two
   screens contradicting each other: a concert on sale in a box office that is
   on no page of the website, a Buy button built from a short name nobody
   filled in. Nothing looks wrong on either screen and the pair is wrong, which
   is why it takes a scarlet edge and the first place in the row. */
.ad-todo-odd button{border-left-color:var(--scarlet)}
.ad-todo-odd button:hover{border-color:var(--scarlet)}
.ad-todo-odd b{color:var(--scarlet)}

/* A reminder carries its own answer. Joined to the row it belongs to rather
   than floating beside it — the gold edge marks the start of one item, and two
   separate chips would read as two items. */
.ad-todo-check button:first-child{border-right:0}
.ad-still{border-left:1px solid var(--line) !important;
  font-weight:700;color:var(--royal);white-space:nowrap}
.ad-still:hover{background:var(--royal);border-color:var(--royal) !important;
  color:#fff}
.ad-still[disabled]{opacity:.6;cursor:default}

/* ---- THE PROGRAMME OF MUSIC, AS ROWS ----
   A row a piece: the grip, the piece, the composer, a note, the cross. The
   interval is a row wearing the band's strip; a part heading is a row with
   one box. The buttons under the list add one of each. */
.ad-pieces{display:grid;gap:8px}
.ad-pieces-list{list-style:none;margin:0;padding:0;display:grid;gap:6px}
.ad-piece{display:grid;grid-template-columns:34px minmax(0,1.4fr) minmax(0,1fr) minmax(0,1fr) 36px;
  gap:6px;align-items:center;background:#fff;border:1px solid var(--line);padding:4px 4px 4px 0}
.ad-piece.is-interval,.ad-piece.is-part{grid-template-columns:34px minmax(0,1fr) 36px}
.ad-piece.is-interval{background:var(--tint)}
.ad-piece.is-interval .ad-sub{margin:0;justify-self:start}
.ad-piece input{min-height:40px;padding:0 10px;font:inherit;font-size:14.5px;
  border:1px solid var(--line);background:#fff;color:var(--ink);min-width:0}
.ad-piece input:focus{outline:3px solid var(--gold);outline-offset:1px;border-color:var(--ink)}
/* A part heading is a label for what follows it, so it is set as this admin
   sets a label — 900 at 11.5 with .14em — and not as a third thing. */
.ad-piece.is-part input{font-weight:900;font-size:11.5px;letter-spacing:.14em;text-transform:uppercase}
.ad-piece .ad-grip{width:34px;min-height:40px;margin:0;color:var(--mute)}
.ad-piece:hover .ad-grip{color:var(--ink)}
.ad-piece.is-dragging{position:relative;z-index:2;box-shadow:0 8px 24px rgba(0,0,0,.14);
  outline:1px solid var(--line)}
.ad-piece-off{width:36px;min-height:40px;font:inherit;font-size:20px;line-height:1;
  background:none;border:0;color:var(--mute);cursor:pointer;transition:.15s}
.ad-piece-off:hover{color:var(--scarlet)}
.ad-piece-off:focus-visible{outline:3px solid var(--scarlet);outline-offset:-3px}
.ad-pieces-add{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 0}
.ad-pieces-btn{min-height:40px;padding:0 14px;font:inherit;font-weight:700;font-size:12.5px;
  letter-spacing:.09em;text-transform:uppercase;background:#fff;border:2px solid var(--line);
  color:var(--ink);cursor:pointer;transition:.15s}
.ad-pieces-btn:hover{border-color:var(--ink)}
.ad-pieces-btn:first-child{border-color:var(--scarlet);color:var(--scarlet)}
.ad-pieces-btn:first-child:hover{background:var(--scarlet);color:#fff}
@media(max-width:640px){
  .ad-piece{grid-template-columns:34px minmax(0,1fr) 36px}
  .ad-piece input[data-piece="by"],.ad-piece input[data-piece="note"]{grid-column:2}
}

/* ---- the programme screen ---- */
.so-prog{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 26px;margin-top:6px}
.so-prog > .f-lg{grid-column:span 12}
.so-prog > .f-md{grid-column:span 6}
.so-prog-go{align-content:start}
.so-prog-says{margin:0 0 8px;font-size:14px;color:var(--mute)}
@media(max-width:820px){.so-prog > .f-md{grid-column:span 12}}

/* ---- the social plan: a poster in the row, and "say it another way" ---- */
.so-plan-poster{display:flex;gap:16px;align-items:flex-start;margin:0 0 14px}
.so-plan-poster img{width:120px;height:150px;object-fit:cover;flex:0 0 auto;
  border:1px solid var(--line);background:var(--tint)}
.so-plan-poster .hint{margin:0}
.so-words .so-again{grid-column:1/-1;margin:2px 0 0}

/* ---- who is online ----
   Faces first, names after them. Five at most: the sixth is a crowd, and the
   band has thirteen accounts.

   EVERY ONE OF THESE IS SCOPED TO .ad-status, and that is not decoration. The
   figure cells carry `.ad-status span{display:block}` — one class and one
   element, which beats a bare class — so `.ad-here{display:flex}` and
   `.ad-who{display:grid}` both lost to it: the faces and the names stacked
   instead of sitting on one line, and the initials sat in the top-left corner
   of their square rather than the middle of it. Measured, not guessed: a 40px
   box reporting display:block with the letter at the top of it. */
/* Set as type on the line rather than as a row of boxes beside it — see the
   note above the .ad-here-faces rule for why. Nothing here has a height of its
   own: the line the fact is on decides it. */
.ad-status .ad-here{display:inline-block;min-height:0;margin:0}
/* The count at the end of the row: the same square as a face, in the same ink
   as the initials, so it reads as one more of them rather than as a badge. */
.ad-status .ad-here-more{display:inline-flex;align-items:center;
  justify-content:center;min-width:26px;height:24px;padding:0 5px;
  font-weight:900;font-size:11.5px;letter-spacing:.02em;color:var(--mute);
  background:var(--tint);border:1px solid var(--line)}

/* A QUARTER OF AN INCH OF SQUARE, ON THE LINE. At forty pixels a face was
   taller than the line it sat on and made the fact half again as tall as the
   two either side of it — which is what made the stacked rail read as three
   rows with different amounts of air. Twenty-four fits inside a 26px line, and
   the negative margins mean even that is not counted against the line's
   height. */
/* CENTRED ON THE WORDS BESIDE THEM. The six pixels below the baseline were
   dropping the square past the bottom of its own line: measured, the face's
   middle sat 7.3px under the middle of the sentence after it, and under the
   little capital before it, so the one fact in the rail with a picture in it
   was the one sitting low. `middle` puts the two middles on the same line to
   within a rounding error. The negative margins stay — they are what stops a
   24px square making the line taller than the two facts either side of it,
   and the cell measures 27px whichever way the square is aligned. */
.ad-status .ad-here-faces{display:inline-flex;align-items:center;
  vertical-align:middle;margin:-6px 8px -6px 0}
.ad-status .ad-here .ad-who{display:grid;place-items:center;
  width:24px;height:24px}
/* AND THE INITIALS ARE NOT A LABEL. `.ad-status b` is the little grey capital
   heading over each figure — one class and one element again — so the letter
   inside a face came out at 10.5px, letter-spaced, and the colour of a caption.
   Everything that rule sets is set back here. */
.ad-status .ad-here .ad-who b{display:block;margin:0;font-size:11.5px;
  font-weight:900;letter-spacing:.03em;line-height:1;text-transform:none;
  color:var(--royal)}
/* SIDE BY SIDE, NOT OVERLAPPING. Overlapped by a third they looked like a row
   of people standing together — until you remember that most of these are
   initials rather than photographs, and a third of a letter is not a letter:
   "SB" and "D" beside each other came out as "SB|D" with the S half eaten.
   Photographs would have survived it; the thing this actually shows would not,
   and it is the state most accounts will be in for a while. */
.ad-status .ad-here-faces{gap:4px}
.ad-status .ad-here-one{display:flex}
.ad-status .ad-here em{display:inline;font-style:normal;color:var(--mute);
  font-size:13.5px;line-height:var(--rail-line)}

/* =============================================================================
   THE CARD
   =============================================================================
   Editing used to unfold underneath the row you pressed. In a list of
   thirty-two players that meant the thing you opened pushed everything below it
   off the screen, eleven fields ran down one column, and you could never see
   the list and the thing at once without scrolling past whichever you were not
   reading.

   It opens as a card over the page instead: one thing on the screen at a time,
   the page behind dimmed and still, Escape and a close button both shutting it.
   The browser's own <dialog> does the work — the keyboard stays inside it, and
   it draws above everything whatever it sits inside.
   ========================================================================== */
.ad-card{width:min(880px,calc(100vw - 32px));max-height:calc(100dvh - 48px);
  /* The dialog itself does not scroll — the column inside it does, and one bar
     is the whole point. A dialog scrolls by default, so this has to say so. */
  overflow:hidden;
  padding:0;border:0;background:#fff;color:var(--ink);
  box-shadow:0 24px 60px rgba(20,16,15,.28)}
.ad-card::backdrop{background:rgba(20,16,15,.55)}

/* THE PAGE BEHIND IS BLURRED, NOT ONLY DARKENED. Three pixels: enough to say
   "this is not what you are working on now", cheap enough not to stutter on a
   laptop. The same amount the admin's own screen changes use. */
.ad-card[open]{animation:ad-card-in var(--ad-calm,.26s) var(--ad-ease,ease) both}
.ad-card[open]::backdrop{animation:ad-card-dim var(--ad-calm,.26s) ease both;
  backdrop-filter:blur(3px)}
@keyframes ad-card-in{
  from{opacity:0;transform:translateY(14px) scale(.965);filter:blur(3px)}
}
@keyframes ad-card-dim{ from{opacity:0} }

/* ---- ONE SCROLL BAR, NOT TWO ----------------------------------------------
   The card was a column with a scrolling middle: a bar down the fields, inside
   the card, inside a page with a bar of its own. Two bars in the same corner is
   a thing to aim at wrongly, and it never says which one moves what.

   The card scrolls as one now, and the head and the foot stay put on top of it
   — the same two things staying still, by a means that does not invent a second
   bar to do it. */
.ad-card-in{display:block;max-height:calc(100dvh - 48px);overflow:auto;
  overscroll-behavior:contain}

/* ---- AND THE BAR IS OURS ----
   The browser's own was seen down the side of the concert card — grey, round-
   ended, and the one thing on the screen not drawn by the band. The card
   carries the site's scrollbar instead: the 4px line and the gold thumb the
   biography panel and the timeline already use, drawn by the same function.
   The native bar is hidden only once the script has put ours in place, so a
   card with scripts off keeps the ordinary one and stays usable.

   It stands in the dialog, beside the scrolling column rather than inside it,
   so it stays put while the fields move; where it starts and ends is set by
   admin.js from the height of the head and the foot, which stay put too. */
.ad-card-in[data-own-bar]{scrollbar-width:none;-ms-overflow-style:none}
.ad-card-in[data-own-bar]::-webkit-scrollbar{display:none}
.ad-card-bar{position:absolute;right:12px;width:4px;background:var(--line);
  z-index:4;cursor:pointer}
.ad-card-thumb{position:absolute;left:-2px;right:-2px;top:0;
  background:var(--gold);will-change:transform;transition:background .15s}
.ad-card-bar:hover .ad-card-thumb,.ad-card-bar.dragging .ad-card-thumb{background:#ffdf5e}

/* The name of the thing, and what kind of thing it is. Ink, so the card has a
   head that holds it together and a reader knows at a glance what they opened —
   the list behind is white and the fields are white. */
.ad-card-top{display:flex;align-items:flex-start;justify-content:space-between;
  gap:18px;padding:20px 24px;background:var(--ink);color:#fff;
  position:sticky;top:0;z-index:3}

.ad-card-what{margin:0 0 3px;font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold)}
/* CAPITALS, LIKE THE SAME WORDS ON THE SITE. This said `text-transform:none`
   and carried a note explaining that a concert's title is a name rather than a
   banner heading, and that What's On sets it as somebody typed it. That second
   half was simply not true: .poster-over h2 (an h3 then), which is the title on the card
   the public reads, is uppercase. So the admin was setting the same words in a
   different case from the page they end up on, for a reason that had stopped
   being a fact — and in Noverion Black at 22px on ink, sentence case is where
   it shows. */
.ad-card-name{margin:0;font-size:22px;line-height:1.15;font-weight:900;
  text-transform:uppercase;letter-spacing:.005em}
.ad-card-x{flex:none;width:44px;height:44px;margin:-6px -8px 0 0;font:inherit;
  font-size:26px;line-height:1;background:none;border:0;color:#fff;
  cursor:pointer;transition:.15s}
.ad-card-x:hover{color:var(--gold)}
.ad-card-x:focus-visible{outline:3px solid var(--gold);outline-offset:2px}

/* ---- the fields ----
   TWELVE COLUMNS, AND A FIELD TAKES WHAT IT NEEDS. A date is three of them, a
   biography is all twelve. Every field used to be the full width, which made a
   form of eleven fields a column half a screen long and told the reader nothing
   about what was expected in any of them. */
/* ---- the crest behind the card ----
   THE WHITE OF THE CARD, NOT THE INK ABOVE IT: bottom-left, bleeding off the
   edge, one flat shade, the same file every white section of the site uses.
   The boxes and the words sit over it, as they do on the page behind.

   It began on the walkthrough alone, where the body is mostly empty and there
   was obviously room for it. A form is denser and the crest shows in the gaps
   rather than behind a single question — which is what a watermark is for, and
   it makes the two kinds of card halves of one thing rather than two designs.

   THE TOP OF THE CROWN SETS THE SIZE. The crest is drawn as tall as the surface
   it is on and anchored to the bottom of it, so the point of the crown lands on
   the top edge — which is what `auto 100%` from the bottom means, and what
   every .mark on this site does. Bigger than that and the crown is cut off
   above the edge, which is the one part of the crest anybody would notice
   missing.

   `contain` RATHER THAN `auto 100%`, AND THAT IS THE SAME RULE. A page section
   is wide and shallow, so its full height always leaves the crest narrower than
   the section and there is only one way for it to be wrong. A card is the other
   shape: an 880px card with a form a thousand deep would draw the crest a
   thousand across, and the part that then goes off the edge is the right-hand
   half of the band's own arms.

   So the surface still sets the size, and the surface is allowed to set it by
   either measure — as tall as the card, or as wide as it, whichever that card
   has room for. On the walkthrough, which is shallow, that is its height and
   nothing changes. On a full form it is the width. Either way the whole crest
   is drawn, anchored to the bottom-left corner, at the size of the thing it is
   on: never cropped, never capped at a number somebody picked. */
.ad-card-fields{display:grid;grid-template-columns:repeat(12,1fr);
  gap:16px 20px;padding:20px 24px 24px;
  background:url('../img/gus-crest-light.png') left bottom/contain no-repeat}
/* THE CONTENTS SIT AT THE TOP OF THEIR CELL, NOT SPREAD DOWN IT. A grid item
   is as tall as the tallest thing in its row, and a grid inside one stretches
   its own rows to fill whatever height it is given — so beside a field with
   three lines of hint under it, the date's label was drawn 70px tall and its
   box 98, with the gap between them doing the stretching. Measured: a 176px
   cell holding 40px of label and 46px of input.

   align-content on the field, align-items on the row: the first stops a field
   spreading its own contents, the second stops a short field being stretched in
   the first place. */
.ad-card-fields{align-items:start}
.ad-card-fields .ad-field{align-content:start}
.ad-card-fields .f-sm{grid-column:span 3}
.ad-card-fields .f-md{grid-column:span 6}
.ad-card-fields .f-lg{grid-column:span 12}
/* AIR ABOVE IT AND NOTHING ELSE. There was a hairline here for a moment, and
   a gold bar for another moment; both were one divider too many beside a strip
   that already says "a heading" on its own. */
.ad-card-fields .ad-sub{grid-column:1/-1;justify-self:start;margin:28px 0 6px}
.ad-card-fields > .ad-sub:first-child{margin-top:2px}
/* Inside a card the boxes are a shade tighter than on a page of their own —
   16px type still, because anything smaller makes a phone zoom in on focus, but
   less air around it. */
.ad-card-fields .ad-field input,
.ad-card-fields .ad-field textarea{padding:10px 12px}
/* The menu keeps the room on its right that its arrow stands in. */
.ad-card-fields .ad-field select{padding:10px 40px 10px 12px}
.ad-card-fields .ad-field textarea{min-height:120px}
.ad-card-fields .hint{margin:5px 0 0;font-size:12.5px;line-height:1.45}

@media(max-width:720px){
  /* One column on a phone, where twelve of anything is a fiction.

     NOT THE ASKING CARD. A `dialog` is centred by the browser's own
     `margin:auto`, and `margin:0` here — right for a form that takes the whole
     screen — was inherited by the small confirmation box as well. That box sets
     its own width a line further down the file and so stayed 358px wide, but
     with no margin left to centre it: it sat hard against the top-left corner
     with a 32px strip of backdrop down the right-hand side, which reads as a
     panel that has come adrift rather than as a question. It is the last thing
     between somebody and deleting a concert. */
  .ad-card:not(.ad-ask){width:100vw;max-width:100vw;max-height:100dvh;margin:0}
  .ad-card:not(.ad-ask) .ad-card-in{max-height:100dvh}
  .ad-card-fields{gap:16px;padding:18px}
  .ad-card-fields .f-sm,.ad-card-fields .f-md{grid-column:1/-1}
}

/* ---- being asked, rather than handed a form ----
   One question at a time, in the words somebody would use out loud. The
   question is the card's heading — big, on the ink, where the name of the thing
   sits when you are editing one — and the box under it is the only thing on the
   screen. */
/* The question is a heading and is set in capitals, like every heading on this
   site — and now like the card's own name above, which is the same words the
   public reads in capitals on What's On. Only the size differs here: this is
   the one thing on the screen. */
.ad-card-ask .ad-card-name{font-size:clamp(25px,3.2vw,34px);max-width:36ch;
  line-height:1.04;
  /* A HEADING BREAKS INTO EVEN LINES, not into a line and one leftover word.
     "Is it a concert or a contest?" was breaking after "a", which leaves the
     word hanging and reads as a mistake rather than as a heading. */
  text-wrap:balance}

/* ---- one question is allowed the whole card ----
   A single box in the corner of an 880px card looks like a form that has failed
   to load the rest of itself. A question asked on its own is drawn at the size
   of the thing being asked. */
.ad-ask-one{padding:26px 24px 22px;min-height:150px;align-content:start}
.ad-ask-one .ad-field{grid-column:1/-1}

/* ONE QUESTION, AND THE CARD IS THE SIZE OF A QUESTION. A single line and a
   sentence of help left the card two hundred pixels deep between a diary behind
   it and a calendar step four hundred deep — the walkthrough grew and shrank
   from question to question, and the short ones looked like an afterthought.
   A floor under the body of the card: the answer box takes what it needs, and
   what is left is the crest rather than blank white. */
.ad-card-ask .ad-card-fields{min-height:clamp(210px,32vh,330px);align-content:start}

/* A line of type big enough to read across a room — this is the only thing on
   the screen, and somebody is looking at it while they think. */
/* ONE SIZE, READ BY BOTH THE BOX AND THE GREY WORDS BEHIND THE CARET. The
   ghost is a copy of the line laid exactly over the real one, so every figure
   that decides where a letter lands has to be the same in both — and when the
   box grew to 26px the ghost stayed at 22px in a padding of its own, which put
   "cert" a size too small and a few pixels too high at the end of "Autumn Con".
   Set once here; the ghost reads the same two variables. */
.ad-ask-one{--ask-type:26px;--ask-pad:22px 20px}
.ad-ask-one .ad-field input[type=text],
.ad-ask-one .ad-field input[type=url],
.ad-ask-one .ad-field input[type=number],
.ad-ask-one .ad-field input[type=time]{
  font-size:var(--ask-type);padding:var(--ask-pad);line-height:1.3}
.ad-ask-one .ad-field select{font-size:18px;padding:13px 40px 13px 15px}
/* A paragraph, in a box you can see a paragraph in. */
.ad-ask-one .ad-field textarea{font-size:18px;padding:15px 17px;min-height:220px;
  line-height:1.55}
.ad-ask-one .hint{font-size:14px;max-width:66ch;margin-top:9px}

/* Every answer visible, rather than a list to open. The band's sections are
   eleven words: reading them is faster than opening anything. */
.ad-ask-one .ad-pick-row{gap:10px}
.ad-ask-one .ad-pick-one span{min-height:58px;padding:0 26px;font-size:16.5px}

/* ---- a choice with the card to itself ----
   THE TWO ANSWERS TAKE THE WIDTH AND THE HEIGHT, because they are the only
   thing on the screen. They were two small chips against the top-left corner
   with the rest of the card empty white below them, which made the one question
   somebody is being asked look like the least important thing on it. Half the
   card each, deep enough to hold the line that says what the difference is,
   and a target nobody can miss on a phone. */
.ad-ask-one .ad-pick-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.ad-ask-one .ad-pick-one.has-why span{min-height:186px;height:100%;padding:24px;
  justify-content:center;gap:14px}
.ad-ask-one .ad-pick-one.has-why b{font-size:23px}
.ad-ask-one .ad-pick-one.has-why i{font-size:15px}

/* THE ANSWERS SIT IN THE MIDDLE OF THE CARD, not against the top of it with the
   floor under them showing. They are the only thing being asked for. */
.ad-card-ask .ad-ask-pick{align-content:center}

/* THE BAND'S BAR, UNDER THE WORD. The gold rule under a heading is the device
   the artwork uses everywhere, and these two words are the heading of their own
   panel — so they carry it, measured from the word the way every other one is.
   Thinner than a page heading's, in proportion to type this size. */
.ad-pick-one.has-why .rule::after{margin-bottom:2px}
@media(max-width:620px){
  /* One above the other: two columns of this depth would each be a column of
     single words down a phone. */
  .ad-ask-one .ad-pick-row{grid-template-columns:1fr}
  .ad-ask-one .ad-pick-one.has-why span{min-height:0}
}

/* ---- the rest of the word ----
   The first answer that starts with what has been typed, drawn in grey behind
   the caret the way a shell finishes a path. A SUGGESTION AND NOT THE VALUE:
   nothing is in the field until somebody takes it, because a box that fills
   itself in is a box that gets saved with a hall nobody chose.

   The ghost is a copy of the line with the typed part made invisible, laid
   exactly over the real one — same font, same padding, same border width — so
   the grey half continues the black half rather than sitting near it. */
/* The wrapper stands where the field stood — it is the grid item now, and
   without this it took one column of twelve and the box came out 60px wide. */
.ad-guess{grid-column:1/-1}
.ad-guess .ad-field{grid-column:auto}
.ad-guess-box{display:block;position:relative}
.ad-guess-ghost{position:absolute;left:0;top:0;right:0;bottom:0;
  padding:var(--ask-pad,16px 18px);
  /* The field's border is two pixels, and a border of one here would shift
     every letter behind the caret by one. */
  border:2px solid transparent;
  font-size:var(--ask-type,22px);line-height:1.3;color:var(--mute);
  pointer-events:none;white-space:pre;overflow:hidden}
.ad-guess-ghost i{font-style:normal;visibility:hidden}

/* ---- taking it ----
   UNDER THE BOX, AND IT SAYS WHAT IT WILL TAKE. It began as a small button laid
   over the right-hand end of the field, which covered the very words it was
   offering and sat on top of any hall name long enough to reach it. A line of
   its own, the width of the field, naming the hall: no overlap, nothing to aim
   at, and it reads as an offer rather than as a control bolted to the box.

   The keys are a shell's and are named on it; the line itself is for the phone,
   where neither of those keys exists. */
.ad-guess-take{display:flex;align-items:center;justify-content:space-between;
  gap:14px;width:100%;margin-top:10px;min-height:48px;padding:0 14px;
  font:inherit;font-size:15px;text-align:left;background:var(--tint);
  border:1px solid var(--line);border-left:3px solid var(--gold);
  color:var(--ink);cursor:pointer;transition:.15s}
.ad-guess-take:hover{border-color:var(--ink);border-left-color:var(--scarlet)}
.ad-guess-take:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-guess-take span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ad-guess-take kbd{flex:none;font:inherit;font-size:11.5px;font-weight:900;
  letter-spacing:.14em;text-transform:uppercase;color:var(--mute);
  border:1px solid var(--line);background:#fff;padding:4px 8px}
@media(hover:none){
  /* No Tab key to press on a phone, so the line does not claim there is one. */
  .ad-guess-take kbd{display:none}
}

/* ---- what this question has been answered before ----
   Somebody adding the fifth committee member is about to type "Management
   Committee" for the fifth time. Only shown where the answers genuinely
   repeat — see seenBefore() — or it would be one button per concert title. */
.ad-ask-seen{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.ad-ask-seen p{margin:0 0 9px;font-size:11.5px;font-weight:900;
  letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
/* TWO ROWS OF FOUR, EVEN. Left to wrap, eight names of wildly different
   lengths came out as a ragged block with a gap at the end of it — "Royal &
   Derngate" beside "The Glasshouse International Centre for Music" beside a
   hole. Four equal columns is a shape; a name too long for its column is cut
   with an ellipsis and says the whole of itself on hover. */
.ad-ask-seen-row{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:8px}
.ad-seen{font:inherit;font-size:14.5px;min-height:48px;padding:0 14px;
  background:#fff;border:1px solid var(--line);color:var(--ink);cursor:pointer;
  transition:.15s;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ad-seen-none{margin:10px 0 0;font-size:13.5px;color:var(--mute)}

@media(max-width:720px){
  /* Two across on a phone, which is as many as a name fits on. */
  .ad-ask-seen-row{grid-template-columns:repeat(2,minmax(0,1fr))}
}
.ad-seen:hover{border-color:var(--scarlet);color:var(--scarlet)}
.ad-seen:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-ask-nope{margin:12px 0 0;font-weight:700;font-size:14px;color:var(--scarlet)}
.ad-ask-end{padding:26px 24px}
.ad-ask-end .lede{margin:0}
.ad-ask-count{font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute)}
.ad-back-step{font:inherit;font-weight:700;font-size:13px;min-height:44px;
  padding:0 12px;background:none;border:0;color:var(--mute);cursor:pointer}
.ad-back-step:hover{color:var(--ink)}
/* The way on is at the far end from the way back, and the count sits between
   them — so the two are never pressed for each other. */
.ad-card-ask .ad-card-foot .btn{margin-left:auto}
.ad-card-ask .ad-card-foot{gap:12px 16px}
/* Each question arrives rather than appearing. */
.ad-card-ask .ad-card-fields{
  animation:ad-unfold var(--ad-quick,.18s) var(--ad-ease,ease) backwards}
@media(prefers-reduced-motion:reduce){
  .ad-card-ask .ad-card-fields{animation:none}
}

/* ---- two answers, drawn as themselves ----
   A list you have to open to see two things in is a list for the sake of being
   one. Radios underneath — the arrow keys move between them and a screen reader
   says "concert, 1 of 2" — with the buttons drawn over the top.

   The chosen one is scarlet, like every other chosen thing in this admin. */
/* ONE CONTROL, TWO NAMES: .pick-row is the same thing on the public pages —
   the concerts-or-contests choice over the What's On wall — so a choice of a
   few is drawn one way on both sides of the site. */
.ad-pick-row,.pick-row{display:flex;flex-wrap:wrap;gap:8px}
.ad-pick-one,.pick-one{position:relative}
.ad-pick-one input,.pick-one input{position:absolute;inset:0;width:100%;height:100%;
  margin:0;opacity:0;cursor:pointer}
.ad-pick-one span,.pick-one span{display:inline-flex;align-items:center;justify-content:center;
  min-height:48px;padding:0 22px;font-weight:700;font-size:15px;
  background:#fff;border:2px solid var(--line);color:var(--ink);
  transition:.15s;pointer-events:none}
.ad-pick-one input:hover + span,.pick-one input:hover + span{border-color:var(--ink)}
.ad-pick-one input:checked + span,.pick-one input:checked + span{background:var(--scarlet);
  border-color:var(--scarlet);color:#fff}
.ad-pick-one input:focus-visible + span,.pick-one input:focus-visible + span{
  outline:3px solid var(--scarlet);outline-offset:2px}

/* ---- EXPLAIN WHEN ASKING, NAME WHEN EDITING -------------------------------
   The line under each answer is the difference between a concert and a contest,
   and it is worth a panel each on the card that asks the question for the first
   time. On the form it is two paragraphs about something already answered,
   taking a third of the height of a form with eleven fields in it — so there
   they are the two words, as they were. */
.ad-card-fields:not(.ad-ask-one) .ad-pick-one.has-why i{display:none}
.ad-card-fields:not(.ad-ask-one) .ad-pick-one.has-why span{
  flex-direction:row;align-items:center;justify-content:center;
  min-height:48px;padding:0 22px}
.ad-card-fields:not(.ad-ask-one) .ad-pick-one.has-why b{font-size:15px;
  letter-spacing:.06em}
.ad-card-fields:not(.ad-ask-one) .ad-pick-one.has-why b.rule::after{display:none}
.ad-ask-one .ad-pick-row:has(.has-why){display:grid;grid-template-columns:1fr 1fr;gap:12px}

/* An option that carries a line of its own is a block, not a chip: the word
   above, the line under it, both left-aligned so the two options read as two
   paragraphs to choose between rather than as two labels. */
.ad-pick-one.has-why span{flex-direction:column;align-items:flex-start;
  justify-content:flex-start;gap:9px;padding:16px;text-align:left;height:100%}
.ad-pick-one.has-why b{font-size:17px;font-weight:900;letter-spacing:.04em;
  text-transform:uppercase;line-height:1}
.ad-pick-one.has-why i{font-style:normal;font-weight:500;font-size:13.5px;
  line-height:1.5;color:var(--mute);
  /* The row sits inside a <label>, and a field's label is capitals — which the
     sentence inside the button would otherwise inherit and be shouted in. */
  text-transform:none;letter-spacing:normal}
.ad-pick-one.has-why input:checked + span i{color:rgba(255,255,255,.92)}
.ad-pick-one input:focus-visible + span{outline:3px solid var(--scarlet);
  outline-offset:3px}

/* ---- asking, in the band's own words ---------------------------------------
   The browser's own box says "localhost:8080 says" in the machine's own font,
   and on a phone it arrives from the top of the screen like a warning about
   something going wrong. This is the same card everything else in the admin
   opens in, at the width of a question rather than of a form. */
.ad-ask{width:min(520px,calc(100vw - 32px))}
.ad-ask .ad-card-fields{display:block;padding:22px 24px 0}
.ad-ask .ad-card-fields > p{margin:0 0 14px;max-width:52ch}
.ad-ask .ad-field{margin-bottom:14px}
.ad-ask .ad-card-foot{margin-top:6px}
.ad-ask .ad-ask-nope{color:var(--scarlet);font-weight:700}

/* Something to be read out loud and typed in somewhere else: big, spaced, and
   in the face the password boxes use, so an l and a 1 cannot be confused —
   though the maker avoids both anyway. */
/* The thing being asked about, said on its own line under the heading rather
   than inside it — see askThem in admin.js for why. Set in the body face, so a
   long name wraps the way prose wraps instead of breaking a line of capitals
   in the middle of a quoted phrase. */
.ad-ask-what{margin:0 0 10px;font-weight:900;font-size:18px;line-height:1.25;
  color:var(--ink)}

.ad-ask-copy{margin:4px 0 18px}
.ad-ask-copy code{display:block;padding:16px 18px;
  font-family:Verdana,Tahoma,'DejaVu Sans',monospace;
  font-size:22px;letter-spacing:.06em;text-align:center;
  background:var(--tint);border:2px solid var(--line);
  user-select:all}

/* ---- the day, the time and all-day, as one line ----------------------------
   A DATE IS A CALENDAR AND A CALENDAR IS HALF A CARD. Drawn open on a form of
   eleven fields, the first answer filled the screen and everything after it was
   below the fold; and it was open whether or not it needed touching, which on
   an entry somebody is editing to fix the venue is every time but one.

   So it is a line: what it says now on the left, the way it will read on the
   site, and a word on the right that opens it. Open where the date is not there
   yet, because a required field hiding behind a line saying "Not set" is a form
   that refuses to save without saying where. */
.ad-when-set{border:1px solid var(--line);background:var(--tint)}
.ad-when-say{display:flex;align-items:center;gap:8px 18px;flex-wrap:wrap;
  width:100%;min-height:56px;padding:12px 16px;font:inherit;text-align:left;
  background:none;border:0;border-left:3px solid var(--gold);color:var(--ink);
  cursor:pointer;transition:.15s}
.ad-when-say:hover{background:#fff;border-left-color:var(--scarlet)}
.ad-when-say:focus-visible{outline:3px solid var(--scarlet);outline-offset:-3px}
.ad-when-lab{font-weight:900;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute)}
.ad-when-val{font-weight:700;font-size:16px}
.ad-when-val em{font-style:normal;color:var(--scarlet)}
.ad-when-do{margin-left:auto;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--scarlet)}
.ad-when-in{display:grid;gap:18px 26px;align-items:start;
  padding:8px 16px 18px;background:#fff;border-top:1px solid var(--line)}
/* The calendar is a month wide whatever else happens; everything else in the
   bracket stands beside it in a column of its own, at the top rather than
   spread down the side of a six-row month. */
.ad-when-side{display:grid;grid-template-columns:minmax(0,1fr);gap:16px;
  align-content:start}
/* One column, whatever width class a field brought with it: a span inside a
   one-column grid invents tracks of nothing and squeezes what is there. */
.ad-when-side > *{grid-column:1}
/* A field carries a width class — .f-md, .f-lg — which spans columns of the
   twelve the card is built on. Inside this two-column bracket those spans
   invent tracks of nothing and push the second column onto a row of its own,
   so they are overruled here rather than being made conditional everywhere. */
.ad-when-in > .ad-field,
.ad-when-in > .ad-when-side{grid-column:1}
@media(min-width:820px){
  .ad-when-in{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}
  .ad-when-in > .ad-when-side{grid-column:2;grid-row:1}
  /* A bracket of one field — a player's date of joining — is one column. */
  .ad-when-in.is-one{grid-template-columns:minmax(0,1fr)}
}

/* ---- the clock -------------------------------------------------------------
   SQUARE. It was a circle, on the argument that a clock is a circle — and the
   review's answer was that there are no circles in this design language, and
   there are not: every plate, stamp, tick and badge on the site is square. So
   the face is a square, the twelve numbers stand on a square with 12, 3, 6 and
   9 at the middles of its sides, and the hands are square-ended bars. A wall
   clock in a school hall, which is where a band plays.

   The shape is otherwise the one every phone uses, because that is the one
   everybody has already learnt: the time written out large at the top, the
   part you are setting picked out in scarlet, and the dial under it. */
.ad-clock{display:grid;gap:14px;justify-items:start;width:100%;max-width:300px}

.ad-clock-read{display:flex;align-items:center;gap:2px}
.ad-clock-part{min-width:60px;min-height:56px;padding:0 6px;font:inherit;
  font-weight:900;font-size:40px;line-height:1;letter-spacing:-.01em;
  background:var(--tint);border:0;color:var(--mute);
  cursor:pointer;transition:.15s}
.ad-clock-part:hover{color:var(--ink)}
.ad-clock-part.on{background:var(--scarlet);color:#fff}
.ad-clock-part:focus-visible{outline:3px solid var(--ink);outline-offset:2px}
.ad-clock-colon{font-weight:900;font-size:34px;line-height:1;padding:0 4px;
  color:var(--mute)}
/* am and pm are one control of two halves, stacked, the way a phone's is. */
.ad-clock-halves{display:grid;gap:2px;margin-left:12px}
.ad-clock-half{min-width:54px;min-height:27px;padding:0 8px;font:inherit;
  font-weight:700;font-size:13px;text-transform:lowercase;
  background:#fff;border:2px solid var(--line);color:var(--mute);
  cursor:pointer;transition:.15s}
.ad-clock-half:hover{border-color:var(--royal);color:var(--royal)}
.ad-clock-half.on{background:var(--scarlet);border-color:var(--scarlet);color:#fff}
.ad-clock-half:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}

.ad-clock-face{position:relative;width:min(300px,72vw);aspect-ratio:1;
  touch-action:none;cursor:pointer}
.ad-clock-face svg{display:block;width:100%;height:100%;overflow:visible}
/* A PALE FACE, NOT AN INK ONE. A black square the size of a hand is the
   heaviest thing on a white form by a long way. Scarlet leads on white, which
   is the rule everywhere else here, so the face is the tint the cards use and
   the answer is scarlet on it. */
.ad-clock-dial{fill:var(--tint);stroke:var(--line);stroke-width:1}
/* TWO HANDS, THREE COLOURS. The one being set is scarlet; the other is ink,
   solid, because it is a fact already given and a grey line read as a fault.
   The pivot is a gold square — the site's third colour, on the one point the
   two hands share. Square ends; nothing rounded. */
.ad-clock-hand{fill:var(--ink);transform-origin:50px 50px;transform-box:view-box;
  transition:transform .22s cubic-bezier(.2,.8,.25,1)}
.ad-clock-hand.is-lead{fill:var(--scarlet)}
.ad-clock-pin{fill:var(--gold)}
.ad-clock.is-unset .ad-clock-hand{opacity:.14}
.ad-clock.is-unset .ad-clock-pin{opacity:.4}

/* The twelve marks are squares over the face. 30px is under the 44 this admin
   holds itself to, and it is the one place that cannot be helped: twelve
   targets on one dial. The hand can be dragged instead, which is the bigger
   target — the whole face. */
.ad-clock-n{position:absolute;transform:translate(-50%,-50%);
  min-width:32px;min-height:32px;padding:0;font:inherit;font-weight:700;
  font-size:14px;line-height:1;background:none;border:0;color:var(--ink);
  cursor:pointer;transition:color .15s,background .15s}
.ad-clock-n:hover{background:#fff;color:var(--royal)}
.ad-clock-n.on{color:#fff;background:var(--scarlet);font-weight:900}
.ad-clock-n:focus-visible{outline:3px solid var(--scarlet);outline-offset:1px}

/* THE FOOT OF THE BRACKET: the two facts about a date that are not a time,
   on one line under the clock. "No time yet" is a plain control — the same
   two-line box as the am/pm halves — pressed while there is no time, so it
   says the state as well as being the way to it. All day is the tick beside
   it. Both are always drawn, so the bracket never changes height. */
.ad-when-foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;
  min-height:44px}
.ad-clock-clear{white-space:nowrap;min-height:40px;padding:0 14px;font:inherit;
  font-weight:700;font-size:13px;background:#fff;border:2px solid var(--line);
  color:var(--mute);cursor:pointer;transition:.15s}
.ad-clock-clear:hover{border-color:var(--royal);color:var(--royal)}
.ad-clock-clear[aria-pressed="true"]{background:var(--scarlet);
  border-color:var(--scarlet);color:#fff;cursor:default}
.ad-clock-clear:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-when-foot .ad-field{gap:0}
/* Beside a button that says "No time yet", the tick says "All day" the same
   way — two facts in the same voice, not one in capitals. */
.ad-when-foot .ad-tick span{text-transform:none;letter-spacing:0;font-size:14px;
  font-weight:700}

/* =============================================================================
   THE CALENDAR
   =============================================================================
   The browser's own date box is three little spinners in whatever order the
   machine's locale says. This is the band's diary instead: Monday first, six
   rows always so the card does not change height as the months go by, and the
   two things that actually go wrong marked on it — a concert put on a Sunday,
   and two concerts put on one afternoon.

   IT IS NOT A WIDGET IN A BOX. The first version had a black title bar with the
   month centred in it and an arrow at each end, a hairline round the outside
   and a grey footer strip — the shape every date picker on the internet had in
   about 2010, and it read as one. This one is a page of a diary: the month set
   in the band's own display type, the days in open space with nothing ruled
   round them, and one hairline where the week begins.
   ========================================================================== */
/* 382 wide, not 360: measured against the clock beside it — a 300px face
   under a 56px readout, over a 44px line of controls, 456px in all. At 360 the
   calendar was 437 and the two columns ended at different heights; at 382 it
   is 455, and the bracket reads as one composition rather than two things
   that happen to be side by side. */
.ad-cal{max-width:382px}

.ad-cal-top{display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;padding:2px 0 10px}
/* THE MONTH AND THE YEAR ARE BUTTONS. Drawn as the heading they were — the
   band's display type, no box — and pressable: the month opens the twelve
   months, the year the twelve years, each in the days' own space. */
.ad-cal-jump{font:inherit;font-weight:inherit;font-size:inherit;letter-spacing:inherit;
  color:inherit;background:none;border:0;padding:0 2px;margin:0 -2px;cursor:pointer;
  border-bottom:3px solid transparent;transition:.15s}
.ad-cal-jump:hover,.ad-cal-jump.on{border-bottom-color:var(--gold)}
.ad-cal-jump:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-cal-year{color:var(--mute);font-weight:700}
/* One cell, three pages, one showing — so the height is the days' whether the
   months or the years are up. */
.ad-cal-body{display:grid}
.ad-cal-page{grid-area:1/1}
.ad-cal-page.is-off{visibility:hidden;pointer-events:none}
.ad-cal-picks{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;
  align-content:center;padding:10px 0}
.ad-cal-pick{min-height:50px;font:inherit;font-weight:700;font-size:15px;
  background:#fff;border:2px solid var(--line);color:var(--ink);cursor:pointer;
  transition:.15s}
.ad-cal-pick:hover{border-color:var(--ink)}
.ad-cal-pick.on{background:var(--scarlet);border-color:var(--scarlet);color:#fff}
.ad-cal-pick:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-cal-month{font-size:23px;font-weight:900;letter-spacing:-.01em;
  line-height:1.1;color:var(--ink)}
/* The year is the quiet half of it: you know which year it is, and you are
   looking for a month. */
.ad-cal-month span{color:var(--mute);font-weight:700}

.ad-cal-steps{display:flex;gap:4px;flex:none}
.ad-cal-step{width:40px;height:40px;flex:none;font:inherit;font-size:20px;
  line-height:1;background:none;border:1px solid var(--line);color:var(--ink);
  cursor:pointer;transition:.15s}
.ad-cal-step:hover{background:var(--ink);border-color:var(--ink);color:#fff}
.ad-cal-step:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}

.ad-cal-week{display:grid;grid-template-columns:repeat(7,1fr);
  padding:0 0 8px;border-bottom:1px solid var(--line);
  font-size:11.5px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  text-align:center;color:var(--mute)}
/* SATURDAY IS THE BAND'S DAY, said in the heading rather than by tinting the
   whole column. A tinted column reads as a spreadsheet; a scarlet letter reads
   as "look here first", which is what it is for. */
.ad-cal-week .is-sat{color:var(--scarlet)}

.ad-cal-days{display:grid;grid-template-columns:repeat(7,1fr);
  gap:2px;padding:6px 0 0}

.ad-cal-day{position:relative;aspect-ratio:1;display:grid;place-items:center;
  font:inherit;font-size:15px;font-weight:500;background:none;border:0;
  color:var(--ink);cursor:pointer;transition:background .12s,color .12s}
.ad-cal-day:hover{background:var(--tint)}
.ad-cal-day:focus-visible{outline:3px solid var(--scarlet);outline-offset:-3px}

/* Saturdays carry the weight instead of a background. */
.ad-cal-day.is-sat{font-weight:900}

/* Already gone. Quieter, and still choosable — a concert entered after the fact
   is a real thing, and refusing it would only teach people to lie about it. */
.ad-cal-day.is-gone{color:var(--mute)}

/* The days either side of the month, in their own places. Quiet enough not to
   be mistaken for this month and solid enough to be aimed at. */
.ad-cal-day.is-spill{color:#C3B8B3;font-weight:500}

/* Today, under the number, in the band's gold. */
.ad-cal-day.is-today b{box-shadow:0 3px 0 var(--gold)}

/* A day the band is already out on: a scarlet bar under the number, the same
   mark the site puts under a heading. The dot it started as was a full stop.
   This is the whole point of drawing a calendar rather than a box — two
   concerts on one afternoon is invisible in "2026-09-06" and obvious here. */
.ad-cal-day.is-busy::after{content:'';position:absolute;left:50%;bottom:6px;
  width:14px;height:3px;margin-left:-7px;background:var(--scarlet)}

.ad-cal-day.on{background:var(--scarlet);color:#fff;font-weight:900}
.ad-cal-day.on:hover{background:var(--royal)}
.ad-cal-day.on::after{background:var(--gold)}

.ad-cal-said{margin:14px 0 0;padding:12px 0 0;border-top:1px solid var(--line)}

/* IN THE WALKTHROUGH IT IS THE ONLY THING ON THE SCREEN, so it takes the whole
   of it. At 340px in an 880px card it sat in the corner like something that had
   not finished loading.

   The cells stop being squares there and become the wide rows a wall calendar
   has — a square cell across a full-width card would be 110px of nothing with a
   number in the middle. */
.ad-ask-one .ad-cal{max-width:none;width:100%}
.ad-ask-one .ad-cal-month{font-size:30px}
.ad-ask-one .ad-cal-week{font-size:12px;padding-bottom:10px}
.ad-ask-one .ad-cal-days{gap:3px;padding-top:8px}
.ad-ask-one .ad-cal-day{aspect-ratio:auto;min-height:58px;font-size:18px}
.ad-ask-one .ad-cal-day.is-busy::after{width:18px;height:3px;margin-left:-9px;
  bottom:9px}
.ad-ask-one .ad-cal-said{font-size:16.5px;margin-top:16px}

/* ---- what the answer means, under the answer ----
   The day of the week under a date, and what the posters will bill an address
   as. Quiet: it is the answer read back, not another thing to fill in. */
/* THE LINE IS HELD OPEN ONLY WHERE IT IS ABOUT TO BE USED. The min-height is
   here so that a line appearing as somebody types an address does not shove the
   rest of the card down under their hands. But on a concert with no address yet
   it reserved that space under every field that could ever have one, which is a
   gap on a new card that nothing accounts for. Empty and not being typed into,
   it takes no room; empty and in use, it holds its line. */
.ad-says{margin:7px 0 0;font-size:13.5px;color:var(--mute);min-height:1.2em}
.ad-says:empty{min-height:0;margin:0}
.ad-field:focus-within .ad-says:empty{min-height:1.2em;margin:7px 0 0}

/* The suggested short name, offered as the words it would be. */
.ad-take-slug{font:inherit;font-size:13.5px;font-weight:700;color:var(--scarlet);
  background:none;border:0;border-bottom:1px solid var(--line);padding:0 1px;
  cursor:pointer}
.ad-take-slug:hover{border-bottom-color:var(--scarlet)}
/* ---- saying the town yourself ----
   The line under an address shows what the rule decided and offers to change
   it; this is what it opens into. Small, on the same line as the way back to
   the rule, because it is a correction to a sentence rather than a field on a
   form — the moment it looks like a field, every concert the rule gets right
   has an empty box on it asking a question nobody needed to answer. */
/* Two classes here for the same reason as below, and a different rule: this is
   a <label>, and `.ad-field label` dresses every label on a form as a block-
   level grey capital heading. Left to that it broke the line and put the way
   back to the address underneath the box. */
.ad-says .ad-bill{display:inline-block;margin-right:10px;
  font-weight:500;font-size:inherit;letter-spacing:0;text-transform:none}
/* TWO CLASSES DELIBERATELY. `.ad-field input` sets the width and height of
   every box on a form — full width, 48px — and says so later in this file than
   this does, so a single class here loses on source order and the correction
   comes out the size of the address above it. */
.ad-says .ad-bill input{font:inherit;font-size:14px;font-weight:500;
  letter-spacing:0;text-transform:none;width:11em;max-width:100%;
  min-height:38px;padding:0 10px;
  border:2px solid var(--line);border-radius:0;background:#fff;color:var(--ink)}
.ad-says .ad-bill input:focus{border-color:var(--ink);
  outline:3px solid var(--scarlet);outline-offset:1px}
.ad-says b{color:var(--ink);font-weight:700}
.ad-ask-one .ad-says{font-size:15px}

/* ---- the foot ----
   The ways of getting rid of the thing sit at one end and the way of being
   finished with it at the other, so the two are never pressed for each other. */
.ad-card-foot{position:sticky;bottom:0;z-index:3;
  display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;
  padding:16px 24px;border-top:1px solid var(--line);background:var(--tint)}
.ad-card-foot .btn{margin-left:auto}
.ad-card-foot .ad-remove{margin:0}

@media(prefers-reduced-motion:reduce){
  .ad-card[open],.ad-card[open]::backdrop{animation:none}
}

/* ---- what has already happened ----
   A diary is mostly the past: seven concerts this season under ninety that have
   gone. They fold away a week after they happen — a concert is still being
   talked about the week after it, and that is when the photographs and the
   result go in. */
/* ---- THE ARCHIVE ----
   A section of the list, not a box under it. The head is the whole width and
   is the button: the red strip names it, the count sits beside it in the
   list's own grey, and SHOW / HIDE is at the far end in the pressable
   capitals. No rule of its own above it — the last entry already draws one,
   and two rules a hand apart was the "something failed to load" look. */
.ad-past{margin-top:28px}
.ad-past-head{width:100%;display:flex;align-items:center;gap:14px;min-height:52px;
  padding:0;background:none;border:0;font:inherit;text-align:left;
  color:var(--mute);cursor:pointer}
.ad-past-head .ad-past-name{margin:0;flex:0 0 auto}
.ad-past-count{flex:1 1 auto;font-size:14px}
.ad-past-count b{font-weight:900;color:var(--ink)}
.ad-past-more{flex:0 0 auto;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--scarlet);transition:.15s}
.ad-past-head:hover .ad-past-more{color:var(--royal)}
.ad-past-head:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
.ad-past-list{border-top:1px solid var(--line)}
.ad-past-list:not([hidden]){margin-top:10px;
  animation:ad-unfold var(--ad-quick,.18s) var(--ad-ease,ease) backwards}

/* ---- WHERE AN ENTRY APPEARS ----
   Four places, four lines, square gold marks — a list, because it is one. Two
   columns where there is room, so it takes two lines of the page, not four. */
.ad-appears{margin:12px 0 0;padding:0;list-style:none;
  display:flex;flex-wrap:wrap;gap:6px 30px;font-size:15.5px}
.ad-appears li{position:relative;padding-left:18px}
.ad-appears li::before{content:"";position:absolute;left:0;top:.5em;
  width:8px;height:8px;background:var(--gold)}

/* ---- THE FILTERS ----
   Under the bar, in a line of their own: the choice of kind as the buttons a
   card uses for a choice, and the tick. Both hide rows the way the search
   does. */
.ad-filters{display:flex;flex-wrap:wrap;align-items:center;gap:12px 22px}
/* The add button keeps to the far end of the bar whatever else is in it, so
   it is in the same place on a list of three and a list of thirty-two. */
/* THE ACTION SITS AT THE RIGHT-HAND END OF THE BAR, on every list, because
   the tally is a label and the button is the thing you came to press. It was
   written against one screen's id, so the Concerts bar pushed its button over
   and the ticketing and social bars left theirs sitting against the count like
   a second sentence. Any bar with a tally in it now behaves the same way. */
.ad-bar > .ad-tally ~ .btn{margin-left:auto}
.ad-filters .ad-pick-one span{min-height:44px;padding:0 16px;font-size:14px}
.ad-filter-tick{display:inline-flex;align-items:center;gap:9px;min-height:44px;
  font-weight:700;font-size:13px;letter-spacing:.06em;color:var(--ink);cursor:pointer}
.ad-filter-tick input{width:18px;height:18px;margin:0;accent-color:var(--scarlet);
  cursor:pointer}

/* A WORD SAYING "OPEN" ON A ROW THAT IS ITSELF THE BUTTON. It was a column of
   its own down the whole list — the same word, thirty-two times, next to an
   arrow already saying it — and on a phone, where the row wraps so the chips
   can drop under the name, it fell onto a third line at the far left with the
   arrow it belonged to still over on the right. The row lights up under the
   pointer and the arrow nudges along; that is the affordance. */

/* ---- the people screen ---- */
/* ---- everybody who can use the admin -------------------------------------
   A GRID, BECAUSE THE QUESTION IS A GRID. Who can reach ticketing is answered
   by running an eye down one column; drawn as thirteen cards it was answered by
   reading thirteen cards. So the four ticks are four columns with a heading
   over them, and the line is a person.

   The pressable part is the whole row: the button is laid across every column
   and the ticks sit over it in their own cells, so pressing a name opens the
   person and pressing a box changes a tick. One control, no overlap of
   meaning — and the chevron ends up at the right-hand edge of the row rather
   than in the middle of it, which is where it would sit if the button only
   covered the name.

   --tick is stated once for both the headings and the rows. They are separate
   elements and the columns have to line up between them; one value is the only
   way that stays true. */
/* 130px is a measured figure: the widest of the four headings set as a small
   capital is ACCOUNTS at 123.5px, and every column is the same width because
   four columns of different widths is not a grid. */
.ad-folk-heads,.ad-folk-list{--tick:130px;--face:54px}
.ad-folk-heads{display:grid;margin-top:4px;padding:0 0 9px;
  grid-template-columns:minmax(0,1fr) repeat(4,var(--tick)) 34px;
  align-items:end;border-bottom:1px solid var(--line)}
.ad-folk-heads span{text-align:center;font-size:11.5px;font-weight:900;
  letter-spacing:.14em;text-transform:uppercase;color:var(--mute);line-height:1.2}
.ad-folk-list{border-top:0}

.ad-folk{display:grid;align-items:center;
  grid-template-columns:minmax(0,1fr) repeat(4,var(--tick)) 34px}
.ad-folk .ad-head{grid-column:1/-1;grid-row:1;min-height:64px;
  padding-right:calc(4 * var(--tick) + 34px)}
.ad-folk .ad-name{font-size:16px}
/* One fact about where somebody stands, not a gold bar and a grey line saying
   the same thing in two weights. Bolder when it is the one worth acting on. */
.ad-folk .ad-sub-text i{font-style:normal}
.ad-folk-wait{font-weight:700;color:var(--ink)}

/* --col is set on the element, by the code that knows which tick it is drawing.
   Written here as :nth-of-type it was a class AND a pseudo-class, which beats
   the plain class the phone rule below uses however late that rule comes — so
   the ticks never came back under the name and a 390px screen laid four
   columns of 150px across it. */
.ad-folk-tick{grid-row:1;grid-column:var(--col);justify-content:center;
  min-height:44px;position:relative;z-index:1}
/* The words are in the heading above, once, rather than beside every box —
   which is what makes the columns columns. The label still says them to a
   screen reader, from the aria-label on the box itself. */
.ad-folk-word{display:none}

/* ---- THE ROW YOU HAVE OPEN --------------------------------------------------
   A list of accounts is a grid you run an eye down, and the one you have opened
   was marked by a chevron that had turned and by a panel appearing underneath
   it — both of which are below the line rather than on it. Opening the fourth
   row on a list of thirteen left the line itself looking exactly like the
   twelve it was among.

   So the bar is scarlet while it is open, ticks and all, and the panel beneath
   it stays white and carries the crest. The two halves then read as one thing:
   a heading and its page. It is the site's own pair — ink or scarlet above,
   white below — used on the smallest surface it has.

   :has(), rather than a class put on by hand. The state is already written on
   the button as aria-expanded, which is where a screen reader reads it from; a
   second copy of the same fact kept in a class is a second copy to forget to
   update. Used once already in this file, on the card that asks one question. */
.ad-folk:has(.ad-head[aria-expanded="true"]){background:var(--scarlet);color:#fff}
/* The tint on hover would paint over the scarlet, so the open row keeps its
   colour and darkens instead — royal, which is the site's answer to "the same
   red, pressed". THE WHOLE BAR, not the button: the button is the left two
   thirds and the ticks are laid over the rest, so darkening only what the
   pointer is technically on would light half a row at a time. */
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-head:hover{background:none}
.ad-folk:has(.ad-head[aria-expanded="true"]):hover{background:var(--royal)}
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-sub-text{color:rgba(255,255,255,.82)}
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-folk-wait{color:#fff}
/* The chevron is drawn from two borders rather than from a colour, so both. */
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-head::after{
  border-right-color:var(--gold);border-bottom-color:var(--gold)}
/* The face, exactly as it is drawn on the ink banner: the frame and the
   initials change and the photograph needs no help. Not .ad-who-dark itself,
   because that class is put on by the code that knows it is drawing onto ink
   and this is a row that has only just become scarlet. */
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-who{
  background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.34);
  color:var(--gold)}
/* GOLD, NOT WHITE. A white box with the browser's dark tick in it reads as an
   empty box at a glance on a scarlet ground — the fill and the surround are
   the two lightest things on the row and the tick is lost between them. Gold
   is the site's mark on scarlet everywhere else, and the tick the browser puts
   inside it comes out dark. An empty box keeps its own outline. */
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-tickbox input{
  accent-color:var(--gold);outline:1px solid rgba(255,255,255,.45);
  outline-offset:-1px}
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-tickbox.is-locked{
  color:rgba(255,255,255,.7)}
.ad-folk:has(.ad-head[aria-expanded="true"]) .ad-tickbox.is-locked input{
  accent-color:rgba(255,255,255,.55)}

/* What unfolds starts where the name does, not under the face. */
.ad-folk-list .ad-body{padding-left:var(--face)}
/* AND THE PANEL IS THE WHITE HALF OF IT. It sits under a scarlet bar now, so it
   is given its own white ground rather than inheriting whatever is behind the
   list, and a little more room at the top and bottom so the pair reads as one
   block rather than as a bar with something loose under it. */
.ad-folk-list .ad-body{background:#fff;padding-top:18px;padding-bottom:28px;
  padding-right:14px}
.ad-folk-more{display:grid;gap:24px 32px;
  grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.ad-folk-more .ad-sub{margin-top:0}
.ad-folk-more .hint{margin:9px 0 0;font-size:13px;line-height:1.5;color:var(--mute)}
/* AIR UNDER THE HEADING. Three columns, and this was the one where the scarlet
   heading was followed straight away by another line of small capitals — "Their
   photograph" and "Who is this?", the same size and weight, four pixels apart,
   reading as one stuttering heading rather than as a heading and the thing
   under it. The other two columns open with a button or a paragraph, which
   carry their own air. Measured at 0px against the 9px the third column's
   words get. */
.ad-folk-more .ad-person-face{padding-top:0;margin-top:9px}
.ad-folk-more .ad-person-do{margin-top:9px}
/* The label goes above the box here rather than beside it: these are columns
   of about 250px, and "Who is this?" beside a menu wrapped to three lines of
   two words. */
.ad-folk-more .ad-who-pick{flex-direction:column;align-items:flex-start;gap:5px}
.ad-folk-more .ad-who-pick select{width:100%}

/* A PHONE HAS NO ROOM FOR A MATRIX. The heading row goes, the ticks come back
   under the name with their words beside them, and the row is as tall as it
   needs to be — which on a phone is the right answer, because there is no
   column to run an eye down. */
@media(max-width:820px){
  .ad-folk-heads{display:none}
  .ad-folk{grid-template-columns:minmax(0,1fr)}
  .ad-folk .ad-head{grid-column:1;padding-right:34px}
  .ad-folk-tick{grid-row:auto;grid-column:1;justify-content:flex-start;
    padding-left:var(--face);min-height:38px}
  .ad-folk-word{display:inline}
  .ad-folk-list .ad-body{padding-left:0}
  /* And the face stays beside the name. A card row wraps on a phone so its
     chips can drop below the name; this row has no chips, and wrapping put a
     40px photograph on a line of its own above every person. */
  .ad-folk .ad-head{flex-wrap:nowrap}
}

/* The photograph controls keep their own description further down this file —
   this is only the row of buttons, which used to be a column because it stood
   at the end of a card and now sits inside one. */
.ad-person-do{display:flex;flex-wrap:wrap;gap:6px}
.ad-person-do button{min-height:44px;padding:0 14px;font:inherit;font-size:12.5px;
  font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  background:#fff;color:var(--ink);border:1px solid var(--line);cursor:pointer}
.ad-person-do button:hover{border-color:var(--ink)}
.ad-tickbox{display:flex;align-items:center;gap:9px;min-height:32px;
  font-size:14px;cursor:pointer}
.ad-tickbox input{width:20px;height:20px;flex:0 0 auto;accent-color:var(--scarlet)}
/* ---- a tick that is not yours to change ----
   What somebody is ticked for is a decision the band makes about them, so
   nobody sets their own — and the account that looks after the accounts is the
   one nobody else may touch at all. The row says so rather than being labelled:
   the box greys the way the browser greys any box it will not take, the words
   beside it on a phone go with it, and the pointer stops offering. The sentence
   is on the label, for a hover and for a screen reader; the server refuses in
   any case. */
.ad-tickbox.is-locked{cursor:default;color:var(--mute)}

/* ---- the same ticks, on the card that makes an account --------------------
   Deliberately the same boxes as the People screen's, because they are the same
   four decisions: what somebody chooses when making an account should look like
   what they will change afterwards. The card gives each one room for a line
   saying what the tick actually lets a person do — on the People screen that
   context is the column heading, and here there is none. */
.ad-ask-ticks{margin:0;padding:0;border:0}
/* EVERY ONE OF THESE IS UNDOING `.ad-field label`, which dresses a label in
   this admin as a small grey capital heading — right for the word above a box,
   wrong for a line of words beside a tick. It is more specific than .ad-tickbox
   on its own, so the whole of it has to be said again here: the layout, the
   type, and the capitals, which are inherited by the words inside. */
.ad-ask-ticks .ad-tickbox{display:flex;align-items:flex-start;gap:11px;
  min-height:0;padding:9px 0;border-bottom:1px solid var(--line);
  font-weight:500;font-size:14.5px;letter-spacing:0;text-transform:none;
  color:var(--ink)}
.ad-ask-ticks .ad-tickbox:last-of-type{border-bottom:0}
/* And the box itself, for the same reason: a form field in this admin is the
   full width of its column, which is right for something you type into and
   absurd for a tick — it made the checkbox as wide as the card and pushed the
   words off the edge of it. */
.ad-ask-ticks .ad-tickbox input{width:20px;height:20px;min-height:0;flex:0 0 auto;
  margin-top:2px;padding:0;border:0;background:none;accent-color:var(--scarlet)}
.ad-ask-ticks .ad-tickbox span{display:block;line-height:1.35}
.ad-ask-ticks .ad-tickbox b{display:block;font-weight:700;font-size:14.5px}
.ad-ask-ticks .ad-tickbox i{display:block;font-style:normal;font-size:13px;
  color:var(--mute)}
.ad-entry.past .ad-folk{opacity:.6}

/* =============================================================================
   A FACE
   =============================================================================
   Most people who use this admin are in the band, and their photograph is
   already on the website. So an account does not carry its own: it carries the
   name of the player it belongs to, and the picture follows from the Players
   list — one photograph of each person, kept by whoever looks after the site.
   functions/_lib/faces.js decides which; this only draws it.

   INITIALS WHEN THERE IS NONE, not a grey outline of a head. Thirteen people
   who know each other are told more by two letters than by a silhouette, and a
   silhouette on every row would say only that nobody had got round to it.

   SQUARE, like everything else on this site. A round avatar is the one place a
   brand with no rounded corners in it always seems to acquire one.

   CALLED .ad-who, NOT .ad-face. There is already an .ad-face on this site — the
   thumbnail against a player in the content lists — declared later in this file,
   so a second one of the same name silently won every property they shared:
   104px squares came out at 46 and the ink screen's frame came out beige. The
   collision cost twenty minutes and would have cost an afternoon if the sizes
   had been closer.

   Royal Red on the initials: small furniture on white, which is the job the
   guidelines give the darker red. 7.64:1 on the tint behind it. */
.ad-who{display:grid;place-items:center;flex:none;overflow:hidden;
  width:44px;height:44px;background:var(--tint);border:1px solid var(--line);
  color:var(--royal)}
.ad-who img{display:block;width:100%;height:100%;object-fit:cover}
.ad-who b{font-weight:900;font-size:15px;letter-spacing:.03em;line-height:1}

.ad-who-sm{width:40px;height:40px}
.ad-who-sm b{font-size:14px}
.ad-who-md{width:64px;height:64px}
.ad-who-md b{font-size:21px}
.ad-who-lg{width:104px;height:104px}
.ad-who-lg b{font-size:34px}

/* On the sign-out tile it stands where the mark stands, so it takes the mark's
   box rather than a size of its own — 76px on the front page, 52 in a wide
   tile, and the foot row spans it across both rows exactly as it does the
   plate. */
.ad-who-tile{width:76px;height:76px;margin-bottom:18px}
.ad-who-tile b{font-size:26px}
.ad-tile.wide .ad-who-tile{width:52px;height:52px;margin:0}
.ad-tile.wide .ad-who-tile b{font-size:18px}
.ad-home-foot .ad-who-tile{grid-row:1/3;align-self:center}

/* ---- the welcome ----
   On ink, where the accent is gold: a tint square with royal initials would be
   a piece of the white page dropped onto a dark screen. The picture itself
   needs no help — it is a photograph — so only the frame and the initials
   change. */
/* ---- on ink ----
   The frame and the initials change; the photograph needs no help. Used by the
   welcome and by the line under the save button, both of which sit on the ink
   banner. */
.ad-who-dark{background:rgba(255,255,255,.06);
  border-color:rgba(255,255,255,.28);color:var(--gold)}
.ad-welcome-face{margin:0 0 18px;background:rgba(255,255,255,.06);
  border-color:rgba(255,255,255,.28);color:var(--gold)}

/* ---- setting one, on the People screen ---- */
.ad-person-face{flex:1 1 100%;display:flex;flex-wrap:wrap;align-items:center;
  gap:10px 16px;padding-top:4px}
.ad-who-pick{display:flex;align-items:center;gap:9px;font-size:11.5px;
  font-weight:900;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
/* Likewise. It was the faintest control in its own row — a 1px hairline and
   14.5px of text beside a 2px button — and it is the one that does the work:
   say who this is and the photograph follows. */
.ad-who-pick select{max-width:min(100%,20em)}
/* The upload is the site's own file-input button, not a second one. */
.ad-who-up span{font-size:13px;padding:0 13px;border-width:2px}
.ad-who-clear{font:inherit;font-weight:700;font-size:13px;letter-spacing:.04em;
  min-height:44px;padding:0 4px;background:none;border:0;cursor:pointer;
  color:var(--scarlet);text-decoration:underline}
.ad-who-clear:hover{color:var(--royal)}
.ad-who-say{font-size:13px;color:var(--mute);min-height:1.2em}

/* ---- what changed ---- */
.ad-diff{width:100%;border-collapse:collapse;font-size:13.5px}
.ad-diff th{text-align:left;font-weight:700;padding:7px 12px 7px 0;
  vertical-align:top;width:40%}
.ad-diff td{padding:7px 12px 7px 0;vertical-align:top;width:30%}
.ad-diff tr+tr th,.ad-diff tr+tr td{border-top:1px solid var(--line)}
.ad-diff .was{color:var(--mute);text-decoration:line-through}
.ad-diff .now{color:var(--ink);font-weight:700}

/* =============================================================================
   THE ANALYTICS SCREEN
   =============================================================================
   It holds more than any other screen in the admin, and for a while it showed
   all of it at once: nine headings down one column, every one at the same
   volume, four screens deep. Nothing was wrong with any single part — the fault
   was that the screen had no opinion about what mattered.

   So it is now read from the top down, in three sizes.

     ONE SENTENCE  — what happened, in the words somebody would use out loud.
     FOUR FIGURES  — and pressing one draws it on the chart underneath.
     FIVE CARDS    — one shape repeated, each showing one face at a time.

   Nothing was taken away. Every list that was on the screen is still on it, and
   the download still carries the lot. What changed is that the reader is shown
   the first five rows and chooses the rest, rather than being handed
   four hundred and made to find the twelve that mattered.
   ========================================================================== */

/* ---- choosing the stretch of time ----
   Presets for the questions somebody actually asks, and two date boxes for the
   one they have not thought of. The presets are not a select: six words visible
   at once are quicker to compare than six hidden behind a click, and on a phone
   they wrap into rows rather than opening a system picker over the page. */
.an-range{display:flex;flex-wrap:wrap;align-items:flex-end;
  justify-content:space-between;gap:14px 22px;margin:0 0 22px;
  padding-bottom:18px;border-bottom:1px solid var(--line)}
.an-presets{display:flex;flex-wrap:wrap;gap:6px}
.an-when-btn{font:inherit;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;min-height:44px;padding:0 13px;cursor:pointer;
  background:none;border:2px solid var(--line);color:var(--ink);
  transition:border-color .16s,background .16s,color .16s}
/* HOVER IS INK, CHOSEN IS SCARLET — the admin's own tab bar (.ad-tab) has said
   so since it was built, and this screen had it the other way round. Filled
   rather than merely outlined either way: a border a shade darker than its
   neighbours is not a state anybody notices. */
.an-when-btn:hover{border-color:var(--ink);color:var(--ink)}
.an-when-btn.on{background:var(--scarlet);border-color:var(--scarlet);color:#fff}

.an-dates{display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  font-size:12.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--mute)}
.an-dates label{display:flex;align-items:center;gap:7px}
.an-dates input{font:inherit;font-size:14px;letter-spacing:0;text-transform:none;
  color:var(--ink);min-height:44px;padding:0 10px;
  border:1px solid var(--line);background:#fff}

/* While the figures are being fetched. Faded rather than replaced by a spinner:
   the numbers on screen are the ones being replaced, and dimming them says
   "these are on their way out" without taking away what there is to read. */
#adminBody.is-waiting{opacity:.55;pointer-events:none;transition:opacity .18s}

.an-each{font-weight:500;letter-spacing:0;text-transform:none;color:var(--mute)}

/* ---- the sentence at the top ----
   The whole screen in one line, in the language somebody would use to say it
   out loud. A reader who stops here has still been told the thing they came
   for; everything below is the working. */
.an-say{max-width:62ch}
.an-say b{font-weight:900}
/* What a visit is, and what the figures are NOT. Set small and grey on purpose:
   it is the small print under the sentence, and at body size it competed with
   the sentence it was explaining. Sessions and page views are the pair everybody
   confuses, so the definition stays on the screen rather than in a manual. */
.an-mean,.an-soft{max-width:74ch;margin-top:10px;font-size:13.5px;
  line-height:1.55;color:var(--mute)}

/* ---- what it is narrowed to ----
   Said on the screen rather than left to be remembered. A filtered figure that
   looks like a total is the most quotable wrong number a page like this can
   produce. Each chip removes its own filter; the last removes them all. */
.an-chips{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  margin:0 0 20px}
.an-chips-say{font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute)}
.an-chip{font:inherit;font-weight:700;font-size:13px;min-height:44px;
  padding:0 12px;cursor:pointer;background:var(--scarlet);color:#fff;border:0;
  transition:background .16s}
.an-chip:hover{background:var(--royal)}
.an-chip-all{background:none;color:var(--mute);border:2px solid var(--line)}
.an-chip-all:hover{background:none;border-color:var(--royal);color:var(--royal)}

/* ---- the headline figures, which ARE the chart's controls ----
   There used to be a strip of figures and, below it, a separate pair of buttons
   saying which of them the chart was drawing: two places to look for one idea.
   Pressing the figure itself is the same gesture with nothing to learn.

   THE PRESSED ONE IS FILLED WITH INK AND CARRIES A SCARLET EDGE ALONG THE TOP,
   so which figure the chart is drawing survives being read in a hurry, in
   greyscale, or by somebody who cannot separate scarlet from grey. */
.an-heads{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:14px;margin:4px 0 10px}
.an-big{position:relative;display:block;width:100%;text-align:left;font:inherit;
  color:inherit;border:1px solid var(--line);background:var(--tint);
  padding:18px 20px;transition:background .18s,border-color .18s,transform .18s}
button.an-big{cursor:pointer}
/* The same lift and the same lightening as every other tile in this admin —
   the figures are pressable, so they behave like the things that are. */
/* :not(.on), or hovering the chosen figure would lighten it back to white —
   the hover rule is more specific than the chosen one and would win. */
button.an-big:not(.on):hover{background:#fff;border-color:var(--royal)}
button.an-big:hover{transform:translateY(-3px)}
button.an-big:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
.an-big::before{content:'';position:absolute;left:-1px;right:-1px;top:-1px;
  height:6px;background:var(--gold);transform:scaleX(0);transform-origin:left;
  transition:transform .22s var(--ad-ease,ease)}
/* SCARLET, NOT INK. Scarlet is what this site fills a chosen thing with and
   ink is what it fills a hovered one with — the admin's tab bar has done both
   since it was built. The gold bar above it sits on scarlet exactly as the
   header's gold rule does. */
.an-big.on{background:var(--scarlet);border-color:var(--scarlet);color:#fff}
.an-big.on::before{transform:scaleX(1)}
.an-big b{display:block;font-size:clamp(28px,3.6vw,42px);line-height:1;
  font-weight:900;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.an-big-what{display:block;margin-top:6px;font-size:11.5px;font-weight:900;
  letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
/* WHITE, NOT GOLD. Gold on scarlet measures 3.75:1 — enough for a bar or a
   piece of display type, not for a 12px label. Gold leads on ink; on scarlet,
   small text is white. */
.an-big.on .an-big-what{color:rgba(255,255,255,.92)}
.an-big-move{display:block;margin-top:12px}
/* The direction is a word AND a colour, never a colour alone: "+34%" says it
   without anybody having to know that scarlet means up, and roughly one man in
   twelve cannot reliably tell this site's scarlet from a green anyway.

   ON INK IT IS GOLD, not scarlet — scarlet on ink measures 3.07:1, the bare
   floor for a graphic and it looks like it. Scarlet leads on white; gold leads
   on ink, everywhere on this site. */
.an-move{display:inline-block;font-weight:900;font-size:14px}
.an-move.up{color:var(--scarlet)}
.an-move.down{color:var(--mute)}
/* Level is neither. It used to be scarlet, which is this site's word for "more"
   — so a month that had not moved was coloured as though it had. */
.an-move.level{color:var(--ink)}
.an-big.on .an-move.up,.an-big.on .an-move.level{color:#fff}
/* The site's own way of quietening text on a dark surface — .dark p is
   rgba(255,255,255,.82) — rather than a grey mixed for this one screen. */
.an-big.on .an-move.down,.an-big.on .an-was{color:rgba(255,255,255,.82)}
.an-was{margin-left:8px;font-size:13px;color:var(--mute)}
.an-soft{margin:0 0 18px}

/* ---- what the chart is drawing, and how it is grouped ----
   Which measure is a choice the browser can make on its own — every one of them
   is already here for every bucket. The grouping is not: it decides what the
   database was asked, so it costs a round trip and sits apart from the thing
   that does not. */
.an-chart-bar{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:8px 20px;margin:14px 0 4px}
.an-drawing{margin:0;font-size:13px;color:var(--mute)}
.an-drawing b{color:var(--ink);font-weight:900}
.an-by{font-size:11.5px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mute);display:flex;align-items:center;gap:8px}
/* Nothing of its own left: it was a 14px box with a 1px edge in a toolbar,
   which is a fourth answer to a question the site had already answered. */

/* ---- the line, once there are too many points for bars ----
   Thin, and one pixel whatever the width: the drawing is stretched to fit its
   box, so without non-scaling-stroke a line drawn a pixel wide comes out three
   on a laptop and hairline on a phone. */
.an-line{height:170px;margin:6px 0 0;border-bottom:2px solid var(--line);
  cursor:crosshair;touch-action:pan-y}
.an-line svg{display:block;width:100%;height:100%;overflow:visible}
/* IT DRAWS ITSELF, left to right, in half a second. The stylesheet cannot know
   how long the path is and the length changes with every range asked for — so
   the path is told to call itself one unit long (pathLength="1" in admin.js),
   and a dash one unit long held back by one unit is a line that has not started
   yet. */
.an-line-path{fill:none;stroke:var(--scarlet);stroke-width:1.5;
  vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round;
  stroke-dasharray:1;stroke-dashoffset:1;animation:an-draw .62s ease-out forwards}
/* Faint. The line is the reading, and a solid wedge under a year of traffic
   makes it harder to follow rather than easier. */
.an-line-fill{fill:var(--scarlet);opacity:.07;stroke:none;
  animation:an-fade .7s ease-out backwards;animation-delay:.15s}
.an-line-cursor{stroke:var(--royal);stroke-width:1;vector-effect:non-scaling-stroke;
  opacity:.45}
/* Every point carries a dot, invisible until it is the one being pointed at —
   drawing them all would turn a smooth line back into a comb. */
.an-dot{fill:var(--scarlet);opacity:0;transform-box:fill-box;
  transform-origin:center;transition:opacity .12s}
.an-dot.on{opacity:1}
/* SCARLET, NOT THE SITE'S GOLD RING, and only because of the surface. Gold on
   white measures 1.77:1 — a focus ring nobody can see is not a focus ring, and
   the standard asks for 3:1 on a mark like this. Scarlet on white is 6.17:1.
   The gold ring is right everywhere it sits on scarlet or ink; here it is not,
   which is why the admin's other rings are scarlet too. */
.an-line:focus-visible{outline:3px solid var(--scarlet);outline-offset:3px}

.an-read{margin:10px 0 0;min-height:1.5em;font-size:14.5px}
.an-read b{font-weight:900}
.an-read-was{margin-left:10px;color:var(--mute);font-size:13px}

/* ---- the stretch before ----
   Drawn behind the current one and deliberately hard to mistake for it: dashed,
   thin, grey. A second line as strong as the first is two charts on one axis,
   and the reader has to work out which is which before they can read either.

   ITS DASHES ARE ITS OWN and must stay that way, which is why it fades in
   instead of drawing itself: the drawing trick above works by taking the dash
   pattern over, and a comparison line that arrived solid would read as a second
   reading rather than as context. */
.an-line-was{fill:none;stroke:var(--mute);stroke-width:1;opacity:.55;
  stroke-dasharray:4 4;vector-effect:non-scaling-stroke;stroke-linejoin:round;
  animation:an-fade .5s ease-out backwards;animation-delay:.3s}

.an-key{display:flex;align-items:center;gap:8px;margin:8px 0 0;
  font-size:12.5px;color:var(--mute)}
.an-key-was{display:block;width:26px;height:0;flex:none;
  border-top:1px dashed var(--mute)}

/* Sits with the SHOW button and is deliberately the quieter of the two: taking
   the figures away is a thing somebody does once a quarter for a committee
   paper, not the reason they opened the screen. */
.an-get:disabled{opacity:.4;cursor:not-allowed}

/* ---- the cards ----
   ONE SHAPE, REPEATED, and each shows one face at a time. Five cards with a
   name and a row of tabs is one thing to learn; nine headings down a column is
   nine things to weigh up, all of them shouting equally.

   align-items:start, so a card with eight rows does not stretch the one beside
   it to match — a stretched card is mostly empty space with a rule round it. */
/* min(100%,400px), NOT 400px. A bare minimum in minmax() is a floor the grid
   keeps even when the column has less room than that — so on a 390px phone the
   cards stayed 400 wide and the whole page could be scrolled sideways by 34px.
   Measured, not guessed: the document was 424px across a 390px window. */
/* ---- how much scarlet a card carries ----
   FULL STRENGTH BELONGS TO THE CHART and to the figure you have chosen — those
   are the reading. Four cards of ranked lists at the same strength turned the
   screen into a wall of red, and a colour used for everything stops pointing at
   anything.

   So the lists are drawn in a wash of the same scarlet rather than in a second
   colour: one red, at two strengths. Measured against the track it sits in —
   #E5A5AB on #E6DDD8 is 1.52:1, which is a bar you can see at a glance; the
   figure is printed beside every one of them in any case, so the bar is the
   shape of the answer rather than the answer itself. */
/* Set here rather than on .an-rank-bar itself because a card can hold other
   ranked things; every bar that stands behind words takes it, and the two
   charts on this screen do not. */
.an-cards{--soft:rgba(190,29,46,.4);
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,400px),1fr));
  gap:18px;align-items:start;margin:30px 0 0}
.an-card{border:1px solid var(--line);background:#fff;padding:18px 20px 22px;
  animation:ad-pop var(--ad-calm,.26s) var(--ad-ease,ease) backwards;
  animation-delay:var(--in,0ms)}
/* Deliberately NOT given the gold bar the site puts under a heading. That bar
   is measured from the words beneath it and its gap equals its own thickness —
   a device built for a heading with a paragraph under it, not for one sharing a
   line with a row of tabs. A plain rule under the whole header keeps the card's
   parts together without inventing a second version of the band's own mark. */
.an-card-top{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:10px 16px;padding-bottom:12px;
  border-bottom:1px solid var(--line)}

/* ---- the card's name ----
   THE BAND'S OWN DEVICE, the same one Book Us uses: a Royal Red strip of white
   Bold text, sentence case, as wide as its words. It is lifted from the social
   media plan, where forty-one blocks are headed exactly like this, and the
   plan's brand note is explicit — Royal Red #A50E0E for on-page elements,
   badges, boxes and rules, "since none sit on a coloured background". Heritage
   Scarlet leads whole surfaces; Royal Red does the small furniture on white.
   White on royal is 7.87:1.

   It replaces the admin's 12px scarlet label, which was too quiet to hold a card
   together — beside a row of 44px tabs it read as a caption for the tabs rather
   than as the name of the thing. Set at 17px rather than Book Us's 20: this one
   shares its line, and the strip has to sit inside a card rather than head a
   section of the page.

   The inset follows the document it came from — 5px at the sides against 4px
   above and below, the fill drawn almost exactly round the words, which is the
   reverse of how a button is padded. */
.an-card-name{display:inline-block;margin:0;background:var(--royal);color:#fff;
  font-weight:700;font-size:17px;line-height:1.2;letter-spacing:.01em;
  text-transform:none;padding:4px 5px}
/* A card's note explains the list under it and must not compete with it. At
   body size — which is what it inherited — three lines of explanation were
   taller and louder than the five rows they were explaining. */
.an-card .hint{margin:12px 0 0;font-size:13.5px;line-height:1.5;max-width:56ch}
.an-card .an-when{font-size:15.5px;margin-top:12px;max-width:46ch}

/* They assemble in the order they are read rather than landing in one frame.
   Written here rather than counted out in the admin: there are four cards, or
   five when the site has had a wrong address asked for, and a stylesheet can
   count that far by itself. */
.an-cards>.an-card:nth-child(2){--in:70ms}
.an-cards>.an-card:nth-child(3){--in:140ms}
.an-cards>.an-card:nth-child(4){--in:210ms}
.an-cards>.an-card:nth-child(n+5){--in:280ms}

.an-subtabs{display:flex;flex-wrap:wrap;gap:4px}
/* 44px, like every other target on this site — the menu rows, the roster jump
   links, the quote dots and the ticket steppers are all 44 and tests/test-mobile
   holds them there. A tab is a thing pressed with a thumb on a phone. */
.an-subtab{font:inherit;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;min-height:44px;padding:0 13px;cursor:pointer;
  background:none;border:1px solid var(--line);color:var(--mute);
  transition:border-color .16s,color .16s,background .16s}
/* An ink OUTLINE on hover, not an ink fill and not a second red: royal is
   spoken for on this screen — it is what the card names are set in — and a
   hovered tab filled with it would read as a second heading. */
.an-subtab:hover{border-color:var(--ink);color:var(--ink)}
.an-subtab.on{background:var(--scarlet);border-color:var(--scarlet);color:#fff}
.an-subtab:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}

/* The face that is showing arrives rather than appearing. Nothing animates on
   the way out — you watch something open, you do not watch it shut. */
.an-panel:not([hidden]){
  animation:ad-unfold var(--ad-quick,.18s) var(--ad-ease,ease) backwards}

/* Five rows, and the rest behind one press. The twentieth most-read page is a
   real answer to a real question, so it is one press away rather than gone. */
.an-rank.folded>li:nth-child(n+6){display:none}
.an-more{margin:8px 0 0;font:inherit;font-weight:700;font-size:12.5px;
  letter-spacing:.09em;text-transform:uppercase;color:var(--scarlet);
  background:none;border:0;padding:0;cursor:pointer;min-height:44px;
  display:inline-flex;align-items:center}
.an-more:hover{color:var(--royal)}
.an-more:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}

/* ---- the clock ----
   Twenty-four bars in a row, midnight to midnight. The same device as the
   thirty-day chart and deliberately so: two charts on one screen that behave
   differently are two things to learn. */
.an-clock{display:flex;align-items:flex-end;gap:2px;height:86px;
  margin:14px 0 0;border-bottom:2px solid var(--line)}
.an-hr{flex:1 1 0;display:flex;align-items:flex-end;height:100%;min-width:0}
/* SCARLET, AND FULL STRENGTH, WHICH IS THE RULE FOR A CHART. This said it was
   scarlet and was drawn at two fifths of it: the wash is set on .an-cards and
   the clock lives inside a card, so it inherited a strength meant for something
   else. The rule is about what the bars ARE, not where they sit — a chart is
   the reading and is drawn at full strength wherever it is; the wash belongs to
   the ranked lists, where the bar sits behind a line of words and the figure is
   printed beside it in any case. Two strengths of one red, each with a job.

   Ink is what it goes to when pointed at, the same way round as the chart. */
.an-hr b{display:block;width:100%;min-height:1px;height:var(--h,0%);
  background:var(--scarlet);transform-origin:bottom;
  animation:an-grow .5s var(--ad-ease,ease) backwards;animation-delay:var(--in,0ms)}
.an-hr:hover b{background:var(--royal)}

.an-when{margin:10px 0 0;font-size:16.5px;max-width:60ch}
.an-when b{font-weight:900}

/* ---- a ranked list where the bar IS the number ----
   The eye compares lengths faster than it compares digits, and the digits are
   there anyway for anybody who wants the figure rather than the shape. */
.an-rank{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:7px}
.an-rank li{display:grid;grid-template-columns:minmax(0,15em) minmax(40px,1fr) auto;
  align-items:center;gap:12px;font-size:14px}
.an-rank-name{overflow-wrap:anywhere}
.an-rank-bar{height:10px;background:var(--line)}
.an-rank-bar b{display:block;height:100%;background:var(--soft,var(--scarlet));
  transform-origin:left;animation:an-fill .55s var(--ad-ease,ease) backwards;
  animation-delay:var(--in,0ms)}
.an-rank-n{font-weight:700;text-align:right;min-width:3.5em;
  font-variant-numeric:tabular-nums}

/* A ranked row that can narrow the screen is a button filling its own row, so
   the whole line is the target rather than the words in it.

   THE ROW ITSELF STOPS BEING A GRID WHEN IT HOLDS ONE. It did not, and the
   result was two grids fighting: the button was laid into the row's first
   column — thirteen ems at most, and free to collapse — so the name got 71
   pixels and the bar 40, and "/index.html" wrapped as "/index.ht ml" on every
   list that could be pressed. Measured, not guessed: the wide lists that could
   not be pressed were drawing their names at 196px and their bars at 863. */
.an-rank.can-pick li{display:block;padding:0}
.an-rank.can-pick button{display:grid;
  grid-template-columns:minmax(0,15em) minmax(40px,1fr) auto;
  align-items:center;gap:12px;width:100%;min-height:44px;padding:2px 6px;
  margin:0 -6px;font:inherit;font-size:14px;text-align:left;cursor:pointer;
  background:none;border:0;color:inherit;transition:background .14s}
.an-rank.can-pick button:hover{background:var(--tint)}
.an-rank.can-pick button:hover .an-rank-bar b{background:var(--royal)}
.an-rank.can-pick button:focus-visible{outline:3px solid var(--scarlet);
  outline-offset:-1px}

@media(max-width:600px){
  /* The name over its own bar rather than three columns squeezed into a phone,
     where the middle one would be about thirty pixels of nothing. */
  .an-rank li,.an-rank.can-pick button{grid-template-columns:1fr auto;
    gap:4px 12px}
  .an-rank-name{grid-column:1}
  .an-rank-n{grid-column:2;grid-row:1}
  .an-rank-bar{grid-column:1/-1}
}

/* ---- how much the site is read ----
   Thirty bars, drawn with heights and nothing else. A charting library would be
   more code than the whole admin to draw a list with heights, and every one of
   them would bring its own colours, its own typeface and its own idea of a
   tooltip into a page built to avoid exactly that. */
.rd-chart{display:flex;align-items:flex-end;gap:3px;height:170px;
  margin:6px 0 0;padding:14px 0 0;border-bottom:2px solid var(--line)}
.rd-bar{flex:1 1 0;display:flex;align-items:flex-end;height:100%;min-width:0}
/* A quiet day is a bar of no height, which reads as missing data rather than as
   a day nobody came. One pixel says "counted, and it was none". */
.rd-bar{position:relative}
/* THEY GROW, LEFT TO RIGHT, and the stagger is capped in admin.js rather than
   proportional: thirty bars fourteen milliseconds apart is a sweep, and three
   hundred at the same spacing is four seconds of watching a chart assemble
   itself, which is a chart nobody can read yet. */
.rd-bar b{display:block;width:100%;min-height:1px;height:var(--h,0%);
  background:var(--scarlet);transform-origin:bottom;
  animation:an-grow .5s var(--ad-ease,ease) backwards;animation-delay:var(--in,0ms)}
.rd-bar:hover b{background:var(--royal)}
/* Reachable with Tab, now that the figure is read off the bar rather than out
   of a tooltip: the ring the rest of the admin uses, on the bar that has it. */
.rd-bar:focus-visible,.an-hr:focus-visible{outline:3px solid var(--scarlet);
  outline-offset:2px}
.rd-bar:focus-visible b,.an-hr:focus-visible b{background:var(--royal)}
/* WHERE THE SAME POSITION IN THE STRETCH BEFORE SAT — a mark across the bar
   rather than a second bar beside it. Two sets of bars at this width become one
   comb and get read as a single series; a level line is the shape of a target
   marker, which people already know how to read. */
.rd-bar i{position:absolute;left:0;right:0;bottom:var(--w,0%);height:0;
  border-top:1px dashed var(--mute);opacity:.75;pointer-events:none}

.rd-axis{display:flex;justify-content:space-between;margin:6px 0 0;
  font-size:12px;font-weight:700;letter-spacing:.06em;color:var(--mute)}

@keyframes an-grow{from{transform:scaleY(.001)}}
@keyframes an-fill{from{transform:scaleX(0)}}
@keyframes an-draw{to{stroke-dashoffset:0}}
@keyframes an-fade{from{opacity:0}}

/* MOVEMENT IS DECORATION AND IT IS THE FIRST THING TO GO. Everything above
   still arrives, still says the same thing and still holds the same figure —
   it simply arrives already there. Note the line: taking only the animation off
   would leave it holding its opening frame, which is a chart with no line in
   it, so the dash it was drawn with is put back as well. */
@media(prefers-reduced-motion:reduce){
  .an-card,.an-panel:not([hidden]),.rd-bar b,.an-hr b,.an-rank-bar b,
  .an-line-fill,.an-line-was{animation:none}
  .an-line-path{animation:none;stroke-dasharray:none;stroke-dashoffset:0}
  .an-big,.an-big::before,.an-chip,.an-when-btn,.an-subtab,
  .an-rank.can-pick button{transition:none}
  button.an-big:hover{transform:none}
}

.ad-note.warn{border-left:4px solid var(--gold);background:var(--tint);
  padding:14px 16px}
.ad-note-form{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.ad-note-form input{flex:1 1 220px;min-height:44px;padding:0 12px;font:inherit;
  border:1px solid var(--line);background:#fff;color:var(--ink)}

/* ---- the welcome ----
   Ink, the crest, a gold rule and the time of day. Square, like everything else.
   It covers the admin for under two seconds and takes any key or any click as
   "yes, thank you, I know who I am".

   THE TYPE IS THE SITE'S, NOT A COPY OF IT. The greeting is the kicker and the
   name is a heading — both declared once, up with the rest of the type, and
   only their colour changed here. Writing the sizes and the tracking out again
   is how a first version ended up setting the name in Title Case with negative
   letter-spacing, which is not how this band sets a heading anywhere else. */
/* THE COVER, put up in the head before the body has painted. It is a rule in
   the stylesheet rather than an element, because an element cannot exist until
   there is a body to put it in — and by then the page has painted, which is the
   flicker this removes. A ::before on the root paints as soon as this file is
   parsed, which is in the head. */
/* PAINTED OVER, NOT TAKEN AWAY. While the server is being asked whether
   somebody is signed in, the door used to be display:none for anybody who was
   signed in last time — which is exactly the person whose password manager has
   something to offer, and a form that is not in the layout is a form no manager
   can see. It is drawn, full size and opaque, with a sheet of ink over the page
   for the fifth of a second the asking takes.

   The same ink as the welcome's own cover, at the same depth, so the two are
   indistinguishable to anybody looking at the screen. */
html.ad-asking::before{content:'';position:fixed;inset:0;z-index:199;
  background:var(--ink)}

html.pre-welcome::before{content:'';position:fixed;inset:0;z-index:199;
  background:var(--ink)}

/* No fade-in on the overlay itself: it arrives on top of a screen that is
   already ink, so fading it in would only delay the crest. The crest, the rule
   and the name have their own entrances and those are the ones worth seeing. */
/* Carries `mark dark` as well, which is where the crest in the corner comes
   from — the site's own watermark rule, not a second one written here. That
   rule sets position:relative; this one is later in the file and at the same
   specificity, so fixed wins. Its overflow:hidden is wanted, and its
   `.mark>*{z-index:1}` is what keeps the crest and the name in front of it. */
.ad-welcome{position:fixed;inset:0;z-index:200;display:grid;place-items:center;
  background:var(--ink);cursor:pointer}

/* The watermark arrives on its own, a beat before the crest, and slowly. It is
   the room the greeting happens in rather than part of the greeting, and
   something that large snapping into place would read as a mistake. */
.ad-welcome::before{animation:ad-wel-mark 1.5s ease both}
.ad-welcome.going{animation:ad-wel-out .5s ease both}
.ad-welcome-in{display:flex;flex-direction:column;align-items:center;
  text-align:center;padding:24px;max-width:min(92vw,760px)}

/* The crest is the point of the screen, so it is given the room to be one.
   Held back from the full width on a phone, where the name underneath needs
   somewhere to go. */
.ad-welcome img{width:clamp(112px,24vw,176px);height:auto;
  animation:ad-wel-crest .78s cubic-bezier(.2,.7,.3,1) both}

/* Drawn from the middle outwards, and sized against the crest above it rather
   than at a number that happens to look right at one width.

   SIX PIXELS IS THE BAND'S BAR, not a thickness chosen by eye. It is the same
   --bar:6px the gold rule under every heading on this site uses; at three it
   was half the brand's own weight and read as a hairline beside a 176px crest.
   Equal space above and below, because here it divides two things rather than
   underlining one — the heading rule's "gap equals thickness" belongs to a bar
   that hugs the word above it, and this one hugs nothing. */
.ad-welcome-rule{display:block;height:6px;width:clamp(150px,32vw,232px);
  background:var(--gold);margin:26px 0;transform:scaleX(0);
  animation:ad-wel-rule .62s .38s cubic-bezier(.2,.7,.3,1) both}

/* The kicker's weight, tracking and casing come from .kicker, up with the rest
   of the type. Only the size is set here, and only because 12px is measured
   against a 48px heading in a column of text — beside a name at 84px on a
   screen with nothing else on it, it disappears. Scaled, not redesigned. */
.ad-welcome-hi{color:var(--gold);margin:0;font-size:clamp(15px,2.4vw,22px);
  font-weight:900;text-transform:uppercase;letter-spacing:.14em;
  animation:ad-wel-up .58s .58s ease both}
.ad-welcome-who{color:#fff;margin:10px 0 0;line-height:1.02;
  animation:ad-wel-up .58s .74s ease both}

@keyframes ad-wel-out{to{opacity:0;visibility:hidden}}
@keyframes ad-wel-crest{from{opacity:0;transform:translateY(14px) scale(.86)}
  to{opacity:1;transform:none}}
@keyframes ad-wel-mark{from{opacity:0}to{opacity:1}}
@keyframes ad-wel-rule{to{transform:scaleX(1)}}
@keyframes ad-wel-up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* Asked for reduced motion, it never runs at all — admin.js returns before
   drawing it. This is here for the case where the setting changes mid-session
   with the overlay already on screen: no movement, and it still goes away. */
@media(prefers-reduced-motion:reduce){
  .ad-welcome,.ad-welcome *{animation:none !important}
}

.ad-bar{display:flex;flex-wrap:wrap;align-items:center;gap:12px;
  margin:0 0 4px;padding-bottom:14px}
.ad-tally{margin:0;font-size:13.5px;color:var(--mute)}
.ad-tally b{color:var(--ink);font-size:14px}
.ad-find{flex:1 1 200px;min-width:0;display:block}
.ad-find input{width:100%;min-height:44px;padding:0 14px;font:inherit;
  font-size:15px;background:#fff;color:var(--ink);border:1px solid var(--line)}
.ad-find input:focus{outline:3px solid var(--gold);outline-offset:1px;
  border-color:var(--ink)}
/* THE ADMIN'S SIZE FOR A SMALL BUTTON, and only the admin's. Written bare, it
   won everywhere — every small button on the public site quietly lost four
   pixels of padding and half a point of type to a rule meant for a list bar.
   The 44px floor is worth having everywhere, so that part has gone up to the
   base rule, and what is left here is scoped to the screens it was written
   for. */
.ad-bar .btn-sm,.ad-actions .btn-sm,.so-form .btn-sm{padding:0 16px;font-size:12px}

.ad-list{border-top:1px solid var(--line)}
.ad-entry{border-bottom:1px solid var(--line)}
/* Gone by, but not gone. A past concert is still edited from here — it holds
   the photographs and the result — so it is quietened rather than hidden. */
.ad-entry.past .ad-head{opacity:.62}
.ad-entry.past .ad-head:hover{opacity:1}

/* The heading IS the control — an entry is opened by pressing its name, not by
   finding a small arrow at one end. */
.ad-head{width:100%;display:flex;align-items:center;gap:14px;
  min-height:64px;padding:12px 38px 12px 0;position:relative;
  background:none;border:0;cursor:pointer;text-align:left;font:inherit;
  color:inherit}
.ad-head:hover{background:var(--tint)}
.ad-head-text{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.ad-name{font-weight:700;font-size:16px}
.ad-name em{color:var(--mute);font-style:italic;font-weight:500}
.ad-sub-text{font-size:13.5px;color:var(--mute);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---- the date, as a date ----
   A block the eye can run down, rather than "2026-08-22" buried in a line of
   prose. It carries the weekday on its bottom line, which is the thing being
   checked; there used to be a second, grey copy of the whole date beside it
   saying the same thing again. See stampHTML() for why the year is usually
   not there. */
.ad-stamp{flex:0 0 auto;display:grid;place-items:center;align-content:center;
  width:58px;padding:7px 0;background:var(--scarlet);color:#fff;
  border-radius:0;line-height:1.1}
.ad-stamp b{font-size:21px;font-weight:900;letter-spacing:-.02em}
.ad-stamp i{font-style:normal;font-size:11.5px;font-weight:900;
  letter-spacing:.14em;text-transform:uppercase}
.ad-stamp u{text-decoration:none;font-size:10px;color:rgba(255,255,255,.72);
  letter-spacing:.06em;white-space:nowrap}
.ad-stamp.past{background:var(--mute)}
/* NO DATE IS NOT A DATE. The dash was drawn inside the scarlet block, so a
   concert with nothing entered had exactly the same weight in the column as
   one happening on Saturday — a solid red plate with a line through it, which
   reads as a cancellation rather than as a blank. */
.ad-stamp-none{width:58px;text-align:center;color:var(--mute);font-size:20px;
  background:var(--tint);border:1px solid var(--line)}

/* ---- a figure on the front of its row ----
   THE SAME BLOCK THE DATE USES, and white on scarlet for the same reason: the
   branding pack calls gold an accent, for dashes and subtle marks, and says in
   as many words that setting text in it cheapens the thing. One figure in gold
   is an accent; forty-four of them down a column is a body of text set in
   gold, which is what the rule exists to prevent.

   Fixed width, so forty-four rows share one left edge for their words. A
   longer figure takes a smaller size rather than a wider block: a block that
   grows moves that row's text out of line with the rest, which is the one
   thing a column down the side is for. */
.ad-token{flex:0 0 auto;display:grid;place-items:center;width:76px;
  min-height:46px;padding:6px 4px;background:var(--scarlet);color:#fff;
  line-height:1.05;text-align:center;overflow:hidden}
.ad-token b{font-size:24px;font-weight:900;letter-spacing:-.02em;
  white-space:nowrap}
.ad-token.n4 b{font-size:19px}
.ad-token.n6 b{font-size:14px;letter-spacing:0}
.ad-token.n8 b{font-size:11px;letter-spacing:.01em}
.ad-token-none{flex:0 0 auto;display:grid;place-items:center;width:76px;
  min-height:46px;background:var(--tint);border:1px solid var(--line);
  color:var(--mute);font-size:20px}

@media(max-width:700px){
  .ad-token,.ad-token-none{width:62px;min-height:42px}
  .ad-token b{font-size:19px}
}

/* ---- a face ----
   A missing photograph becomes an initial rather than a broken-image mark,
   which is what a roster half filled in actually looks like. */
.ad-face{flex:0 0 auto;width:46px;height:46px;border-radius:0;
  object-fit:cover;background:var(--line)}
/* A cover is a landscape: the news list's thumbnails are wide. */
.ad-face-wide{width:76px;height:50px}
.ad-face-none{display:grid;place-items:center;background:var(--tint);
  border:1px dashed var(--line);color:var(--mute);
  font-weight:900;font-size:16px}

/* ---- chips ----
   Only ever things worth acting on: what is missing, what is unusual. A chip on
   every row would be a column, and a column nobody reads. */
.ad-chips{flex:0 0 auto;display:flex;flex-wrap:wrap;gap:5px;justify-content:flex-end;
  max-width:210px}
.ad-chip{font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;padding:4px 8px;border-radius:0;
  background:var(--tint);color:var(--mute);border:1px solid var(--line)}
.ad-chip-gold{background:var(--gold);color:var(--ink);border-color:var(--gold)}
.ad-chip-ink{background:var(--ink);color:#fff;border-color:var(--ink)}
.ad-chip-scarlet{background:var(--scarlet);color:#fff;border-color:var(--scarlet)}

/* ---- what changed, as a diary -------------------------------------------
   The list had been seven copies of one line. The same face, the same name,
   the same address and the same "Today at 11:51" on every row, with the four
   words that differed set third in a queue behind them — so reading it meant
   reading the identical part seven times to find the part that was not.

   Said the way a diary says it, each of those repeats is drawn once: the date
   over everything that happened on it, the person over their own run of it,
   and one line per thing underneath. Every line is then the same shape and
   the same height — a time, and what was done — and the column of times down
   the left is the thing the eye runs on.

   --at is the width of that column, and it is a MEASURED figure rather than a
   guessed one. Noverion has no tabular figures — tabular-nums does nothing to
   it, because the face has no such table — so a time is between 31.8px (11:11)
   and 54.1px (04:44) wide at 13px. Set to the widest of the two hundred and
   forty times a clock can show, plus a little, so no time ever runs into the
   words beside it and the words all start on the same edge whatever the hour
   happens to be. The trailing edge of the times is ragged and that is the right
   way round: the ragged edge falls in the white between the columns, and the
   two straight ones are the page's own margin and the line of summaries the eye
   actually runs down. It is also the indent everything else is measured from,
   so the summaries and the detail that unfolds under them share one edge. */
.ad-log{--at:56px;--at-gap:14px;border-top:0}

/* A LABEL, IN THE ADMIN'S LABEL CAPITALS. This screen has exactly two ways of
   setting small capitals — 900/11.5px/.14em for a label, 700/12.5px/.09em for
   something you press — and a date over a day's work is a label, not a control.
   It arrived as a third setting halfway between the two, which is the kind of
   thing that reads as almost-right on one screen and as slop across five. */
.ad-log-day,.ad-folk-part{margin:0;padding:0 0 9px;border-bottom:1px solid var(--line);
  font-size:11.5px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mute)}
/* Only between groups. The first heading sits under the lede, which has its
   own space; a second one is opening a new day — or the people who no longer
   have access — and wants the air to say so. */
.ad-entry+.ad-log-day,.ad-entry+.ad-folk-part{margin-top:34px}

/* The head of a run, not a row in its own right: smaller than the face on the
   people screen, and a shade taller than the lines underneath rather than half
   as tall again — 53px against 47px. At 40px it stood over its own run like a
   heading over a paragraph, which is more weight than a name needs. */
.ad-log-by{display:flex;align-items:center;gap:11px;padding:13px 0 8px}
.ad-log-by .ad-who{width:32px;height:32px}
.ad-log-by .ad-who b{font-size:12px}
.ad-log-by b{font-size:14.5px}
.ad-log-mail{font-size:13px;color:var(--mute);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* One line, one height, whoever did it and however many times. The baseline is
   what aligns, not the box: the time and the summary are different sizes, and
   centring them leaves the smaller one sitting a pixel or two high. */
.ad-log .ad-head{min-height:46px;align-items:baseline;
  gap:var(--at-gap);padding:10px 38px 10px 0}
.ad-log-at{flex:0 0 auto;width:var(--at);font-size:13px;color:var(--mute);
  font-variant-numeric:tabular-nums}
.ad-log .ad-name{font-size:15px}
/* How much is behind the line, in the line rather than in a badge on the end
   of it. A chip on nearly every row is a column, and a column of near-identical
   chips is read once and then never again. */
.ad-log-n{font-weight:500;font-size:13px;color:var(--mute);white-space:nowrap}
.ad-log .ad-body{padding-left:calc(var(--at) + var(--at-gap))}

/* ---- the posters ----------------------------------------------------------
   The form on the left, the poster on the right, and the poster is the actual
   picture — a canvas at the size the file will be, shown smaller. Nothing here
   is a preview of anything; it is the thing.

   The sheet it sits on is the admin's tint, so a white poster has an edge and
   a scarlet one is not shouting from a white page. */
.so{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,420px);
  gap:26px 40px;align-items:start}
.so-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 20px;
  align-content:start}
.so-form .f-lg{grid-column:1/-1}
/* The two boxes the fields are drawn into are not cells: their children are.
   Without this every field of a poster stacked inside one cell of a
   two-column grid, and "start from" sat alone in the other. */
.so-cells{display:contents}
/* A field sits at the top of its cell, as on a card: a grid row is as tall as
   the tallest thing in it, and a box stretched to match a neighbour's hint is
   a box that looks like it wants a paragraph. */
.so-form .ad-field{align-self:start}
.so-form .ad-field input[type=text]{align-self:start}
/* The three posters to choose from are three cards, like concert and contest
   on the concert card — the choice changes everything under it. */
.so-templates{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.so-templates .ad-pick-one span{min-height:100%;padding:14px}
.so-templates .ad-pick-one b{font-size:14px}
.so-templates .ad-pick-one i{font-size:12.5px}

.so-side{display:grid;gap:18px;position:sticky;top:20px}
.so-sheet{background:var(--tint);border:1px solid var(--line);padding:18px}
.so-sheet canvas{display:block;width:100%;height:auto;
  box-shadow:0 10px 30px rgba(20,16,15,.16)}
/* THE POSTER TAKES A HAND. A poster with a photograph on it is dragged; one
   without is only a picture, and says so by not offering a hand. `touch-action`
   is what stops a drag on a phone scrolling the page instead of moving the
   photograph. */
.so-stage{position:relative}
.so-canvas.is-live{cursor:pointer;touch-action:none}
.so-canvas.is-live.is-held{cursor:grab}
.so-canvas.is-live.is-dragging{cursor:grabbing}
.so-canvas:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
/* THE PICKED-UP PICTURE, drawn the way every program that moves one draws it:
   a thin line round it and eight grips. Over the canvas, never in it — the
   file that comes out has no handles on it. The line is scarlet rather than
   the usual blue because this is the band's screen. */
.so-frame{position:absolute;box-sizing:border-box;
  border:1.5px solid var(--scarlet);box-shadow:0 0 0 1px rgba(255,255,255,.75) inset;
  pointer-events:none}
/* Square grips, not the round ones the newer programs draw: this site has no
   rounded corner on it anywhere, and a round handle here would be the only
   one. White with a scarlet edge, so they can be seen on a photograph of
   anything. */
.so-grip{position:absolute;width:13px;height:13px;margin:-7px 0 0 -7px;
  background:#fff;border:1.5px solid var(--scarlet);
  pointer-events:auto;touch-action:none}
.so-grip-nw{left:0;top:0;cursor:nwse-resize}
.so-grip-n{left:50%;top:0;cursor:ns-resize}
.so-grip-ne{left:100%;top:0;cursor:nesw-resize}
.so-grip-e{left:100%;top:50%;cursor:ew-resize}
.so-grip-se{left:100%;top:100%;cursor:nwse-resize}
.so-grip-s{left:50%;top:100%;cursor:ns-resize}
.so-grip-sw{left:0;top:100%;cursor:nesw-resize}
.so-grip-w{left:0;top:50%;cursor:ew-resize}
@media(max-width:600px){ .so-grip{width:17px;height:17px;margin:-9px 0 0 -9px} }
.so-place-row{display:flex;align-items:center;gap:14px}
.so-place-row input[type=range]{flex:1 1 auto;min-width:0;accent-color:var(--scarlet)}
.so-place-row .so-link{flex:0 0 auto;white-space:nowrap}
.so-place .hint{margin:6px 0 0}
.so-do{display:grid;gap:10px}
.so-do .hint{margin:0;font-size:13px;color:var(--mute);min-height:1.2em}
.so-photo{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:center}
.so-photo input[type=text]{flex:1 1 200px;min-height:44px}

/* THE CHOICE OFFERED AS A PICTURE OF ITSELF. Where a concert can be drawn two
   ways, each way is drawn — with this concert's own words on it — rather than
   described. Two cards rather than three, because a choice of two is what
   there is.

   THE PICTURE IS SMALL ON PURPOSE, and beside the words rather than above
   them. What is being decided here is which of two posters this is — white
   with the crest, or a photograph under a scarlet band — and that is settled
   by the shape and the colour, which are exactly what survives at 120px. Drawn
   full width it was 460px of poster in a form, a second preview beside the
   real one, and it pushed every field of the poster below the fold. The card
   is now the height of the thumbnail and no more. */
.so-templates.has-thumbs{grid-template-columns:repeat(2,minmax(0,1fr))}
.so-templates .ad-pick-one.has-thumb span{display:grid;padding:12px;gap:3px 14px;
  grid-template-columns:120px minmax(0,1fr);grid-template-rows:auto auto;
  align-items:start;text-align:left}
/* The title and the line under it meet in the middle of the thumbnail's
   height: the words are one block set against the picture, not two things
   hanging from the top of it. */
.so-templates .ad-pick-one.has-thumb b{grid-column:2;grid-row:1;align-self:end}
.so-templates .ad-pick-one.has-thumb i{grid-column:2;grid-row:2;align-self:start}
.so-thumb{display:block;width:120px;height:auto;aspect-ratio:4/5;margin:0;
  grid-column:1;grid-row:1/3;align-self:center;
  background:var(--paper);border:1px solid var(--line);
  box-shadow:0 3px 10px rgba(20,16,15,.14)}
.so-templates .ad-pick-one input:checked + span .so-thumb{border-color:var(--gold)}
@media(max-width:520px){
  .so-templates .ad-pick-one.has-thumb span{grid-template-columns:88px minmax(0,1fr)}
  .so-thumb{width:88px}
}

/* WHERE THE BOX BEING TYPED INTO LANDS ON THE SHEET. Gold, which is how this
   site points at anything, and light enough to read the words through: the
   point is to find them, not to hide them. Over the canvas, never in it — the
   file that comes out has no marks on it. An answer can land in two places, so
   there may be more than one of these at a time. */
.so-lit-wrap{position:absolute;inset:0;pointer-events:none}
/* The line does the pointing and the wash only says which side of it is
   inside. At .22 it dulled a black title to brown; the point is to find the
   words, not to put a filter over them. */
.so-lit{position:absolute;display:block;box-sizing:border-box;
  border:2px solid var(--gold);background:rgba(241,197,50,.15);
  box-shadow:0 0 0 1px rgba(20,16,15,.5),0 0 0 3px rgba(241,197,50,.28)}

/* WHAT THE DRAWING NOTICED. Said in the band's scarlet, beside the sheet, and
   left there: a poster with no ticket line may be exactly what somebody meant,
   so none of this stands between anybody and the download. */
.so-check{border-left:4px solid var(--scarlet);padding-left:14px}
.so-check ul{margin:8px 0 0;padding-left:18px;display:grid;gap:7px}
.so-check li{font-size:13.5px;line-height:1.45;color:var(--ink)}
.so-do-one{margin:0}
.so-do-one .so-link{font-size:13.5px}

/* WATCHING IT MOVE. The button and how far through it is, on one line: a
   progress bar with no numbers on it, because seven seconds does not need
   telling in figures. The bar is the site's gold on the site's line. */
.so-reel-row{display:flex;align-items:center;gap:14px}
.so-reel-row .btn{flex:0 0 auto}
.so-reel-bar{flex:1 1 auto;min-width:0;height:6px;background:var(--line);
  display:block;overflow:hidden}
.so-reel-bar i{display:block;height:100%;width:0;background:var(--gold)}
.so-reel .hint{margin:8px 0 0}

@media(max-width:900px){
  .so{grid-template-columns:1fr}
  .so-side{position:static}
  .so-templates{grid-template-columns:1fr}
  /* Named with both classes because the two-column rule for drawn templates,
     .so-templates.has-thumbs further up, outranks the plain one above and kept
     two columns on a phone: the "Drawn as" titles were squeezed to 1px wide
     and the Posters screen scrolled sideways by 43px at 390. */
  .so-templates.has-thumbs{grid-template-columns:1fr}
}

/* ---- what wants posting -----------------------------------------------------
   The change log's list — a day at a time, one line each — with a tick at the
   start of the line, because ticking is what this screen is for. The line is
   still the button that opens it; the tick sits beside it, not inside it. */
.so-plan-row{display:flex;align-items:stretch}
.so-plan .so-tick{flex:0 0 auto;min-height:0;padding:0 14px 0 0;align-self:center}
.so-plan .so-tick input{width:22px;height:22px}
.so-plan .ad-head{flex:1 1 auto;gap:14px}
/* The row's button is width:100% everywhere else, and beside the tick that is
   100% plus the tick, which pushed What wants posting 19px off the side of a
   phone. Here it takes what is left instead, and may shrink to do so. */
.so-plan .ad-head{min-width:0;width:auto;flex:1 1 0}
.so-plan .ad-head{min-height:64px;align-items:center}
.so-plan .ad-log-at{display:none}
.so-plan .ad-body{padding-left:36px}
.so-plan .ad-name em{color:var(--mute);font-style:normal;font-weight:500}
/* Late is said with the number, in scarlet, and not with a box. */
.so-plan .is-late .ad-name{color:var(--scarlet)}
.so-reach{margin:0 0 22px;font-size:14px;color:var(--mute)}
.so-reach b{color:var(--ink);font-size:15px}

/* ---- the words --------------------------------------------------------------
   Three boxes side by side, one per place, each with its copy button. The text
   is read-only here: it is words to start from, changed in the app. */
.so-words{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:18px 22px}
.so-word{display:grid;gap:8px;align-content:start}
.so-word .ad-sub{margin:0}
.so-word textarea{width:100%;box-sizing:border-box;font:inherit;font-size:14px;
  line-height:1.5;padding:10px 12px;border:1px solid var(--line);background:#fff;
  color:var(--ink);resize:vertical}
.so-form-words{margin-bottom:22px}

.so-copy{justify-self:start;min-height:36px;padding:0 12px;font:inherit;
  font-size:12px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  background:#fff;color:var(--ink);border:1px solid var(--line);cursor:pointer}
.so-copy:hover{border-color:var(--ink)}
.so-copy.is-done{background:var(--ink);color:var(--gold);border-color:var(--ink)}
.so-link{font:inherit;font-weight:700;font-size:13px;color:var(--scarlet);
  background:none;border:0;padding:0;cursor:pointer;text-decoration:underline}

/* ---- links ---------------------------------------------------------------- */
.so-links{display:grid;gap:8px;margin:12px 0 30px}
/* The buttons line up with the box, not with the label-and-box together —
   centred against the pair they floated between the two. */
.so-linkrow{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:flex-end}
.so-linktext{flex:1 1 320px;display:grid;gap:3px;min-width:0}
.so-linktext b{font-size:13px}
.so-linktext input{width:100%;box-sizing:border-box;font:inherit;font-size:13.5px;
  color:var(--mute);min-height:36px;padding:0 10px;border:1px solid var(--line);
  background:#fff}

/* The shapes are a grid of two, so six of them are three even rows rather
   than a ragged wrap; and each carries its size in small figures. */
.so-shapes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
.so-shapes .ad-pick-one span{width:100%;box-sizing:border-box;justify-content:flex-start;gap:8px}
/* "Instagram square 1080×1080" is wider than half a phone. Allowed to wrap, the
   size drops under the name; held on one line, it pushed the Right Size and
   Pictures screens 34px off the side at 390. */
.so-shapes .ad-pick-one span{flex-wrap:wrap}
/* The shape buttons carry their size in small figures. */
.ad-pick-one i{font-style:normal;font-weight:500;font-size:12px;color:inherit;opacity:.75}
input[type=range]{width:100%;accent-color:var(--scarlet)}

/* ---- the press pack ---------------------------------------------------------
   A page for other people's designers and sub-editors: two biographies at the
   lengths that get asked for, a list of facts to check against, the crest with
   its rules, and the colours as numbers. Set plainly, because the reader is
   going to copy from it. */
.press-h{margin:0 0 10px;font-size:12.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute)}
.press-copy{max-width:62ch;font-size:16.5px;line-height:1.65}
.press-copy+.press-copy{margin-top:14px}
/* Two biographies start on the same line. A split centres its halves, which is
   right for a paragraph beside a photograph and wrong for fifty words beside a
   hundred and fifty — the short one sat a third of the way down the long one. */
.press-top{align-items:start}

.press-facts{margin:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:0 40px}
.press-facts>div{display:grid;grid-template-columns:150px minmax(0,1fr);gap:14px;
  padding:14px 0;border-bottom:1px solid var(--line);align-items:baseline}
.press-facts dt{margin:0;font-size:12.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute)}
.press-facts dd{margin:0;font-size:15.5px;line-height:1.55}

.press-crest-tile{display:grid;gap:16px;justify-items:start}
.press-crest-tile img{width:220px;height:auto;padding:26px;background:#fff;
  border:1px solid var(--line)}
.press-swatches{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;
  margin-top:16px}
.press-swatch{padding:16px 14px;color:#fff;display:grid;gap:4px}
.press-swatch b{font-size:13px;letter-spacing:.06em;text-transform:uppercase}
.press-swatch span{font-size:13px;opacity:.85;font-variant-numeric:tabular-nums}

.press-photos{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:20px;margin-top:22px}
.press-photos figure{margin:0}
.press-photos img{width:100%;height:auto;border:1px solid var(--line)}
.press-photos figcaption{margin-top:8px;font-size:13.5px;color:var(--mute)}
.press-photos figcaption a{color:var(--scarlet)}
@media(max-width:600px){
  .press-facts>div{grid-template-columns:1fr;gap:4px}
}

/* ---- the door list, which is read in a hurry ------------------------------
   Set as type on the page rather than in boxes, the way the admin's own strip
   of facts is: a figure, and a label under it in the capitals this site uses
   for labels. The one screen somebody reads standing up in a doorway with a
   queue in front of them is not the place for a decoration. */
.dl-nums{display:flex;flex-wrap:wrap;gap:14px 34px;margin:22px 0 0;
  padding:0 0 18px;border-bottom:1px solid var(--line)}
.dl-nums>div{display:grid;gap:2px}
.dl-nums b{font-size:30px;font-weight:900;line-height:1.05}
.dl-nums span{font-size:11.5px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute)}

/* One press, and it is the biggest thing on the screen — a door is dark, the
   phone is at arm's length, and whoever is holding it is also taking money.
   Taking one back is deliberately smaller and only appears once there is
   something to take back: it is the correction, not the job. */
.dl-door{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;
  margin:22px 0 26px}
.dl-sell{min-height:58px;padding:0 28px;font-size:14px}
.dl-back{min-height:44px;padding:0 14px;font:inherit;font-size:12.5px;
  font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  background:#fff;color:var(--mute);border:1px solid var(--line);cursor:pointer}
.dl-back:hover{color:var(--scarlet);border-color:var(--scarlet)}
.dl-door .hint{flex:1 1 100%;margin:0;font-size:13.5px;color:var(--mute)}

/* ---- the bookings on a concert, in the box office ----
   The one place a refund is pressed. It sits at the foot of the concert's own
   card, under the seats and the prices, because that is the tick that guards
   the takings — and a button that moves money belongs behind it rather than on
   the door list a volunteer reads in a doorway.

   The refund promise is said above the list rather than beside each row: it is
   a fact about the concert's date, not about one booking, and repeated down a
   column of twenty it would read as a warning about each of them. */
.tk-orders{margin:4px 0 8px}
.tk-orders .tk-rule{border-left:3px solid var(--gold);padding-left:12px;
  margin:0 0 10px;color:var(--ink)}
/* A table may scroll sideways inside its own box; a page may not. Even with the
   amount moved out of the chip, a long name beside a long address can still be
   wider than a phone, and this keeps that inside the table rather than letting
   it drag the whole admin across. */
.tk-orders-wrap{overflow-x:auto;margin-top:12px}
.tk-orders-table{margin-top:0;min-width:100%}
.tk-orders-table td:last-child{text-align:right;white-space:nowrap}
.tk-orders-table .btn-sm{min-height:36px;padding:0 14px}

/* ON A PHONE IT STOPS BEING A TABLE.
   Four columns in 390px put the REFUND button off the right-hand edge, inside
   a box you had to drag sideways to reach — the action the list exists for,
   hidden behind a gesture nobody would think to make. So each booking becomes
   a block: who, then what they paid, then the button across the full width
   where a thumb already is.

   The headings go with the columns, so the two figures carry their own labels.
   Without them "4" and "£48.00" sit side by side meaning nothing in
   particular. */
@media(max-width:640px){
  .tk-orders-wrap{overflow-x:visible}
  .tk-orders-table,.tk-orders-table tbody,
  .tk-orders-table tr,.tk-orders-table td{display:block;width:auto}
  .tk-orders-table thead{display:none}
  .tk-orders-table tr{padding:16px 0;border-bottom:1px solid var(--line)}
  .tk-orders-table tr:last-child{border-bottom:0}
  .tk-orders-table td{padding:0;border:0;white-space:normal}
  .tk-orders-table td:first-child{font-weight:700;width:auto}
  .tk-orders-table td:nth-child(2),
  .tk-orders-table td:nth-child(3){
    display:inline-block;width:auto;margin:10px 22px 0 0;font-weight:700}
  .tk-orders-table td:nth-child(2)::before{content:'Seats'}
  .tk-orders-table td:nth-child(3)::before{content:'Paid'}
  .tk-orders-table td:nth-child(2)::before,
  .tk-orders-table td:nth-child(3)::before{
    display:block;font-weight:900;font-size:11px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--scarlet);margin-bottom:2px}
  .tk-orders-table td:last-child{margin-top:14px;text-align:left;
    white-space:normal}
  /* NOT full width. A 44px target is the floor a thumb needs and this clears
     it; a button stretched across the screen is the easiest thing on the page
     to hit by accident, which is the wrong property for the one control that
     moves money out of the band's account. */
  .tk-orders-table td:last-child .btn{min-height:44px;padding:0 20px}
}

/* ---- the guest list itself ----
   It borrowed .rec-table, which is the reading-figures table, and inherited
   two of that table's decisions that are wrong here.

   The first is fatal. .rec-table hides its last column below 640px, because
   there the last column is a date nobody needs on a phone. Here the last
   column is the REFERENCE — and this list is read on a phone, in a doorway, by
   somebody holding it in one hand while a queue waits. The one thing a person
   at a door says out loud is "what was the name, or the reference?", and on
   every phone in the band it was not on the screen.

   The second is only ugly: its first column is 64px wide and never wraps,
   which suits a rank ("1.") and does not suit "Mrs Elizabeth Fothergill".

   So the door keeps the look and states its own widths. */
.dl-table td:first-child{width:auto;white-space:normal}
.dl-table td:nth-child(2),
.dl-table td:nth-child(3){width:62px;white-space:nowrap}
.dl-table td:last-child{white-space:nowrap;font-weight:700;color:var(--ink);
  font-variant-numeric:tabular-nums}
@media(max-width:640px){
  /* Said back explicitly, because it is the whole reason this class exists. */
  .dl-table td:last-child,.dl-table th:last-child{display:table-cell}
  .dl-table{font-size:13.5px}
  .dl-table td,.dl-table th{padding-right:10px}
  .dl-table td:nth-child(2),.dl-table td:nth-child(3){width:38px}
}

@media(max-width:600px){
  .dl-sell{width:100%}
  .dl-nums{gap:14px 26px}
}

/* ---- what people have sent in -------------------------------------------
   The same list as the change log, because it is the same kind of thing: a
   column of times, the day said once above them, and one line each. Two lines
   here rather than one — who wrote, and the first of what they wrote — and
   every row has both, so the pitch stays even without a height being set.

   An answered enquiry is quietened rather than hidden, which is what this site
   already does with a concert that has been and gone. It is still the thing
   somebody looks up in March to find out what was agreed in November. */
.ad-post-said{margin:0;max-width:68ch;font-size:15.5px;line-height:1.6}
/* WHO IT CAME FROM, UNDER WHAT THEY SAID, and quieter than it. There is no
   rule for .hint in this stylesheet, so a footnote inherits the body — 17px of
   ink, which on this screen puts an address and a retention policy at the same
   weight as the message and the line above the list. Set here rather than
   globally: a rule for every .hint on the site would change five screens to
   fix one, and this is the screen with the problem. */
.ad-post-from,.ad-post-done{margin:0;font-size:13.5px;color:var(--mute)}
.ad-post+.hint{margin:26px 0 0;max-width:72ch;font-size:13.5px;color:var(--mute)}

/* THE PREVIEW GOES WHEN THE WHOLE THING ARRIVES. The line under the name is
   the first of what they wrote, which is exactly what the paragraph below it
   opens with — so an open enquiry said its first sentence twice, once in grey
   and once in ink, an inch apart. */
.ad-post .ad-head[aria-expanded="true"] .ad-sub-text{display:none}

.ad-post-do{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
/* The same button the People screen uses, laid in a row rather than a column —
   drawn from one description so the two screens cannot drift apart. */
.ad-post-do>*{min-height:44px;padding:0 14px;font:inherit;font-size:12.5px;
  font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  display:inline-flex;align-items:center;text-decoration:none;
  background:#fff;color:var(--ink);border:1px solid var(--line);cursor:pointer}
.ad-post-do>*:hover{border-color:var(--ink)}
/* Quieter than the other two until it is aimed at, because it is the one thing
   in this admin that cannot be undone. */
.ad-post-do .ad-post-forget{color:var(--mute)}
.ad-post-reply,.ad-post-mark{font:inherit}
.ad-post-do .ad-post-forget:hover{color:var(--scarlet);border-color:var(--scarlet)}

/* A phone has no room to give a column of times an indent as well, so the
   detail comes back to the edge. The times themselves stay: they are 42px. */
@media(max-width:600px){
  .ad-log{--at-gap:10px}
  .ad-log .ad-body{padding-left:0}
  /* The address goes, not the face with it: a face drawn as initials is a
     <span> too, and hiding every span at the head of a run took the initials
     off the screen for everybody who has no photograph yet. */
  .ad-log-mail{display:none}
  /* Not here it does not. A row on a card list wraps on a phone so its chips
     can drop below the name instead of squeezing it; this row has no chips,
     and wrapping it puts the time on a line of its own with nothing beside it
     and the words underneath — 127px of screen for one change. The words wrap
     inside their own column instead, which is what the column is for. */
  .ad-log .ad-head{flex-wrap:nowrap}
}

.ad-head::after{content:'';position:absolute;right:12px;top:50%;
  width:9px;height:9px;margin-top:-6px;
  border-right:2px solid var(--scarlet);border-bottom:2px solid var(--scarlet);
  transform:rotate(45deg);transition:transform .2s ease}
.ad-head[aria-expanded=false]::after{transform:rotate(-45deg)}
/* A ROW THAT OPENS A CARD POINTS ALONG, NOT DOWN. The arrow says where the
   thing is about to appear, and a chevron pointing down at a row that no longer
   unfolds is the page telling a small lie about itself.

   The nudge on hover is written translate-then-rotate, in that order: after a
   rotation the axes have turned with it, and translateX would send the arrow
   diagonally. */
.ad-head[data-card]::after{transform:rotate(-45deg);margin-top:-5px}
.ad-head[data-card]:hover::after{transform:translateX(3px) rotate(-45deg)}
@media(prefers-reduced-motion:reduce){.ad-head::after{transition:none}}

/* A phone is where a photograph actually is, so this is the layout that
   matters most, not a fallback. Side by side leaves the button squeezed into
   about 90px; stacked it is a full-width target. */
@media(max-width:600px){
  .ad-photo-tile{max-width:100%}
  .ad-pick span{width:100%;justify-content:center}

  /* THE DIFF TABLE STOPS BEING A TABLE.
     Three columns at 40/30/30 of about 330px is 132px for a field name and
     99px each for the old and new values — where the names are things like
     "Committee & staff — Andrew Rigby — role" and the values are sentences.
     Every cell wraps to four or five lines and the row becomes unreadable.

     Stacked, each row is the field name and then two labelled lines. The
     labels are added here rather than in the markup because they are only
     meaningful in this layout: with columns, the headings say it already. */
  .ad-diff,.ad-diff tbody,.ad-diff tr,.ad-diff th,.ad-diff td{
    display:block;width:auto}
  .ad-diff tr{padding:12px 0}
  .ad-diff tr+tr{border-top:1px solid var(--line)}
  .ad-diff tr+tr th,.ad-diff tr+tr td{border-top:0}
  .ad-diff th{padding:0 0 7px}
  .ad-diff td{padding:2px 0 2px 52px;position:relative;min-height:20px}
  .ad-diff td::before{position:absolute;left:0;top:3px;width:46px;
    font-size:11.5px;font-weight:900;letter-spacing:.14em;text-transform:uppercase;
    color:var(--mute)}
  .ad-diff .was::before{content:"Was"}
  .ad-diff .now::before{content:"Now"}

  .ad-head{gap:11px;padding-right:30px}
  .ad-stamp,.ad-stamp-none{width:48px}
  .ad-stamp b{font-size:18px}
  .ad-face{width:40px;height:40px}
  /* Chips drop below the name rather than squeezing it to nothing. */
  .ad-head{flex-wrap:wrap}
  .ad-chips{max-width:none;justify-content:flex-start;width:100%;padding-left:59px}
}

/* ONE COLUMN, AND IT IS THE WIDTH OF THE CARD.
   Written without a template this is a grid of one implicit column, and an
   implicit column is as wide as the widest thing in it — grid items refuse to
   shrink below their own content unless they are told they may. So anything
   wide inside a card dragged the column past the card and the whole admin
   scrolled sideways on a phone: measured at 390px, the body was 342 and the
   fields inside it 460. minmax(0,1fr) pins the column to the card and lets the
   contents give way instead, which is what every other grid on this site
   already does by having a template at all. */
.ad-body{padding:6px 0 26px;display:grid;grid-template-columns:minmax(0,1fr);
  gap:18px}
/* ---- the heading over a part of a form ----
   A HEADING AND THE LABEL UNDER IT WERE THE SAME SIZE, and only their colour
   said which was which: "WHAT IT IS" in scarlet at 11.5px, then "TITLE" in
   grey at 11.5px, six pixels apart. Hierarchy carried by colour alone is not
   hierarchy — it is two things the same size, one of them red — and on a form
   of four parts it read as a stutter rather than as a structure.

   So it is the band's own device for exactly this job: the Royal Red strip of
   white Bold text, sentence case, as wide as its words. Book Us heads its four
   offers with it (.offer h3, at 20px, where it heads a section of a page) and
   the Analytics cards head themselves with it (.an-card-name, at 17px, where
   it sits inside a card). This is the third place and the same size as the
   second, for the same reason: it is inside a card rather than heading a page.

   THE BRAND NOTE IS EXPLICIT ABOUT THE COLOUR. Royal Red is for on-page
   elements, badges, boxes and rules, "since none sit on a coloured
   background"; Heritage Scarlet leads whole surfaces. A strip on the white of
   a card is the first of those. White on royal is 7.87:1.

   Sentence case, like the other two — which also takes this rule out of the
   admin's two-ways-of-setting-capitals question altogether, since it no longer
   sets any.

   AND THE INSET IS THE DOCUMENT'S, not this file's memory of it: 4px above and
   below against 5px at the sides. The note beside .an-card-name has said so
   since the day it was written and the rule under it said 4px 7px; Book Us
   said 5px 7px. Three drawings of one device, none of them the specified one.
   verify-site.js holds the three together now.

   NOT ALSO A GOLD BAR. It carried one for about ten minutes. A strip and a bar
   are two devices saying "heading" over the same three words. */
.ad-sub{display:inline-block;margin:14px 0 0;padding:4px 5px;
  background:var(--royal);color:#fff;
  font-weight:700;font-size:17px;line-height:1.2;letter-spacing:.01em;
  text-transform:none}

/* ---- THE STORY BOX ----
   Three buttons over the box, in the pressable capitals, and the page the
   words make drawn under it in the site's own story styles. */
.ad-story{display:grid;gap:8px}
.ad-story-tools{display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px}
.ad-story-tools button,.ad-story-pic span{display:inline-flex;align-items:center;
  min-height:36px;padding:0 12px;font:inherit;font-weight:700;font-size:12.5px;
  letter-spacing:.09em;text-transform:uppercase;background:#fff;
  border:2px solid var(--line);color:var(--ink);cursor:pointer;transition:.15s}
.ad-story-tools button:hover,.ad-story-pic:hover span{border-color:var(--ink)}
.ad-story-pic{position:relative;display:inline-block}
.ad-story-pic input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.ad-story-pic:focus-within span{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-story-say{font-size:13px;color:var(--mute)}
.ad-story-view{padding:18px 22px;border:1px solid var(--line);background:#fff;
  font-size:15.5px;line-height:1.6}
.ad-story-view p{margin:0 0 1em}
.ad-story-view p:last-child{margin-bottom:0}
.ad-story-view h2{font-size:19px;font-weight:900;letter-spacing:-.01em;
  text-transform:none;margin:1.2em 0 .4em}
.ad-story-view h2:first-child{margin-top:0}
.ad-story-view figure{margin:1.2em 0}
.ad-story-view figure img{display:block;width:100%;height:auto}
.ad-story-view figcaption{margin-top:7px;font-size:13px;color:var(--mute)}
.ad-story-view .story-film iframe{display:block;width:100%;aspect-ratio:16/9;border:0;
  background:var(--ink)}

/* ---- one field ---- */
.ad-field{display:grid;gap:7px}
/* A GROUP OF BUTTONS HAS NO SINGLE CONTROL TO POINT A <label> AT, so its label
   is a span that the group names as its own — and it has to look like every
   other label on the form, which it did not: "What kind needed" came out in
   sentence case beside eleven small capitals. */
.ad-field label,.ad-field .ad-field-label{display:block;font-weight:900;
  font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
/* AN ASTERISK, NOT THE WORD. "What kind needed" read, for a second, as a
   question — what kind is needed? — and the word was in red on eleven labels
   at once. A mark people already know, with what it means said once at the
   foot of the card. Bigger than the label so it is not mistaken for a full
   stop, and it sits a shade high because that is where an asterisk sits. */
.ad-field label em,.ad-field .ad-field-label em{font-style:normal;
  color:var(--scarlet);letter-spacing:0;text-transform:none;
  font-size:15px;line-height:0;position:relative;top:1px}
.ad-req-key{font-size:12.5px;color:var(--mute)}
.ad-req-key em{font-style:normal;color:var(--scarlet);font-weight:900;font-size:15px}
.ad-field input,.ad-field textarea{
  /* THE WEIGHT AS WELL AS THE FAMILY. A form control does not inherit either:
     the family was asked for and the weight was not, so every box in the admin
     was drawing its text at 400 — a weight this site does not own and the
     browser makes up — while everything around it was Medium. It showed up as
     the grey suggestion behind the caret being visibly heavier than the words
     typed over it. */
  font-family:inherit;font-weight:inherit;font-size:16px;padding:13px 15px;
  border:2px solid var(--line);border-radius:0;background:#fff;color:var(--ink);
  width:100%;min-height:48px}
/* A menu on a form takes the whole width, like the boxes above and below it.
   Everything else about it is the one menu rule near the top of this file. */
.ad-field select{width:100%}
/* 16px is not a style choice. Below it, iOS zooms the page in when a field is
   focused and does not zoom back out, which leaves somebody stranded at 150%
   halfway through a form. */
.ad-field textarea{line-height:1.5;resize:vertical}
/* On a card the box is sized by its words (see growTextarea in admin.js), so
   the browser's own resize handle has nothing left to do. */
.ad-card .ad-field textarea{resize:none;overflow:hidden}
/* ---- the dots in a password box --------------------------------------------
   THE MASK IS A GLYPH LIKE ANY OTHER, and it comes from whatever face the box
   is set in. Noverion's is a small middot sitting low on the line, so a typed
   password looked like a row of full stops — smaller than the address in the
   box above it and nothing like the dots anybody expects.

   So password boxes, and only password boxes, are set in a face whose bullet is
   a bullet. Nobody reads prose in one: what matters is that a dot looks like a
   dot and that they are far enough apart to be counted. */
/* AND SMALLER THAN THE WORDS AROUND THEM. A bullet in a face that has one is
   drawn at about a third of its type size, where a middot is a tenth of it — so
   the same box that was showing full stops showed something closer to buttons.
   Four fifths of the size, which puts a dot at 3.5px against the 5px it was and
   the 1.5px it started at.

   Written for all three places a password box appears, because the boxes on the
   sign-in card and in the admin's own form both carry sizes of their own that
   would otherwise win. */
/* ---- what the browser fills in ---------------------------------------------
   A remembered address arrives in Chrome's own pale mint, which on a white card
   looks like a box that has gone transparent and let the photograph through.
   The colour cannot be set directly — it is painted over the box — so the box
   is filled with an inset shadow instead, which is the way round everybody uses
   because it is the only one that works. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--ink);
  -webkit-box-shadow:0 0 0 40px #fff inset;
  box-shadow:0 0 0 40px #fff inset;
  /* Long enough that it never actually arrives: the animation is only there to
     keep the shadow from being repainted away. */
  transition:background-color 9999s ease-in-out 0s}

input[type=password],
.ad-field input[type=password],
.ad-gate-card .form input[type=password]{
  font-family:Verdana,Tahoma,'DejaVu Sans',sans-serif;
  font-size:.8em;letter-spacing:.14em}

/* ---- SHOWING A PASSWORD ---------------------------------------------------
   Behind a row of dots a mistyped password and a wrong one look the same, and
   the sentence you get back for them is the same too. So the box can be opened.

   The button sits inside the right-hand end of the box rather than beside it:
   beside it, the box gets shorter and every other box on the form is suddenly
   a different width. It is the site's own pressable capitals, in scarlet,
   which is what everything you can press in here is.

   The face changes with the state, and deliberately: the dots need the
   letter-spacing to read as dots rather than as a smudge, and letters do not —
   spaced-out letters would be the harder thing to check, which is the whole
   point of pressing it. */
.pw-box{position:relative;display:block}
.pw-box input{width:100%;padding-right:74px}
.pw-see{position:absolute;top:0;right:0;height:100%;padding:0 13px;
  background:none;border:0;cursor:pointer;
  font:inherit;font-weight:700;font-size:12.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--scarlet);transition:color .15s}
.pw-see:hover{color:var(--royal)}
.pw-see:focus-visible{outline:3px solid var(--gold);outline-offset:-3px}
.pw-box input[type=text]{font-family:inherit;font-size:1em;letter-spacing:0}

.ad-field input:focus,.ad-field select:focus,.ad-field textarea:focus{
  border-color:var(--ink);outline:3px solid var(--scarlet);outline-offset:1px}
/* ---- the help under a field -----------------------------------------------
   THERE WHILE IT IS NEEDED. A sentence under every field all the time turns a
   form of eleven fields into two hundred words about things the reader already
   knows — and the sentences are worth having, because they are read once, by
   whoever is filling that field in for the first time.

   So: shown while the field is empty, shown while somebody is in it, and quiet
   the moment it has an answer. Nothing is hidden that has not been answered. */
.ad-field .hint{margin:0;font-size:13px;line-height:1.45;color:var(--mute)}
/* On a card, and on the poster form, which is the same kind of form drawn
   outside a card. */
.ad-card-fields .ad-field.is-answered .hint,
.so-form .ad-field.is-answered .hint{display:none}
.ad-card-fields .ad-field.is-answered:focus-within .hint,
.so-form .ad-field.is-answered:focus-within .hint{display:block}

.ad-field-tick{gap:4px}
.ad-tick{display:flex;align-items:center;gap:11px;min-height:44px;
  cursor:pointer;font-weight:700;font-size:15px;letter-spacing:0;
  text-transform:none;color:var(--ink)}
.ad-tick input{width:22px;height:22px;min-height:0;accent-color:var(--scarlet);
  flex:0 0 auto;padding:0}

/* A picture is shown, not described. Nobody can tell from a web address whether
   it is the right photograph. */
/* A photograph, and the one control that changes it, side by side. Stacked on a
   phone — see the phone block at the foot of this file. Square, like everything
   else here. */
/* =============================================================================
   THE DOOR
   =============================================================================
   A BAND PHOTOGRAPH, DARKENED, WITH THE FORM ON TOP. It was a white page with
   SIGN IN set enormous across it and four paragraphs underneath — the shape of
   a form rather than the shape of a door, and the first thing anybody in the
   band sees of the admin.

   The photograph is the one the site already falls back to on the homepage,
   handed over by site.js. Under it, ink and the crest, so a picture that never
   arrives leaves something deliberate rather than a hole. */
.ad-gate{position:relative;isolation:isolate;
  min-height:min(760px,78dvh);display:flex;align-items:center;
  padding:56px 24px;background:var(--ink)}
.ad-gate-art{position:absolute;inset:0;z-index:-1;
  background:var(--ink) center/cover no-repeat;
  animation:ad-gate-rise 1.1s var(--ad-ease,ease) both}

/* ---- THE CREST IS IN THE CARD ---------------------------------------------
   NOT OVER THE PHOTOGRAPH. It sat at the bottom-left of the picture with the
   footer's at the bottom-left immediately beneath it — two of them in a
   vertical line down the same edge, which is what the rule about using it
   sparingly and never on adjacent sections is there to stop.

   In the card it is the same watermark the walkthrough cards carry: pale, on
   white, bleeding off the bottom-left corner, with the form standing over it.
   The footer's is a long way below and in another colour altogether, so the two
   never read as a pair. */
.ad-gate-card{position:relative;overflow:hidden}
.ad-gate-card > *{position:relative;z-index:1}
.ad-gate-card::before{content:'';position:absolute;z-index:0;inset:0;
  pointer-events:none;
  /* As tall as the card and anchored to its foot, so the point of the crown
     meets the top edge — the size the crest is always drawn at here. */
  background:url('../img/gus-crest-light.png') left bottom/auto 100% no-repeat}
/* The scrim is heavier at the edges than in the middle, so the photograph is
   still a photograph where nothing is written over it. */
.ad-gate-art::after{content:'';position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(20,16,15,.94) 0%,rgba(20,16,15,.80) 44%,
                                   rgba(20,16,15,.62) 100%)}
@media(max-width:820px){
  .ad-gate-art::after{background:rgba(20,16,15,.86)}
}
@keyframes ad-gate-rise{from{opacity:0;transform:scale(1.06)}}

/* THE TWO COLUMNS START LEVEL. Centred against each other, the words on the
   left floated somewhere in the middle of a card half again as tall, which
   reads as two things that happen to be near each other rather than as one
   page. Level tops give them an edge in common, and the kicker lands on the
   same line as the heading on the card. */
.ad-gate-in{position:relative;width:100%;max-width:var(--wrap);margin:0 auto;
  display:grid;gap:34px 56px;align-items:start;
  grid-template-columns:minmax(0,1fr) minmax(0,470px)}
/* The kicker sits on its own line above ADMIN and the card's heading does not,
   so a little off the top of the left column puts the two headings level. */
@media(min-width:901px){ .ad-gate-say{padding-top:26px} }
@media(max-width:900px){
  .ad-gate-in{grid-template-columns:minmax(0,1fr);gap:26px}
}

.ad-gate-say{color:#fff}
.ad-gate-say .kicker{color:var(--gold);margin-bottom:10px}
.ad-gate-big{font-size:clamp(54px,8vw,104px);line-height:.94;
  text-transform:uppercase;letter-spacing:.005em;color:#fff}
/* A bar in proportion to the words above it — the same 10px the hero on the
   homepage uses, at the same size of type.

   AND THE GAP ABOVE IT EQUALS ITS OWN THICKNESS, which is the brand rule and
   is what the correction below is for: it takes out the dead space every line
   box carries under the cap baseline. The site's 0.19em is measured against the
   line-height its headings use; this one is set tighter, at .94, so the same
   correction overshot and left the bar a pixel off the letters. Measured: 1px
   of gap under a 6px bar. 0.141em puts the gap back to the thickness, and both
   scale with the type, so it holds all the way down the clamp. */
.ad-gate-big.rule::after{margin-top:calc(var(--bar) - 0.141em)}
/* :not(.kicker), for the second time in this stylesheet — a kicker is a <p>,
   and a rule written for "the sentence under the heading" catches it on the way
   past. Here it took the size off it and then hid it altogether on a phone. */
.ad-gate-say p:not(.kicker){margin:26px 0 0;max-width:34ch;font-size:17px;
  color:rgba(255,255,255,.82)}
@media(max-width:900px){.ad-gate-say p:not(.kicker){display:none}}

/* The form is a white card standing on the photograph — the same white the
   admin's own cards are, so signing in and using it are the same place. */
.ad-gate-card{background:#fff;padding:36px 36px 30px;
  box-shadow:0 28px 70px rgba(20,16,15,.45)}
/* The picture is what fills the door when there is one; when there is not, the
   ink and the words are the page and the card is the only thing on it. */
/* SIGN IN carries the same bar as everything else this site calls a heading —
   4px of it, in proportion to 40px of type, and it draws itself from the left
   when the card arrives. */
.ad-gate-h{font-size:40px;line-height:1;text-transform:uppercase;
  letter-spacing:.01em;margin:0 0 26px}
.ad-gate-h.rule::after{margin-top:calc(var(--bar) - 0.155em)}

/* The card itself arrives a beat after the words on the left, rising and
   settling on the same curve everything else on this site moves with.

   IT RISES, IT DOES NOT FADE, and that is not a taste decision. The fade began
   at opacity 0 and, with the delay, left every field in this card completely
   transparent for the first fifth of a second and not solid until nearly a
   second in. A password manager looks for a sign-in form when the page
   arrives, and the commonest test for "can this be filled" is whether the
   field can be seen — a transparent box is not a box, so it found nothing
   worth offering, on a form that was otherwise correct in every particular.
   Measured, not guessed: the fields read opacity 0 at load and 0.46 at 400ms.

   The rise alone still reads as an arrival against the photograph, and the
   gold bar still draws itself across the heading inside the card. */
.ad-gate-card{animation:ad-gate-card-in .72s .22s cubic-bezier(.22,.61,.36,1) both}
@keyframes ad-gate-card-in{
  from{transform:translateY(26px) scale(.985)}
}
@media(prefers-reduced-motion:reduce){
  .ad-gate-card,.ad-gate-art{animation:none}
}
/* The boxes are bigger than the admin's own, because this is the one form
   somebody fills in standing up, on the door of a concert, in the dark. */
.ad-gate-card .form input{font-size:18px;padding:15px 16px;min-height:54px}
.ad-gate-card .btn{min-height:56px;font-size:14px}
.ad-gate-card .form{margin:0}
.ad-gate-card .btn{width:100%;justify-content:center;margin-top:4px}
.ad-gate-card .ad-stay{margin-top:18px}
.ad-gate-card .hint{margin-top:6px;font-size:13px;line-height:1.5;color:var(--mute)}
/* Quiet, under the tick: it is the way out for somebody who is stuck, not one
   of the two things this card is for. */
.ad-gate-lost{margin:16px 0 0}
.ad-gate-lost button{padding:4px 0;font:inherit;font-size:14px;background:none;
  border:0;border-bottom:2px solid var(--line);color:var(--mute);cursor:pointer;
  transition:.15s}
.ad-gate-lost button:hover{color:var(--scarlet);border-bottom-color:var(--scarlet)}
.ad-gate-lost button:focus-visible{outline:3px solid var(--scarlet);outline-offset:2px}
/* One or the other on the card, never both. */
#adminForgotForm,.ad-gate-back{display:none}
.ad-gate-card.is-lost #adminLogin,
.ad-gate-card.is-lost .ad-stay,
.ad-gate-card.is-lost .ad-gate-lost:not(.ad-gate-back){display:none}
/* GRID, NOT BLOCK. A .form is a grid, and its boxes are full width because a
   grid stretches them; showing this one as a block put the address box back to
   whatever width a browser thinks an <input> is — 275px against a button of
   398, on the same card as a sign-in box that fills it. */
.ad-gate-card.is-lost #adminForgotForm{display:grid}
.ad-gate-card.is-lost .ad-gate-back{display:block}
#adminForgotForm .ad-says{margin:10px 0 0;min-height:1.4em}
#adminForgotForm .hint{margin:0 0 16px}

/* ---- a picture is one tile ------------------------------------------------
   THE PICTURE IS THE BUTTON. It was an address box, a thumbnail, a button and a
   sentence stacked down the form — four controls for "which photograph is
   this?", with the address box first and largest although hardly anybody ever
   types one. Now it is the picture itself, which opens the machine's own file
   window when it is pressed, as everything else that takes a photograph does.

   Empty, it is a dashed frame saying what it wants. The address is put away
   behind a word, for the times somebody has a link rather than a file. */
.ad-photo{margin-top:8px;display:grid;gap:12px;justify-items:start}
/* THE SHAPE IS THE LABEL. These two fields are the same control with almost
   the same name, side by side, and the only real difference between them is
   what shape of picture they want: a landscape photograph for the homepage
   card, portrait artwork for a poster. Drawn as two identical squares, the
   commonest mistake is the same picture in both. */
/* THE PICTURE TAKES ITS COLUMN, AND THE ACTIONS GO UNDER IT.
   The tile stood beside its own actions, so a 406px column was split into a
   232px picture and whatever was left for three words — which put "Paste an
   address" on one line, "Remove" on another and the sentence explaining the
   poster on a third, in a channel too narrow for any of them. The picture is
   the thing being decided; it gets the width, and the actions stand under it
   in a row, where a row of buttons has room to be a row.

   Wide rather than tall for a photograph, tall for a poster, both bounded so
   neither ever becomes the tallest thing on the card. */
.ad-photo-tile{position:relative;display:block;width:100%;max-width:340px;
  aspect-ratio:4/3;
  border:2px dashed var(--line);background:var(--tint);cursor:pointer;
  transition:.15s;overflow:hidden}
.ad-photo.is-portrait .ad-photo-tile{max-width:228px;aspect-ratio:4/5}
.ad-photo.has-photo .ad-photo-tile{border-style:solid}
.ad-photo-tile:hover{border-color:var(--scarlet)}
.ad-photo-tile input{position:absolute;width:1px;height:1px;opacity:0;
  pointer-events:none}
.ad-photo-tile:focus-within{outline:3px solid var(--scarlet);outline-offset:2px}
.ad-thumb{display:block;width:100%;height:100%}
.ad-thumb img{width:100%;height:100%;object-fit:cover;display:block}

/* The word sits under the picture when there is one, and in the middle of the
   frame when there is not. */
.ad-photo-word{position:absolute;left:0;right:0;bottom:0;padding:8px 10px;
  font-weight:900;font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  text-align:center;color:var(--mute)}
.ad-photo.has-photo .ad-photo-word{color:#fff;
  background:linear-gradient(180deg,rgba(20,16,15,0),rgba(20,16,15,.72))}
.ad-photo:not(.has-photo) .ad-photo-word{top:0;display:flex;
  align-items:center;justify-content:center}

.ad-photo-side{width:100%;display:grid;gap:10px}
/* THEY ARE BUTTONS. They were words with a line under them, which is what this
   site uses for a link in a sentence — so three things that change a picture
   read as three things to read. The admin's own outline button, at the small
   size the rest of the screen uses. */
.ad-photo-acts{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0}
.ad-photo-box{display:block}

/* The file input itself is never shown — every browser draws it differently and
   none of them draw it like this site. The label is the button, which is why it
   carries the focus ring rather than the input. */
.ad-pick{display:inline-block}
.ad-pick input{position:absolute;width:1px;height:1px;opacity:0;
  overflow:hidden;clip:rect(0 0 0 0)}
.ad-pick span{display:inline-flex;align-items:center;min-height:44px;
  padding:0 16px;cursor:pointer;font:inherit;font-weight:700;font-size:14px;
  border:2px solid var(--ink);background:#fff;color:var(--ink)}
.ad-pick span:hover{background:var(--ink);color:#fff}
.ad-pick input:focus-visible + span{outline:3px solid var(--scarlet);
  outline-offset:2px}

.ad-photo-say{margin:0;font-size:13px;color:var(--mute);min-height:1.2em}

/* Putting the website back. Set apart from the table of what changed, and
   below it, because it does more than that table describes — it replaces
   everything, and somebody who has just read three rows should not meet this
   as though it undid only those three. */
.ad-undo{margin-top:18px;padding-top:16px;border-top:2px solid var(--line)}
.ad-undo-go{font:inherit;font-weight:700;font-size:14px;min-height:44px;
  padding:0 16px;cursor:pointer;border:2px solid var(--scarlet);
  background:#fff;color:var(--scarlet)}
.ad-undo-go:hover{background:var(--scarlet);color:#fff}
.ad-undo-go[disabled]{opacity:.6;cursor:default}
.ad-undo .hint{margin-top:8px}
/* Long label, deliberately — it says what it does rather than "Undo", which
   would be shorter and would not warn anybody. So it wraps and grows instead of
   staying one line and running off the side. */
.ad-undo-go{max-width:100%;height:auto;padding:11px 16px;text-align:left;
  line-height:1.3}

.ad-entry-foot{margin-top:6px;display:flex;align-items:center;
  justify-content:space-between;gap:16px}

/* ---- THE GRIP ----
   Where the order is decided by hand, every row carries one: six small squares
   at the left-hand edge, the mark for "take hold of this" that every phone has
   taught. Quiet until the row is hovered; the row itself is still opened by
   pressing its name. Square dots — there are no circles in this design. */
.ad-entry.can-move{display:flex;align-items:stretch}
.ad-entry.can-move .ad-head{flex:1 1 auto;min-width:0}
/* The squares are --mute at rest and --ink on hover. They were --line, about
   1.3:1 on white, which is a control a person with low vision cannot find
   (WCAG 1.4.11 asks 3:1 of anything you have to see to use); --mute is about
   6:1 and still the quietest grey the palette has, so the row keeps its calm. */
.ad-grip{flex:0 0 auto;display:grid;place-items:center;width:34px;margin-right:2px;
  padding:0;background:none;border:0;color:var(--mute);cursor:grab;
  touch-action:none;transition:color .15s}
.ad-grip svg{width:20px;height:20px}
.ad-entry:hover .ad-grip,.ad-grip:hover{color:var(--ink)}
.ad-grip:focus-visible{outline:3px solid var(--gold);outline-offset:-3px;color:var(--ink)}
.ad-grip:active{cursor:grabbing}
/* While a search is filtering, moving a row would put it among things not on
   screen. The grip says so by looking unavailable; admin.js refuses in words. */
.ad-list.is-filtered .ad-grip{opacity:.35;cursor:default}

/* THE ROW IN HAND. Lifted — white, a shadow, above the others — and the rows it
   passes step aside with a short slide, so where it will land is shown before
   it is let go. The one being dragged does not animate: it is under a finger,
   and a finger that is followed a tenth of a second late feels like mud. */
.ad-list.is-sorting .ad-entry{transition:transform .14s var(--ad-ease,ease)}
.ad-list.is-sorting .ad-entry.is-dragging{transition:none;position:relative;z-index:2;
  background:#fff;box-shadow:0 8px 24px rgba(0,0,0,.14);
  outline:1px solid var(--line)}
.ad-list.is-sorting .ad-entry.is-dragging .ad-grip{color:var(--ink);cursor:grabbing}
.ad-list.is-sorting .ad-head{pointer-events:none}
.ad-remove{font:inherit;font-weight:700;font-size:13px;min-height:44px;
  padding:0 2px;background:none;border:0;cursor:pointer;
  color:var(--scarlet);border-bottom:2px solid transparent}
.ad-remove:hover{border-bottom-color:var(--scarlet)}

.ad-actions{margin-top:26px}

/* Two boxes side by side where there is room, stacked where there is not. Dates
   and times, seats and prices: pairs that are read together. */
.ad-two{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media(max-width:620px){.ad-two{grid-template-columns:1fr}}

/* Something that cannot be changed is shown as text, not as a greyed-out box.
   A disabled field invites people to try. */
.tk-fixed{margin:0;font-weight:700;font-size:16px;padding:13px 0}

/* WHAT THE DIARY ALREADY ANSWERED, held together as one block so it reads as
   a quotation from another screen rather than as five fields somebody forgot
   to make editable. A hairline down the left, the same device the note at the
   top of this page uses for the same reason. */
/* ON INK, BECAUSE IT IS SETTLED. These five are the diary's answer, shown here
   and sent back untouched — but drawn as pale labels over pale values on the
   same white as the boxes below them, they read as five fields somebody had
   forgotten to make editable. The band's own ground for a thing that is stated
   rather than asked says it in one glance: this is a fact, and the form starts
   underneath it. Gold on the way back to where it can be changed, which is what
   gold does on ink everywhere else on this site. */
.tk-from{margin:0 0 26px;padding:20px 22px;background:var(--ink);color:#fff;
  display:grid;gap:18px;border-bottom:4px solid var(--gold)}
.tk-from .ad-two{gap:18px 26px;margin:0}
.tk-from .ad-field{margin:0}
.tk-from label,.tk-from .ad-field-label{color:rgba(255,255,255,.62)}
.tk-from .tk-fixed{padding:3px 0 0;font-size:16px;color:#fff}
.tk-from > .hint{margin:2px 0 0;font-size:13px;color:rgba(255,255,255,.66)}
.tk-from a{color:var(--gold)}
.tk-from a:hover{color:#fff}

/* What the numbers add up to, said in a sentence — a wrong capacity is obvious
   in "30 seats at £15.00 — a full hall is £450" and invisible in a box. */
.tk-sums{background:var(--tint);border-left:4px solid var(--gold);
  padding:14px 16px;margin:4px 0}
.tk-sums p{margin:0;font-size:15px}
.tk-live{background:var(--tint);padding:14px 16px;margin:4px 0;font-size:15px}
.tk-live p{margin:0 0 6px}
.tk-live p:last-child{margin:0}
.tk-on{color:#0B6B3A}

/* ---- what happened when you saved ---- */
.ad-note{padding:15px 18px;margin:0 0 22px;font-size:15px;
  border-left:4px solid var(--line);background:var(--tint)}
.ad-note.ok{border-left-color:#0B6B3A;background:#F1F8F3}
.ad-note.bad{border-left-color:var(--scarlet);background:#FFF4F4}

/* ---------- responsive ---------- */
@media(max-width:1000px){
  .cards,.steps{grid-template-columns:1fr 1fr}
  .record{grid-template-columns:1fr 1fr}
  .split,.split-2{grid-template-columns:1fr;gap:36px}
  /* WHAT IS BEING BOUGHT COMES BEFORE THE BUTTON THAT BUYS IT. Stacked, the
     aside falls under the clock and the payment button, so on a phone the
     concert, the date and the amount were below the fold at the moment
     somebody was deciding to pay. It goes first. */
  .ck-split>aside{order:-1}
  .players{grid-template-columns:repeat(4,1fr)}
  /* No longer a grid, so the old grid-template-columns here did nothing once
     the footer became a row. The brand block takes the full width and the three
     link columns share what is left, still evenly spaced. */
  .foot-brand{flex:1 1 100%}
  .f-col{flex:1 1 auto}
  .specs{grid-template-columns:1fr}
  .spec:nth-child(odd){padding-right:0}
  /* THE MENU STARTS WHERE THE HEADER ENDS, MEASURED
     This was inset:58px. The header is 73px, so the menu opened 15px too high
     and its first link went up behind the header. --hdr-h is the measured
     height, so the two now meet exactly however the header changes.

     It covers the page to the bottom rather than stopping partway: a press
     anywhere off the links shuts it, and there is nowhere on screen that looks
     pressable but isn't. The links sit at the top; the rest is the darkened
     page showing through.

     100dvh, not 100vh. On a phone vh is the height of the screen with the
     address bar HIDDEN, which is taller than what can actually be seen while it
     is showing — so a menu sized in vh runs off the bottom by the height of the
     bar. dvh is the space there is right now. */
  .nav{position:fixed;top:var(--hdr-h);left:0;right:0;bottom:0;
    height:calc(100dvh - var(--hdr-h));
    background:var(--ink);flex-direction:column;
    align-items:stretch;gap:0;padding:8px 24px 22px;display:none;
    border-bottom:2px solid var(--gold);
    overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
  .nav.open{display:flex}

  /* The page behind is held still while the menu is over it. A page that scrolls
     under a menu standing still reads as the menu having come adrift from the
     site. */
  html.nav-open,html.nav-open body{overflow:hidden}
  /* The dropped-down menu is a stack of rows, not a row of tabs, so the
     header-bottom trickery above is undone here. */
  .nav{align-self:auto;margin-bottom:0}
  /* 14px above and below a 13px line makes a 44px row — a target that can be hit
     with a thumb without looking. flex:0 0 auto stops the links stretching to
     share out a tall menu between them, which on a phone held sideways would
     give six links wildly different heights. */
  .nav a{padding:14px 0;border-bottom:1px solid rgba(255,255,255,.1);
    flex:0 0 auto;min-height:44px;align-items:center}
  .nav .btn{align-self:auto;margin:14px 0 0;justify-content:center;
    flex:0 0 auto;min-height:52px}
  /* In the dropped-down menu the icons stay a row, centred, under everything
     else. The hairline that divides them from the nav on a wide screen would be
     a vertical line in the middle of a stack here, so it becomes a rule across
     the top instead. Bigger targets too: this is the touch layout. */
  .social{align-self:auto;margin:20px 0 0;padding:18px 0 0;gap:8px;
    justify-content:center;
    border-left:0;border-top:1px solid rgba(255,255,255,.14)}
  .social a{width:44px;height:44px}
  .social svg{width:21px;height:21px}
  .burger{display:flex}
  .brand i{display:none}
}
@media(max-width:640px){
  body{font-size:16px}
  .sec{padding:58px 0}
  .hero-in{padding:60px 24px 74px}
  .cards,.steps{grid-template-columns:1fr}
  .players{grid-template-columns:repeat(2,1fr)}
  .roster-jump{gap:6px}
  .roster-jump a{font-size:11px;padding:8px 11px}
  /* On a phone everything stacks, so the three link columns take a full line
     each rather than being squeezed side by side. */
  .f-col{flex:1 1 100%}
  /* Nothing to add here: sizeCredit() matches the line to whatever width the
     rule has at this breakpoint, and the 12px floor in the base rule is what
     applies if the script never runs. */
  .form .row{grid-template-columns:1fr}
  .spec{grid-template-columns:1fr;gap:4px}
}

/* =============================================================================
   THE PRINTED PROGRAMME  (programme.html, drawn by programme.js)
   =============================================================================
   A5 pages in the band's colours and type, the browser prints or saves as a
   PDF. THE SIZE IS SAID ONCE: --pg-w, --pg-h and @page below. Everything else
   is a fraction of the page, the way the posters are fractions of their width,
   so a change of size is a change of three lines.

   The cover is the band's white concert poster drawn again: the crest light
   behind, the title in black capitals with the gold rule under it, the badge
   in the middle, the facts at the foot — with PROGRAMME where the tickets
   would be. Inside, every page is headed the way the site heads a page: a
   kicker in small capitals, the word in display capitals, the gold rule.
   Square everything; one weight of rule; the red strip for a part.
   ========================================================================== */
/* ---- THE MARGINS, AND WHY THEY ARE THESE ------------------------------------
   --pg-w/--pg-h  the sheet. A5, 148 × 210mm.
   --pg-m         the type margin, 12mm on all four edges. Two reasons for
                  that number and not a smaller one. It sets the measure: 148
                  less two margins is 124mm, which at 10.5pt is about 65
                  characters a line — the middle of the 60-to-75 a paragraph
                  is comfortable at. And it clears the edge no home printer
                  can reach: almost every inkjet and laser refuses the outer
                  4 to 6mm of the sheet, so anything inside 8mm is a gamble
                  on whose printer it is.
   --pg-gutter    4mm more on the bound edge, and only there. A programme is
                  folded or stapled down the middle, and the fold eats the
                  inner margin — so the inner edge is 16mm and the outer 12,
                  which is what makes the two open pages look even once the
                  booklet is closed. Which edge that is alternates: a
                  right-hand page (the 1st, 3rd, 5th) is bound on its left, a
                  left-hand page on its right. Chrome does not honour
                  @page :left / :right, so the pages count themselves.

   THE FULL-BLEED PAGES ARE THE EXCEPTION, on purpose. The cover and the back
   are ink and artwork to the paper's edge, which a home printer will fringe
   with white and a print shop will not. The cover keeps the poster's own
   margins (5.5% of the width, as posters.js draws them at A4) so that the
   printed poster and the printed programme are the same drawing. */
.pg-body{--pg-w:148mm;--pg-h:210mm;--pg-m:12mm;--pg-gutter:4mm;
  margin:0;background:#4a403d;color:var(--ink);font-family:var(--f);font-weight:500}
@page{size:A5;margin:0}

/* The bar for the screen. Never printed. */
.pg-bar{position:sticky;top:0;z-index:5;display:flex;align-items:center;gap:18px;
  padding:12px 22px;background:var(--ink);color:#fff;border-bottom:4px solid var(--gold)}
.pg-bar-text{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}
.pg-bar-text b{font-size:16px}
.pg-bar-text span{font-size:13px;color:rgba(255,255,255,.72)}
.pg-none{max-width:60ch;margin:60px auto;padding:0 22px;color:#fff;font-size:16px;line-height:1.6}
.pg-none code{background:rgba(255,255,255,.12);padding:1px 6px}

.pg-main{padding:30px 0 60px}
.pg-pages{display:flex;flex-direction:column;align-items:center;gap:26px}
.pg-page{position:relative;width:var(--pg-w);height:var(--pg-h);overflow:hidden;
  background:#fff;box-shadow:0 18px 50px rgba(0,0,0,.35);
  padding:var(--pg-m);display:flex;flex-direction:column;
  font-size:10.5pt;line-height:1.5}
/* The bound edge, alternating — see the note on --pg-gutter above. */
.pg-page:nth-child(odd){padding-left:calc(var(--pg-m) + var(--pg-gutter))}
.pg-page:nth-child(even){padding-right:calc(var(--pg-m) + var(--pg-gutter))}
/* THE TWO THAT BLEED TAKE NONE OF IT: they are artwork to the paper's edge,
   and a padding on them is not a margin — an absolutely positioned child is
   laid out against the PADDING box, so 16mm of gutter moved the cover's
   crest and the back's mark 16mm in from the wall they are supposed to run
   off. Written to the same weight as the alternating rules above and after
   them, so it wins on order rather than by accident. Their own words carry
   their margins: the cover the poster's, the back cover .pg-back-in's. */
.pg-page.pg-cover,.pg-page.pg-back{padding:0}
/* A page whose words still run past its foot after the carrying-over says
   so — a welcome too long for a page is the writer's to shorten. */
.pg-page.is-over::after{content:"Runs over — shorten the words on this page";
  position:absolute;left:0;right:0;bottom:0;padding:5px 0;
  background:var(--gold);color:var(--ink);font-size:9pt;font-weight:700;text-align:center}

/* ---- the devices every page shares ---- */
.pg-head{margin:0 0 6mm}
.pg-head.is-continued .pg-h{font-size:18pt}
.pg-kicker{display:block;font-size:8.5pt;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--scarlet);margin-bottom:2mm}
.pg-h{font-size:26pt;font-weight:900;line-height:1;letter-spacing:.005em;
  text-transform:uppercase;margin:0}
.pg-rule{display:block;width:26mm;height:1.6mm;background:var(--gold);margin-top:3mm}
.pg-label{display:block;font-size:8pt;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mute);margin-bottom:.8mm}
/* The band's red strip, the same inset as everywhere else on the site: 4px
   above and below, 5px at the sides. Only the size differs. */
.pg-strip{display:inline-block;padding:4px 5px;background:var(--royal);color:#fff;
  font-weight:700;font-size:12pt;line-height:1.2;letter-spacing:.01em;text-transform:none}
.pg-missing{color:var(--mute);font-style:italic}
.pg-note{margin-top:auto;padding-top:4mm;font-size:8.5pt;color:var(--mute)}

/* ---- the cover ---- */
.pg-cover{padding:0;background:#fff}
.pg-cover-in{position:relative;z-index:1;display:flex;flex-direction:column;height:100%;
  padding:calc(var(--pg-w) * .05) calc(var(--pg-w) * .055) calc(var(--pg-w) * .06)}
.pg-cover-title{font-size:calc(var(--pg-w) * .155);font-weight:900;line-height:.98;
  letter-spacing:.005em;text-transform:uppercase;margin:0;color:var(--ink)}
.pg-cover-in .pg-rule{width:45%;height:calc(var(--pg-w) * .011);margin-top:calc(var(--pg-w) * .03)}
.pg-cover-mid{flex:1 1 auto;display:grid;place-items:center;padding:calc(var(--pg-w) * .04) 0}
.pg-badge{width:62%;max-height:100%;object-fit:contain}
.pg-cover-foot{display:grid;gap:2mm;justify-items:start}
.pg-cover-when{margin:0;font-size:12.5pt;font-weight:700}
.pg-cover-where{margin:0;font-size:11pt;font-weight:700}
.pg-cover-where span{font-weight:500;color:var(--mute)}
/* The band's own poster as the cover: full bleed, PROGRAMME on a band at the foot. */
.pg-cover-art .pg-art{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.pg-cover-band{position:absolute;left:0;right:0;bottom:0;padding:5mm var(--pg-m);
  background:linear-gradient(180deg,rgba(20,16,15,0),rgba(20,16,15,.7))}

/* ---- welcome ---- */
.pg-prose p{margin:0 0 1em;text-align:justify;-webkit-hyphens:auto;hyphens:auto}
.pg-md{display:flex;align-items:center;gap:5mm;margin-top:auto;padding-top:5mm;
  border-top:1px solid var(--line)}
.pg-md + .pg-md{margin-top:3mm;padding-top:3mm}
.pg-md-face{width:18mm;height:18mm;object-fit:cover;flex:0 0 auto}
.pg-md b{font-size:13pt;font-weight:900}

/* ---- the programme of music ----
   .pg-tunes, not .pg-music: the PAGE is .pg-music, and a list sharing its
   name took the page's margins off with its own padding:0. A page's class
   and the things on it never share a name here. */
.pg-tunes{list-style:none;margin:0;padding:0}
.pg-piece{display:grid;grid-template-columns:1fr auto;column-gap:5mm;align-items:baseline;
  padding:2.2mm 0;border-bottom:1px solid var(--line);break-inside:avoid}
.pg-piece b{font-size:11.5pt;font-weight:700}
.pg-piece i{font-style:normal;font-size:9.5pt;color:var(--mute);text-align:right}
.pg-piece small{grid-column:1/-1;font-size:9pt;color:var(--mute)}
.pg-part{padding:5mm 0 1.5mm;font-size:8.5pt;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;color:var(--scarlet)}
.pg-interval{padding:4.5mm 0 2.5mm}

/* ---- the band ---- */
.pg-md-line{margin:0 0 5mm}
.pg-md-line b{font-size:13pt;font-weight:900}
.pg-stands{columns:2;column-gap:8mm}
.pg-sec{break-inside:avoid;margin:0 0 4.5mm}
.pg-sec ul{list-style:none;margin:0;padding:0}
/* A HANGING INDENT, because every player now carries their part and two
   columns of an A5 page are 58mm wide — "Archie Batty  Assistant Principal
   Cornet" does not fit on one line and never will. So the part is kept whole
   (it wraps as a phrase, not between "Second" and "Baritone") and anything
   that runs on is set in from the name, which is what makes a wrapped line
   read as belonging to the name above rather than as the next player. */
/* A HANGING INDENT, because every player now carries their part and a column
   of an A5 page is 58mm wide — "Archie Batty  Assistant Principal Cornet"
   does not fit on one line and never will. THE NAME AND THE PART ARE EACH
   UNBREAKABLE and the only place a line may turn is the space between them,
   so a long entry becomes a name with its part under it rather than "Archie /
   Batty" or "Second / Baritone". What runs on is set in from the name, which
   is what makes the second line read as belonging to the entry above it
   rather than as the next player. */
.pg-sec li{font-size:10pt;line-height:1.45;padding-left:4mm;text-indent:-4mm}
.pg-sec li>span{white-space:nowrap}
.pg-sec li i{font-style:normal;color:var(--mute);font-size:8.5pt;margin-left:1.5mm;
  white-space:nowrap}

/* ---- what's next ---- */
.pg-dates{list-style:none;margin:0;padding:0}
.pg-dates li{display:grid;grid-template-columns:22mm 1fr;gap:4mm;padding:2.5mm 0;
  border-bottom:1px solid var(--line);align-items:baseline}
.pg-next-date{font-weight:900;color:var(--scarlet);font-size:10pt;letter-spacing:.02em}
.pg-next-what b{display:block;font-size:11pt}
.pg-next-what i{font-style:normal;font-size:9pt;color:var(--mute)}
.pg-follow{display:flex;align-items:center;gap:6mm;margin-top:7mm}
.pg-qr{flex:0 0 auto;width:28mm;height:28mm}
.pg-qr rect{fill:var(--ink)}
.pg-follow b{display:block;font-size:11pt}
.pg-follow span{display:block;font-size:9.5pt;color:var(--mute)}
/* ---- where else to find the band ----
   The mark and the handle, three across. On the what's-next page they sit
   under the website's address with the mark in scarlet; on the back cover
   they are gold on ink, which is the crest's own pairing. */
/* The three sit across the whole width rather than in the column beside the
   QR code, where they broke two and one. */
.pg-socials{list-style:none;margin:5mm 0 0;padding:0;display:flex;flex-wrap:wrap;
  justify-content:space-between;align-items:flex-start;gap:2mm 4mm}
/* The mark and its two lines are centred on one another: one small mark
   against a two-line block, and nothing to stretch. */
.pg-socials li{display:flex;align-items:center;gap:1.8mm}
/* ONE SQUARE FOR ALL SIX MARKS, on white and on ink alike, and its size is
   worked out from the type beside them rather than typed. The two line
   heights are declared once, here — the handle takes the first, the label the
   second — and the square is the two added together, so the mark stands the
   full height of its two lines. Change the type and the marks follow.

   THE SQUARE IS THE BOX, NOT A PLATE. Nothing is drawn round the mark; the
   square is only what each mark is scaled inside, and the scaling is by
   optical area (see programme.js), so three unlike shapes carry the same
   weight. One height for all three was tried instead and put back: it cuts
   the tall thin f down to the height of the wide YouTube mark, and at that
   size the f reads as the smaller of the two. */
.pg-socials{--pg-line-a:11.25pt;--pg-line-b:9.1pt}
.pg-social-mark{flex:0 0 auto;display:block;color:var(--scarlet);
  width:calc(var(--pg-line-a) + var(--pg-line-b));
  height:calc(var(--pg-line-a) + var(--pg-line-b))}
.pg-socials b{display:block;font-size:9pt;font-weight:700;line-height:var(--pg-line-a)}
.pg-socials i{display:block;font-style:normal;font-size:7pt;color:var(--mute);
  letter-spacing:.12em;text-transform:uppercase;line-height:var(--pg-line-b)}
.pg-socials.is-dark{justify-content:center;gap:2mm 6mm;margin:0 0 6mm}
/* On the ink the same mark in gold, which is the crest's own pairing with
   black. Nothing else changes. */
.pg-socials.is-dark .pg-social-mark{color:var(--gold)}
.pg-socials.is-dark b{color:#fff}
.pg-socials.is-dark i{color:rgba(255,255,255,.6)}
.pg-book{margin-top:auto;padding-top:5mm}
.pg-book p{margin:2.5mm 0 0;font-size:9.5pt;line-height:1.5}

/* ---- THE CREST ON THE TWO COVERS ----
   Both carry the site's own device and nothing of their own — .mark at the
   front, .mark.dark at the back, the classes the footer and every page banner
   use — so the corner is drawn in one place for the whole site.

   AND NOTHING OF THEIR OWN INCLUDES THE SIZE. The device's rule is
   `auto 100%` — the crest set to the full HEIGHT of the surface, so it stands
   on the bottom edge and reaches the top corner. An A5 sheet is 148 by 210
   and the artwork 1221 by 1365, so that draws it 188mm wide on a 148mm page
   and runs 40mm off the right-hand side.

   BOTH SIZINGS WERE PUT ON THE PAGE AND LOOKED AT. Fitted to the width
   instead (`100% auto`), the point of the crest's lowest ray lands on the
   right-hand wall — measured, that point is at x=1214 of 1221, so the fit is
   exact to within the file's own margin — but the crest then stops 45mm short
   of the top and the corner it is meant to fill is empty. Daniel looked at
   the two and kept the full height: the crest reaching the top corner is what
   it does everywhere else on this site, and running off the side is what a
   bleeding watermark is for.

   AND NO OPACITY ON THE BACK. It was tried at .5 to "lift it off the ink" and
   did the opposite: black at half strength over #14100F measures (10,8,7),
   nearer the ink than the (0,0,0) the brand asks for. The band's rule — a
   black surface takes a #000000 mark — is both the more visible and the
   correct one. */
.pg-back{background:var(--ink);color:#fff}
.pg-back-in{position:relative;z-index:1;height:100%;display:flex;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;gap:3mm;
  padding:var(--pg-m)}
/* The crest, the name and the line hold the middle of the sheet; the handles
   and the small print sit down at the foot, where somebody looks for them. */
.pg-back-mid{flex:1 1 auto;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:3mm}
.pg-back .pg-badge{width:34%}
.pg-back-name{font-size:20pt;font-weight:900;letter-spacing:.02em;margin-top:4mm}
.pg-back-line{font-style:normal;font-size:9pt;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold)}
.pg-back-foot{margin:0;font-size:8.5pt;line-height:1.6;color:rgba(255,255,255,.72)}

/* A page whose words run past its foot says so on the screen; on paper the
   browser flows them on to another. */
/* ---- on paper ----
   No bar, no ground, no shadow; each page is a sheet, the same box as on the
   screen. THE SAME BOX ON PURPOSE: letting a page grow and the browser
   paginate it looked right until it was tried — Chrome loses the margins of
   a flex column it has to break. So a page is always one sheet, and a list
   too long for its page is carried on to another page by programme.js
   before printing, which is what a typesetter would do. */
@media print{
  .pg-body{background:none}
  .pg-bar{display:none}
  .pg-main{padding:0}
  .pg-pages{display:block}
  .pg-page{box-shadow:none;margin:0;break-after:page;page-break-after:always;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
  .pg-page:last-child{break-after:auto;page-break-after:auto}
  .pg-page.is-over::after{display:none}
}
