/* Ipsloop — single stylesheet. Mobile-first, dark by design. */

/* Self-hosted so the CSP in _headers stays as it is: `style-src 'self'` and
   `font-src 'self'` both forbid Google Fonts, and loosening them to borrow two
   typefaces would be a poor trade. Latin subsets only, ~96KB total, served
   under the immutable cache rule for /assets/*. */
@font-face {
  font-family: "Instrument Sans";
  src: url("/assets/fonts/instrument-sans.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}
@font-face {
  font-family: "Spline Sans Mono";
  src: url("/assets/fonts/spline-sans-mono.woff2") format("woff2");
  font-weight: 400 600;
  font-display: swap;
}
@font-face {
  font-family: "Barlow Condensed";
  src: url("/assets/fonts/barlow-condensed-600.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Barlow Condensed";
  src: url("/assets/fonts/barlow-condensed-800.woff2") format("woff2");
  font-weight: 800;
  font-display: swap;
}

:root {
  /* True black, so the white hand-drawn logo and the type sit directly on the
     page rather than on a slightly-grey panel. */
  --bg: #000000;
  --surface: #0c0c0c;
  --surface-2: #161616;
  --line: #282828;
  /* Dividers inside the listing carry structure rather than decoration, so they
     sit a step above --line: #282828 is 1.42:1 on black and effectively
     invisible on a phone at half brightness. */
  --rule: #3a3a3a;
  --text: #ffffff;
  --muted: #9a9a9a;
  --accent: #c6ff3e;
  --accent-ink: #000000;

  --wrap: 46rem;
  --radius: 0.75rem;

  /* Three faces, each with a job. Display is a condensed grotesk — the register
     of a rig-case stencil, and it buys back the width a phone doesn't have.
     Body is a humanist sans that isn't the framework default. Mono carries
     times and prices, which are data and should align like data. */
  --font: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-display: "Barlow Condensed", "Archivo Narrow", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Spline Sans Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

/* Any class that sets `display` (e.g. .form { display: grid }) outranks the
   browser's own [hidden] rule, so hiding via the attribute silently fails
   without this. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

/* The column keeps the footer on the bottom edge of a short page — an empty
   listing, an error state, a 404 — instead of leaving it stranded mid-screen
   with dead black beneath it. main takes the slack, so a long page is
   unaffected and the footer is still scrolled to rather than pinned over
   content.
   dvh rather than vh is the whole point on a phone: 100vh counts the area
   behind Safari's chrome, so it would push the footer just below the fold and
   add a phantom scroll to every page. The vh line is the fallback beneath. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

main { flex: 1; }

/* Form controls do not inherit the page font on their own. */
input, select, textarea, button { font-family: inherit; }
input, select, textarea { font-weight: 400; }
button { font-weight: 700; }

img { max-width: 100%; height: auto; display: block; }

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

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

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- Header ------------------------------------------------------------- */

.site-header {
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(0, 0, 0, 0.88);
  backdrop-filter: blur(10px);
}

/* Centred masthead: wordmark on top, nav centred beneath it, at every width.
   The logo is the brand, so it leads rather than sharing a row. */
.site-header .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  padding-block: 0.875rem;
}

/* The wordmark is artwork, not type. line-height:0 stops the anchor adding a
   descender's worth of dead space under the image. */
.brand {
  display: block;
  line-height: 0;
  flex-shrink: 0;
}

.brand img {
  display: block;
  height: 1.5rem;
  width: auto;
}

@media (min-width: 40rem) {
  .brand img { height: 2rem; }
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem 1.25rem;
  font-size: 0.875rem;
}

@media (max-width: 34rem) {
  .site-nav { gap: 0.25rem 1rem; font-size: 0.8125rem; }
}

.site-nav a {
  color: var(--muted);
  text-decoration: none;
  padding-block: 0.25rem;
  font-weight: 700;
}

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

.site-nav a[aria-current="page"] {
  color: var(--text);
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* --- Typography --------------------------------------------------------- */

main { padding-block: 2.5rem 4rem; }
main.listing { padding-block: 0 4rem; }

/* A condensed display face wants positive tracking and more size than a
   grotesk at the same optical weight — negative tracking crushes it. */
h1, h2, h3 {
  font-family: var(--font-display);
  line-height: 1.06;
  letter-spacing: 0.01em;
  margin: 0 0 0.75rem;
  text-wrap: balance;
}

h1 { font-size: clamp(2.75rem, 11vw, 4.25rem); font-weight: 800; }
h2 { font-size: clamp(1.75rem, 6vw, 2.25rem); font-weight: 800; }
h3 { font-size: 1.375rem; font-weight: 600; }

p { margin: 0 0 1rem; }

.lead {
  font-size: 1.125rem;
  color: var(--muted);
  max-width: 34rem;
}

.page-intro { margin-bottom: 2.5rem; }

/* --- Hero --------------------------------------------------------------- */

.hero {
  position: relative;
  padding-block: 3.5rem 3rem;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}

.hero::before {
  content: "";
  position: absolute;
  inset: -40% -20% auto -20%;
  height: 30rem;
  background: radial-gradient(50% 50% at 50% 50%, rgba(198, 255, 62, 0.10), transparent 70%);
  pointer-events: none;
}

.hero .wrap { position: relative; }

.hero h1 { margin-bottom: 1rem; }

.hero h1 em {
  font-style: normal;
  color: var(--accent);
}

/* --- Buttons ------------------------------------------------------------ */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.75rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.8125rem 1.375rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}

.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.btn-primary:hover { background: #d4ff77; }

.btn-secondary {
  background: transparent;
  color: var(--text);
  border-color: var(--line);
}

.btn-secondary:hover { border-color: var(--muted); }

.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

.btn-block { width: 100%; }

/* --- Content sections --------------------------------------------------- */

.section { padding-block: 2.75rem; }
.section + .section { border-top: 1px solid var(--line); }

.cards {
  display: grid;
  gap: 1rem;
  margin-top: 1.5rem;
}

/* Paragraphs carry a bottom margin only, so anything following the panels
   would sit flush against them. Matching the gap above puts the cards in an
   even well of space rather than leaving them front-heavy. A sibling selector
   rather than a bottom margin on .cards: when the panels end a section, the
   section's own padding is already the right amount of room. */
.cards + p { margin-top: 1.5rem; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
}

.card h3 { margin-bottom: 0.375rem; }
.card p { margin: 0; color: var(--muted); font-size: 0.9375rem; }

@media (min-width: 40rem) {
  .cards { grid-template-columns: repeat(3, 1fr); }
}

/* --- Page strip ---------------------------------------------------------- */
/* Replaces <h1>What's On</h1> plus a lead paragraph, which together restated
   the nav item directly above them and cost 200px of a 390px screen before the
   first event appeared. This says something the nav does not, in one line. */

.page-strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  padding-block: 0.625rem;
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}

.page-strip h1 {
  font: inherit;
  letter-spacing: inherit;
  margin: 0;
  color: var(--muted);
}

.page-strip p { margin: 0; }

.page-strip a {
  color: var(--text);
  text-decoration: none;
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* --- Genre filter chips --------------------------------------------------- */
/* Sourced from the genres table, which anon could already read — see
   supabase/genres.sql. Only genres present in the current listing get a chip. */

/* One swipeable row rather than a wrapping block: eight chips wrapping cost
   three lines and pushed the first event further down the phone than the
   heading this replaced. Outdented so it scrolls edge to edge. */
.genre-filters {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem;
  margin-inline: -1.25rem;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
}

.genre-filters::-webkit-scrollbar { display: none; }

.chip {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  white-space: nowrap;
  min-height: 2.75rem;
  padding: 0.375rem 0.875rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  cursor: pointer;
}

.chip:hover { border-color: var(--muted); color: var(--text); }

.chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

/* --- Day band ------------------------------------------------------------- */
/* One sticky band per day, outdented to the full width of the column. The date
   is carried here once instead of on every event, and "Tonight" answers the
   only question most visitors arrive with. --header-height is measured and set
   by js/whats-on.js so the band stacks under the masthead rather than beneath
   it, including while the install banner is pushing the header down. */

.day-band {
  position: sticky;
  top: var(--header-height, 5.75rem);
  z-index: 5;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0 -1.25rem;
  padding: 0.3125rem 1.25rem 0.375rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 1.4375rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  line-height: 1.15;
  text-transform: uppercase;
  white-space: nowrap;
}

.day-count {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  opacity: 0.75;
}

/* --- Event rows ----------------------------------------------------------- */
/* A ruled column, not cards. Time holds a fixed left column so the eye can run
   down it; everything else flows in one measure beside it. */

.event-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.event {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: 0.875rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--rule);
}

.day:last-child .event:last-child { border-bottom: 0; }

.event-time {
  padding-top: 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.3;
}

.event-end {
  display: block;
  color: var(--muted);
  font-size: 0.71875rem;
}

.event-body {
  display: block;
  color: inherit;
  text-decoration: none;
}

.event-head {
  display: flex;
  align-items: baseline;
  gap: 0.625rem;
}

.event-name {
  flex: 1 1 auto;
  font-size: 1.4375rem;
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: 0.01em;
  margin: 0;
  text-wrap: pretty;
}

/* Only short figures reach the head — js/whats-on.js sends prose pricing to the
   venue line — so this never needs to wrap, and must not: a wrapped "£8 DICE ↗"
   drops its arrow onto a line of its own. */
.event-price {
  flex: 0 0 auto;
  white-space: nowrap;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 0.78125rem;
  font-weight: 500;
  color: var(--text);
}

.event-price.is-free { color: var(--accent); font-weight: 600; }
.event-arrow { color: var(--accent); }

/* Venue leads and the free-text genre trails it: that column is a phrase, not
   a token, and a pill built for "House" cannot hold "Japanese kissa-style
   listening bar". */
.event-where {
  margin: 0.25rem 0 0;
  font-size: 0.90625rem;
  line-height: 1.4;
  color: var(--text);
}

.event-genre { color: var(--muted); }

.event--linked:hover .event-name { color: var(--accent); }

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

@media (prefers-reduced-motion: no-preference) {
  .event-name, .chip { transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease; }
}

/* --- Status / feedback -------------------------------------------------- */

.status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.875rem;
  color: var(--muted);
  padding: 1.75rem 0;
}

.status-error { color: #ff8f8f; }

.notice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 1.25rem;
}

.notice h2 { margin-bottom: 0.5rem; }
.notice p:last-child { margin-bottom: 0; }

/* --- Form --------------------------------------------------------------- */

.form { display: grid; gap: 1.25rem; margin-top: 2rem; }

/* align-content keeps a field its natural height. Without it, two fields
   sharing a .field-row stretch to match each other, so a hint under one of
   them silently inflates the input next to it. */
.field { display: grid; gap: 0.4375rem; align-content: start; }

.field label {
  font-size: 0.875rem;
  font-weight: 600;
}

.field .hint {
  font-size: 0.8125rem;
  color: var(--muted);
}

.field-row { display: grid; gap: 1.25rem; }

@media (min-width: 34rem) {
  .field-row { grid-template-columns: 1fr 1fr; }
}

input, select, textarea {
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  padding: 0.75rem 0.875rem;
  width: 100%;
  min-height: 2.875rem;
}

textarea { min-height: 7.5rem; resize: vertical; }

input:hover, select:hover, textarea:hover { border-color: #3a3a46; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(198, 255, 62, 0.15);
}

/* Date and time fields. The browser draws its picker icon almost black, which
   on this surface is a smudge, so it is inverted to a light glyph and dimmed
   to sit below the value it belongs to. The whole field opens the picker (see
   openPickerOnClick in js/submit.js), so the pointer cursor is honest across
   all of it, not just the icon. */
input[type="date"],
input[type="time"] { cursor: pointer; }

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
  filter: invert(1);
  opacity: 0.55;
  cursor: pointer;
  padding: 0.25rem;   /* a bigger target for anyone who does aim at the icon */
}

input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="date"]:focus::-webkit-calendar-picker-indicator,
input[type="time"]:focus::-webkit-calendar-picker-indicator {
  opacity: 1;
}

