/* ==========================================================================
   GodSend public — public.css: the visitor surfaces, over tokens.css
   --------------------------------------------------------------------------
   Loaded by partials/public-head.ejs, third of three:

       <link rel="stylesheet" href="/css/fonts.css">    the two brand faces
       <link rel="stylesheet" href="/css/tokens.css">   the palette and scales
       <link rel="stylesheet" href="/css/public.css">   this file

   Nothing else. No theme.css — that is the admin SHELL (title bar, nav,
   toasts) and a visitor has no use for any of it — no admin.css, no script.

   WHO THIS IS FOR. A stranger who tapped a link inside a social app, on a
   phone, on cellular, often in a dark room, with seconds of patience and
   exactly one decision to make. Everything below serves the choice and
   nothing competes with it: no brand furniture, no footer, no explanation.

   THE LOOK IS THE SHOW'S (2026-09-05). Before this date these pages were a
   neutral dark console: system sans, white headings, a soft 10px box, one
   bright red held in reserve. That was defensible and it was nobody's — a
   visitor arriving from godlessengineering.com landed somewhere that shared
   no colour, no typeface and no shape with the place they came from. The
   three moves that close the gap are the three the show's own site makes:

     1. THE HEADING IS RED AND CONDENSED. Its `h1,h2,h3,h4,h5,h6` rule sets
        colour #c23d3d and family American Captain, and that pairing is the
        single most recognisable thing about the site.
     2. THE PRIMARY CONTROL IS A SOLID RED BLOCK with a white display-face
        label. Here that is the LIVE row — the one row on the page that is
        genuinely the primary action when it exists.
     3. BLACK AND #1f1f1f ALTERNATE. The show's site bands them full-bleed
        down the page; a one-column chooser bands them row against ground,
        which is the same contrast doing the same work at this width.

   BASE RULES ARE DUPLICATED FROM theme.css §1 ON PURPOSE — the box model,
   the body font, the focus ring, reduced motion, forced colours. They
   cannot be shared without loading the shell, and the shell is exactly what
   must not load here. If one changes there, check here.

   NOTHING HERE KNOWS WHAT /live IS. Selectors key on the classes the
   default interstitial template renders (.chooser, .choices, .choice,
   .notice); a second interstitial created through the service arrives
   styled with zero changes here.

   CONTRAST. Two grounds carry almost everything: bg-0 (the page) and bg-1
   (a choice), with bg-2/bg-3 under hover and press. Every ratio below was
   computed on 2026-09-05 with the WCAG relative-luminance formula from the
   token values. Target WCAG 2.2 Level AA. The one rule to keep in mind when
   editing: --red is legal as LARGE text and as a boundary on bg-0/bg-1
   only; anything smaller, or on a lighter ground, takes --red-ink.
   ========================================================================== */


/* ==========================================================================
   §1  BASE (mirrors theme.css §1)
   ========================================================================== */

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

html {
  background: var(--bg-0);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;              /* as on .chooser below; the body was missed */
  /* 17px/1.6 against the admin's 14px/1.5, and against this file's own
     previous 16px/1.5: the show's site runs 18px/1.7 and this is read at
     arm's length in a queue, not scanned at a desk. */
  font: 400 var(--text-body-public) / var(--leading-public) var(--font-sans);
  color: var(--ink-1);             /* 21.00:1 on bg-0 */
  background: var(--bg-0);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* One ring, 2px, at 2px offset, in RED-INK rather than red: --red measures
   2.42:1 against a pressed control and would fail the non-text floor there
   silently, where --red-ink holds 7.17 / 5.62 / 4.83 / 4.31 across the four
   grounds. Never removed for a mouse user's benefit.
   [T1: WCAG 2.2 — 2.4.7 Focus Visible (AA); 1.4.11 Non-text Contrast (AA)] */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--red-ink);
  outline-offset: 2px;
}

::selection { background: color-mix(in srgb, var(--red) 45%, transparent); }

/* Clip pattern, NOT display:none — the record's "no figure" note and any
   future hidden label must stay in the accessibility tree. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ==========================================================================
   §2  THE COLUMN
   --------------------------------------------------------------------------
   One column, phone-first. 29rem (464px) holds a headline and five choices
   at the new type size; on a desktop it sits centred with the page's black
   around it. The column is centred VERTICALLY in the viewport so that on a
   phone the choices fall into the lower half — where the thumb already is —
   rather than crowding the status bar. Taller content (thirty choices)
   simply starts at the top and scrolls; align-content cannot push content
   off the top. [UNSOURCED — practitioner judgment] on 29rem and the centring.
   ========================================================================== */

