/*
 * Public site presentation — consumes the semantic token layer only
 * (design/tokens.css; never the private --rb-* palette, with one
 * sanctioned exception: the gold ramp motif gradient, which is a
 * brand primitive, not a component color).
 *
 * Volume map (docs/brand/brand.md): data and evidence stay quiet;
 * the marquee is the page's one Loudest moment; bracket frames on
 * card-of-matches data; 404 is loud with humor.
 */

/* --- layout shell ----------------------------------------------------- */

body {
  max-width: 64rem;
  margin: 0 auto;
  /* Fluid page rhythm: inline gutter and bottom space flex with the viewport
   * (frontend PRD intrinsic-first). The min holds comfortable at 360px. */
  padding: 0 var(--space-fluid-md) var(--space-fluid-xl);
  /* Body copy on the fluid type scale — no breakpoint jump phone→desktop. */
  font-size: var(--font-fluid-md);
}

main {
  display: block;
}

/* Intrinsic-first responsive media: images never exceed their column, so no
 * public page type overflows horizontally at 360px regardless of the source
 * asset's intrinsic width (frontend PRD: no horizontal overflow at 360px).
 * The 404 brand plate keeps its own rule below. */
main img {
  max-width: 100%;
  height: auto;
}

/* The Commons primary image (media_assets figure) sits quietly in its column. */
figure.commons-image {
  margin: var(--space-fluid-md) 0;
  max-width: 100%;
}

section {
  margin: var(--space-fluid-lg) 0;
}

/* --- header chrome: logo + ever-present search (public-site PRD) ------ */

header.site {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
  padding: var(--space-3) 0;
  border-bottom: 2px solid var(--color-accent); /* hard rule, gold */
  margin-bottom: var(--space-5);
}

header.site .site-logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

header.site .site-logo svg {
  height: 2.25rem;
  width: auto;
  display: block;
}

header.site form[role="search"] {
  display: flex;
  gap: var(--space-2);
  flex: 1 1 16rem;
}

header.site input[type="search"] {
  flex: 1;
  font: inherit;
  color: var(--color-fg);
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm); /* bracket-board, not pill */
  padding: var(--space-2) var(--space-3);
}

header.site button[type="submit"] {
  font-family: var(--font-display);
  font-weight: var(--font-weight-bold);
  font-size: var(--font-size-md);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--color-accent-fg);
  background: var(--color-accent);
  border: 0;
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
}

/* --- marquee: the one Loudest moment ---------------------------------- */

.marquee {
  margin: var(--space-fluid-lg) 0 var(--space-fluid-md);
}

