/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * Table of contents
 *   1. Tokens         — design-token layer (#94)
 *   2. Reset & base   — element resets, html/body, base typography
 *   3. Primitives     — generic helpers (.visually-hidden, .h1--accent)
 *   4. Components     — re-usable UI blocks (nav, buttons, cards, ranking)
 *   5. Page overrides — selectors scoped to one page
 *   6. Motion         — @keyframes + reduced-motion fallbacks
 *
 * Why one file? Propshaft does not bundle CSS — every @import or partial
 * costs an extra HTTP request. With this stylesheet under 1k lines, the
 * single-file structure is faster than splitting.
 */

/* =====================================================================
 * Tokens
 * ===================================================================== */

:root {
  /* ── Color tokens — existing (do not rename or revalue; #94) ──────── */
  --bg: #faf9f7;
  --fg: #0a0a0a;
  --fg-secondary: rgba(10, 10, 10, 0.6);
  --fg-tertiary: rgba(10, 10, 10, 0.1);
  --accent: #c8102e;
  --rule: 1px solid rgba(10, 10, 10, 0.12);

  /* ── Color tokens — additive (#94) ────────────────────────────────── */
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --accent-strong: #a00d24;
  --accent-soft: rgba(200, 16, 46, 0.08);
  --on-accent: #ffffff;
  --success: #18794e;
  --focus-ring: rgba(200, 16, 46, 0.45);
  --scrim: rgba(10, 10, 10, 0.55);

  /* ── Type scale (1.2 ratio, #94) ──────────────────────────────────── */
  --text-xs:   0.694rem;
  --text-sm:   0.833rem;
  --text-base: 1rem;
  --text-lg:   1.2rem;
  --text-xl:   1.44rem;
  --text-2xl:  1.728rem;
  --text-3xl:  2.074rem;
  --text-4xl:  2.488rem;

  /* ── Spacing scale (4px base, #94) ────────────────────────────────── */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.25rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;

  /* ── Radius (#94) ─────────────────────────────────────────────────── */
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-full: 9999px;

  /* ── Elevation (#94) ──────────────────────────────────────────────── */
  --elevation-1: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 1px rgba(0, 0, 0, 0.04);
  --elevation-2: 0 4px 8px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.06);
  --elevation-3: 0 10px 20px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(0, 0, 0, 0.08);

  /* ── Motion (#94) ─────────────────────────────────────────────────── */
  --motion-fast: 120ms ease-out;
  --motion-base: 200ms ease-out;
  --motion-slow: 360ms cubic-bezier(0.16, 1, 0.3, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #141210;
    --fg: #dedad4;
    --fg-secondary: rgba(222, 218, 212, 0.7);
    --fg-tertiary: rgba(222, 218, 212, 0.22);
    --accent: #e8192c;
    --rule: 1px solid rgba(222, 218, 212, 0.1);

    /* ── Additive tokens — dark mode (#94) ──────────────────────────── */
    --surface:        #1c1a17;
    --surface-raised: #25221e;
    --accent-strong:  #ff3344;
    --accent-soft:    rgba(232, 25, 44, 0.12);
    /* --on-accent stays #ffffff (verified AA in dark mode) */
    --success:        #46a974;
    --focus-ring:     rgba(232, 25, 44, 0.55);
    --scrim:          rgba(0, 0, 0, 0.65);

    /* shadows pick up a darker tint in dark mode */
    --elevation-1: 0 1px 2px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.3);
    --elevation-2: 0 4px 8px rgba(0, 0, 0, 0.5), 0 2px 4px rgba(0, 0, 0, 0.35);
    --elevation-3: 0 10px 20px rgba(0, 0, 0, 0.55), 0 4px 8px rgba(0, 0, 0, 0.4);
  }
}

/* =====================================================================
 * Reset & base
 * ===================================================================== */

/* Ensure the HTML hidden attribute always wins over author display rules */
[hidden] { display: none !important; }

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

html, body {
  height: 100%;
}

body {
  font-family: 'DM Sans', -apple-system, sans-serif;
  background: var(--bg);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1.5rem 2rem 1.25rem;
  gap: 0;
}

h1 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(3rem, 8vw, 5.5rem);
  font-weight: 900;
  font-style: italic;
  letter-spacing: -0.03em;
  line-height: 0.92;
  font-variation-settings: 'opsz' 144, 'WONK' 1;
  max-width: 5ch;
}

/* =====================================================================
 * Primitives
 * ===================================================================== */

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

