/* Tan theme — the old DECAY site's terminal aesthetic. Strictly three
   colours: black, forest green, and tan. No white, cream, or grey. Cards
   and panels sit on the tan page and are set apart by black borders and a
   slightly deeper tan wash. All text and boxes are black; green appears
   only on the blog post divider (hr). Anything on a dark (inverted)
   surface is tan. */
:root {
  --bg: #d2b48c;          /* tan page background */
  --surface: #d2b48c;     /* cards — same tan, separated by black borders */
  --surface-alt: #c2a06e; /* deeper tan wash for panels / inset areas */
  --ink: #111;            /* all text and borders — black */
  --muted: #111;          /* secondary text — also black */
  --accent: #336633;      /* forest green — blog post divider (hr) only */
  --on-ink: #d2b48c;      /* tan text on a black surface */

  /* Calendar category palette — a deliberate, scoped exception to the
     three-colour rule above. The calendar grid was hard to read with
     every event on the same dark tan card, so event cards get a light,
     desaturated "nature" tone per category (see db.EventCategory) instead.
     These are shipped fallbacks only — the calendar page always overrides
     them with an admin-editable palette (see db.CalendarColors,
     /admin/calendar-colors), rendered as a :root block in calendar.templ.
     Nowhere else on the site uses these. */
  --cal-film: #ecdfb2;       /* wheat */
  --cal-music: #d8cce9;      /* lavender */
  --cal-art: #e8c6b0;        /* clay */
  --cal-tech: #bcdbd6;       /* water */
  --cal-games: #bcd7ec;      /* sky */
  --cal-activism: #bdcd93;   /* moss */
  --cal-community: #cddabd;  /* sage */
  --cal-other: #e4dac6;      /* sand — fallback for uncategorized types */
  --cal-day-bg: #e4dac6;     /* sand — the day cells' own background */

  /* Admin calendar (/admin/staff) category colors — a separate three-way
     split (event / booking request / staff meeting) from the event-type
     palette above, and never shown on the same page as it. Without these,
     every entry rendered the same sand as the day cell behind it, so
     nothing but a thin border stripe told the three kinds apart. */
  --cal-admin-event: #ecdfb2;   /* wheat */
  --cal-admin-request: #e8c6b0; /* clay */
  --cal-admin-staff: #bcdbd6;   /* water */
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: #111;
  font-family: 'Archivo', Arial, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

.mono {
  font-family: 'Space Mono', monospace;
}

.page {
  max-width: 520px;
  margin: 0 auto;
  position: relative;
  min-height: 100vh;
}

/* The calendar page. Seven columns need more measure than the site's
   usual narrow column gives them. */
.page-wide {
  max-width: 880px;
}

/* The admin panel. Its tables are seven columns wide and its nav carries
   a link per section, neither of which fits the public site's measure.
   Wide enough that the nav lays out as one row on a desktop window
   instead of collapsing behind the hamburger — at 960px it never could,
   whatever the screen size. */
.page-admin {
  max-width: 1280px;
}

/* Intro splash */

.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  opacity: 1;
  pointer-events: none;
  transition: opacity 0.6s ease;
}

.intro.is-hidden {
  opacity: 0;
}

.intro-frame {
  width: 150px;
  height: 150px;
  overflow: hidden;
}

.intro-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.intro-label {
  font-size: 12px;
  letter-spacing: 0.2em;
  color: var(--muted);
  margin-top: 20px;
}

/* Header */

.site-header {
  container-type: inline-size;
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 20px;
  background: var(--bg);
  border-bottom: 3px solid #111;
}

/* The wordmark is a 2.44:1 rectangle, so it's sized by height with the
   width left to follow — never both, which would squash it to a square.
   38px is as tall as it can go without growing the header: the hamburger
   beside it is 39px, and that's what sets the row's height. */
.site-header img {
  height: 38px;
  width: auto;
}

/* The nav wraps rather than running past the header edge — it gained
   enough items that it no longer fits on one line on a phone. */
.site-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
  row-gap: 8px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.site-nav a {
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 3px 7px;
}

/* The hamburger toggle is a checkbox hack: no JS needed, and the nav is
   still a plain list of links if CSS fails to load. The checkbox itself
   is never shown — the label is what people see and click. */