.marquee-title {
  font-family: var(--font-display);
  font-weight: 800;
  /* The Loudest moment on the fluid type scale (semantic token, not a raw
   * clamp): flexes smoothly 360px→desktop with no breakpoint jump. */
  font-size: var(--font-fluid-marquee);
  line-height: var(--line-height-tight);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  margin: 0 0 var(--space-2);
  /* Gold ramp — reserved for the marquee (brand motif). */
  background: linear-gradient(
    to bottom,
    var(--rb-gold-300),
    var(--rb-gold-500) 55%,
    var(--rb-gold-700)
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: var(--rb-gold-700); /* fallback when background-clip:text unsupported */
  -webkit-text-fill-color: transparent;
  padding-bottom: var(--space-2);
  border-bottom: 2px solid var(--color-accent); /* hard rule */
  display: block;
}

.marquee-kicker {
  font-size: var(--font-size-sm);
  color: var(--color-fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 var(--space-1);
}

/* --- quiet data (tables, attributes, prose) --------------------------- */

h2 {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
  border-bottom: 1px solid var(--color-border);
  padding-bottom: var(--space-1);
}

.grain {
  display: inline-block;
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  color: var(--color-fg-muted);
  padding: 0.1rem var(--space-2);
  border-radius: var(--radius-sm);
}

.attr {
  margin: var(--space-2) 0;
}

.attr .label {
  font-weight: var(--font-weight-medium);
}

table {
  border-collapse: collapse;
  width: 100%;
  /* Bracket frame: square corners on card-of-matches data. */
  border: 1px solid var(--color-border);
}

td,
th {
  text-align: left;
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

thead th {
  font-size: var(--font-size-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--color-bg-elevated);
}

nav.pagination {
  display: flex;
  gap: var(--space-3);
  font-size: var(--font-size-sm);
  margin-top: var(--space-2);
}

/* --- match history: container-first reshape (issue 0043) --------------- *
 * The most data-dense block on the site. Its wrapper is a query container,
 * so the table reshapes to its OWN width — honest in the workshop and in any
 * page slot, never to the viewport (design.md: container queries for
 * components). Wide containers get the natural full table (the base `table`
 * rules above); narrow ones (< the rb-cq-match-stack threshold) stack each
 * match into a labelled card so there is no horizontal scroll at 360px.
 *
 * Baseline tier: container queries are Newly Available. Their absence
 * degrades gracefully — without @container support the block stays the plain
 * full table, which already fits at 360px via the fluid floors — so no
 * @supports guard is needed (design.md Baseline policy: guard only when
 * absence breaks layout or meaning). */
.match-history {
  /* Lazily-introduced named container width — the first component to need one
   * (design.md: breakpoint tokens added lazily, at the component). */
  --rb-cq-match-stack: 28rem;
  container-type: inline-size;
  container-name: match-history;
}

@container match-history (max-width: 28rem) {
  /* Stacked per-match layout. Restyling `display` strips the elements'
   * implicit table semantics, so the markup pins role="table/row/cell"
   * explicitly (see _match_history.html) to keep both shapes a table for
   * assistive tech. */
  .match-history table,
  .match-history thead,
  .match-history tbody,
  .match-history tr,
  .match-history td {
    display: block;
    width: 100%;
  }

  /* The visual header row is redundant once each cell self-labels; hide it
   * accessibly (it keeps its columnheader role for the a11y tree). */
  .match-history thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .match-history tr {
    border: 1px solid var(--color-border); /* bracket frame per match card */
    margin-bottom: var(--space-2);
    padding: var(--space-1) 0;
  }

  .match-history td {
    border-bottom: 0;
    padding: var(--space-1) var(--space-2);
    /* Label each stacked cell from its column header (data-label in markup);
     * CSS-generated, so no inline style — CSP-safe. */
    display: flex;
    gap: var(--space-2);
    overflow-wrap: anywhere; /* long Persona names never overflow at 360px */
  }

  .match-history td::before {
    content: attr(data-label) ":";
    font-weight: var(--font-weight-medium);
    color: var(--color-fg-muted);
    flex: 0 0 8rem;
  }
}

/* --- evidence UI: always quiet (voice.md register 1) ------------------ */

.conflict {
  color: var(--color-danger);
  font-weight: var(--font-weight-medium);
}

.claims-link {
  font-size: var(--font-size-sm);
  color: var(--color-fg-muted);
}

footer.citations {
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-6);
  padding-top: var(--space-3);
  font-size: var(--font-size-sm);
}

footer.citations h2 {
  border: 0;
  font-size: var(--font-size-md);
}

/* --- site footer ------------------------------------------------------- */

footer.site {
  margin-top: var(--space-7);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  font-size: var(--font-size-sm);
  color: var(--color-fg-muted);
}

/* --- 404 / dead ends: loud, with humor --------------------------------- */

.dead-end {
  text-align: center;
  padding: var(--space-7) var(--space-4);
}

.dead-end .marquee-title {
  display: inline-block;
  border-bottom: 0;
  font-size: clamp(2.5rem, 9vw, 4.5rem);
}

.dead-end img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  margin-top: var(--space-5);
  box-shadow: var(--shadow-md);
}

.dead-end p {
  font-size: var(--font-size-lg);
}

/* --- a11y helpers ------------------------------------------------------ */

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

/* --- cross-document view transitions (issue 0045) --------------------- *
 * Sanctioned navigation polish: pure-CSS, no JS, no router. The CSS opt-in
 * makes same-origin MPA navigations animate; browsers without support just
 * navigate instantly and unbroken (design.md Baseline policy: single-engine
 * tier, harmless when absent). Timing rides the duration/easing tokens, so
 * the reduced-motion kill switch in tokens.css (which zeroes --duration-*)
 * collapses every transition to an instant cut with no per-rule diligence.
 *
 * view-transition-name convention (design.md): one shared name per
 * cross-page-persistent element, kebab-case, prefixed `vt-`. A name must be
 * unique among rendered elements on a page; duplicates simply disable that
 * pair's morph (graceful) rather than break navigation. Reserved names:
 *   vt-hero-name  — an entity's name, morphing from a search-result row into
 *                   the destination page's marquee title. */
@view-transition {
  navigation: auto;
}

/* Default crossfade for the old/new page roots, on the motion tokens. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--duration-base);
  animation-timing-function: var(--ease-standard);
}

/* Named hero-morph: the entity name travels between pages. The marquee title
 * is the shared landing element on every entity/search page. The search page
 * tags its single best-match result with the same name (see below) so the row
 * morphs into the marquee on navigation. */
.marquee-title {
  view-transition-name: vt-hero-name;
}

/* The hero element's own morph uses the emphasized easing and slow token —
 * a touch more presence than the page crossfade, still token-bound. */
::view-transition-old(vt-hero-name),
::view-transition-new(vt-hero-name) {
  animation-duration: var(--duration-slow);
  animation-timing-function: var(--ease-emphasized);
}

/* Source side: the first search result is the likely hero. Naming only the
 * first keeps the name unique on the page (a list of results would otherwise
 * collide and disable the morph). When that result is the one followed, its
 * name morphs into the destination marquee; otherwise the page still
 * crossfades. No JS, no markup change — pure selector. */
.results li[data-testid="search-result"]:first-child a {
  view-transition-name: vt-hero-name;
}
