/* Unholy Land archive system
   Shared visual contract for map, band, artist and collection pages. */
:root {
  /* The interface material. This file does NOT touch --accent: the one red is
     still #e0453e and still means brand, the close X and a band that is gone.
     What changes here is --ui-accent — everything that used to borrow the red
     for chrome resolves to this instead. One line, one meaning, and the red
     stays greppable where CLAUDE.md says it lives.

     THE NAME IS A LIE AND IT IS KEPT ON PURPOSE. These were brass — #b99b66
     and its two shades — and the whole site was warm under them. It is steel
     now, and the site is meant to read like a cold room: the archive is a
     record of a scene, a great deal of which is dead, and warmth was an
     invitation the subject never extended. The token keeps the old name
     because forty-odd rules across four stylesheets read it, and a rename is
     forty chances to miss one while another session is working in the same
     tree — bandworld.css already set this precedent with --bw-gold, which is
     #8b939d and has been grey for as long as it has existed.

     Steel is a touch brighter than the brass it replaced, not dimmer: 8.09:1
     on this ground against the brass's 7.60:1. Cold is a hue decision and
     legibility is a contrast one, and the second must not be spent paying for
     the first. */
  --archive-brass: #9aa6b2;
  --archive-brass-hi: #c8d3de;
  --archive-brass-dim: #5c646d;
  --ui-accent: var(--archive-brass);
  --bg: #030507;
  --bg-90: rgb(3 5 7 / .95);
  --panel: rgb(8 10 13 / .97);
  --panel-solid: #080a0d;
  --surface: #090b0e;
  --surface-raised: #0d1014;
  --border: #2a2e34;
  /* --border draws card edges, ledges and rules, and at 1.43:1 on this ground
     that is exactly right: a divider is decoration and WCAG asks nothing of
     it. The boundary of a *control* is a different thing — it is the only
     thing saying where the field begins — and 1.4.11 asks 3:1 of it. #282c31
     was 1.37:1 against the field's own #0d0f0f fill, so the search, the two
     flyer selects and every input in the portal were drawn with an edge
     nobody could locate. 3.26:1 now, and still under --dim (5.03) so a
     resting field reads quieter than the text inside it. A separate token
     because raising --border itself would have lightened seventy-two card
     edges to fix six controls. */
  --control-border: #5f656b;
  --text: #cdd2d8;
  --white: #e9edf1;
  --muted: #8f959c;
  /* #6f757c measured 4.31:1 on this ground — under AA, and it is not carrying
     body copy but the 9.5–11px tracked capitals, which is the worst place on
     the site to be a tenth of a stop short. 5.24:1 now, and still two clear
     steps below --muted (6.63) and --text (13.18), so the three-level
     hierarchy the greys were chosen for survives the lift. */
  --dim: #7d838b;
  --radius: 0;
  --archive-shadow: 0 22px 46px rgb(2 3 3 / .72);
  --ease: cubic-bezier(.2, .82, .2, 1);

  /* ── how long a thing is allowed to take ──────────────────────
     One scale, and every duration on the site is one of these five. The
     principle underneath: information is not entering the screen, it is being
     uncovered — so nothing overshoots and nothing bounces. A bounce is a
     spring, a spring is a toy, and this is an archive.

     Entry and exit take different curves on purpose. Something arriving
     decelerates hard into place (it settles); something leaving accelerates
     away (it is dismissed). A shared symmetric curve made every open feel
     like the same event as every close. */
  --mo-micro: .14s;   /* a press, a tick, a checkbox */
  --mo-hover: .2s;    /* hover, highlight, a colour changing hands */
  --mo-open: .32s;    /* a card opening, a filter resolving */
  --mo-move: .64s;    /* a structural move, a map flying */
  --mo-rite: 1.1s;    /* the one ceremonial beat a page is allowed */
  --ease-out: cubic-bezier(.16, 1, .3, 1);    /* arriving */
  --ease-in: cubic-bezier(.7, 0, .84, 0);     /* leaving */
  /* Reduced motion does not mean no motion — it means no motion through
     space. Every spatial reveal on the site is written to collapse onto this
     one short crossfade instead of snapping, so a state change stays legible
     to someone who asked not to be moved. */
  --mo-fade: .12s;

  /* Measure and rhythm — the second half of the shared contract. Colour was
     already one system here; these say how wide a page runs, how far apart
     its blocks sit, and how small a tile is allowed to get before the grid
     drops a column. They are tokens and nothing consumes them by default, so
     adding them changes no page until that page opts in — which is the point:
     a route adopts the archive's measure by reading these instead of carrying
     its own numbers. museum.css is the first reader. */
  --arch-max: 1120px;        /* page measure, gutters excluded */
  --arch-gutter: 24px;       /* page edge to content */
  --arch-gap: 12px;          /* between tiles in a grid */
  --arch-gap-lg: 20px;       /* between large tiles (covers, sleeves) */
  --arch-block: 56px;        /* between one section and the next */
  --arch-tile: 158px;        /* narrowest a grid tile may become */
  --arch-tile-lg: 190px;     /* narrowest for logo/name tiles */
  --arch-rule: #16191d;      /* hairline inside a block — quieter than --border */
}