.nav-toggle {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.nav-toggle-btn {
  display: none;
  border: 1px solid var(--ink);
  background: var(--bg);
  /* Sized as a touch target rather than to the glyph — this is the only
     way into the nav on a phone. */
  padding: 6px 12px;
  font-size: 18px;
  line-height: 1.4;
  cursor: pointer;
}

.nav-toggle:focus-visible ~ .nav-toggle-btn {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* Below this width the nav collapses behind the hamburger button instead
   of wrapping onto several lines. This has to be a container query, not
   a @media (viewport) query: the header sits inside .page or .page-wide,
   which cap it at 520px or 880px regardless of how wide the actual
   browser window is, and the nav needs close to 1000px to lay out on one
   line. A @media threshold can only ever describe the viewport, so on any
   page capped narrower than that, no viewport width made it wrap correctly
   — it just always wrapped onto a second line instead of collapsing,
   doubling the header's height on every screen size, not just phones.

   The threshold is the header's *content* box, which is what an
   inline-size container reports — 40px narrower than the header itself.
   1200px is set just under what the admin row measures (~1196px including
   the wordmark), so the admin panel lays its nav out inline on a desktop
   window and only falls back to the hamburger when it genuinely can't
   fit. The public column is far narrower than this at any window size, so
   it always collapses, as before. */
@container (max-width: 1200px) {
  .nav-toggle-btn {
    display: block;
  }

  /* Scoped through .site-header to outrank .admin-nav's own flex:1, which
     is declared later in this file — without that, flex:1 zeroes the
     basis and crushes the opened admin menu into whatever strip is left
     beside the logo instead of giving it the full row. */
  .site-header .site-nav {
    display: none;
    flex: 0 0 100%;
    width: 100%;
    margin-top: 12px;
    /* The header is sticky, so any part of an opened menu that falls past
       the bottom of the screen can't be scrolled to — it's just gone. On a
       landscape phone the full list is taller than the viewport, which put
       the last few links out of reach entirely. Cap it to what's actually
       on screen and let the menu itself scroll. */
    max-height: calc(100vh - 96px);
    max-height: calc(100dvh - 96px);
    overflow-y: auto;
  }

  /* Auto-fit columns rather than one long stack: 11 links in a single
     column swallow most of a phone screen, and on anything short they
     don't fit at all. Narrower than ~2 columns' worth, this collapses to
     the single column on its own. */
  .nav-toggle:checked ~ .site-nav {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(116px, 1fr));
    gap: 6px;
  }

  .site-nav a {
    text-align: center;
    padding: 8px 10px;
  }
}

/* Small phones (and the narrow cover screens on folding ones) give the
   sticky header's own chrome real weight, so it gets trimmed back — this
   one is genuinely about the device's screen, not the container. */
@media (max-width: 380px) {
  .site-header {
    padding: 12px;
    gap: 8px;
  }

  .site-header img {
    height: 28px;
  }
}

/* Hero */

.hero {
  padding: 48px 20px;
  text-align: center;
  border-bottom: 2px solid #111;
}

.hero-box {
  border: 3px solid #111;
  padding: 28px 20px;
  max-width: 360px;
  margin: 0 auto;
}

.hero-box img {
  width: 100%;
  height: auto;
  /* Block, or the image sits on the text baseline and leaves a strip of
     gap between it and the frame's bottom edge. */
  display: block;
}

/* A photo fills its frame edge to edge. The padding on .hero-box is
   matting for the wordmark, which needs room to breathe inside the
   border; around a photograph it just reads as a gap. */
.hero-box-image {
  padding: 0;
  max-width: 420px;
}

.hero-tagline {
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 24px 0 0;
}

/* About */

.about {
  padding: 56px 20px;
  border-bottom: 2px solid #111;
}

.about-statement {
  font-weight: 900;
  font-size: 26px;
  line-height: 1.3;
  text-transform: uppercase;
  margin: 0;
}

.about-body {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
  margin: 18px 0 0;
}

/* Section label */

.section-label {
  font-size: 12px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
}

.section-label-link {
  display: inline-block;
  background: #111;
  color: var(--on-ink);
  padding: 4px 8px;
}

/* Any link inline in a paragraph gets the same tan-on-black treatment,
   so it reads as a link at a glance instead of blending into the text.
   Group bullets are listed here too: their lines are parsed for links the
   same way a paragraph's are, and an <li> isn't a <p>. Addresses written
   into an event description run long (a bandcamp album, a Google Doc), so
   they break inside the chip rather than pushing the page sideways. */
p a,
.group-bullets a {
  display: inline-block;
  background: #111;
  color: var(--on-ink);
  padding: 1px 6px;
  overflow-wrap: anywhere;
}

/* Events */

.events {
  padding: 44px 20px;
  border-bottom: 2px solid #111;
  background: var(--surface-alt);
}

/* Month heading on the /events listing, repeated down the page. */
.event-month {
  display: block;
  font-size: 12px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 32px;
  padding-bottom: 6px;
  border-bottom: 2px solid #111;
}

.event-month:first-child {
  margin-top: 0;
}

.event-list {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.event-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border: 2px solid #111;
  background: var(--surface);
  transition: background 0.15s ease, color 0.15s ease;
}

.event-item:hover {
  background: #111;
  color: var(--on-ink);
}

.event-item.is-live {
  border-color: var(--accent);
}

.event-title {
  font-weight: 700;
  font-size: 15px;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.event-live-badge {
  font-size: 10px;
  letter-spacing: 0.1em;
  font-weight: 700;
  border: 2px solid var(--accent);
  background: var(--accent);
  color: var(--on-ink);
  padding: 2px 8px;
}

.event-item:hover .event-live-badge {
  color: var(--on-ink);
}

.event-meta {
  font-size: 11px;
  color: var(--muted);
  margin-top: 5px;
  text-transform: uppercase;
}

.event-item:hover .event-meta {
  color: var(--on-ink);
}

/* Role chips keep their tan background on hover, so their text has to stay
   dark rather than inheriting the card's inverted (tan-on-black) color —
   otherwise it's tan text on a tan chip. */
.event-item:hover .volunteer-list li {
  color: var(--muted);
}

.event-date {
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}

.btn-outline {
  display: block;
  text-align: center;
  margin-top: 18px;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 2px solid var(--ink);
  color: var(--ink);
  padding: 14px;
  background: var(--surface);
}

.view-toggle {
  display: flex;
  margin-top: 18px;
}

.view-toggle-btn {
  flex: 1;
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 2px solid var(--ink);
  color: var(--ink);
  padding: 12px;
  background: var(--surface);
}

.view-toggle-btn + .view-toggle-btn {
  border-left: none;
}

.view-toggle-btn.is-active {
  background: var(--ink);
  color: var(--on-ink);
}

.subscribe-note {
  font-size: 11px;
  line-height: 1.6;
  color: var(--muted);
  margin: 12px 0 0;
  text-align: center;
}

.subscribe-note span {
  border: 1px solid var(--muted);
  padding: 1px 4px;
}

/* Event detail */

.event-detail {
  padding: 44px 20px;
  border-bottom: 2px solid #111;
}

.event-back {
  display: block;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 24px;
}

.event-detail-title {
  font-weight: 900;
  font-size: 28px;
  line-height: 1.2;
  text-transform: uppercase;
  margin: 8px 0 0;
}

.event-detail-when {
  font-size: 13px;
  font-weight: 700;
  margin: 12px 0 0;
}

.event-detail-where {
  font-size: 12px;
  color: var(--muted);
  margin: 4px 0 0;
}

.event-flyer {
  display: block;
  width: 100%;
  max-width: 520px;
  height: auto;
  margin: 24px 0;
  border: 2px solid #111;
}

.event-detail-body {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
  margin: 16px 0 0;
  white-space: pre-line;
}

.event-volunteers {
  margin-top: 32px;
  padding: 16px;
  border: 2px solid #111;
  background: var(--surface-alt);
}

.volunteer-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
}

.volunteer-list li {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 2px solid #111;
  background: var(--surface);
  padding: 6px 10px;
}

.volunteer-note {
  font-size: 11px;
  color: var(--muted);
  margin: 12px 0 0;
}

/* Share and download sit side by side, unlike the full-width buttons below
   them (More info, Full calendar) which each get a row to themselves. */
.event-detail-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}