.h1--accent {
  color: var(--accent);
  max-width: none;
  text-align: center;
}

/* =====================================================================
 * Components
 * ===================================================================== */

/* ── Site Nav ──────────────────────────────────────────── */
.site-nav {
  display: flex;
  justify-content: center;
  gap: 2rem;
  margin-bottom: 1.5rem;
}

.nav-link {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--fg-secondary);
  position: relative;
  padding-top: 0.75rem;
}

.nav-link--active {
  color: var(--fg);
}

.nav-link--active::before {
  content: '◆';
  font-size: 0.35rem;
  color: var(--accent);
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}

/* Remove browser default form/button styling around Sign out */
.site-nav form {
  display: contents;
}

.site-nav form button {
  background: none;
  border: none;
  margin: 0;
  cursor: pointer;
}

/* ── Marquee Plate ─────────────────────────────────────── */
.site-header {
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  margin-top: 1.5rem;
}

.marquee-plate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-top: 2px solid var(--fg);
  border-bottom: 2px solid var(--fg);
  border-left: var(--rule);
  border-right: var(--rule);
  padding: 0.4rem 2rem;
  position: relative;
}

.marquee-plate::before,
.marquee-plate::after {
  content: '◆';
  font-size: 0.35rem;
  color: var(--fg-secondary);
  position: absolute;
}
.marquee-plate::before { left: 0.55rem; }
.marquee-plate::after  { right: 0.55rem; }

.marquee-plate__text {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 0.6875rem;
  font-weight: 700;
  font-style: italic;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  font-variation-settings: 'opsz' 9, 'WONK' 1;
}

/* ── .card — unified section container (#98) ──────────
   Collapses .hero, .rankings, .phase-links, .profile-section into a
   single block with modifiers for the small layout deltas. */
.card {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  max-width: 480px;
  margin-top: 2.5rem;
}

.card--hero {
  text-align: center;
  gap: 1rem;
  margin-top: 0.75rem;
}

.card--profile {
  margin-top: 2rem;
}

.tagline {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.8125rem;
  font-weight: 300;
  letter-spacing: 0.06em;
  color: var(--fg-secondary);
}

.comparison-count {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.8125rem;
  font-weight: 300;
  letter-spacing: 0.06em;
  color: var(--fg-secondary);
  margin-top: -0.5rem;
}

/* ── .btn — unified button component (#96) ────────────── */
/* Single base class + size + fill modifiers replaces .cta-button,
   .restart-button, .share-btn, .copy-btn, .submit-btn, .phase-link.
   `.share-network-btn` is a dropdown row, not a button — left as-is. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'DM Sans', sans-serif;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
}

/* Sizes */
.btn--md {
  min-height: 38px;
  font-size: 0.7rem;
  padding: 0.5rem 1.75rem;
}

.btn--sm {
  font-size: 0.65rem;
  padding: 0.45rem 0.9rem;
}

/* Fills */
.btn--solid {
  background: var(--fg);
  color: var(--bg);
  border-color: var(--fg);
}
.btn--solid:hover {
  background: transparent;
  color: var(--fg);
}

.btn--ghost {
  color: var(--fg);
  border-color: var(--fg-tertiary);
}
.btn--ghost:hover {
  color: var(--fg);
  border-color: var(--fg);
}

.btn--accent {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
  letter-spacing: 0.16em;
  padding-left: 2.25rem;
  padding-right: 2.25rem;
}
.btn--accent:hover {
  background: transparent;
  color: var(--accent);
}

[data-controller="share"] {
  position: relative;
  display: inline-block;
}

.share-dropdown {
  position: absolute;
  bottom: calc(100% + 0.25rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  min-width: 14rem;
  background: var(--bg);
  border: 1px solid var(--fg);
}

.share-network-btn {
  display: block;
  width: 100%;
  background: transparent;
  color: var(--fg);
  font-family: 'DM Sans', sans-serif;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.6rem 1rem;
  border: none;
  border-bottom: var(--rule);
  text-align: left;
  cursor: pointer;
  transition: background 0.15s;
}

.share-network-btn:hover {
  background: var(--fg-tertiary);
}

.share-network-btn:last-child {
  border-bottom: none;
}

/* ── Phase list (the chip-row inside .card) ─────────────── */
.phase-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
}

/* ── .eyebrow — unified small-uppercase label (#98) ─────
   Collapses .rankings-eyebrow, .section-heading, .template-name. */
.eyebrow {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  width: 100%;
  text-align: center;
}