/* Deliberate exception to the site-wide bold: a bold placeholder reads as a
   value the user has already typed. Lighter and dimmer keeps hint distinct
   from content. */
input::placeholder, textarea::placeholder {
  color: #757575;   /* 4.56:1 on black — AA */
  font-weight: 400;
}

.fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 1.25rem;
}

.fieldset legend {
  padding: 0;
  margin-bottom: 0.25rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Honeypot: hidden from people, tempting to bots. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-error {
  color: #ff8f8f;
  font-size: 0.9375rem;
  margin: 0;
}

/* --- Footer ------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 2rem;
  color: var(--muted);
  font-size: 0.875rem;
}

.site-footer p { margin: 0; }
.site-footer a { color: var(--muted); }
.site-footer a:hover { color: var(--text); }

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


/* --- Segmented choice (radio groups) ------------------------------------ */

.choice {
  border: 0;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.5rem;
}

.choice legend {
  padding: 0;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
}

.segmented {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
}

/* The radio itself is removed from view but stays focusable, so keyboard and
   screen-reader behaviour is the browser's own rather than a reimplementation. */
.segmented input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.segmented label {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.875rem;
  padding: 0.625rem 0.875rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--surface);
  font-size: 0.9375rem;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.segmented label:hover { border-color: #3a3a46; }

.segmented input[type="radio"]:checked + label {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* Focus ring has to be drawn on the label, since the input is invisible. */
.segmented input[type="radio"]:focus-visible + label {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}


/* --- Centred composition -------------------------------------------------- */
/* Editorial content is centred; functional content is not. Centred prose is
   fine in short bursts, but forms and listings are scanned rather than read,
   and a ragged left edge makes that measurably harder. */

.hero .wrap,
.section .wrap,
.page-intro,
.site-footer .wrap {
  text-align: center;
}

.lead {
  margin-inline: auto;
}

.actions {
  justify-content: center;
}

.cards .card {
  text-align: center;
}

/* Opt back out: anything the reader has to work through rather than glance at. */
.form,
.event-list,
.notice {
  text-align: left;
}

/* The event card's own centred-looking meta row still starts from the left. */
.event-meta {
  justify-content: flex-start;
}

/* --- Alerts page ---------------------------------------------------------- */

.alerts-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  text-align: left;
}

.alerts-card h2 { font-size: 1.25rem; margin-bottom: 0.5rem; }
.alerts-card p { color: var(--muted); }
.alerts-card .actions { margin-top: 1.25rem; justify-content: flex-start; }

.alerts-status:empty { display: none; }

.alerts-status {
  margin: 0 0 1rem;
  padding: 0.625rem 0.875rem;
  border-radius: 0.5rem;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 0.875rem;
  color: var(--text);
}

/* The 6pm digest switch. Wider than a genre tile because it carries a line of
   explanation, but styled as one so the two read as the same kind of control. */
.digest-option {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  margin: 1.25rem 0 0;
  padding: 0.875rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--surface-2);
  cursor: pointer;
}

.digest-option:hover { border-color: #3a3a46; }

.digest-option:has(input:checked) {
  border-color: var(--accent);
  background: rgba(198, 255, 62, 0.08);
}

.digest-option input {
  width: 1.125rem;
  height: 1.125rem;
  min-height: 0;
  padding: 0;
  /* Nudged down to sit on the first line of the label, not above it. */
  margin: 0.125rem 0 0;
  accent-color: var(--accent);
  flex: 0 0 auto;
}

.digest-label {
  font-size: 0.9375rem;
  font-weight: 700;
}

.digest-option .hint {
  display: block;
  margin-top: 0.1875rem;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--muted);
}

.genre-grid {
  border: 0;
  padding: 0;
  margin: 1.25rem 0 0;
  display: grid;
  gap: 0.5rem;
  grid-template-columns: 1fr;
}

@media (min-width: 30rem) {
  .genre-grid { grid-template-columns: 1fr 1fr; }
}

.genre-option {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.6875rem 0.875rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--surface-2);
  font-size: 0.9375rem;
  font-weight: 700;
  cursor: pointer;
}