main {
  display: grid;
  align-content: center;
  width: 100%;
  max-width: 29rem;
  min-height: 100vh;
  min-height: 100svh;              /* the visible viewport under a mobile toolbar; older engines keep 100vh */
  margin-inline: auto;
  padding: var(--space-8) var(--space-5);
}


/* ==========================================================================
   §3  THE COPY
   --------------------------------------------------------------------------
   Operator copy of unknown length — a headline up to 200 characters, a
   subhead, a body of up to 2,000 — inside a 280px column at the 320px
   floor. One long word must wrap rather than widen the document
   (SC 1.4.10 Reflow). Body text keeps the operator's line breaks.

   THE HEADLINE IS THE BRAND MOMENT: the show's display face, at the show's
   heading colour, at a size a condensed face needs to carry. 34px rising to
   44px, where the old neutral h1 ran 28px/34px — a condensed face sets
   optically smaller than a text face at the same nominal size, so the number
   goes up while the block gets no taller. --red at 34px+ is LARGE text and
   clears AA's 3:1 for large text at 4.03:1 on the page.
   [T1: WCAG 2.2 — 1.4.3 Contrast (Minimum) (AA), large-text threshold]
   ========================================================================== */

h1 {
  margin: 0 0 var(--space-3);
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 400;                /* the face ships in one weight; see fonts.css */
  line-height: var(--display-leading);
  letter-spacing: var(--display-tracking);
  color: var(--red);               /* 4.03:1 on bg-0 — large text */
  overflow-wrap: anywhere;
}
@media (min-width: 480px) {
  h1 { font-size: 44px; }
}

/* The rule under the head. The show's site separates its bands with a hard
   colour change edge to edge; a 29rem column cannot band, so the same edge
   is drawn as a short red rule — structure, not decoration, and the only
   thing between the headline and the first choice. */
.chooser-head,
.page-head {
  margin-bottom: var(--space-6);
  padding-bottom: var(--space-4);
  border-bottom: 2px solid var(--red);   /* 4.03:1 on bg-0, over the 3:1 non-text floor */
}
.chooser-head > :last-child,
.page-head > :last-child { margin-bottom: 0; }

.chooser-sub {
  margin: 0 0 var(--space-2);
  font-size: var(--text-body-public);
  color: var(--ink-2);             /* 11.42:1 on bg-0 */
}
.chooser-body {
  margin: 0;
  font-size: var(--text-lg);
  color: var(--ink-2);
  white-space: pre-line;
  overflow-wrap: anywhere;
}
/* The on-air line (F1). Printed only when the chooser CAN be live — one whose
   rows are hand-set targets rather than platforms says nothing at all rather
   than claiming to be a channel list. It is the last child of the head, so
   .chooser-head > :last-child already zeroes the bottom margin. */
.chooser-status {
  margin: var(--space-2) 0 0;
  font-size: var(--text-lg);
  color: var(--ink-2);
}

.chooser-empty { margin: 0; color: var(--ink-2); }
/* The interstitial's own second line for its empty state (migration 009) —
   the schedule, typically. pre-line as .chooser-body, for the same reason:
   an operator's line breaks are meant. */
.chooser-empty-body {
  margin: var(--space-2) 0 0;
  font-size: var(--text-lg);
  color: var(--ink-2);
  white-space: pre-line;
  overflow-wrap: anywhere;
}
/* The show's schedule (migration 012): the answer to "when do I come back?",
   so it takes the full ink rather than the secondary one the lines around it
   use. Under the status line on a chooser with rows, under the empty copy on
   one without. */
.chooser-schedule {
  margin: var(--space-2) 0 0;
  font-size: var(--text-lg);
  color: var(--ink-1);
  overflow-wrap: anywhere;
}

/* The empty chooser gets a way out (F3): the same row the 404 offers, so a
   chooser with nothing to give is not a dead end while home is published. */
.chooser .card-go { margin-top: var(--space-6); }


/* The 404: the same column, one sentence. */
.notice p {
  margin: 0;
  font-size: var(--text-body-public);
  color: var(--ink-2);
}

/* The share card page (public/unfurl.ejs): the same column, read by a
   link-preview fetcher that only wants the <head> and by a person who almost
   never arrives. Site line above the title, then the one choice: the target. */
.notice .card-site {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);             /* 7.65:1 on bg-0 */
}
.notice .card-go { margin-top: var(--space-6); }