.eyebrow--ruled {
  padding-bottom: 0.5rem;
  border-bottom: var(--rule);
}

.eyebrow--lead {
  /* For section headings that want breathing room below them. */
  margin-bottom: 1rem;
}

/* legacy .rankings-eyebrow keeps its own block so we can remove it
   cleanly — superseded by .eyebrow.eyebrow--ruled */

/* List of film rows inside a .card (was .rankings-list). */
.rankings-list {
  list-style: none;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.rankings-list--results {
  margin-top: 2rem;
}

/* ── .film-row — unified film row component (#97) ───────
   Replaces .ranking-item, .rank-item, .ranking-item--session.
   Border is driven through --rule / --fg-tertiary so the row stays
   visible in both color schemes (the hard-coded rgba(222,218,212,…)
   in the old .rank-item was a dark-mode literal that rendered nearly
   borderless in light mode). */
.film-row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  position: relative;
}

/* Read-only result row (homepage, /results, /community, /profile). */
.film-row--result {
  padding: 0.5rem 0 0.5rem 3rem;
  border-bottom: var(--rule);
  transition: opacity 400ms ease, transform 400ms ease, box-shadow 400ms ease;
}

.film-row--result.is-grabbed {
  opacity: 0.7;
  transform: scale(1.02) translateX(4px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 1;
}

/* Podium treatment — applied per-item for top-3 rows. Currently colors the
   rank number with the accent token; future visual polish can layer here. */
.film-row--result.film-row--podium .rank-num,
.film-row--result:first-child .rank-num {
  color: var(--accent);
}

/* Profile session row variant — sits inside .film-row--result and adds
   right-aligned date / fills the row. */
.film-row--session {
  justify-content: space-between;
  width: 100%;
}

.rank-num {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.5rem;
  font-weight: 800;
  font-style: italic;
  line-height: 1;
  width: 2.5rem;
  text-align: right;
  color: var(--fg-tertiary);
  letter-spacing: -0.04em;
  font-variation-settings: 'opsz' 72, 'WONK' 1;
  font-variant-numeric: tabular-nums;
  position: absolute;
  left: 0;
}

.rank-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1rem;
  font-weight: 600;
  font-style: italic;
  letter-spacing: -0.01em;
  line-height: 1.2;
  font-variation-settings: 'opsz' 36, 'WONK' 0;
}

.rankings-meta {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--fg-secondary);
  text-align: center;
  margin-top: -0.4rem;
}

.rankings-empty {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.8rem;
  color: var(--fg-secondary);
  text-align: center;
}

.rankings-link {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 150ms ease;
}

.rankings-link::after {
  content: ' →';
}

.rankings-link:hover {
  border-bottom-color: var(--accent);
}

/* ── .banner — unified alert block (#98) ────────────────
   Collapses .flash-alert (--toast) + .error-list (--error). */
.banner {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  padding: 0.75rem 1rem;
  color: var(--fg);
  border-left: 2px solid var(--fg-tertiary);
  background: transparent;
  list-style: none;
  margin: 0 0 1.5rem;
}

.banner--info {
  border-left-color: var(--fg-secondary);
}

.banner--error {
  border-left-color: var(--accent);
  background: var(--accent-soft);
}

.banner--success {
  border-left-color: var(--success);
  color: var(--success);
}

.banner--toast {
  position: fixed;
  top: 4rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--fg-tertiary);
  padding: 0.5rem 1.25rem;
  white-space: nowrap;
  pointer-events: none;
  animation: flash-in-out 4s ease forwards;
}

.banner li {
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg);
  padding: 0;
}