.genre-option:hover { border-color: #3a3a46; }

.genre-option input {
  width: 1.125rem;
  height: 1.125rem;
  min-height: 0;
  padding: 0;
  margin: 0;
  accent-color: var(--accent);
  flex: 0 0 auto;
}

.genre-option:has(input:checked) {
  border-color: var(--accent);
  background: rgba(198, 255, 62, 0.08);
}


/* --- Admin ---------------------------------------------------------------- */
/* /admin is the only signed-in page. It reuses the public form controls,
   .genre-option and .btn wholesale; what follows is layout only. */

.admin-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 2rem;
}

.admin-bar h1 { margin-bottom: 0.25rem; }

.admin-who {
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted);
}

.admin-section h2 { margin-bottom: 1rem; }

.admin-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
}

.admin-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
  display: grid;
  gap: 1rem;
}

.admin-item-head h3 { margin: 0 0 0.25rem; }

.admin-when {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--accent);
}

.admin-details { display: grid; gap: 0.375rem; }

/* Label above value on narrow screens, beside it once there is room — a
   submission is scanned, and a ragged left edge makes that harder. */
.admin-field {
  display: grid;
  gap: 0.125rem;
  margin: 0;
  font-size: 0.9375rem;
  overflow-wrap: anywhere;
}