html { color-scheme: dark; background: var(--bg); }
body { background: var(--bg); color: var(--text); }

/* ── grain ────────────────────────────────────────────────────
   One layer over the whole site at three and a half per cent. It is the
   difference between a dark web page and a printed thing that has been kept
   somewhere: at this strength nobody sees it, everybody reads it.

   It also does a job. The band photograph behind a museum hero is a long
   grayscale gradient dissolving into near-black, which is the exact case
   eight-bit colour cannot express — the fade arrives in visible steps, and on
   the wide dark skies in this archive those steps are bands across the top of
   the page. Grain is dither: the noise breaks the step boundaries up and the
   banding stops being a shape.

   Drawn by the renderer from one filter primitive, so it is no request and no
   file. Fixed rather than scrolled — it is the surface of the glass, not of
   the page — and behind everything but above the museum's photo plate, which
   sits at -1 for its own reasons.

   overlay rather than a flat opacity: overlay leaves black alone and lifts
   only what already has light in it, so the grain lands on the photographs
   and the brass and never turns the page's black into grey. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* The map is the one page where the ground is a photograph of the world and
   not the archive's own black; leaflet's panes carry their own compositing
   and a blend layer over them costs a frame for nothing.

   The child combinator is the whole rule. Written as `body:has(#map)` this
   also caught band.html, which holds a second, smaller #map — the related
   bands — buried inside .mapwrap, and so switched the grain off across the
   entire band page including the museum view. That is precisely the page the
   grain was written for: the photograph behind a museum hero is the long
   grayscale fade that bands in eight bits, and the dither is what breaks the
   steps up. On the map page #map is a direct child of body and nothing else
   is; on every other page it is nested or absent. */
body:has(> #map)::after { display: none; }

/* ── an object is lit from above ──────────────────────────────
   Every framed thing on the site — a cover in its sleeve, a scan on the
   wall, a face in its frame — was a picture with a hairline round it, which
   reads as pasted on. One inside highlight along the top edge is the whole
   difference between pasted and hung: it is the light in the room catching
   the frame's top lip, and the eye reads depth from it without ever noticing
   it is there. Five per cent white; more and it becomes a border.

   It has to be its own layer rather than an inset shadow on the frame: the
   picture fills the frame edge to edge and would paint straight over a
   shadow drawn behind it. So the highlight is an ::after — above the image,
   below nothing — and it takes no clicks. */
.mu-art::after, .mu-paper::after, .mu-frame::after, #album-card .ac-cover::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .05);
}
/* each of the four is already a positioned box, but say so — an ::after with
   inset:0 against a static parent would find the page instead of the frame */
.mu-art, .mu-paper, .mu-frame, #album-card .ac-cover { position: relative; }

/* ── the reveal ───────────────────────────────────────────────
   A block marked [data-reveal] is held back until it is close enough to be
   looked at, then rises a little and comes up. That is the whole primitive,
   and it is deliberately small: one property pair, one distance, one
   duration. What makes it read as an archive rather than as a web page is
   the restraint — 14px, not 60; opacity and translate only, never scale,
   never blur, never a rotation.

   A block may also stagger its own children by marking them [data-reveal-i],
   which nav.js numbers into --i. The step is 44ms and the run is capped at
   ten, because past about half a second the last tile in a row is arriving
   long after the reader's eye already went there and it reads as lag rather
   than as sequence.

   Nothing here is required for the page to be legible: without javascript no
   element ever gets .is-in — so the rule is written the other way round, and
   an unrevealed block is only held once js has said it is watching by putting
   .reveal-armed on the root. */