/* ── Rank Slot / Form ──────────────────────────────────── */
.rank-slot {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.rank-slot label {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.125rem;
  font-weight: 700;
  font-style: italic;
  font-variation-settings: 'opsz' 72, 'WONK' 1;
  color: var(--fg-secondary);
  min-width: 1.5rem;
  text-align: right;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.rank-form-footer {
  display: flex;
  justify-content: center;
  margin-top: 1.75rem;
}

.rank-year {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.5875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--fg-secondary);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
  align-self: center;
  padding: 0.2rem 0.45rem;
  border: 1px solid var(--fg-tertiary);
  flex-shrink: 0;
}

/* ── Rank: sortable list ──────────────────────────────── */
.rank-list {
  list-style-position: outside;
  padding-left: 2.75rem;
  margin: 1rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
  max-width: 480px;
}

.rank-list ::marker {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600;
  font-style: italic;
  font-variation-settings: 'opsz' 72, 'WONK' 1;
  color: var(--fg-secondary);
}

/* Draggable variant — used on /rank. Border is now driven through
   --fg-tertiary which auto-flips in dark mode (#97 fix). */
.film-row--draggable {
  align-items: center;
  gap: 0.85rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--fg-tertiary);
  background: transparent;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.2rem;
  font-weight: 500;
  font-style: italic;
  font-variation-settings: 'opsz' 36, 'WONK' 0;
  line-height: 1.25;
  color: var(--fg);
  cursor: grab;
  user-select: none;
  /* Prevent the browser from claiming touch gestures (scroll/zoom) over the
     draggable item — without this, SortableJS drag is hijacked by scroll on
     iOS Safari and Android Chrome. */
  touch-action: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.film-row--draggable:hover {
  border-color: var(--fg);
  background: var(--accent-soft);
}

.film-row--draggable:active { cursor: grabbing; }

.film-row--draggable:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.drag-handle {
  color: var(--fg-tertiary);
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
  pointer-events: none;
}

.film-row__title {
  flex: 1;
  min-width: 0;
}

.sortable-chosen { border-color: var(--accent); }
.sortable-ghost  { opacity: 0.35; background: rgba(232, 25, 44, 0.06); }

/* ── Drag feel (#100 / #119) ──────────────────────────────
   `.is-drag` styles the SortableJS forceFallback clone (the element
   that tracks the cursor). Other v2-only classes (.is-grabbed lift,
   .is-ghost insertion bar, .is-flashing reorder pulse, .focus-hint
   chip) were retired in #119 after Martin's staging testing showed
   the v2 polish felt worse than the simpler baseline. */
.is-drag {
  background: var(--surface-raised);
  border-color: var(--accent);
  box-shadow: var(--elevation-3);
  opacity: 0.95;
}

/* ── Task framing (#101) ──────────────────────────────────
   The visible directive + per-round sub-label that appears between
   the progress component and the draggable list. */
.rank-instruction {
  margin-top: var(--space-4);
  margin-bottom: var(--space-3);
}

.rank-instruction__task {
  font-family: 'Fraunces', Georgia, serif;
  font-size: var(--text-lg);
  font-weight: 600;
  font-style: italic;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--fg);
  font-variation-settings: 'opsz' 36, 'WONK' 0;
}

.rank-instruction__round {
  font-family: 'DM Sans', sans-serif;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin-top: var(--space-1);
  font-variant-numeric: tabular-nums;
}

/* ── .chip — small inline badge (#101) ──────────────────
   Year chip on film rows; reusable for any short uppercase tag. */
.chip {
  display: inline-flex;
  align-items: center;
  margin-left: auto;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--fg-tertiary);
  border-radius: var(--radius-full);
  font-family: 'DM Sans', sans-serif;
  font-size: 0.5875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--fg-secondary);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  background: transparent;
}

.chip--year {
  /* Years on the draggable rows live between the title and the (future)
     thumbnail slot. Tabular numerals keep the chip widths aligned. */
}

.chip--match {
  /* Divergence-vs-community badge on profile session rows (#39).
     Tinted with the accent so it reads as a friendly "agreement %"
     rather than a neutral year. */
  color: var(--accent);
  border-color: var(--accent-soft);
  background: var(--accent-soft);
  margin-left: var(--space-2);
  margin-right: var(--space-2);
}

/* ── Compare (#66) — head-to-head two-column layout ─────
   Stacks vertically on narrow screens; side-by-side from 600px up. */
.compare {
  width: 100%;
  max-width: 720px;
  margin: var(--space-5) auto 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

@media (min-width: 600px) {
  .compare {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
  }
}

.compare__column {
  min-width: 0;
}

/* ── Results celebration (#104) ──────────────────────────
   Top-3 podium + eyebrow stat + staged reveal + confetti. Owner-only
   pieces are gated in the partial; CSS is always present (cheap). */

.results-stat {
  /* Promotes the comparisons/rounds line from .comparison-count to a
     confident eyebrow — same .eyebrow base class, just visually punchier. */
  color: var(--fg);
  margin-top: var(--space-1);
  letter-spacing: 0.14em;
}

.celebrate {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space-2);
  width: 100%;
  max-width: 480px;
  margin: var(--space-6) auto var(--space-5);
}

.celebrate__slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: var(--space-3) var(--space-2);
  border: 1px solid var(--fg-tertiary);
  background: var(--surface);
  text-align: center;
  min-height: 110px;
  position: relative;
}