.event-detail-actions .btn-outline {
  flex: 1;
  margin-top: 0;
}

/* Calendar grid */

/* Below a certain width a day cell can't hold a legible event, so the
   grid keeps a floor and scrolls sideways inside this wrapper rather than
   forcing the whole page to scroll. On anything wider than a phone it
   fits and this never engages. */
.calendar-scroll {
  margin-top: 18px;
  overflow-x: auto;
}

.calendar {
  width: 100%;
  min-width: 460px;
  border-collapse: collapse;
  table-layout: fixed;
  background: var(--surface);
}

.calendar th {
  border: 2px solid #111;
  padding: 8px 4px;
  font-size: 11px;
  letter-spacing: 0.1em;
  background: #111;
  color: var(--on-ink);
}

.cal-day {
  border: 2px solid #111;
  vertical-align: top;
  height: 132px;
  width: 14.28%;
  padding: 6px;
  background: var(--cal-day-bg);
}

.cal-day.is-outside {
  background: var(--bg);
}

.cal-day.is-today {
  background: var(--cal-day-bg);
  box-shadow: inset 0 0 0 3px #111;
}

.cal-date {
  display: block;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  margin-bottom: 5px;
}

.cal-day.is-today .cal-date {
  color: #111;
}

.cal-event {
  display: block;
  border: 1px solid #111;
  background: var(--cal-other);
  padding: 5px 6px;
  margin-bottom: 5px;
  font-size: 11px;
  line-height: 1.4;
}

.cal-event.cal-cat-film { background: var(--cal-film); }
.cal-event.cal-cat-music { background: var(--cal-music); }
.cal-event.cal-cat-art { background: var(--cal-art); }
.cal-event.cal-cat-tech { background: var(--cal-tech); }
.cal-event.cal-cat-games { background: var(--cal-games); }
.cal-event.cal-cat-activism { background: var(--cal-activism); }
.cal-event.cal-cat-community { background: var(--cal-community); }
.cal-event.cal-cat-other { background: var(--cal-other); }

/* The admin calendar's own three categories (see --cal-admin-* above) —
   distinct from the event-type classes just above, and from each other,
   so events, booking requests, and staff meetings read apart at a glance
   instead of blending into the day cell behind them. */
.cal-event.cal-cat-event { background: var(--cal-admin-event); }
.cal-event.cal-cat-request { background: var(--cal-admin-request); }
.cal-event.cal-cat-staff { background: var(--cal-admin-staff); }

.cal-event-time {
  display: block;
  font-size: 10px;
  color: var(--muted);
}

/* Scoped to devices with a real pointer — on touch, :hover applies on tap
   and sticks until something else is tapped, leaving the card that was
   just tapped looking like a solid black box in the screenshot right
   before the browser navigates away. */
@media (hover: hover) {
  .cal-event:hover {
    background: #111;
    color: var(--on-ink);
  }

  .cal-event:hover .cal-event-time {
    color: var(--on-ink);
  }
}

.cal-event-title {
  display: block;
  font-weight: 700;
  overflow-wrap: anywhere;
}

/* Below 700px wide the grid is cramped even with the horizontal scroll,
   so mobile gets the agenda list automatically instead — the reverse of
   desktop, where the grid is what you land on. Width alone only catches
   portrait phones, though — a phone rotated to landscape is often
   700-926px wide but just as short as it is in portrait, so the height
   leg of the query catches it too. Tablets and resized desktop windows
   stay well above both thresholds. */
.cal-agenda {
  display: none;
}

@media (max-width: 700px), (max-height: 500px) {
  .calendar-scroll {
    display: none;
  }

  .cal-agenda {
    display: block;
  }
}

/* Prose pages (about, support, policies) */

.prose-list {
  margin: 18px 0 0;
}

.prose-list dt {
  font-weight: 700;
  font-size: 14px;
  text-transform: uppercase;
  margin-top: 16px;
}

.prose-list dd {
  margin: 4px 0 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
}

.prose-bullets {
  margin: 18px 0 0;
  padding-left: 18px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
}

.prose-bullets li {
  margin-bottom: 8px;
}

.plain-list {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  font-size: 13px;
  line-height: 1.9;
}

.pull-quote {
  margin: 18px 0 0;
  padding: 14px 16px;
  border-left: 4px solid #111;
  background: var(--surface-alt);
  font-size: 14px;
  line-height: 1.6;
  font-style: italic;
  color: var(--ink);
}

.postal {
  font-size: 13px;
  line-height: 1.7;
  font-style: normal;
  margin-top: 12px;
  border: 2px solid #111;
  padding: 12px 14px;
  background: var(--surface);
}

.partner-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 14px;
  align-items: center;
  margin-top: 18px;
}

.partner-grid img {
  width: 100%;
  height: auto;
  display: block;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.footer-links a {
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 3px 7px;
}

/* Gallery */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
  margin-top: 18px;
}

.gallery-item {
  margin: 0;
  border: 2px solid #111;
  background: var(--surface);
}

/* Photos arrive in whatever shape a phone took them, so each is cropped
   to a square tile — a mixed-aspect grid reads as a mess. The full-size
   original is a click away, uncropped. */
.gallery-item img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}

.gallery-caption {
  font-size: 10px;
  line-height: 1.5;
  color: var(--muted);
  padding: 6px 8px;
  border-top: 2px solid #111;
}

/* Recent uploads on /media. Same tile treatment as the photo gallery, but
   a separate class on purpose: .gallery is what the lightbox binds to, and
   these tiles link out to YouTube rather than opening in place. Wider
   columns, since a 16:9 still is unreadable at photo-tile size. */