html.reveal-armed [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
}
[data-reveal] {
  transition: opacity var(--mo-open) var(--ease-out),
              transform var(--mo-open) var(--ease-out);
}
html.reveal-armed [data-reveal].is-in { opacity: 1; transform: none; }

html.reveal-armed [data-reveal-i] {
  opacity: 0;
  transform: translateY(10px);
}
[data-reveal-i] {
  transition: opacity var(--mo-open) var(--ease-out),
              transform var(--mo-open) var(--ease-out);
  transition-delay: calc(min(var(--i, 0), 10) * 44ms);
}
html.reveal-armed [data-reveal-i].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  /* the spatial part goes, the state change stays visible */
  [data-reveal], [data-reveal-i] {
    transition: opacity var(--mo-fade) linear;
    transition-delay: 0s;
  }
  html.reveal-armed [data-reveal],
  html.reveal-armed [data-reveal-i] { transform: none; }
}

/* One navigation material and one control geometry on every route. */
#nav, #topbar {
  border-bottom: 1px solid #212429;
  background: rgb(8 9 9 / .96);
  box-shadow: 0 9px 28px rgb(2 3 3 / .5);
  backdrop-filter: blur(12px) saturate(.7);
}
#nav, #topbar { gap: 24px; }
#brand span, #topbar #brand span { color: var(--accent); }
#navlinks, #topnav { min-width: 0; gap: 20px; }
#navlinks a, #navlinks button, #topnav a, #topnav button {
  color: #cdd2d8;
  font-size: 15px;
  transition: color .2s ease, background-color .2s ease, transform .16s ease;
}
#navlinks a:hover, #navlinks button:hover, #topnav a:hover, #topnav button:hover { color: var(--archive-brass-hi); }
#navlinks a:active, #navlinks button:active, #topnav a:active, #topnav button:active { transform: translateY(1px); }
#navlinks .nav-honors, #topnav .nav-honors { color: var(--archive-brass-hi); }

/* Two controls in the nav are their own sigil rather than a word — the die
   for a random band, the eye for the footage. Sized to the honors icon
   beside them so the row reads as one set, and each keeps a title and an
   aria-label because an icon with no accessible name is a button nobody can
   describe. */
#navlinks .nav-ico, #topnav .nav-ico {
  display: inline-flex;
  align-items: center;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  /* barely held back at rest, not dimmed: with the word gone the icon is the
     whole control, and a faint one is a control nobody finds */
  opacity: .9;
  transition: opacity .2s ease, transform .16s ease;
}
#navlinks .nav-ico img, #topnav .nav-ico img { height: 19px; width: auto; display: block; }

/* ── the one control on this bar that is a character, not a mark ──
   The picked-releases page is a numeral in the nav by decision: the wall is
   five records a year, and the bar says 5. It sits among six traced sigils,
   so it has to carry the same weight as a drawing rather than read as a
   stray digit — the blackletter is what does that, and it is the same face
   the year headings on that page are set in.

   19px to match the sigils exactly: line-height 1 and a block box, so the
   glyph occupies the row the drawings occupy and nothing on the bar shifts.
   Steel like every other mark up here — this is interface, and the gold is
   an honor's alone. */
#navlinks .nav-ico.nav-num, #topnav .nav-ico.nav-num {
  font-family: var(--display-font);
  font-size: 21px;
  line-height: 19px;
  height: 19px;
  color: var(--archive-brass);
  text-decoration: none;
}
#navlinks .nav-ico.nav-num:hover, #topnav .nav-ico.nav-num:hover {
  color: var(--archive-brass-hi);
}

/* NO CAPTION ON THIS ONE, at any width. The rule further down gives every
   sigil its word — as a tooltip under it, and above 1400px as a permanent
   caption beside it — because a traced wreath or a microphone is not a
   convention anybody arrives knowing. A numeral is: it is already legible,
   and the page it opens is about that number. Left alone it printed a small
   "5" next to the large one on any wide screen, which reads as a rendering
   fault rather than a label.
   aria-label carries the accessible name, so nothing is lost to a screen
   reader — what goes is the visible word, which is what was asked for. */