.celebrate__slot--gold {
  border-color: var(--accent);
  background: var(--accent-soft);
  min-height: 140px;
  order: 2;
}

.celebrate__slot--silver { order: 1; }
.celebrate__slot--bronze { order: 3; }

.celebrate__rank {
  font-family: 'Fraunces', Georgia, serif;
  font-size: var(--text-2xl);
  font-weight: 800;
  font-style: italic;
  color: var(--fg-tertiary);
  font-variation-settings: 'opsz' 72, 'WONK' 1;
}

.celebrate__slot--gold .celebrate__rank {
  color: var(--accent);
}

.celebrate__title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: var(--text-sm);
  font-weight: 600;
  font-style: italic;
  color: var(--fg);
  margin-top: var(--space-2);
  line-height: 1.2;
  font-variation-settings: 'opsz' 36, 'WONK' 0;
}

/* Staged reveal — added by celebration_controller on owner pages only. */
.celebrate.is-revealing .celebrate__slot {
  opacity: 0;
  transform: translateY(8px);
  animation: celebrate-rise 360ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.celebrate.is-revealing .celebrate__slot--bronze { animation-delay:  80ms; }
.celebrate.is-revealing .celebrate__slot--silver { animation-delay: 220ms; }
.celebrate.is-revealing .celebrate__slot--gold   { animation-delay: 360ms; }

.celebrate__loop-cta {
  /* "Rank another saga →" — a `.btn--solid` with a little extra emphasis. */
  margin-top: var(--space-3);
}

/* Confetti — injected by the controller into .results-body when owner. */
.confetti-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 100;
}

.confetti-piece {
  position: absolute;
  top: -10px;
  width: 8px;
  height: 12px;
  border-radius: 1px;
  opacity: 0.95;
  animation: confetti-fall 1300ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.results-body {
  /* Need a positioning context so the confetti layer's `inset: 0` works. */
  position: relative;
}

@media (prefers-reduced-motion: reduce) {
  .celebrate.is-revealing .celebrate__slot {
    opacity: 1;
    transform: none;
    animation: none;
  }
  .confetti-piece {
    animation: none;
    display: none;
  }
}

/* ── Onboarding banner (#103) ─────────────────────────────
   Inline first-run hint shown on /rank batch 1, gated by onboarding_v1.
   Dismissed via the onboarding Stimulus controller which writes a
   localStorage flag. Reuses .banner.banner--info from #98 for the base
   look; the .onboarding-banner modifier adds layout + a close button. */
.onboarding-banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.onboarding-banner__copy {
  flex: 1;
  font-family: 'DM Sans', sans-serif;
  font-size: var(--text-sm);
  line-height: 1.45;
  letter-spacing: 0;
  text-transform: none;
  color: var(--fg);
}

.onboarding-banner__copy strong {
  display: block;
  margin-bottom: var(--space-1);
  color: var(--fg);
  letter-spacing: 0.02em;
}

.onboarding-banner__close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--fg-tertiary);
  border-radius: var(--radius-full);
  color: var(--fg-secondary);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: color var(--motion-fast), border-color var(--motion-fast);
}

.onboarding-banner__close:hover {
  color: var(--fg);
  border-color: var(--fg);
}