@media (min-width: 34rem) {
  .admin-field { grid-template-columns: 8rem 1fr; gap: 0.75rem; }
}

.admin-field-key {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.admin-tags { display: grid; gap: 0.5rem; }

.admin-tag-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.5rem;
}

.admin-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}

/* The untagged-approval warning. Amber rather than red: it is a caution about
   reach, not an error, and the action is still allowed. */
.admin-note {
  margin: 0;
  font-size: 0.875rem;
  color: #ffcf70;
  flex: 1 1 14rem;
}

.admin-note:empty { display: none; }

.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.75rem;
  border-bottom: 1px solid var(--line);
}

.admin-tab {
  appearance: none;
  border: 0;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 700;
  padding: 0.625rem 0.25rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}

.admin-tab:hover { color: var(--text); }

.admin-tab[aria-selected="true"] {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.admin-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The notify checkbox is a .genre-option like the tags above it, but it is a
   decision rather than a tag — full width keeps them from reading as one set. */
#add-notify-wrap { margin-top: 0.25rem; }

/* --- Stats ---------------------------------------------------------------- */
/* Four headline numbers are stat tiles, not charts: a single figure has no
   shape to plot. The two bar lists each carry one measure, so they are one
   colour — a genre is identified by its label, not its hue — and every bar
   carries its value, which is why there is no axis and nothing to hover for. */

/* Four tiles is a fixed count, so the columns are stated rather than left to
   auto-fit — which was free to choose three and orphan the fourth. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  margin-bottom: 2.5rem;
}

@media (min-width: 48rem) {
  .stat-grid { grid-template-columns: repeat(4, 1fr); }
}

.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
}

.stat-value {
  margin: 0;
  font-size: 2.5rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--accent);
}

.stat-label {
  margin: 0.5rem 0 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.stat-hint {
  margin: 0.25rem 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.stats-heading {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 0.75rem;
}

.bar-list {
  list-style: none;
  margin: 0 0 2.5rem;
  padding: 0;
  display: grid;
  gap: 0.375rem;
}

.bar-row {
  display: grid;
  grid-template-columns: 7.5rem 1fr 2.5rem;
  align-items: center;
  gap: 0.75rem;
  padding: 0.25rem 0.375rem;
  border-radius: 0.375rem;
  font-size: 0.875rem;
}

.bar-row:hover { background: var(--surface); }

.bar-label { color: var(--muted); }

/* Recessive track, so the ink belongs to the data rather than the container. */
.bar-track {
  height: 0.625rem;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
}

.bar-fill {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 4px;
}

/* Tabular figures so the column of values lines up digit for digit. */
.bar-value {
  text-align: right;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 30rem) {
  .bar-row { grid-template-columns: 5.5rem 1fr 2rem; gap: 0.5rem; font-size: 0.8125rem; }
}
