/* Notturnometer static site — minimal hand-rolled CSS. No build step,
   no framework, no JS. Braggoscope register: dense, factual, readable.
   Warm palette merged from teststyle.css (2026-07-15). */

:root {
  --measure:    70ch;
  --bg:         #FAF9F4;  /* off-white */
  --text:       #1B1B18;  /* warm near-black */
  --muted:      #6B675F;  /* secondary text */
  --link:       #A6402A;  /* rust accent */
  --link-hover: #7A2E1C;
  --border:     #DEDACF;  /* warm hairline */
  --header-bg:  #F0EDE3;  /* warm fill for table headers */

  /* PagefindUI accent → match the site's rust so the search box belongs. */
  --pagefind-ui-primary:    var(--link);
  --pagefind-ui-text:       var(--text);
  --pagefind-ui-background: var(--bg);
  --pagefind-ui-border:     var(--border);
}

* {
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
               Arial, sans-serif;
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.075rem);
  line-height: 1.55;
  color: var(--text);
  background: var(--bg);
  margin: 0;
  padding: 0;
  -webkit-font-smoothing: antialiased;
}

header, footer {
  padding: 1rem 1.5rem;
  border-bottom: 1px solid var(--border);
}

/* Full-width masthead spanning the viewport: wordmark left, search filling the
   centre, nav right. Wraps on narrow screens. */
header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
}
/* Search centres between the wordmark (left) and nav (right): a bounded width
   (capped so it doesn't sprawl on ultrawide) with auto side margins splitting
   the free space equally. */
header #search {
  flex: 0 1 40rem;
  margin: 0 auto;
}

/* On wide windows the header mirrors the content column as a 3-column grid:
   1fr | (--measure minus main's 2x1.5rem padding) | 1fr, inside the header's
   own 1.5rem padding — so the middle column's left edge lands EXACTLY on the
   main text's left boundary (both boxes are border-box, both centred), and
   the search box fills that column: aligned left AND right with the content.
   Wordmark and nav live in the gutters. Below the breakpoint the gutters
   can't fit the wordmark, so the flex layout above stays. */
@media (min-width: 60rem) {
  header {
    display: grid;
    grid-template-columns: 1fr calc(var(--measure) - 3rem) 1fr;
    align-items: center;
  }
  .wordmark { grid-column: 1; justify-self: start; }
  header #search { grid-column: 2; width: 100%; margin: 0; }
  header nav { grid-column: 3; justify-self: end; }
}

/* PagefindUI renders its results drawer as a sibling of the search input,
   inside #search. Left in normal flow the drawer grows #search when results
   appear — which grows the header, and since the header centres its items the
   wordmark and nav shift down and the whole page follows. Float the drawer as
   an overlay instead: the input alone sets the header's height (fixed), and
   results drop over the content below. The drawer carries .pagefind-ui__hidden
   (display:none) while search is inactive, so the bordered box only appears
   with results. */
header #search .pagefind-ui { position: relative; }
header #search .pagefind-ui__drawer:not(.pagefind-ui__hidden) {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  right: 0;
  z-index: 50;
  max-height: 75vh;
  overflow-y: auto;
  padding: 1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

/* The wordmark: the site name doubling as the home link. Typeset as a brand
   (larger/heavier than the nav), no nav underline. */
.wordmark {
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--text);
  text-decoration: none;
}
.wordmark:hover,
.wordmark:focus-visible {
  color: var(--link);
}

footer {
  border-bottom: none;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.9rem;
  margin-top: 3rem;
}

/* Nav links read as structural (text-coloured, subtle underline) and go
   rust only on hover — distinct from inline body links. */
header nav a {
  margin-right: 1rem;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: 2px;
}

header nav a:hover {
  color: var(--link);
  border-color: var(--link);
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.5rem;
}

/* Per-episode / per-night blocks (home + episode pages) get a hairline
   separator between successive sections. */
section + section {
  margin-top: 2rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border);
}

h1 {
  font-size: 1.6rem;
  margin-bottom: 0.25rem;
  letter-spacing: -0.01em;
}

/* The composer byline is a standalone <p> under the work title (moved out
   of the <h1> during the search work). */
.composer-byline {
  margin-top: 0;
  color: var(--muted);
}

/* The muted credit line under a "last night" episode title
   (piece count + the outbound BBC programme-page link). */
.ep-meta {
  margin-top: 0;
  color: var(--muted);
  font-size: 0.95rem;
}