.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
  margin-top: 18px;
}

.video-item {
  margin: 0;
  border: 2px solid #111;
  background: var(--surface);
}

.video-item a {
  display: block;
  position: relative;
}

.video-item img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* A play marker, so a still reads as a video rather than a photo. */
.video-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  color: #fff;
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.9);
  opacity: 0.85;
}

.video-item a:hover .video-play {
  opacity: 1;
}

.video-caption {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 10px;
  line-height: 1.5;
  color: var(--muted);
  padding: 6px 8px;
  border-top: 2px solid #111;
}

.video-title {
  color: #111;
  overflow-wrap: anywhere;
}

.video-date {
  font-size: 9px;
}

/* Pager */

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 24px;
  border: 2px solid #111;
  padding: 12px 14px;
  background: var(--surface);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.pager-link {
  white-space: nowrap;
}

/* Kept in the layout rather than hidden, so the row doesn't shift when
   an end of the list is reached. */
.pager-link.is-disabled {
  color: var(--muted);
}

.pager-status {
  color: var(--muted);
  text-align: center;
}

.admin-table .nowrap,
.nowrap {
  white-space: nowrap;
}

/* Merch */

.merch {
  padding: 44px 20px;
  border-bottom: 2px solid #111;
}

.merch-intro {
  font-size: 13px;
  color: var(--muted);
  margin: 10px 0 20px;
}

.merch-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 12px;
}

.merch-item {
  display: block;
  text-align: center;
}

/* A buyable item posts to /shop/checkout instead of linking out, so the
   card is a <button> inside a <form>. display:contents drops the form from
   the grid's box layout, and the reset makes the button match the <a>
   variant exactly. */
.merch-form {
  display: contents;
}

button.merch-item {
  all: unset;
  display: block;
  box-sizing: border-box;
  width: 100%;
  text-align: center;
  cursor: pointer;
}

.merch-photo {
  position: relative;
  border: 2px solid #111;
  aspect-ratio: 1;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-alt);
  color: var(--muted);
  font-size: 11px;
  text-align: center;
  padding: 8px;
}

/* A product photo fills the square frame, so the padding that centres
   placeholder text has to go. */
.merch-photo:has(img) {
  padding: 0;
}

.merch-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.merch-variants {
  font-size: 10px;
  line-height: 1.5;
  color: var(--muted);
  margin-top: 4px;
}

.merch-name {
  font-weight: 700;
  font-size: 12px;
  text-transform: uppercase;
  margin-top: 8px;
}

.merch-price {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}

/* Media */

.media {
  padding: 44px 20px;
  border-bottom: 2px solid #111;
}

.media-list {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.media-video {
  border: 2px solid #111;
}

.media-video-frame {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-alt);
  color: var(--muted);
  font-size: 12px;
}

/* The embedded player fills the 16:9 frame. */
.media-video-frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.media-video-caption {
  padding: 12px 14px;
  font-size: 11px;
  text-transform: uppercase;
  display: flex;
  justify-content: space-between;
}

.media-video-caption span:last-child {
  color: var(--muted);
}

.media-audio {
  border: 2px solid #111;
  padding: 14px;
  display: flex;
  align-items: center;
  gap: 14px;
}

.media-audio-art {
  width: 48px;
  height: 48px;
  border: 2px solid #111;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-alt);
  color: var(--muted);
  font-size: 8px;
  text-align: center;
}

.media-audio-title {
  font-weight: 700;
  font-size: 13px;
  text-transform: uppercase;
}

.media-audio-meta {
  font-size: 10px;
  color: var(--muted);
  margin-top: 3px;
}

/* Contact */

.contact {
  padding: 44px 20px 30px;
  text-align: center;
}

.contact-heading {
  font-weight: 900;
  font-size: 19px;
  text-transform: uppercase;
  line-height: 1.3;
  margin: 12px 0 20px;
}

.signup-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.signup-input {
  border: 2px solid #111;
  background: none;
  padding: 16px 14px;
  font-size: 14px;
  color: #111;
  text-align: center;
  width: 100%;
}

.signup-submit {
  border: 2px solid #111;
  background: none;
  color: #111;
  padding: 16px;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.signup-submit:hover {
  background: #111;
  color: var(--on-ink);
}

.volunteer-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 100%;
}

.volunteer-form input,
.volunteer-form textarea {
  border: 2px solid #111;
  background: none;
  padding: 12px 14px;
  font-size: 14px;
  color: #111;
  font-family: 'Archivo', Arial, sans-serif;
  width: 100%;
}

.volunteer-form textarea {
  font-family: 'Space Mono', monospace;
  resize: vertical;
  min-height: 80px;
}