#navlinks .nav-ico.nav-num::after, #topnav .nav-ico.nav-num::after {
  content: none;
}
#navlinks .nav-ico:hover, #topnav .nav-ico:hover { opacity: 1; }
#navlinks .nav-ico:active, #topnav .nav-ico:active { transform: translateY(1px); }

/* The sigil of the page you are already on. .on has been in the markup since
   flyers.html was written and nothing has ever styled it, so it marked
   nothing. Opacity alone cannot do the job — the icons sit at .9 at rest and
   the step to 1 is invisible — so it is a rule under the mark, in the same
   steel as every other ledge on the bar.

   Drawn with box-shadow rather than a border so it costs no layout: a border
   would need padding under one icon and shift that one drawing up against its
   neighbours. Spread -4 on a 1px-tall shadow leaves a short centred tick, not
   a full-width underline, and it sits above the hover label at 100% + 9px. */
#navlinks .nav-ico.on, #topnav .nav-ico.on {
  opacity: 1;
  box-shadow: 0 5px 0 -4px var(--archive-brass-dim);
}

/* ── the sigil is 19px; the thumb is not ──────────────────────
   A 19×19 target fails 2.5.8 outright, and on a phone it is a control you
   miss and then miss again. What grows is an invisible box around the icon,
   not the icon: the drawing stays 19px and nothing on the bar moves.

   The box takes half the row's gap on each side, so the boxes tile edge to
   edge — every tap in the sigil row lands on a sigil, and none of them
   overlaps its neighbour. Two islands of 44px with a dead strip between them
   would be worse than this, and on a 375px phone carrying seven controls in
   one row there is no width for them anyway: 39×43 on a mouse, 33×43 on a
   thumb, against the 24×24 the standard asks. The remaining gap to 44 is the
   single-row bar, and it is a deliberate trade — see the note below on what
   three rows of chrome cost.

   ::after is already the label, so this is ::before. Both keep
   pointer-events, since the box is the target. */
#navlinks .nav-ico, #topnav .nav-ico, #nav-close {
  --hit-x: 10px;   /* half of the 20px gap #navlinks/#topnav set */
  --hit-y: 12px;
}
#navlinks .nav-ico::before, #topnav .nav-ico::before, #nav-close::before {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100% + var(--hit-x) * 2);
  height: calc(100% + var(--hit-y) * 2);
}

/* The word that used to be the control now appears under it on hover. The
   native title tooltip would do this, but it waits a second, it is styled by
   the operating system and it cannot be read on a keyboard — this answers
   :focus-visible too, so tabbing to a sigil says what it is. aria-label is
   still the accessible name; this is only the visible one. */
#navlinks .nav-ico, #topnav .nav-ico { position: relative; }
#navlinks .nav-ico::after, #topnav .nav-ico::after {
  content: attr(data-label);
  position: absolute;
  top: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%) translateY(-3px);
  white-space: nowrap;
  font: 400 10px/1 "Helvetica Neue", Arial, sans-serif;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--archive-brass-hi);
  background: rgb(8 9 9 / .97);
  border: 1px solid #262a30;
  padding: 6px 10px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
  z-index: 5;
}
#navlinks .nav-ico:hover::after, #topnav .nav-ico:hover::after,
#navlinks .nav-ico:focus-visible::after, #topnav .nav-ico:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  #navlinks .nav-ico::after, #topnav .nav-ico::after { transition: none; }
}

/* ── and on a wide screen it does not wait to be asked ────────
   A tooltip only answers a reader who already suspected there was something
   to hover. Three of these four sigils — the honors wreath, the scroll, the
   microphone — are not conventions anybody arrives knowing, so on first
   contact the nav is four drawings and a guess, and the pages behind them go
   unvisited by everyone who did not guess.

   The label was moved under the icon to buy width, and that trade is real on
   a laptop and imaginary at 1400px, where the bar carries a brand, a 520px
   search and four icons across a screen with several hundred pixels spare.
   So above 1400 the same ::after stops being a plate that floats under the
   sigil and becomes a word beside it: `position: static` drops it into the
   .nav-ico's own inline-flex, where it lays out as the second item next to
   the img. Same element, same attribute, same string — nothing here is a
   second copy of the label that could drift from the first.

   Below 1400 it is the tooltip exactly as it was. */