/* Home "Browse" section: the axis menu grouped into labelled columns.
   auto-fit collapses 4 columns -> fewer -> 1 as the viewport narrows. */
.browse-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1rem 1.5rem;
  margin: 0.75rem 0;
}
.browse-groups h3 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
  margin: 0 0 0.35rem 0;
}
.browse-groups ul.plain { margin: 0; }
.browse-groups li { margin: 0.15rem 0; }

h2 {
  font-size: 1.15rem;
  margin-top: 2rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.25rem;
}

a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--link) 40%, transparent);
  text-underline-offset: 0.15em;
}

a:hover,
a:focus-visible {
  color: var(--link-hover);
  text-decoration-color: currentColor;
}

a:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
}

table {
  border-collapse: collapse;
  width: 100%;
  margin: 0.75rem 0;
  font-size: 0.95rem;
}

th, td {
  border: 1px solid var(--border);
  padding: 0.35rem 0.6rem;
  text-align: left;
  vertical-align: top;
}

th {
  background: var(--header-bg);
  font-weight: 600;
}

dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 1rem;
  margin: 0.75rem 0;
}

dt {
  font-weight: 600;
  color: var(--muted);
}

dd {
  margin: 0;
}

ul.plain, ol.plain {
  list-style: none;
  padding-left: 0;
  margin: 0.5rem 0;
}

.disclosure {
  color: var(--muted);
  font-style: italic;
  font-size: 0.9rem;
}

/* CSS-only tooltip (no JS): a dotted-underlined term whose data-tip text
   appears in a bubble on hover/keyboard focus. Used on the PID column
   header; give the element tabindex="0" so keyboard users can reach it.
   The bubble hangs below and grows LEFTWARD (right-anchored) because PID
   is the table's last column — a left-anchored bubble would overflow the
   viewport edge. */
abbr.tip {
  position: relative;
  cursor: help;
  text-decoration: underline dotted var(--muted);
  text-underline-offset: 0.15em;
}

/* Flag-emoji tooltips: the dotted underline sits badly under an emoji glyph,
   so flags rely on the cursor + bubble alone. */
abbr.tip.flag {
  text-decoration: none;
}

abbr.tip:hover::after,
abbr.tip:focus::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 1;
  width: max-content;
  max-width: 16rem;
  padding: 0.35rem 0.55rem;
  border-radius: 4px;
  background: var(--text);
  color: var(--bg);
  font-weight: 400;
  font-size: 0.85rem;
  line-height: 1.35;
  white-space: normal;
  text-align: left;
}

/* By-year bar strip (composer + artist pages): the airings-per-year table
   as a compact histogram. Bars are hoverable/focusable; the data-tip readout
   is anchored to the STRIP (bars are static, .year-bars is the positioned
   ancestor), so it appears in one consistent spot above the strip and can
   never overflow the viewport at the edge bars. Missing years render as
   transparent gap slots so the timeline stays honest. */
.year-bars-fig {
  margin: 0.75rem 0 1.5rem 0;
}

.year-bars {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 3.5rem;
  margin-top: 2.4rem;   /* room for the readout bubble */
}

.year-bars .bar {
  flex: 1 1 0;
  max-width: 2.5rem;    /* sparse strips don't become giant slabs */
  min-height: 2px;      /* a 1-airing year stays visible next to a 300 peak */
  background: var(--muted);
  border-radius: 1px 1px 0 0;
}

.year-bars .bar.gap {
  background: transparent;
  min-height: 0;
}

.year-bars .bar:hover,
.year-bars .bar:focus {
  background: var(--text);
  outline: none;
}

.year-bars .bar:hover::after,
.year-bars .bar:focus::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 0.4rem);
  left: 0;
  z-index: 1;
  width: max-content;
  padding: 0.35rem 0.55rem;
  border-radius: 4px;
  background: var(--text);
  color: var(--bg);
  font-size: 0.85rem;
  line-height: 1.35;
  white-space: nowrap;
}

.year-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 0.25rem;
  color: var(--muted);
  font-size: 0.85rem;
}

.facts {
  margin: 0.75rem 0 1.5rem 0;
}

/* Performance-page airing dates: one line per year -- the year label in the
   left column, that year's airings as a dot-separated run of episode links
   that wraps within the right column. */
dl.airing-years {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: 0.9rem;
  row-gap: 0.3rem;
}

@media (max-width: 480px) {
  header nav a { margin-right: 0.75rem; }
  section + section { margin-top: 1.5rem; padding-top: 1.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