.onboarding-banner__close:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* ── Completion micro-moment (#102) ──────────────────────
   Replaces the form in-frame for ~600ms before the redirect to /results.
   Centred copy + a full progress bar (all segments lit). */
.completion-moment {
  margin-top: var(--space-6);
  margin-bottom: var(--space-6);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  animation: completion-rise var(--motion-slow) both;
}

.completion-moment__title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: var(--text-lg);
  font-weight: 700;
  font-style: italic;
  color: var(--accent);
  letter-spacing: -0.01em;
  font-variation-settings: 'opsz' 36, 'WONK' 1;
  text-transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .completion-moment {
    animation: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* .is-grabbed is still used by the homepage demo-ranking animation
     to mimic a drag lift — under reduced motion, drop the scale. */
  .is-grabbed {
    transform: none;
    transition: none;
  }
  /* .is-drag is SortableJS's floating clone — it NEEDS the inline
     transform translate3d() that SortableJS sets each frame to follow
     the cursor. Only suppress the entry transition, not transform. */
  .is-drag {
    transition: none;
  }
}

/* ── Ranking Progress ─────────────────────────────────── */
.ranking-progress {
  width: 100%;
  max-width: 480px;
  margin-top: 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.ranking-progress__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.ranking-progress__count {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  font-variant-numeric: tabular-nums;
}

.ranking-progress__pct {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 0.875rem;
  font-weight: 700;
  font-style: italic;
  color: var(--fg-secondary);
  font-variant-numeric: tabular-nums;
  font-variation-settings: 'opsz' 36, 'WONK' 1;
}

.ranking-progress__bar {
  width: 100%;
  height: 3px;
  background: var(--fg-tertiary);
  overflow: hidden;
}

.ranking-progress__fill {
  height: 100%;
  background: var(--accent);
  transition: width 0.4s ease;
  min-width: 0;
}

/* ── .progress — segmented batch progress (#99) ─────────
   Flag-gated replacement for .ranking-progress on /rank. */
.progress {
  width: 100%;
  max-width: 480px;
  margin-top: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.progress__segments {
  display: flex;
  gap: var(--space-2);
  width: 100%;
}

.progress__segment {
  flex: 1;
  height: 6px;
  border-radius: var(--radius-full);
  background: transparent;
  border: 1px solid var(--fg-tertiary);
  transition: background var(--motion-base), border-color var(--motion-base);
}

.progress__segment--done {
  background: var(--accent);
  border-color: var(--accent);
}

.progress__segment--current {
  background: var(--accent);
  border-color: var(--accent);
  animation: progress-pulse 1.6s ease-in-out infinite;
}

.progress__segment--upcoming {
  background: transparent;
  border-color: var(--fg-tertiary);
}

.progress__label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: 'DM Sans', sans-serif;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  font-variant-numeric: tabular-nums;
}

/* Issue #119 staging follow-up — the current batch number gets a
   larger, accent-coloured treatment so it reads at a glance from the
   small uppercase "BATCH … / ~5" surround. */
.progress__label-number {
  display: inline-block;
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0;
  margin: 0 0.15em;
  vertical-align: baseline;
}

.progress__anticipation {
  color: var(--accent);
  font-style: italic;
  font-family: 'Fraunces', Georgia, serif;
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  text-transform: none;
  font-variation-settings: 'opsz' 36, 'WONK' 1;
}

@media (prefers-reduced-motion: reduce) {
  .progress__segment--current {
    animation: none;
  }
}

/* ─── Auth Forms ─────────────────────────────────────────── */

.auth-form {
  width: 100%;
  max-width: 380px;
  margin: 0 auto;
  padding: 0 1.5rem;
}

.auth-heading {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: clamp(2.5rem, 8vw, 3.75rem);
  line-height: 1.1;
  padding-bottom: 0.2em;
  overflow: visible;
  margin-bottom: 2rem;
}

/* ── .field — unified form-field (#98) ─────────────────
   Replaces .form-field. Focus state moves to 2px --focus-ring
   underline + a faint --accent-soft fill. */
.field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin-bottom: 1.25rem;
}

.field label {
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  font-family: 'DM Sans', sans-serif;
  font-weight: 500;
}

.field input {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--fg-secondary);
  padding: 0.5rem 0;
  color: var(--fg);
  font-size: 1rem;
  font-family: 'DM Sans', sans-serif;
  outline: none;
  width: 100%;
  transition: border-color 0.2s, background 0.2s;
}

.field input:focus {
  border-bottom: 2px solid var(--focus-ring);
  background: var(--accent-soft);
}

/* Issue #65 — hint copy under handle field. */
.field__hint {
  font-family: 'DM Sans', sans-serif;
  font-size: var(--text-xs);
  color: var(--fg-secondary);
  line-height: 1.4;
  margin-top: var(--space-1);
  letter-spacing: 0;
  text-transform: none;
}
.field__hint code {
  font-family: 'DM Sans', sans-serif;
  background: var(--accent-soft);
  padding: 0 var(--space-1);
}

/* Checkbox-style field — overrides the default vertical layout */
.field--checkbox label {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: var(--space-2);
  font-family: 'DM Sans', sans-serif;
  font-size: var(--text-sm);
  color: var(--fg);
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
}
.field--checkbox input[type="checkbox"] {
  width: auto;
  margin: 0;
  margin-top: 0.2rem;
}

.form-submit {
  margin-top: 1.75rem;
  text-align: center;
}

.form-submit .btn {
  width: 100%;
}

.auth-alt {
  margin-top: 1.5rem;
  font-size: 0.875rem;
  color: var(--fg-secondary);
  text-align: center;
}

