/* ============================================================================
   GAMESWA — /unity-cup, page-local styles
   Session D · 2026-08-11
   ----------------------------------------------------------------------------
   Loads after tokens/base/components/chrome. Everything here composes the
   shared tokens. NO HEX APPEARS IN THIS FILE, by rule and on purpose.

   Why page-local rather than components.css: the profile card, the RUSH radar
   and the headline stat exist on this page only, and four sessions editing one
   shared stylesheet in parallel is how a merge conflict eats a night. If a
   second page ever needs one of these, promote it into components.css then and
   delete it from here.

   Built at 390px first. Every min-width query below is the adaptation up.
   ========================================================================== */

/* ── HERO ────────────────────────────────────────────────────────────────*/
.ucc-hero__sub { margin-top: var(--gw-s-5); }

/* Provenance line. Small, quiet, and the reason the numbers below are worth
   reading at all. Hidden until the data file confirms it. */
.ucc-provenance {
  margin-top: var(--gw-s-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gw-s-2) var(--gw-s-3);
}
.ucc-provenance::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 1px;
  background: var(--gw-punct-fill);
  flex: none;
}

/* ── HEADLINE STAT ───────────────────────────────────────────────────────
   The watch rate is the one idea of the numbers section. Everything else in
   the grid supports it, so it gets the size and they do not.               */
.ucc-headline {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  column-gap: var(--gw-s-1);
  margin-bottom: var(--gw-s-8);
}
.ucc-headline__value,
.ucc-headline__unit {
  font-family: var(--gw-font-display);
  font-weight: 900;
  line-height: 0.85;
  letter-spacing: var(--gw-track-display);
  color: var(--gw-text);
  font-variant-numeric: tabular-nums;
}
.ucc-headline__value { font-size: var(--gw-t-hero); }
.ucc-headline__unit  { font-size: var(--gw-t-xxl); color: var(--gw-punct); align-self: start; }
.ucc-headline__label {
  grid-column: 1 / -1;
  max-width: 22ch;
  margin: var(--gw-s-4) 0 0;
  font-family: var(--gw-font-display);
  font-weight: 700;
  font-size: var(--gw-t-lg);
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--gw-text);
}
.ucc-headline__note {
  grid-column: 1 / -1;
  margin: var(--gw-s-3) 0 0;
}

/* ── STAT GRID ───────────────────────────────────────────────────────────
   Two up at 390px. A stat that is not verified is never in this list, so the
   grid is naturally ragged and that is correct, not a layout bug.          */
.ucc-stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gw-s-6) var(--gw-s-5);
  border-top: 1px solid var(--gw-rule);
  padding-top: var(--gw-s-6);
}
/* ── RESERVING THE DATA BLOCK ────────────────────────────────────────────
   Session F, 2026-08-11. Measured, not guessed. Do not delete without
   re-measuring CLS at 200ms latency.

   Every number on this page arrives from content/ucc-data.json AFTER the
   document has painted, which is the correct design: no unverified number is
   ever in the markup. But nothing reserved the space it lands in, so on a
   real connection the headline and the eight-stat grid appeared out of
   nothing and shoved the rest of the page down. Measured on this branch at
   390px, 200ms latency, 4x CPU: CLS 0.281, against a 0.1 "good" threshold and
   a hard "zero layout shift" rule in CLAUDE.md. It is invisible on a fast
   local server, which is why it survived four sessions. It is worst on
   exactly the connection our audience is on: mobile data, at a turf.

   `hidden` is the wrong tool even once it works, because it removes the box
   and the content still has nowhere to land. `data-ucc-pending` keeps the box
   in layout and only suppresses the paint, so the block occupies its final
   size from the first frame and the numbers appear without moving anything.

   The stat grid is empty until JS fills it, so it has no natural height to
   hold. These are the measured rendered heights of the eight verified stats,
   rounded up:
       <640px   2 columns, 4 rows   457.2px  ->  458px
       >=640px  3 columns, 3 rows   310.4px  ->  311px
       >=900px  4 columns, 2 rows   245.8px  ->  268px  (1440 wraps to 267.8)
   Reserving a little more than needed costs whitespace. Reserving less costs
   a shift. If a stat is ever un-verified the grid gets shorter and leaves a
   gap, which is the right trade: the rule is that we never render a number we
   cannot defend, not that we never leave space. */
.ucc-headline[data-ucc-pending],
.ucc-stats[data-ucc-pending] { visibility: hidden; }

.ucc-stats[data-ucc-pending] { min-height: 458px; }

/* Once the render pass has run and the reservation is released, a grid that
   ended up with nothing in it still collapses. Data unreachable, or every
   stat un-verified, must not leave a permanent empty slab. */
.ucc-stats:empty:not([data-ucc-pending]) { display: none; }

/* NO JAVASCRIPT: nothing will ever release the reservation, so reserving is
   the wrong behaviour. Session D's contract for this page with JS off is that
   the data blocks are ABSENT and the page still reads as a case study, so
   these collapse rather than holding ~600px of blank ground open forever. */
html.no-js .ucc-provenance[data-ucc-pending],
html.no-js .ucc-headline[data-ucc-pending],
html.no-js .ucc-stats[data-ucc-pending] { display: none; min-height: 0; }
.ucc-stats .gw-stat__label { max-width: 16ch; }

@media (min-width: 640px) {
  .ucc-stats[data-ucc-pending] { min-height: 311px; }
  .ucc-stats { grid-template-columns: repeat(3, 1fr); }
  /* The columns are wide enough here that a 16ch cap only creates ragged
     two- and three-line labels next to one-line ones. */
  .ucc-stats .gw-stat__label { max-width: 22ch; }
}
@media (min-width: 900px) {
  .ucc-stats { grid-template-columns: repeat(4, 1fr); }
  .ucc-stats[data-ucc-pending] { min-height: 268px; }
}