.volunteer-form button {
  border: 2px solid #111;
  background: none;
  color: #111;
  padding: 12px;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-family: 'Space Mono', monospace;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.volunteer-form button:hover {
  background: #111;
  color: var(--on-ink);
}

.social-links {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 24px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.social-links a {
  color: var(--ink);
  border: 1px solid var(--ink);
  padding: 3px 7px;
}

/* Footer */

.site-footer {
  border-top: 2px solid #111;
  padding: 22px 20px 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
}

.footer-copyright {
  margin-top: 12px;
}

.site-footer span {
  font-size: 10px;
  color: var(--muted);
}

.site-footer .copyright {
  color: var(--muted);
  margin-top: 8px;
}

/* Admin */

.admin-main {
  max-width: 900px;
  margin: 0 auto;
  padding: 32px 20px 60px;
}

/* The admin nav carries a link per section plus the signed-in name and a
   log-out button — 15 items. On a desktop window that's one row; below
   roughly 1250px it collapses behind the hamburger rather than wrapping. */
.admin-header {
  flex-wrap: wrap;
  gap: 12px;
}

/* Tighter than the public nav: with 15 items, the difference between a
   16px and a 6px gap across 14 of them is most of what decides whether
   the row fits at all. */
.admin-nav {
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  row-gap: 8px;
  /* The nav takes the space left over and lines up to the right, so the
     row reads logo-then-nav however many items it holds. */
  justify-content: flex-end;
  flex: 1;
}

/* Nav links sit on the text baseline; without this they stretch to the
   height of the log-out button beside them. */
.admin-nav > a,
.admin-nav > span,
.admin-nav > form {
  align-self: center;
}

.admin-nav > a {
  padding: 3px 6px;
}

/* Keyed to the same container query that collapses the nav behind the
   hamburger, not a viewport width — the admin header is capped at 960px
   whatever the window is doing, so a @media threshold would flip these at
   a width unrelated to when the menu actually collapses, leaving the
   opened menu laid out for a row it isn't in. */
@container (max-width: 1200px) {
  .admin-nav > a,
  .admin-nav > span,
  .admin-nav > form {
    align-self: stretch;
  }

  /* The log-out button is wrapped in a form, so the form has to become a
     flex box for the button to fill its cell like the links do. */
  .admin-nav > form {
    display: flex;
  }

  .admin-nav > form > .admin-btn {
    flex: 1;
  }

  .admin-whoami {
    justify-content: center;
  }
}


.admin-heading {
  font-weight: 900;
  font-size: 20px;
  text-transform: uppercase;
  margin: 32px 0 16px;
}

.admin-heading:first-child {
  margin-top: 0;
}

.admin-back {
  display: inline-block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-bottom: 16px;
}

.admin-sub {
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0 0 12px;
}

.admin-tag {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1px solid var(--muted);
  padding: 1px 5px;
  margin-left: 8px;
  color: var(--muted);
}

.admin-flyer-preview {
  display: block;
  max-width: 260px;
  height: auto;
  border: 2px solid #111;
  margin-bottom: 16px;
}

.admin-fieldset {
  border: 1px solid #111;
  padding: 12px;
  margin: 4px 0;
}

.admin-fieldset legend {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0 6px;
}

.admin-next {
  border: 2px solid #111;
  background: var(--surface-alt);
  padding: 16px;
  margin-bottom: 8px;
}

.admin-next-title {
  display: block;
  font-weight: 900;
  font-size: 18px;
  text-transform: uppercase;
  margin-top: 8px;
}

.admin-next-when {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
}

.admin-whoami {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* The small square beside a name in a list or the nav. A photo and the
   initials fallback are the same size, so a mixed list doesn't jump. */
.admin-avatar {
  width: 24px;
  height: 24px;
  flex: none;
  object-fit: cover;
  border: 1px solid #111;
  background: var(--surface-alt);
}

.admin-avatar-empty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--muted);
}

/* Keeps the avatar, name, and "you" tag on one line in the accounts
   table. */
.admin-who {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Edit sits next to Delete without the form below it. */
.admin-row-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.admin-row-actions a.admin-btn {
  text-decoration: none;
}

/* The account card: photo left, name and blurb right — an AIM profile,
   more or less. */
.profile-card {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  border: 2px solid #111;
  background: var(--surface-alt);
  padding: 16px;
  margin-bottom: 24px;
  max-width: 480px;
}

.profile-avatar {
  width: 96px;
  height: 96px;
  flex: none;
  border: 2px solid #111;
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.profile-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.profile-initials {
  font-family: 'Space Mono', monospace;
  font-size: 28px;
  text-transform: uppercase;
  color: var(--muted);
}

.profile-body {
  min-width: 0;
}

.profile-name {
  font-weight: 900;
  font-size: 18px;
  text-transform: uppercase;
  margin: 0;
}

.profile-meta {
  font-size: 11px;
  color: var(--muted);
  margin: 2px 0 10px;
}

/* Blurbs are typed by hand and can carry a long unbroken string; wrapping
   it keeps one out of the card's edge. */
.profile-blurb {
  font-size: 13px;
  line-height: 1.6;
  margin: 0;
  overflow-wrap: anywhere;
}

.profile-blurb-empty {
  color: var(--muted);
}

.admin-form select {
  border: 2px solid #111;
  padding: 8px;
  font: inherit;
  font-size: 13px;
  background: var(--surface);
}

.admin-caption-form {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}

.admin-caption-form input {
  flex: 1;
  min-width: 0;
  border: 1px solid #111;
  padding: 6px;
  font: inherit;
  font-size: 12px;
}

.admin-photo-actions {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}

/* Scoped to .admin-form label so it outweighs that rule's flex-direction:
   column — otherwise the checkbox stacks above its text and centres instead
   of sitting left of it. */
.admin-check,
.admin-form label.admin-check {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  font-size: 13px;
  text-transform: none;
  letter-spacing: 0;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 24px;
  font-size: 13px;
}

.admin-table th,
.admin-table td {
  border: 1px solid #111;
  padding: 8px 10px;
  text-align: left;
  vertical-align: middle;
}

.admin-table th {
  background: var(--surface-alt);
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.05em;
}

.admin-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 480px;
  margin-bottom: 32px;
}

.admin-form label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.admin-form label.inline {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.admin-form input,
.admin-form textarea {
  border: 2px solid #111;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 14px;
  background: var(--surface);
  color: #111;
}

.admin-form input[type="checkbox"] {
  width: auto;
}

.admin-form textarea {
  min-height: 140px;
  resize: vertical;
}

.admin-btn {
  border: 2px solid #111;
  background: none;
  color: #111;
  padding: 8px 14px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
  font-family: 'Space Mono', monospace;
}

.admin-btn:hover {
  background: #111;
  color: var(--on-ink);
}

/* A log-out button sized to sit among the nav's text links rather than
   tower over them. Defined after .admin-btn so it wins the cascade. */
.admin-btn-small {
  padding: 4px 10px;
  font-size: 11px;
}

.admin-btn-danger {
  border-color: #a00;
  color: #a00;
}

.admin-btn-danger:hover {
  background: #a00;
  color: var(--on-ink);
}

.admin-flash {
  padding: 10px 14px;
  border: 2px solid #111;
  margin-bottom: 16px;
  font-size: 13px;
}

.admin-flash-error {
  border-color: #a00;
  color: #a00;
}

.cal-unscheduled {
  margin-top: 18px;
  margin-bottom: 18px;
}

.cal-unscheduled-list {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.cal-unscheduled-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 12px;
}

.cal-unscheduled-date {
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}

.upload-progress {
  height: 8px;
  border: 2px solid #111;
  margin-top: 10px;
  padding: 1px;
}

.upload-progress-bar {
  height: 100%;
  width: 0;
  background: #111;
  transition: width 0.15s linear;
}

.admin-login-wrap {
  max-width: 320px;
  margin: 80px auto;
  padding: 0 20px;
}

/* Dashboard cards --------------------------------------------------- */

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
  margin-top: 18px;
}

.dashboard-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  border: 2px solid #111;
  padding: 18px;
  background: var(--surface);
  text-decoration: none;
  color: #111;
  transition: background 0.15s ease, color 0.15s ease;
}

.dashboard-card:hover {
  background: #111;
  color: var(--on-ink);
}

.dashboard-card-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.dashboard-card-title {
  font-weight: 900;
  font-size: 18px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.dashboard-card-meta {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
}

.dashboard-card:hover .dashboard-card-meta {
  color: var(--on-ink);
}

.dashboard-card-desc {
  font-size: 14px;
  line-height: 1.5;
  margin: 0;
  color: #111;
}

.dashboard-card:hover .dashboard-card-desc {
  color: var(--on-ink);
}

/* Reports ------------------------------------------------------------- */

/* A heading with an action button parked on the right of the same line. */
.admin-heading-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

/* Quarter jump links, wrapping onto a second row on narrow screens. */
.report-periods {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 16px;
}

.report-period {
  border: 2px solid #111;
  padding: 4px 10px;
  font-size: 12px;
  text-decoration: none;
  color: #111;
}

.report-period:hover {
  background: #111;
  color: var(--on-ink);
}

/* The quarter currently shown reads as pressed, not clickable. */
.report-period.is-current {
  background: #111;
  color: var(--on-ink);
}

.report-range {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
  margin-bottom: 20px;
}

.report-range label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
}

.report-range input {
  border: 2px solid #111;
  padding: 6px 8px;
  font-family: 'Space Mono', monospace;
}

/* One past event on the entry screen: heading line, then two inline
   forms that wrap their fields on narrow screens. */
.report-entry {
  border: 2px solid #111;
  padding: 12px 14px;
  margin-bottom: 12px;
}

.report-entry-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}