.auth-alt__link {
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 1px;
  transition: color 0.15s;
}

.auth-alt__link:hover {
  color: var(--accent);
}

/* ── .staging-debug — dev.mcuranks.com only (#119) ──────
   Small fixed bar at the bottom-right of every staging page showing
   the deployed git SHA + ranking-engine config overrides so we don't
   chase browser-cache ghosts again. Never rendered in production. */
.staging-debug {
  position: fixed;
  bottom: var(--space-2);
  right: var(--space-2);
  z-index: 9999;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  max-width: calc(100vw - var(--space-4));
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-md);
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(8px);
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.92);
  /* Container ignores pointer events so it doesn't intercept clicks on
     content behind the bar's gaps. Pills below re-enable so the SHA is
     selectable / clickable. */
  pointer-events: none;
}

.staging-debug__pill {
  display: inline-block;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.12);
  white-space: nowrap;
  /* Re-enable interaction so the SHA is selectable + the link is clickable. */
  pointer-events: auto;
  user-select: text;
  cursor: text;
}

.staging-debug__pill--link {
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}

.staging-debug__pill--link:hover {
  background: rgba(255, 255, 255, 0.18);
  text-decoration: underline;
}

/* Issue #116 — relaxed-completion arm: green = on (test), muted = off (control)
   so the current arm is unmistakable at a glance during validation. */
.staging-debug__pill--on {
  background: rgba(70, 169, 116, 0.30);
  border-color: rgba(70, 169, 116, 0.55);
  font-weight: 600;
}

.staging-debug__pill--off {
  opacity: 0.65;
}

/* =====================================================================
 * Page overrides
 * ===================================================================== */

/* ── Results Page ──────────────────────────────────────── */
.results-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  margin-top: 2rem;
}

/* ── Profile Page ──────────────────────────────────────── */
/* The profile section heading uses the unified .eyebrow.eyebrow--ruled
   pair from the Components section. The .session-date is the only
   profile-specific style left here. */

.session-date {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.75rem;
  font-weight: 300;
  color: var(--fg-secondary);
  letter-spacing: 0.04em;
  margin-left: auto;
  padding-right: 1rem;
}

.empty-state {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.875rem;
  color: var(--fg-secondary);
  text-align: center;
}

/* =====================================================================
 * Motion
 * ===================================================================== */