/* ── NARRATIVE ───────────────────────────────────────────────────────────*/
.ucc-narrative .gw-body { max-width: 46ch; }

/* ── PROFILE CARDS ───────────────────────────────────────────────────────
   Two states per slot: the real card (consent on file), and the hold state
   that says what it is waiting for. There is no third state and there is no
   fake player.                                                             */
.ucc-profiles {
  margin-top: var(--gw-s-7);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gw-s-5);
}
@media (min-width: 720px) { .ucc-profiles { grid-template-columns: 1fr 1fr; gap: var(--gw-s-6); } }

.ucc-card {
  display: flex;
  flex-direction: column;
  gap: var(--gw-s-4);
  background: var(--gw-surface-2);
  border: 1px solid var(--gw-rule);
  border-radius: var(--gw-r-md);
  padding: var(--gw-s-5);
}

/* The whole card is one tap target on a phone. */
a.ucc-card { transition: border-color var(--gw-dur-fast) ease, transform var(--gw-dur-fast) var(--gw-ease); }
a.ucc-card:hover { border-color: var(--gw-rule-strong); transform: translateY(-2px); }

.ucc-card__top {
  display: flex;
  align-items: center;
  gap: var(--gw-s-4);
}
.ucc-card__radar { flex: none; width: 84px; height: 84px; }
.ucc-card__name {
  font-family: var(--gw-font-display);
  font-weight: 900;
  font-size: var(--gw-t-lg);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--gw-track-display);
  color: var(--gw-text);
  margin: 0;
}
.ucc-card__stat {
  margin: var(--gw-s-2) 0 0;
  font-size: var(--gw-t-sm);
  line-height: 1.5;
  color: var(--gw-text-muted);
}
.ucc-card__go {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--gw-s-2);
  min-height: 44px;
  font-family: var(--gw-font-data);
  font-size: var(--gw-t-data);
  letter-spacing: var(--gw-track-data);
  text-transform: uppercase;
  color: var(--gw-accent-text);
}
.ucc-card__go::after { content: '\2192'; }

/* Hold state. Reads as the same slate the media slots use, so an unfilled
   card looks deliberate rather than broken. F5: it states WHY. */
.ucc-card--hold {
  /* The hold state keeps the presence a real card will have, so the section
     does not visibly grow when consent lands. */
  min-height: 260px;
  background:
    repeating-linear-gradient(
      135deg,
      var(--gw-surface-3) 0 10px,
      var(--gw-surface-2) 10px 20px
    );
  align-items: center;
  justify-content: center;
  text-align: center;
}
.ucc-card--hold .ucc-card__radar { opacity: 0.5; }
.ucc-card__hold-title {
  font-family: var(--gw-font-display);
  font-weight: 800;
  font-size: var(--gw-t-md);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--gw-text-muted);
  margin: 0;
}
.ucc-card__hold-reason {
  margin: 0;
  max-width: 30ch;
  font-family: var(--gw-font-data);
  font-size: var(--gw-t-data);
  letter-spacing: 0.08em;
  line-height: 1.7;
  text-transform: uppercase;
  color: var(--gw-text-faint);
}

/* ── RUSH RADAR ──────────────────────────────────────────────────────────
   A tease and nothing more: shape, no axis names, no legend, no numbers, no
   methodology. Draws on when it scrolls in. Instant under reduced motion.  */
.ucc-radar__ring { fill: none; stroke: var(--gw-rule-strong); stroke-width: 1; }
.ucc-radar__spoke { stroke: var(--gw-rule); stroke-width: 1; }
.ucc-radar__shape {
  fill: var(--gw-blue-veil);
  stroke: var(--gw-accent);
  stroke-width: 2;
  stroke-linejoin: round;
  transform-origin: 50% 50%;
  transform: scale(0.2);
  opacity: 0;
  transition: transform var(--gw-dur-slow) var(--gw-ease),
              opacity var(--gw-dur-slow) var(--gw-ease);
}
.is-visible .ucc-radar__shape,
html.no-js .ucc-radar__shape { transform: scale(1); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .ucc-radar__shape { transform: scale(1); opacity: 1; transition: none; }
}

/* ── ORGANIZER QUOTE ─────────────────────────────────────────────────────*/
.ucc-quote { margin: 0; max-width: 24ch; }
.ucc-quote blockquote {
  margin: 0;
  color: var(--gw-text);
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.15;
  max-width: 20ch;
  border-left: 2px solid var(--gw-punct-fill);
  padding-left: var(--gw-s-5);
}
.ucc-quote figcaption { margin-top: var(--gw-s-4); padding-left: calc(var(--gw-s-5) + 2px); }
@media (min-width: 720px) {
  .ucc-quote, .ucc-quote blockquote { max-width: 30ch; }
}

/* ── CTA ─────────────────────────────────────────────────────────────────
   The closing button is DESKTOP ONLY, and this is a deliberate call worth
   reading before deleting.

   On mobile the sticky WhatsApp bar is permanently on screen in thumb reach.
   At the end of the page it lands directly beneath this section, so a second
   identical green button here puts two competing accent CTAs in one view,
   touching, which is the thing the brief bans. Desktop hides the sticky bar,
   so there the button is the only CTA and it belongs.

   The action is never lost on mobile: the sticky bar IS the action, and it
   sits immediately under the headline, reading as one unit. Revert = delete
   the two rules below. */
.ucc-cta__action { display: none; margin: var(--gw-s-6) 0 0; }
@media (min-width: 768px) { .ucc-cta__action { display: block; } }
@media (min-width: 720px) {
  .ucc-cta .gw-display { max-width: 14ch; }
}