.report-entry-type {
  font-size: 11px;
  opacity: 0.7;
}

.report-entry-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
  margin-bottom: 8px;
}

.report-entry-form label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
}

.report-entry-form input {
  border: 2px solid #111;
  padding: 5px 7px;
  font-family: 'Space Mono', monospace;
  width: 90px;
}

/* Notes take whatever room is left on the line. */
.report-entry-form .report-entry-notes {
  flex: 1 1 200px;
}

.report-entry-form .report-entry-notes input {
  width: 100%;
}

.report-entry-donations {
  align-self: center;
  font-size: 12px;
}

/* Board & staff profiles on the About page ---------------------------- */

.team-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-top: 16px;
}

/* Three across is the desktop layout; drop to two then one as the column
   narrows so the portraits never get squeezed. */
@media (max-width: 900px) {
  .team-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 600px) {
  .team-grid {
    grid-template-columns: 1fr;
  }
}

.team-card {
  border: 2px solid #111;
  display: flex;
  flex-direction: column;
}

.team-photo {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  border-bottom: 2px solid #111;
}

/* When there's no portrait yet, show the person's initials rather than a
   broken image or an empty box. */
.team-photo-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #111;
  color: var(--on-ink);
  font-size: 40px;
  letter-spacing: 0.05em;
}

.team-body {
  padding: 12px 14px 16px;
}

.team-name {
  font-weight: 700;
  font-size: 17px;
  margin: 0;
}

.team-pronouns {
  font-weight: 400;
  font-size: 12px;
  opacity: 0.65;
  margin-left: 6px;
}

.team-role {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 2px 0 8px;
  opacity: 0.8;
}

.team-bio-button {
  margin-top: 8px;
  padding: 8px 12px;
  font-size: 12px;
}

.team-bio {
  font-size: 14px;
  line-height: 1.5;
  margin: 0 0 8px;
}

.team-bio:last-child {
  margin-bottom: 0;
}

/* Groups & programs --------------------------------------------------- */

.group-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
  margin-top: 16px;
}

.group-card {
  border: 2px solid #111;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-decoration: none;
  color: #111;
}

.group-card:hover {
  background: #111;
  color: var(--on-ink);
}

.group-card-name {
  font-weight: 900;
  font-size: 20px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.group-card-summary {
  font-size: 14px;
  line-height: 1.5;
}

.group-card-more {
  font-size: 12px;
  margin-top: auto;
}

/* Detail page */
.group-hero {
  width: 100%;
  max-height: 340px;
  object-fit: cover;
  display: block;
  border: 2px solid #111;
  margin-bottom: 16px;
}

.group-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 16px;
}

.group-pill {
  border: 2px solid #111;
  padding: 3px 10px;
  font-size: 12px;
}

.group-section {
  margin-top: 20px;
}

.group-section-title {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0 0 8px;
}

.group-bullets {
  margin: 0;
  padding-left: 20px;
}

.group-bullets li {
  font-size: 15px;
  line-height: 1.6;
  margin-bottom: 4px;
}

/* Shop additions: description, sold-out badge --------------------------- */

.merch-desc {
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
  margin-top: 6px;
}

/* A sold-out card doesn't link anywhere, so dim it and drop the pointer.
   An item with no checkout path yet (not synced from Stripe, no manual
   buy link) gets the same treatment, minus the "Sold out" badge — it
   isn't sold out, it just isn't purchasable through the site yet. */
.merch-item.is-soldout,
.merch-item.is-unavailable {
  opacity: 0.72;
  cursor: default;
}

.merch-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  background: #111;
  color: var(--on-ink);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 2px 6px;
}

/* A group's own upcoming schedule, set off from the sections below it. */
.group-schedule {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 2px solid #111;
}