@media (min-width: 1400px) {
  #navlinks .nav-ico::after, #topnav .nav-ico::after {
    position: static;
    transform: none;
    opacity: 1;
    background: none;
    border: 0;
    padding: 0 0 0 8px;
    color: var(--archive-brass);
    letter-spacing: .18em;
    /* the sigil is the control and the word is its caption, so the word does
       not get to be as loud as it was when it WAS the control */
    font-size: 9.5px;
    transition: color .2s ease;
  }
  #navlinks .nav-ico:hover::after, #topnav .nav-ico:hover::after,
  #navlinks .nav-ico:focus-visible::after, #topnav .nav-ico:focus-visible::after {
    transform: none;
    color: var(--archive-brass-hi);
  }
}
/* ── what a sigil is ──────────────────────────────────────────
   The plate that opens under a badge on hover. It is the honors page's own
   object, shrunk: the name in the display face in gold, the short rule, then
   the criteria in the muted text. A visitor who meets a sigil on a member
   card and a visitor who meets it on badges.html are told the same thing in
   the same voice, which is the point — thirteen drawings that only one page
   in seven explained.

   Gold and not brass. Everything else in this file repoints `--ui-accent` at
   the archive's brass, but the honors are the one thing on the site that is
   allowed to stay warm: `--gold` is the honors gold, archive-system leaves it
   alone by rule, and a plate describing an honor is part of the badge, not
   part of the chrome around it. (It spent one pass as bone and came back —
   see the `--gold` note in CLAUDE.md for why.)

   Positioned by js in viewport coordinates — see mountTips in honors.js for
   why it is parked on <body> rather than inside the badge. Nothing here may
   use `position: absolute`: it would resolve against the page instead of the
   window and the plate would sit wherever the document happened to be
   scrolled to. */