/* ==========================================================================
   §4  THE CHOICES
   --------------------------------------------------------------------------
   THE control, and on the show's site the control IS the display face: its
   button rule sets `font-family: 'AmCap Eternal'`, so these rows take it
   too. 19px, because a condensed face at the body's 17 would read smaller
   than the copy around it.

   58px tall — the 44px phone floor plus a margin for a thumb on a moving bus
   — full width, one per row, 12px apart so two never share a miss. A surface
   one step above the page (bg-1, the show's own band colour) with a boundary
   that clears 3:1 on both of its sides: edge-ctl is 5.69:1 against bg-0
   outside and 4.47:1 against bg-1 inside. 6px corners, the show's own button
   radius, against the 10px the old sheet used.
   [T1: WCAG 2.2 — 2.5.8 Target Size (Minimum) (AA); 1.4.11 Non-text Contrast (AA)]

   role="list" on the <ul> is set in the template, because list-style:none
   below is what makes WebKit drop the list semantics otherwise.
   ========================================================================== */

.choices {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.choice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 58px;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: var(--display-tracking);
  color: var(--ink-1);             /* 16.48:1 on bg-1 */
  background: var(--bg-1);
  border: 1px solid var(--edge-ctl);
  border-radius: var(--radius-md);
  text-decoration: none;
  transition: background-color 0.12s ease, border-color 0.12s ease;
  /* iOS paints its own grey flash on a tap; :active below is the feedback. */
  -webkit-tap-highlight-color: transparent;
}
.choice:hover  { background: var(--bg-2); border-color: var(--edge-ctl-hover); }   /* label 14.16:1 */
.choice:active { background: var(--bg-3); }                                        /* label 12.63:1 */

.choice-label {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ON AIR — THE PRIMARY CONTROL, and the one place this sheet fills with red.
   The show's site draws its primary button as a solid #c23d3d block with a
   white display-face label, and a live row is the only row on either surface
   that is genuinely the primary action when it exists. It was a red OUTLINE
   before; an outline among five other outlines is a difference you have to
   look for, and this one should not need looking for.

   Three channels, none of them ever alone: the WORD "live now" comes from the
   template, so it is in the accessible name; the fill is the second; the dot
   is the third. Nothing pulses.
   White on this red is 5.21:1 — text-legal — which is the whole reason the
   fill can carry a label at all; the old neon could not and needed dark ink.
   The fill is 4.03:1 against the page, so the block reads as a control
   boundary in its own right and takes no border.
   [T1: WCAG 2.2 — 1.4.1 Use of Color (A); 1.4.3 (AA); 1.4.11 (AA)] */
.choice[data-live] {
  color: var(--ink-on-red);        /* 5.21:1 on --red */
  background: var(--red);
  border-color: var(--red);
}
.choice[data-live]:hover  { background: var(--red-hover); border-color: var(--red-hover); }   /* label 5.97:1 */
.choice[data-live]:active { background: var(--red-active); border-color: var(--red-active); } /* label 6.54:1 */
/* A red ring on a red fill would vanish; the live choice takes an ink ring
   (21.00:1 against the page it sits on). */
.choice[data-live]:focus-visible { outline-color: var(--ink-1); }

.choice-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;       /* the markup says "live now"; the sheet shouts it */
  color: var(--ink-on-red);
}
/* The dot is white on the red fill — a red dot on red is no dot at all. */
.choice-status::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ink-on-red);   /* 5.21:1 on --red */
}


/* ==========================================================================
   §5  DEFENSIVE (mirrors theme.css §1 and §5)
   --------------------------------------------------------------------------
   The one transition on .choice is a colour fade; reduced motion drops it
   with everything else. In forced-colors mode the UA replaces every colour,
   so the boundaries, the filled live row and the dot are restated in system
   colours or they vanish.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media (forced-colors: active) {
  .chooser-head, .page-head { border-bottom-color: Highlight; }
  .choice { border: 1px solid LinkText; }
  /* The fill is gone in forced colours — the UA paints its own — so the live
     row falls back to the boundary treatment it used to have, and the dot
     takes the accent it is allowed. */
  .choice[data-live] { border: 2px solid Highlight; }
  .choice-status::before { background: Highlight; }
  :focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
}