/* A group's tagged photos, set off like its schedule. */
.group-photos {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 2px solid #111;
}

/* The admin photo tag dropdown sits between caption and save. */
.admin-caption-form select {
  border: 2px solid #111;
  padding: 4px;
  font-family: 'Space Mono', monospace;
  font-size: 12px;
}

/* Booking request queue -------------------------------------------------- */

.booking-card {
  border: 2px solid #111;
  padding: 14px 16px;
  margin-bottom: 14px;
}

.booking-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}

.booking-head strong {
  font-size: 16px;
}

.booking-badge {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: #111;
  color: var(--on-ink);
  padding: 2px 6px;
}

.booking-badge-muted {
  background: var(--muted);
}

.booking-when {
  font-size: 11px;
  color: var(--muted);
  margin-left: auto;
}

.booking-fields {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 2px 12px;
  font-size: 13px;
  margin: 0 0 10px;
}

.booking-fields dt {
  color: var(--muted);
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.04em;
}

.booking-fields dd {
  margin: 0;
}

.booking-desc {
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-line;
  margin: 0 0 12px;
}

.booking-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Admin media: compact edit form under each video thumbnail. */
.admin-media-form {
  gap: 6px;
}

.admin-media-form label {
  font-size: 11px;
}

/* Blog post body: rendered Markdown ------------------------------------ */
/* Posts are authored in Markdown, so a post body carries real structure —
   headings, lists, quotes, code — rather than the flat paragraphs the
   event/about pages use. */
.post-body {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
  margin: 20px 0 0;
}

.post-body > :first-child {
  margin-top: 0;
}

.post-body p {
  margin: 0 0 16px;
}

.post-body h2,
.post-body h3,
.post-body h4 {
  font-family: "Archivo", sans-serif;
  color: #111;
  line-height: 1.2;
  margin: 28px 0 10px;
}

.post-body h2 { font-size: 22px; }
.post-body h3 { font-size: 18px; }
.post-body h4 { font-size: 15px; text-transform: uppercase; letter-spacing: 0.06em; }

.post-body a {
  color: var(--ink);
  text-decoration: none;
  border: 1px solid var(--ink);
  padding: 0 4px;
  /* Keep the box intact when a link wraps across lines. */
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.post-body ul,
.post-body ol {
  margin: 0 0 16px;
  padding-left: 20px;
}

.post-body li {
  margin-bottom: 6px;
}

.post-body blockquote {
  margin: 18px 0;
  padding: 12px 16px;
  border-left: 4px solid #111;
  background: var(--surface-alt);
  font-style: italic;
}

.post-body blockquote p:last-child {
  margin-bottom: 0;
}

.post-body img {
  max-width: 100%;
  height: auto;
  border: 2px solid #111;
}

.post-body hr {
  border: none;
  border-top: 2px solid var(--accent);
  margin: 28px 0;
}

.post-body code {
  font-family: "Space Mono", monospace;
  font-size: 0.9em;
  background: var(--surface-alt);
  padding: 1px 5px;
  border: 1px solid var(--ink);
}

.post-body pre {
  background: #111;
  color: var(--surface-alt);
  padding: 14px 16px;
  overflow-x: auto;
  margin: 0 0 16px;
}

.post-body pre code {
  background: none;
  border: none;
  color: inherit;
  padding: 0;
}

.post-body table {
  border-collapse: collapse;
  width: 100%;
  margin: 0 0 16px;
  font-size: 14px;
}

.post-body th,
.post-body td {
  border: 2px solid #111;
  padding: 6px 10px;
  text-align: left;
}

/* Internal meetings calendar (admin) ---------------------------------- */
/* Meetings come from the read-only Nextcloud feed, so their cells aren't
   links — drop the events grid's hover-invert, which would imply a click,
   and mark them with an accent stripe instead. */
.cal-meeting {
  cursor: default;
  border-left: 3px solid #111;
}

.cal-meeting:hover {
  background: var(--surface-alt);
  color: inherit;
}

.cal-meeting:hover .cal-event-time {
  color: var(--muted);
}

/* Booking requests share the meeting's non-inverting hover (still a real
   link, unlike a meeting, but a dashed stripe keeps the three categories
   visually distinct at a glance). */
.cal-request {
  border-left: 3px dashed #111;
}

/* Category toggles: three independent checkboxes, each hiding its own
   category on the grid below via a pure-CSS sibling selector — same
   technique as the nav hamburger and the public calendar's view switch. */
.cal-filter-toggle {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.cal-filter-btn {
  display: inline-block;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 2px solid #111;
  padding: 6px 10px;
  margin: 12px 8px 0 0;
  cursor: pointer;
  background: var(--surface);
  color: var(--muted);
}

.cal-filter-toggle:checked + .cal-filter-btn {
  background: #111;
  color: var(--on-ink);
}

#cal-filter-event:not(:checked) ~ .calendar-scroll .cal-cat-event {
  display: none;
}

#cal-filter-request:not(:checked) ~ .calendar-scroll .cal-cat-request {
  display: none;
}

#cal-filter-staff:not(:checked) ~ .calendar-scroll .cal-cat-staff {
  display: none;
}

.admin-subheading {
  font-family: "Archivo", sans-serif;
  font-size: 18px;
  margin: 28px 0 10px;
}

.meeting-list {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
}

.meeting-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  padding: 12px 0;
  border-top: 2px solid #111;
}

.meeting-row:last-child {
  border-bottom: 2px solid #111;
}

.meeting-when {
  flex: 0 0 140px;
  display: flex;
  flex-direction: column;
  font-size: 12px;
}

.meeting-date {
  font-weight: 700;
  color: #111;
}

.meeting-time {
  color: var(--muted);
}