@keyframes flash-in-out {
  0%   { opacity: 0; transform: translateX(-50%) translateY(-6px); }
  12%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  72%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Pulsing dot on the current batch segment (#99). */
@keyframes progress-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

/* Completion-moment entry (#102). */
@keyframes completion-rise {
  0%   { opacity: 0; transform: translateY(6px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* Podium slot rises into place — staged via per-slot animation-delay (#104). */
@keyframes celebrate-rise {
  0%   { opacity: 0; transform: translateY(12px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* Confetti drop (#104). --spin is set per-piece by the controller. */
@keyframes confetti-fall {
  0%   { transform: translateY(0)              rotate(0deg); opacity: 1; }
  100% { transform: translateY(480px) rotate(var(--spin, 540deg)); opacity: 0; }
}

/* ─────────────────────────────────────────────────────────────────
   Climbers & Fallers (#67) — week-over-week movement on /community.
   Two-column layout, collapses to stacked on narrow viewports.
   ───────────────────────────────────────────────────────────────── */
.cf-card {
  margin-top: 1.25rem;
}

.cf-heading {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.4rem;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.02em;
  margin: 0 0 0.25rem;
  text-align: center;
  color: var(--fg);
}

.cf-subhead {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--fg-secondary);
  text-align: center;
  margin: 0 0 1.25rem;
}

.cf-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
}

@media (max-width: 540px) {
  .cf-grid {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  /* Issue #117 — pin the Submit button to the bottom of the viewport on small
     phones so it never scrolls off the bottom of the fold. Sticky keeps it in
     its own scroll container (no overlap with content above), and the
     safe-area inset clears the iOS home indicator. The solid background hides
     list rows scrolling underneath; the hairline separates it from them. */
  .rank-form-footer {
    position: sticky;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 8px);
    z-index: 5;
    margin-top: 1rem;
    padding: 0.75rem 0 calc(env(safe-area-inset-bottom, 0px) + 0.25rem);
    background: var(--bg);
    border-top: 1px solid var(--rule);
  }
}

.cf-col-heading {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin: 0 0 0.6rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.cf-arrow {
  font-size: 0.85rem;
  line-height: 1;
}

.cf-arrow--up   { color: var(--accent); }
.cf-arrow--down { color: var(--fg-tertiary); }

.cf-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.cf-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--border-faint, rgba(255, 255, 255, 0.06));
}

.cf-row:last-child {
  border-bottom: none;
}

.cf-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1rem;
  font-weight: 600;
  font-style: italic;
  letter-spacing: -0.01em;
  color: var(--fg);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cf-delta {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.8rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.cf-delta--up   { color: var(--accent); }
.cf-delta--down { color: var(--fg-secondary); }

/* ─────────────────────────────────────────────────────────────────
   Reactions (#69) — emoji bar on /r/:token. Authenticated users
   click to toggle; anonymous users see a read-only bar + sign-in CTA.
   ───────────────────────────────────────────────────────────────── */
.reactions {
  margin-top: 1.25rem;
  text-align: center;
}

.reactions__bar {
  list-style: none;
  padding: 0;
  margin: 0;
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: center;
}

.reactions__item {
  margin: 0;
}

/* button_to wraps each button in a <form>; reset the form's defaults. */
.reactions__item form.button_to {
  display: inline;
  margin: 0;
  padding: 0;
}

.reactions__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-full, 999px);
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--fg);
  font-family: 'DM Sans', sans-serif;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--motion-fast, 120ms), border-color var(--motion-fast, 120ms), transform var(--motion-fast, 120ms);
}

.reactions__btn:hover {
  background: var(--surface-raised, rgba(255, 255, 255, 0.04));
  border-color: var(--fg-tertiary);
}

.reactions__btn:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.reactions__btn.is-active {
  background: var(--accent-soft, rgba(229, 62, 62, 0.12));
  border-color: var(--accent);
  color: var(--accent-strong, var(--accent));
}

.reactions__btn--readonly {
  cursor: default;
}

.reactions__btn--readonly:hover {
  background: transparent;
  border-color: var(--rule);
}

.reactions__emoji {
  font-size: 1.05rem;
  line-height: 1;
}

.reactions__count {
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--fg-secondary);
}

.reactions__count.is-zero {
  opacity: 0.5;
}

.reactions__cta {
  margin: 0.75rem 0 0;
  font-family: 'DM Sans', sans-serif;
  font-size: 0.85rem;
  color: var(--fg-secondary);
}

.reactions__signin-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .reactions__btn { transition: none; }
}

/* ─────────────────────────────────────────────────────────────────
   Leaderboard (#52) — most loved, most controversial, your match.
   Each section is a .leaderboard-card with a shared heading style.
   ───────────────────────────────────────────────────────────────── */
.leaderboard-card {
  margin-top: 1.25rem;
}

.leaderboard-card__heading {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.4rem;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.02em;
  margin: 0 0 0.25rem;
  color: var(--fg);
}

.leaderboard-card__subhead {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.85rem;
  color: var(--fg-secondary);
  margin: 0 0 1rem;
}

.leaderboard-meta {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.75rem;
  color: var(--fg-secondary);
  margin-left: auto;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* "Your community match" — single big number with a caption. */
.leaderboard-you {
  text-align: center;
}

.leaderboard-you__score {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
}

.leaderboard-you__pct {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 2.75rem;
  font-weight: 800;
  font-style: italic;
  letter-spacing: -0.04em;
  color: var(--accent);
  line-height: 1;
}

.leaderboard-you__caption {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.85rem;
  color: var(--fg-secondary);
}

/* ─────────────────────────────────────────────────────────────────
   Template stats (#53) — /templates/:slug/stats. Headline numbers
   grid + community top 3 + CTA.
   ───────────────────────────────────────────────────────────────── */
.stats-card {
  margin-top: 1.25rem;
}

.stats-card__heading {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.4rem;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
  color: var(--fg);
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1.25rem;
  margin: 0;
}

.stats-grid__item {
  margin: 0;
  text-align: center;
}

.stats-grid__label {
  font-family: 'DM Sans', sans-serif;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin: 0 0 0.3rem;
}

.stats-grid__value {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.75rem;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.02em;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
  margin: 0;
  line-height: 1.1;
}

/* Franchise eyebrow on the homepage — sits above each grouped set of
   template buttons (#71). Spacing only; visual style inherits from
   .eyebrow / .eyebrow--ruled. */
.franchise-eyebrow {
  margin-top: 1.25rem;
}

.franchise-eyebrow:first-child {
  margin-top: 0.75rem;
}