/* ==========================================================================
   §6  THE PAGE
   --------------------------------------------------------------------------
   The aggregate page: the front page at `/` and every other published page
   at its own slug (src/views/public/page.ejs). It reuses §4's rows whole —
   the 58px choice, the 12px gap, the filled live row, the focus ring — and
   adds only what it has that the chooser does not: a head with an optional
   avatar, an image card for the featured row, operator section headings, and
   the Follow pills.

   THE COLUMN STARTS AT THE TOP HERE, against §2's vertical centring. The
   chooser is a handful of rows and centres well; a page that scrolls must
   put its head — the show's name — on the first screen rather than pushing
   it under the fold. [UNSOURCED — practitioner judgment]

   THE CARD'S BOX HAS ITS HEIGHT BEFORE THE IMAGE DOES. `aspect-ratio` on an
   auto-height box reserves 16:9 from the first layout, so a hot-linked
   preview arriving late never shifts the rows under it and CLS stays 0 by
   construction. The CSP forbids an inline style, so this is the only way to
   size a box whose image dimensions are unknown at render time.
   [T1: MDN — CSS aspect-ratio, Baseline widely available]

   CONTRAST: pill text is ink-1 (16.48:1 on bg-1) and the pill boundary is
   edge-ctl (5.69:1 outside, 4.47:1 inside). Section headings are --red-ink
   and NOT --red: at 15px they are small text, where --red would measure
   4.03:1 and fail, and --red-ink measures 7.17:1. This is the split the
   token comment describes, and the section headings are where it bites.
   [T1: WCAG 2.2 — 1.4.3 Contrast (Minimum) (AA); 1.4.11 Non-text Contrast (AA)]
   ========================================================================== */

main.page { align-content: start; }

/* The one brand element, and the page's og:image. `width`/`height` are
   ATTRIBUTES in the markup — the CSP has no room for a style — so the circle
   is reserved before the bytes land. */
.page-avatar {
  display: block;
  width: 56px;
  height: 56px;
  margin-bottom: var(--space-3);
  border-radius: 50%;
  object-fit: cover;
  background: var(--bg-2);
}

.page-tagline {
  margin: 0;
  font-size: var(--text-body-public);
  color: var(--ink-2);             /* 11.42:1 on bg-0 */
  overflow-wrap: anywhere;
}

/* Two lists in a row — the live row above the operator's list, or one group
   after another — sit one row-gap apart, so the seam reads as the same
   rhythm as the rows themselves. */
.page .choices + .choices { margin-top: var(--space-3); }

/* THE CARD: the first link item, when its stored preview has a picture.
   Position is the highlight and the picture is recognition; there is no
   text-card variant, because a bigger row for the first item alone would be
   emphasis for its own sake. */
.choice-card {
  display: grid;
  padding: 0;
  overflow: hidden;
}
.choice-media {
  aspect-ratio: 16 / 9;
  width: 100%;
  background: var(--bg-2);
}
.choice-media img {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* A BROKEN card image (persona review F17) — hot-linked, so a featured
   video gone private is enough. A loaded image is a replaced element and
   never draws a pseudo-element; a broken one stops being replaced and does,
   so this panel exists only on failure and hides the browser's broken-image
   icon and frame behind the box's own ground. No script and no handler: the
   CSP allows neither inline, and the public head loads no script at all.
   The box keeps its 16:9 either way, so a slow image still costs no shift. */
.choice-media img::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--bg-2);
}
.choice-card .choice-label {
  padding: var(--space-4);
  font-size: 23px;
  line-height: 1.05;
}

/* Operator section headings and Follow share one register with §3's
   .card-site: the display face, uppercase, tracked out. They are the show's
   h2 — red, per its own heading rule — but at 15px they are SMALL text, so
   they take --red-ink and not --red. */
.page-heading,
.follow-heading {
  margin: var(--space-8) 0 var(--space-3);
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--red-ink);           /* 7.17:1 on bg-0 */
  overflow-wrap: anywhere;
}

/* THE FOLLOW PILLS. Text, not logos: a platform's name is as recognisable as
   its mark, needs no second sprite, and raises no trademark question. 44px is
   the phone floor the chooser's rows already apply. Square-cornered like
   everything else the show draws — a fully round pill was the one shape on
   these pages with no counterpart on its site.
   [T1: WCAG 2.2 — 2.5.8 Target Size (Minimum) (AA)] */
.follow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pill {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  color: var(--ink-1);             /* 16.48:1 on bg-1 */
  background: var(--bg-1);
  border: 1px solid var(--edge-ctl);
  border-radius: var(--radius-md);
  font: 400 17px / 1 var(--font-display);
  letter-spacing: var(--display-tracking);
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: background-color 0.12s ease, border-color 0.12s ease;
  -webkit-tap-highlight-color: transparent;
}
.pill:hover  { background: var(--bg-2); border-color: var(--edge-ctl-hover); }
.pill:active { background: var(--bg-3); }

/* Forced colours, restated AFTER the rules above rather than folded into §5:
   the UA replaces every colour, and a later `border: 1px solid var(--edge-ctl)`
   would simply win over an earlier system-colour one. The card's media box has
   no boundary of its own — the card's does — so it takes a seam that keeps the
   picture from bleeding into the label. */
@media (forced-colors: active) {
  .choice-media { border-bottom: 1px solid LinkText; }
  .pill { border: 1px solid LinkText; }
}