.meeting-body {
  flex: 1 1 240px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.meeting-title {
  font-weight: 700;
}

.meeting-loc {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.meeting-desc {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  white-space: pre-line;
}

/* Markdown editor toolbar (admin blog) -------------------------------- */
.md-editor {
  display: flex;
  flex-direction: column;
}

.md-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 6px;
  border: 2px solid #111;
  border-bottom: none;
  background: var(--surface-alt);
}

.md-btn {
  border: 1px solid #111;
  background: var(--surface);
  color: #111;
  min-width: 30px;
  padding: 4px 8px;
  font-family: "Space Mono", monospace;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}

.md-btn:hover {
  background: #111;
  color: var(--on-ink);
}

/* The textarea butts directly against the toolbar, so they read as one
   control; the toolbar owns the top border. */
.md-editor textarea {
  margin: 0;
}

/* Blog post image strip (admin edit page) ----------------------------- */
.post-image-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 12px 0 20px;
}

.post-image {
  margin: 0;
  border: 2px solid #111;
  width: 160px;
  display: flex;
  flex-direction: column;
}

.post-image img {
  width: 100%;
  height: 110px;
  object-fit: cover;
  display: block;
  border-bottom: 2px solid #111;
}

.post-image figcaption {
  display: flex;
  gap: 6px;
  padding: 6px;
  justify-content: space-between;
}

/* Blog embeds (YouTube / Bandcamp) ------------------------------------ */
.embed {
  margin: 20px 0;
  border: 2px solid #111;
}

/* Responsive 16:9 video that keeps its ratio at any width. */
.embed-video {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  padding: 0;
}

.embed-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Bandcamp's player is a fixed-height strip; let it span the column. */
.embed-audio {
  display: block;
  width: 100%;
  height: 120px;
}

/* Photo gallery lightbox ---------------------------------------------- */
.gallery-item a { cursor: zoom-in; }

body.lightbox-open { overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px;
  background: rgba(0, 0, 0, 0.92);
}

/* Win over the [hidden] UA display:none while the flex layout is set. */
.lightbox[hidden] { display: none; }

.lightbox-figure {
  margin: 0;
  max-width: 90vw;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.lightbox-img {
  max-width: 90vw;
  max-height: 82vh;
  object-fit: contain;
  border: 2px solid var(--on-ink);
  background: #111;
}

.lightbox-caption {
  color: var(--on-ink);
  font-size: 12px;
  text-align: center;
  max-width: 80vw;
}

.lightbox-caption[hidden] { display: none; }

.lightbox-close,
.lightbox-nav {
  border: 2px solid var(--on-ink);
  background: rgba(0, 0, 0, 0.4);
  color: var(--on-ink);
  cursor: pointer;
  line-height: 1;
  font-family: 'Space Mono', monospace;
}

.lightbox-nav {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  font-size: 28px;
}

.lightbox-nav[hidden] { display: none; }

.lightbox-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 44px;
  height: 44px;
  font-size: 24px;
}

.lightbox-close:hover,
.lightbox-nav:hover {
  background: var(--surface);
  color: #111;
}

@media (max-width: 640px) {
  .lightbox-nav { width: 38px; height: 38px; font-size: 22px; }
}

/* Booking email history + reply ------------------------------------------ */

.email-msg {
  border: 2px solid #111;
  margin-bottom: 8px;
}

.email-msg > summary {
  cursor: pointer;
  padding: 8px 12px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  list-style: none;
}

.email-msg > summary::-webkit-details-marker {
  display: none;
}

.email-msg > summary:hover {
  background: var(--surface-alt);
}

.email-dir {
  font-weight: bold;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.email-date {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.email-subject {
  font-weight: bold;
}

.email-snippet {
  flex-basis: 100%;
  font-size: 13px;
  color: var(--muted);
}

.email-headers {
  padding: 8px 12px;
  font-size: 12px;
  border-top: 2px solid #111;
  background: var(--surface-alt);
}

.email-body {
  margin: 0;
  padding: 10px 12px;
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.5;
  max-height: 24em;
  overflow-y: auto;
}

.email-quoted {
  border-top: 2px solid #111;
}

.email-quoted > summary {
  cursor: pointer;
  padding: 6px 12px;
  font-size: 11px;
  color: var(--muted);
  list-style: none;
}

.email-quoted > summary::-webkit-details-marker {
  display: none;
}

.email-quoted-body {
  color: var(--muted);
  font-size: 13px;
  border-top: 2px solid #111;
}

.email-compose {
  border: 2px solid #111;
  margin-top: 16px;
}

.email-compose > summary {
  cursor: pointer;
  padding: 10px 14px;
  font-weight: bold;
  list-style: none;
}

.email-compose > summary::-webkit-details-marker {
  display: none;
}

.email-compose > summary:hover {
  background: var(--surface-alt);
}

.email-compose form {
  padding: 0 14px 14px;
}

.email-compose label {
  display: block;
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 10px;
}

.email-compose input[type="text"],
.email-compose textarea {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 4px;
  padding: 8px 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: normal;
  border: 2px solid #111;
  background: var(--surface);
}

.email-compose textarea {
  resize: vertical;
  min-height: 8em;
  line-height: 1.5;
}

.send-preview {
  margin: 0 0 16px;
}

.send-preview dt {
  font-weight: bold;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.send-preview dd {
  margin: 0 0 8px;
}

/* Order confirmation — the page Stripe returns a buyer to. The card is an
   inset panel like the admin ones: a black border on the deeper tan wash,
   no third colour introduced for "success". */

.order-card {
  border: 2px solid #111;
  background: var(--surface);
  padding: 20px;
  margin-bottom: 20px;
}

.order-code-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: 16px;
  border-bottom: 2px solid #111;
  margin-bottom: 16px;
}

.order-code-label {
  font-size: 10px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The code is read back over the phone and typed into emails, so it's the
   largest thing on the page and spaced out enough to transcribe. */
.order-code {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.18em;
  word-break: break-all;
}

.order-pending {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding-bottom: 16px;
  border-bottom: 2px solid #111;
  margin: 0 0 16px;
}

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

.order-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid #111;
}

.order-qty {
  font-size: 11px;
  color: var(--muted);
}

.order-name {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
}

.order-line {
  font-size: 12px;
  white-space: nowrap;
}

.order-total {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 12px 0 0;
}

.order-note {
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
  margin: 16px 0 0;
}