.ho-tip {
  position: fixed;
  z-index: 900;
  left: 0; top: 0;
  width: max-content;
  max-width: min(300px, calc(100vw - 20px));
  padding: 13px 15px 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  background: linear-gradient(168deg, #0f1115, #060707 64%);
  border: 1px solid var(--gold-dim, #a37e2c);
  box-shadow: 0 18px 38px rgb(2 3 3 / .66), inset 0 1px 0 rgb(255 255 255 / .05);
  pointer-events: none;
  opacity: 0;
  transform: translateY(-3px);
  /* visibility rather than [hidden]: display:none has no box, and the plate is
     measured before it is shown so it can be centred on its badge and flipped
     when there is no room above. Hidden this way it keeps the box, the
     measurement is the real one, and it still leaves the accessibility tree
     between shows. The 0s delay holds it visible for the length of the fade
     out and drops it the instant that finishes. */
  visibility: hidden;
  transition: opacity .16s ease, transform .16s ease, visibility 0s .16s;
}
.ho-tip.ho-on {
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
  transition: opacity .16s ease, transform .16s ease, visibility 0s;
}
.ho-tip.ho-below { transform: translateY(3px); }
.ho-tip.ho-below.ho-on { transform: translateY(0); }
.ho-tip-name {
  font-family: var(--display-font);
  font-size: 19px; line-height: 1.1; font-weight: 400;
  color: var(--gold, #e3b44a);
  letter-spacing: .5px;
}
.ho-tip-rule {
  width: 34px; height: 1px; margin: 9px 0 10px;
  background: var(--gold-dim, #a37e2c);
}
/* pre-line, because the musician's own figure — "12 releases", "1987–2019" —
   is appended to the criteria on its own line: what the mark asks, then what
   this person did to earn it. */
.ho-tip-crit {
  white-space: pre-line;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 12.5px; line-height: 1.6;
  color: var(--muted, #97a0aa);
}
@media (prefers-reduced-motion: reduce) {
  .ho-tip { transition: none; }
}
/* A badge is a thing you can ask about. The museum's row already said so;
   now every context does, and the ones that print no label need it most. */
.honor, .band-honors, .artist-honors, .mu-honcount { cursor: help; }

#nav-close { color: var(--accent); }

#search, input, select, textarea {
  border-color: var(--control-border);
  border-radius: 0 !important;
  background: #0d0f0f;
  color: var(--text);
}
#search:focus, input:focus, select:focus, textarea:focus {
  border-color: var(--archive-brass);
  box-shadow: 0 0 0 1px rgb(185 155 102 / .24);
}
#search-results {
  border-color: var(--border);
  border-radius: 0 !important;
  background: #101111;
  box-shadow: 0 16px 32px rgb(2 3 3 / .72);
}
.sr-row:hover { background: #15181b; }

button, [role='button'] { border-radius: 0 !important; }
button:focus-visible, a:focus-visible, [role='button']:focus-visible, input:focus-visible, select:focus-visible {
  outline: 1px solid var(--archive-brass-hi);
  outline-offset: 3px;
}

/* Gothic display is identity. Interface hierarchy uses the archive label face. */
.archive-section-title,
.body h2:not(#artist-name),
.credits-head,
.legend-head h2 {
  color: var(--archive-brass) !important;
  font-family: var(--nav-font) !important;
  font-size: 10px !important;
  font-weight: 700 !important;
  line-height: 1.2 !important;
  letter-spacing: .19em !important;
  text-transform: uppercase;
}

/* ── Shared physical surfaces and overlays ────────────────────
   These are the third material level, and until now they were only the
   second: --border round a grey that read as an application dialog dropped
   on top of the archive rather than a case standing in it. Three levels, and
   they are now actually three — the page's black, a panel's --surface, and
   this: darker than the panel, on a brass hairline, standing off the page on
   a shadow deep enough to be a gap rather than an edge.

   The gradient stays and is the point of the level: it is a case lit from
   the upper left, and the light is what separates it from the wall. The
   inset highlight along its top lip is the same one every framed object on
   the site carries — the exhibit and the case are lit by the same lamp. */
#album-card, #album-modal, #fresh-modal, #cinema-modal, #gigform-modal, #fw-card, .holders {
  border-color: var(--archive-brass-dim);
  border-radius: 0 !important;
  background: linear-gradient(148deg, #101216, #060707 62%);
  box-shadow: var(--archive-shadow), inset 0 1px 0 rgb(255 255 255 / .045);
}
/* The page behind an overlay goes out of focus, not merely dark: it is the
   same blur the top bar is made of, so nothing here introduces a material
   the site does not already use. */
#album-overlay, #fresh-overlay, #cinema-overlay, #gigform-overlay, #fw-overlay {
  background: rgb(4 5 5 / .8);
  backdrop-filter: blur(14px) saturate(.6);
  -webkit-backdrop-filter: blur(14px) saturate(.6);
}
#album-card .ac-cols h3, #album-card .ac-press h3, #album-card .ac-physical-label,
#album-modal h3 {
  color: var(--archive-brass) !important;
  font: 700 9px/1.2 var(--nav-font) !important;
  letter-spacing: .17em !important;
  text-transform: uppercase;
}
#album-card .ac-title { color: var(--white); }
#album-card .ac-meta, #album-card .ac-facts dt, #album-card .p-role, #album-card .t-no, #album-card .t-len { color: var(--muted); }
#album-card .ac-cover { border: 1px solid #3d434a; box-shadow: 12px 18px 30px rgb(2 3 3 / .64); }

/* Collection pages share one title color. Red is no longer generic chrome. */
.honors-hero h1, .fw-hero h1, .legendary-hero h1, .updates-hero h1 { color: var(--archive-brass-hi) !important; }
.legend-item, .badge-entry, .release, .tile { border-radius: 0 !important; }

/* Map controls use the same near-black and brass material as the archive. */
#legend, #panel {
  border-color: var(--border);
  background: rgb(12 13 13 / .95);
  box-shadow: var(--archive-shadow);
}
#legend .legend-head, #status-filter, #timeline { border-color: #22262b; }
.leaflet-control-zoom a { border-radius: 0 !important; background: #101111 !important; color: var(--text) !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; }
}

@media (max-width: 860px) {
  #nav, #topbar { box-shadow: 0 6px 18px rgb(2 3 3 / .6); }
}

/* ── the phone's top bar is one row ───────────────────────────
   It was three: brand and X, then the search field on its own full-width
   line, then the sigils wrapped underneath. On a 375×812 phone that came to
   about 300px — thirty-seven per cent of the screen spent on chrome before
   the archive got a pixel, and the sigils ended up so far from the wordmark
   they read as a second, unrelated toolbar.

   One row: the wordmark, the three sigils, the way back. The search field
   does not fit beside them and does not need to — it is the one control here
   that is used deliberately, so it collapses to its own sigil and opens on a
   tap. :focus-within is the whole mechanism: no javascript, no toggle state
   to keep, and it answers the keyboard for free. Open, it takes the second
   row it always had; closed, that row does not exist.

   Scoped under both bar ids because the map carries #topbar and the six
   document pages carry #nav, and the two must not drift. */
@media (max-width: 860px) {
  #nav, #topbar {
    flex-wrap: wrap;
    align-items: center;
    gap: 0 14px;
    padding: 10px 14px;
    height: auto;
  }
  /* Both bars are flattened so the ordering below addresses the same set of
     controls whichever markup it is looking at: on the map the field is a
     sibling of the sigils, on the six document pages it sits inside the same
     <nav> as them. display:contents makes both cases one flat row. */
  #navlinks, #topnav { display: contents; }
  #nav #brand, #topbar #brand, #topbar h1 { order: 1; margin-right: auto; }
  #nav #brand, #topbar h1 { font-size: 23px; }
  #navlinks .nav-ico, #topnav .nav-ico { order: 3; }
  /* The way back holds the right end, where an exit belongs. relative, not
     static, because the hit box above is absolute and needs this to be its
     containing block — static would measure it against the page. `right`
     comes with it: static ignores the offset band.css sets for the desktop
     corner, relative honours it, and the X slid --pad to the left and put
     its hit box 16px inside the sigil beside it. */
  #nav-close { order: 4; position: relative; right: auto; margin-left: 4px; }
  /* display:contents hands the sigils to the bar, so it is the bar's 14px
     gap they tile into now, not the nav's 20px */
  #navlinks .nav-ico, #topnav .nav-ico, #nav-close { --hit-x: 7px; }

  /* the field, closed: a sigil the width of the ones beside it */
  #searchbox {
    order: 2;
    flex: 0 0 auto;
    width: 30px; min-width: 0;
    transition: width var(--mo-open) var(--ease-out),
                flex-basis var(--mo-open) var(--ease-out);
  }
  #searchbox #search {
    width: 100%;
    padding-left: 26px;
    border-color: transparent;
    background-color: transparent;
    /* the magnifier is the label while the field is shut; it is drawn rather
       than set in a font so it takes the brass without loading anything */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%239aa6b2' stroke-width='1.6'%3E%3Ccircle cx='8.6' cy='8.6' r='5.4'/%3E%3Cpath d='M12.6 12.6 17 17'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 5px center;
    background-size: 17px 17px;
    cursor: pointer;
  }
  /* the placeholder would show through the 30px window as "Sear…" */
  #searchbox #search::placeholder { color: transparent; }

  /* Open, it drops to a line of its own — order past every other control, so
     the wrap puts it under them rather than splitting the row in half. */
  #searchbox:focus-within {
    order: 9;
    flex: 1 1 100%;
    width: auto;
    margin-top: 10px;
  }
  /* The closed state sets border-color: transparent from two ids up, which
     out-specifies #search:focus — so the open field has to name its own edge
     or it opens with no edge at all. It names the brass one every other
     focused field on the site gets: #3a424e was 1.89:1 here, and it was also
     the only place a focused control looked different on a phone. */
  #searchbox:focus-within #search {
    border-color: var(--archive-brass);
    background-color: var(--panel-solid);
    cursor: text;
  }
  #searchbox:focus-within #search::placeholder { color: var(--muted); }
  #search-results { width: 100%; }
}
@media (max-width: 860px) and (prefers-reduced-motion: reduce) {
  #searchbox { transition: none; }
}

/* Below 360 the one row becomes two — measured on the flyer wall, which
   carries the most controls of the seven and still holds one line at 360.
   Wrapped, the sigils sit 28.5px apart from centre to centre, and a 43px hit
   box would reach 14px into the row above it: the box that is there to stop
   you missing would start catching taps meant for something else. 27px in
   that case, which still clears the 24px the standard asks and cannot
   collide with a 28.5px pitch. */
@media (max-width: 359px) {
  #navlinks .nav-ico, #topnav .nav-ico, #nav-close { --hit-y: 4px; }
}
