/* ============================================================
   WordPlayLeague — marketing site
   Palette inherited from the app (html_generator_v2.py, v6) so the
   site and the product read as one thing.
   System fonts only: page speed was half the reason for leaving Wix,
   and a font CDN hands some of it straight back.
   ============================================================ */

:root {
  --bg:        #1a1a1b;
  --bg-2:      #202022;
  --surface:   #26262a;
  --line:      #35353a;
  --line-soft: #2b2b2f;

  --text:      #d7dadc;
  --text-soft: #a8acae;
  --text-mute: #82858a;

  --cyan:      #00e8da;
  --cyan-deep: #00c4b8;
  --cyan-dim:  rgba(0, 232, 218, 0.12);
  --orange:    #ffa64d;
  --red:       #ff5c5c;

  --body:  "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --data:  ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;

  /* Type scale. Deliberately steeper at the top than the first pass: the gap
     between our page and the references was mostly headline size and air. */
  --step--1: clamp(0.8rem, 0.78rem + 0.1vw, 0.87rem);
  --step-0:  clamp(1rem, 0.97rem + 0.16vw, 1.1rem);
  --step-1:  clamp(1.2rem, 1.12rem + 0.38vw, 1.45rem);
  --step-2:  clamp(1.6rem, 1.38rem + 1.05vw, 2.3rem);
  --step-3:  clamp(2.2rem, 1.72rem + 2.3vw, 3.6rem);
  --step-4:  clamp(2.7rem, 1.9rem + 3.8vw, 5rem);

  /* Spacing scale — one ladder, used everywhere, so rhythm is consistent. */
  --sp-1: 0.5rem;
  --sp-2: 0.85rem;
  --sp-3: 1.35rem;
  --sp-4: 2.1rem;
  --sp-5: 3.25rem;
  --sp-6: clamp(4rem, 2.6rem + 6vw, 8rem);

  --radius:    14px;
  --radius-lg: 20px;
  --elev: 0 24px 60px -34px rgba(0, 0, 0, 0.92);

  --ease: cubic-bezier(0.22, 0.68, 0.32, 1);

  --wrap: 1280px;
  --gut:  clamp(1.1rem, 0.7rem + 1.9vw, 2.25rem);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  margin: 0;
  line-height: 1.12;
  letter-spacing: -0.025em;
  text-wrap: balance;
  font-weight: 750;
}
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }
p, ul, ol { margin: 0; }

a { color: var(--cyan); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--cyan-deep); }

:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 3px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
}

/* Skip link — keyboard users shouldn't tab the whole nav on every page */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--cyan);
  color: #10201f;
  padding: 0.6rem 1rem;
  font-weight: 700;
  z-index: 100;
}
.skip:focus { left: 0; }

/* ---------------- header ---------------- */
.site-head {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(26, 26, 27, 0.88);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line-soft);
}
.site-head .wrap {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-block: 0.65rem;
  flex-wrap: wrap;
}
.brand {
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: 1.05rem;
  text-decoration: none;
  color: var(--text);
  margin-right: auto;
}
.brand span { color: var(--cyan); }
.nav {
  display: flex;
  gap: 0.25rem 1.15rem;
  flex-wrap: wrap;
  align-items: center;
  font-size: var(--step--1);
}
.nav a {
  color: var(--text-soft);
  text-decoration: none;
  padding: 0.3rem 0;
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--cyan); }

/* ---------------- buttons ---------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--data);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.7rem 1.15rem;
  border-radius: 5px;
  border: 2px solid var(--cyan);
  background: var(--cyan);
  color: #10201f;
  cursor: pointer;
  transition: transform 0.16s ease, background 0.16s ease, box-shadow 0.16s ease;
}
.btn:hover {
  color: #10201f;
  background: var(--cyan-deep);
  transform: translateY(-2px);
  box-shadow: 0 10px 24px -12px rgba(0, 232, 218, 0.65);
}
.btn--ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--text);
}
.btn--ghost:hover {
  background: transparent;
  border-color: var(--cyan);
  color: var(--cyan);
  box-shadow: none;
}
.btn--sm { padding: 0.45rem 0.85rem; }

/* ---------------- prose pages (legal, rules) ---------------- */
.prose {
  padding-block: clamp(2.5rem, 1.6rem + 3.4vw, 4.5rem);
}
.prose .wrap { max-width: 50rem; }

.prose-head { margin-bottom: 2.25rem; }
.prose-head .eyebrow {
  font-family: var(--data);
  font-size: var(--step--1);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-bottom: 0.6rem;
}
.prose-head .updated {
  color: var(--text-mute);
  font-size: var(--step--1);
  margin-top: 0.7rem;
}

.prose h2 {
  font-size: var(--step-1);
  margin-top: 2.4rem;
  margin-bottom: 0.65rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line-soft);
}
.prose h2:first-of-type { border-top: 0; padding-top: 0; }
.prose h3 {
  font-size: var(--step-0);
  margin-top: 1.5rem;
  margin-bottom: 0.4rem;
  color: var(--text);
}
.prose p { margin-bottom: 0.95rem; color: var(--text-soft); }
.prose ul { margin: 0 0 1rem 1.15rem; padding: 0; color: var(--text-soft); }
.prose li { margin-bottom: 0.35rem; }
.prose strong { color: var(--text); font-weight: 650; }

/* A call-out for the things carriers and auditors look for */
.keyline {
  border-left: 3px solid var(--cyan);
  background: var(--cyan-dim);
  border-radius: 0 6px 6px 0;
  padding: 1rem 1.15rem;
  margin: 1.4rem 0;
}
.keyline p { color: var(--text); margin-bottom: 0.5rem; }
.keyline p:last-child { margin-bottom: 0; }

code, .mono {
  font-family: var(--data);
  font-size: 0.92em;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 0.08em 0.36em;
  word-break: break-word;
}

/* ---------------- footer ---------------- */
.site-foot {
  border-top: 1px solid var(--line-soft);
  background: var(--bg-2);
  padding-block: 2.5rem;
  margin-top: 4rem;
  font-size: var(--step--1);
  color: var(--text-mute);
}
.foot-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  justify-content: space-between;
  align-items: flex-start;
}
.foot-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
}
.foot-links a { color: var(--text-soft); text-decoration: none; }
.foot-links a:hover { color: var(--cyan); }
.foot-note {
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line-soft);
  max-width: 70ch;
  line-height: 1.6;
}

/* ============================================================
   HOMEPAGE
   ============================================================ */

.sec { padding-block: clamp(3rem, 1.8rem + 5vw, 6rem); }
.sec--alt { background: var(--bg-2); border-block: 1px solid var(--line-soft); }
.sec-head { max-width: 46rem; margin-bottom: 2.5rem; }
.sec-head .eyebrow {
  font-family: var(--data);
  font-size: var(--step--1);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--cyan);
  margin-bottom: 0.7rem;
}
.sec-head p { color: var(--text-soft); margin-top: 0.9rem; font-size: var(--step-1); line-height: 1.55; }
.lede { color: var(--text-soft); max-width: 62ch; }
.lede + .lede { margin-top: 0.9rem; }

/* ---------- hero ---------- */
.hero { position: relative; overflow: hidden; padding-block: clamp(2.75rem, 1.5rem + 5vw, 5.5rem); }
.hero::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(56% 42% at 80% 6%, rgba(0,232,218,0.13), transparent 62%),
    radial-gradient(44% 38% at 6% 84%, rgba(255,166,77,0.09), transparent 64%);
}
.hero > .wrap { position: relative; z-index: 1; }
.hero-grid { display: grid; gap: clamp(2rem, 1rem + 4vw, 3.5rem); align-items: center; }
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.05fr 0.95fr; } }
.hero h1 { font-size: clamp(2.2rem, 1.6rem + 2.9vw, 3.9rem); }
.hero h1 em { font-style: normal; color: var(--cyan); display: block; }
.hero-sub { font-size: var(--step-1); color: var(--text-soft); max-width: 40ch; margin-top: 1.2rem; line-height: 1.5; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 1.9rem; }
.hero-badge { display: flex; align-items: center; gap: 0.7rem; margin-top: 1.5rem; color: var(--text-mute); font-size: var(--step--1); }
.hero-badge img { width: 74px; height: auto; flex: none; }
.shot { width: 100%; height: auto; border-radius: 10px; display: block; }
.shot-frame { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--bg-2); box-shadow: 0 24px 54px -30px rgba(0,0,0,0.95); }

/* ---------- proof strip ---------- */
.proof { display: grid; gap: 1px; background: var(--line-soft); border-block: 1px solid var(--line-soft); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 760px) { .proof { grid-template-columns: repeat(4, 1fr); } }
.proof div { background: var(--bg); padding: 1.4rem 1.2rem; text-align: center; }
.proof .n { font-size: var(--step-2); font-weight: 760; letter-spacing: -0.03em; color: var(--cyan); font-variant-numeric: tabular-nums; }
.proof .k { font-family: var(--data); font-size: 0.72rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--text-mute); margin-top: 0.3rem; }

/* ---------- generic card grids ---------- */
.grid { display: grid; gap: 1.1rem; }
@media (min-width: 700px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } .grid--2 { grid-template-columns: repeat(2, 1fr); } }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 1.4rem 1.45rem; }
.card h3 { margin-bottom: 0.5rem; }
.card p { color: var(--text-soft); font-size: calc(var(--step-0) * 0.97); }
.card .num { font-family: var(--data); font-size: 0.74rem; letter-spacing: 0.14em; color: var(--cyan); display: block; margin-bottom: 0.55rem; }
.card--free { border-color: rgba(0,232,218,0.4); }
.tag { display: inline-block; font-family: var(--data); font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: #10201f; background: var(--cyan); border-radius: 3px; padding: 0.12rem 0.45rem; margin-left: 0.5rem; vertical-align: 0.14em; }

/* ---------- split rows ---------- */
.split { display: grid; gap: clamp(1.75rem, 1rem + 3vw, 3rem); align-items: center; }
@media (min-width: 880px) { .split { grid-template-columns: 1fr 1fr; } .split--flip > :first-child { order: 2; } }

/* ---------- pricing ---------- */
.price-grid { display: grid; gap: 1.1rem; }
@media (min-width: 760px) { .price-grid { grid-template-columns: repeat(3, 1fr); } }
.price { background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 1.5rem; display: flex; flex-direction: column; gap: 0.55rem; }
.price .amt { font-size: var(--step-2); font-weight: 760; letter-spacing: -0.03em; }
.price .amt small { font-size: var(--step--1); font-weight: 400; color: var(--text-mute); letter-spacing: 0; }
.price .who { font-family: var(--data); font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--cyan); }
.price p { color: var(--text-soft); font-size: calc(var(--step-0) * 0.95); }

/* ---------- testimonials ---------- */
.quotes { display: grid; gap: 1.1rem; }
@media (min-width: 820px) { .quotes { grid-template-columns: repeat(3, 1fr); } }
.quote { background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 1.5rem; display: flex; flex-direction: column; gap: 0.9rem; }
.quote blockquote { margin: 0; color: var(--text); font-size: calc(var(--step-0) * 1.02); line-height: 1.55; }
.quote .who { font-family: var(--data); font-size: 0.74rem; letter-spacing: 0.1em; color: var(--text-mute); text-transform: uppercase; }

/* ---------- faq ---------- */
.faq { display: grid; gap: 0; border: 1px solid var(--line); border-radius: 9px; overflow: hidden; }
.faq details { border-bottom: 1px solid var(--line-soft); background: var(--surface); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  cursor: pointer; list-style: none; padding: 1.05rem 1.3rem;
  font-weight: 650; display: flex; justify-content: space-between; gap: 1rem; align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font-family: var(--data); color: var(--cyan); font-size: 1.2rem; line-height: 1; flex: none; }
.faq details[open] summary::after { content: "\2212"; }
.faq summary:hover { color: var(--cyan); }
.faq .answer { padding: 0 1.3rem 1.2rem; color: var(--text-soft); }
.faq .answer p + p { margin-top: 0.7rem; }

/* ---------- closing CTA ---------- */
.close-cta { text-align: center; }
.close-cta h2 { max-width: 20ch; margin-inline: auto; }
.close-cta p { color: var(--text-soft); max-width: 52ch; margin: 1rem auto 0; }
.close-cta .hero-actions { justify-content: center; }

/* Screenshots inside prose: cap at their natural width so tall phone captures
   don't blow up to the full measure, and give them an edge against the page. */
.prose .shot {
  max-width: min(100%, 420px);
  width: auto;
  margin: 0.4rem 0 0.2rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-2);
}
.prose .shot[width="903"], .prose .shot[width="1100"], .prose .shot[width="330"] {
  max-width: min(100%, 620px);
}
.prose p:has(> .shot) { margin-bottom: 1.4rem; }

/* ---------------- signup form (/register) ---------------- */
.signup { max-width: 30rem; display: flex; flex-direction: column; gap: 1rem; margin-top: 0.5rem; }
.signup .field { display: flex; flex-direction: column; gap: 0.35rem; }
.signup label { font-size: var(--step--1); color: var(--text-soft); font-weight: 600; }
.signup label span { color: var(--cyan); }
.signup input {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.65rem 0.8rem;
  color: var(--text);
  font: inherit;
  font-size: var(--step-0);
}
.signup input:focus-visible { border-color: var(--cyan); outline: 2px solid var(--cyan); outline-offset: 1px; }
.signup .consent {
  font-size: var(--step--1);
  color: var(--text-mute);
  line-height: 1.6;
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
  border-radius: 6px;
  padding: 0.9rem 1rem;
  margin: 0;
}
.signup button { align-self: flex-start; }

/* ---------------- league index ---------------- */
.league-grid { display: grid; gap: 0.9rem; margin: 1.6rem 0 0.5rem; }
@media (min-width: 640px) { .league-grid { grid-template-columns: repeat(2, 1fr); } }
.league-card {
  display: flex; flex-direction: column; gap: 0.3rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 1.15rem 1.25rem;
  text-decoration: none;
  color: var(--text);
  transition: transform 0.16s ease, border-color 0.16s ease;
}
.league-card:hover { transform: translateY(-2px); border-color: rgba(0,232,218,0.45); color: var(--text); }
.league-card h2 { font-size: var(--step-1); margin: 0; border: 0; padding: 0; }
.league-card .meta { font-family: var(--data); font-size: 0.74rem; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-mute); margin: 0; }
.league-card .go { font-family: var(--data); font-size: var(--step--1); color: var(--cyan); margin-top: 0.5rem; }

/* ---------------- embedded app views ---------------- */
.embed-frame {
  margin: 1.6rem 0 0.6rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg-2);
}
.embed-frame iframe { display: block; width: 100%; height: 760px; border: 0; }
@media (max-width: 600px) { .embed-frame iframe { height: 620px; } }
.embed-fallback { font-size: var(--step--1); color: var(--text-mute); }

/* ============================================================
   FOUNDATIONS PASS — section formula, air, motion
   Appended last so it wins over the first-pass rules above.
   ============================================================ */

/* ---- air ---- */
.sec { padding-block: var(--sp-6); }
.prose { padding-block: clamp(3rem, 2rem + 4vw, 5.5rem); }
.sec-head { max-width: 50rem; margin-bottom: var(--sp-5); }
.grid, .price-grid, .quotes, .league-grid { gap: var(--sp-3); }
.split { gap: clamp(2.25rem, 1.2rem + 4vw, 4.5rem); }

/* ---- the section formula: eyebrow pill, big two-line headline, quiet subhead
        Both references converge on this, and it is what our first pass lacked. ---- */
.eyebrow {
  display: inline-block;
  font-family: var(--data);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cyan);
  background: var(--cyan-dim);
  border: 1px solid rgba(0, 232, 218, 0.28);
  border-radius: 999px;
  padding: 0.3rem 0.8rem;
  margin-bottom: var(--sp-3);
}
.sec-head .eyebrow, .prose-head .eyebrow { margin-bottom: var(--sp-3); }
.prose-head .eyebrow { color: var(--cyan); background: var(--cyan-dim); }

.sec-head h2, .close-cta h2 {
  font-size: var(--step-3);
  letter-spacing: -0.032em;
  line-height: 1.05;
  max-width: 18ch;
}
.close-cta h2 { max-width: 22ch; }
.sec-head p {
  font-size: var(--step-1);
  color: var(--text-soft);
  margin-top: var(--sp-3);
  max-width: 54ch;
  line-height: 1.5;
}
.split h2 { font-size: var(--step-3); letter-spacing: -0.032em; line-height: 1.05; max-width: 16ch; }
.prose-head h1, .hero h1 { letter-spacing: -0.035em; }
.hero h1 { font-size: var(--step-4); line-height: 1.0; }

/* ---- cards: bigger radius, softer elevation, quieter borders ---- */
.card, .price, .quote, .league-card, .faq, .shot-frame, .embed-frame {
  border-radius: var(--radius);
  border-color: var(--line-soft);
}
.shot-frame { border-radius: var(--radius-lg); box-shadow: var(--elev); }
.card, .price, .quote { padding: var(--sp-4); }
.card:hover, .league-card:hover, .quote:hover {
  transform: translateY(-4px);
  border-color: rgba(0, 232, 218, 0.4);
  box-shadow: var(--elev);
}
.card, .league-card, .quote {
  transition: transform 0.28s var(--ease), border-color 0.28s var(--ease),
              box-shadow 0.28s var(--ease);
}

/* ---- proof strip gets room to breathe ---- */
.proof div { padding: var(--sp-4) var(--sp-3); }
.proof .n { font-size: var(--step-2); }

/* ============================================================
   MOTION
   Elements are VISIBLE by default. The reveal styles only apply once the
   inline head script has confirmed JS is running and motion is wanted, so a
   crawler, a JS failure, or reduced-motion all get the finished page with no
   blank space. Apple's page shows what the other way round looks like when
   the observer does not fire.
   ============================================================ */
.js-motion [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.62s var(--ease), transform 0.62s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.js-motion [data-reveal].is-in {
  opacity: 1;
  transform: none;
}
.js-motion [data-reveal].is-in { will-change: auto; }

@media (prefers-reduced-motion: reduce) {
  .js-motion [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .card:hover, .league-card:hover, .quote:hover { transform: none; }
  .btn:hover { transform: none; }
}

/* ============================================================
   HERO DEMO — the thread filling up, the table filling in beside it
   ============================================================ */
.demo {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 540px) { .demo { grid-template-columns: 1.15fr 0.85fr; } }

/* phone */
.demo-phone {
  background: #0e0e12;
  border: 1px solid var(--line);
  border-radius: 26px;
  padding: 0.75rem 0.6rem 0.6rem;
  box-shadow: var(--elev), 0 0 0 1px rgba(0,232,218,0.1), 0 0 40px -16px rgba(0,232,218,0.3);
  position: relative;
}
.demo-phone::before {
  content: "";
  display: block;
  width: 60px; height: 4px;
  border-radius: 999px;
  background: #2a2a31;
  margin: 0 auto 0.6rem;
}
.demo-head {
  font-family: var(--data);
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-mute);
  text-align: center;
  padding-bottom: 0.5rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--line-soft);
}
.demo-thread {
  height: 310px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0 0.25rem;
  scroll-behavior: smooth;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 22px);
  mask-image: linear-gradient(180deg, transparent 0, #000 22px);
}

/* chat bubbles */
.bub {
  align-self: flex-start;
  max-width: 85%;
  background: #1c1c22;
  border: 1px solid var(--line-soft);
  border-radius: 13px 13px 13px 4px;
  padding: 0.45rem 0.6rem 0.5rem;
  position: relative;
  animation: bubIn 0.34s var(--ease) both;
}
.bub--mine {
  align-self: flex-end;
  background: rgba(0, 232, 218, 0.13);
  border-color: rgba(0, 232, 218, 0.3);
  border-radius: 13px 13px 4px 13px;
}
@keyframes bubIn {
  from { opacity: 0; transform: translateY(9px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
.bub-who {
  display: block;
  font-family: var(--data);
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-bottom: 0.15rem;
}
.bub--mine .bub-who { color: var(--cyan); }
.bub-txt { font-size: 0.8rem; color: var(--text); line-height: 1.35; }
.bub-react {
  position: absolute;
  right: -6px; bottom: -9px;
  font-size: 0.78rem;
  background: #16161b;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.05rem 0.28rem;
  animation: pop 0.3s var(--ease) both;
}
@keyframes pop { from { opacity: 0; transform: scale(0.5); } to { opacity: 1; transform: none; } }

/* the wordle grid, 5 wide */
.wgrid {
  display: grid;
  grid-template-columns: repeat(5, 9px);
  gap: 2px;
  margin-top: 0.35rem;
}
.wt { width: 9px; height: 9px; border-radius: 2px; display: block; }
.wt--correct { background: var(--cyan); }
.wt--present { background: var(--orange); }
.wt--absent  { background: #34343c; }

/* the table beside it */
.demo-table {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
}
.demo-table-head {
  font-family: var(--data);
  font-size: 0.62rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--cyan);
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line-soft);
  background: rgba(0, 232, 218, 0.06);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.demo-table-head i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--cyan);
  animation: blip 2s ease-in-out infinite;
}
@keyframes blip { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }
.demo-table ul { list-style: none; margin: 0; padding: 0.3rem 0; min-height: 268px; }
.drow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.8rem;
  padding: 0.42rem 0.8rem;
  font-size: 0.82rem;
  opacity: 0;
  transform: translateX(10px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.drow.in, .js-nomotion .drow { opacity: 1; transform: none; }
.drow-name { color: var(--text-soft); }
.drow-score {
  font-family: var(--data);
  font-weight: 700;
  color: var(--cyan);
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .bub, .bub-react { animation: none; }
  .drow { opacity: 1; transform: none; transition: none; }
  .demo-table-head i { animation: none; }
}

/* ---- proof strip, tightened ----------------------------------------------
   Was four tall cards with dim labels. Now one slim line: numbers in the
   accent, labels in readable body colour rather than the muted grey. */
.proof {
  display: block;
  background: var(--bg-2);
  border-block: 1px solid var(--line-soft);
  padding-block: 0.85rem;
  grid-template-columns: none;
  gap: 0;
}
.proof-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0.35rem 1.9rem;
  font-size: var(--step--1);
  color: var(--text-soft);
}
.proof-list li { display: inline-flex; align-items: baseline; gap: 0.42rem; white-space: nowrap; }
.proof-list li + li::before {
  content: "";
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--line);
  margin-right: 1.5rem;
  align-self: center;
}
.proof-list b {
  font-size: 1.12rem;
  font-weight: 760;
  color: var(--cyan);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 560px) {
  .proof-list { gap: 0.3rem 1.1rem; justify-content: flex-start; }
  .proof-list li + li::before { margin-right: 0.8rem; }
}

/* ---- demo proportions: make the phone actually phone-shaped ----
   First pass was squat — a 270x310 thread reads as a tablet. Real handsets are
   about 2.1:1, so the thread grows and the phone column is pinned narrow. */
.demo { grid-template-columns: 1fr; }
@media (min-width: 560px) {
  .demo {
    grid-template-columns: minmax(0, 248px) 1fr;
    gap: var(--sp-3);
    align-items: stretch;
  }
}
.demo-phone { border-radius: 30px; padding: 0.8rem 0.55rem 0.7rem; }
.demo-thread { height: 468px; }
.demo-table { display: flex; flex-direction: column; }
.demo-table ul { min-height: 0; flex: 1; }
@media (max-width: 559px) {
  .demo-thread { height: 330px; }
}

/* Longer fade at the top of the thread so older messages dissolve rather than
   getting a hard cut, and roomier table rows so the column fills its height. */
.demo-thread {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, rgba(0,0,0,0.35) 34px, #000 76px);
  mask-image: linear-gradient(180deg, transparent 0, rgba(0,0,0,0.35) 34px, #000 76px);
  padding-top: 0.2rem;
}
.demo-table ul { display: flex; flex-direction: column; justify-content: flex-start; padding: 0.45rem 0; }
.drow { padding: 0.62rem 0.9rem; font-size: 0.86rem; }
.drow + .drow { border-top: 1px solid rgba(255,255,255,0.04); }
.drow-score { font-size: 0.95rem; }

/* ============================================================
   HERO DEMO v2 — loose bubbles left, the real Latest Scores tab right
   The phone UI mirrors the app's own view (see
   image_artifacts/update screenshots with new ui/latest_scores_2026.png):
   cyan league title, four pills, the Wordle # line, then score cards.
   ============================================================ */
.demo { display: grid; grid-template-columns: 1fr; gap: var(--sp-3); align-items: center; }
@media (min-width: 620px) { .demo { grid-template-columns: 1fr minmax(0, 252px); } }

/* --- loose bubbles, no phone frame --- */
.demo-bubbles {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  align-items: flex-start;
  justify-content: flex-end;
  min-height: 300px;
}
.demo-bubbles .bub {
  max-width: 240px;
  background: #1e1e25;
  border: 1px solid var(--line-soft);
  border-radius: 14px 14px 14px 5px;
  padding: 0.45rem 0.65rem 0.5rem;
  box-shadow: 0 10px 26px -18px rgba(0,0,0,0.9);
}
.demo-bubbles .bub--mine {
  align-self: flex-end;
  background: rgba(0,232,218,0.12);
  border-color: rgba(0,232,218,0.3);
  border-radius: 14px 14px 5px 14px;
}

/* --- the phone --- */
.lphone {
  background: #07070b;
  border: 1px solid #2a2a33;
  border-radius: 30px;
  padding: 0.55rem 0.45rem;
  box-shadow: var(--elev), 0 0 0 1px rgba(0,232,218,0.09), 0 0 46px -18px rgba(0,232,218,0.3);
}
.lscreen {
  background: #0b0b10;
  border-radius: 24px;
  padding: 0.7rem 0.5rem 0.6rem;
  height: 470px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.lhead { text-align: center; margin-bottom: 0.5rem; }
.lhead .emoji { font-size: 0.9rem; display: block; line-height: 1; }
.lhead .lleague {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--cyan);
  letter-spacing: -0.02em;
  display: block;
  margin-top: 0.1rem;
}
.lhead .lbrand {
  font-size: 0.56rem;
  font-weight: 700;
  background: linear-gradient(90deg, var(--orange), #8ddc6b);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  display: block;
}
.lpills { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 0.5rem; }
.lpill {
  font-size: 0.54rem;
  font-weight: 700;
  text-align: center;
  padding: 0.3rem 0.1rem;
  border-radius: 999px;
  border: 1px solid #23232c;
  color: #6f737a;
  background: #111118;
}
.lpill.on {
  color: var(--cyan);
  border-color: rgba(0,232,218,0.55);
  box-shadow: 0 0 12px -4px rgba(0,232,218,0.6) inset;
}
.lwordle {
  text-align: center;
  font-size: 0.56rem;
  font-weight: 700;
  color: var(--cyan);
  margin-bottom: 0.45rem;
}
.lcards { display: flex; flex-direction: column; gap: 0.4rem; overflow: hidden; flex: 1; }

.lcard {
  background: #12121a;
  border: 1px solid #1e1e28;
  border-radius: 11px;
  padding: 0.45rem 0.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.42s var(--ease), transform 0.42s var(--ease);
}
.lcard.in { opacity: 1; transform: none; }
.lcard-who { display: flex; flex-direction: column; gap: 0.18rem; }
.lname { font-size: 0.78rem; font-weight: 750; color: #e9ecee; letter-spacing: -0.01em; }
.lscore {
  align-self: flex-start;
  font-size: 0.6rem;
  font-weight: 800;
  color: var(--orange);
  background: rgba(255,166,77,0.14);
  border-radius: 4px;
  padding: 0.05rem 0.3rem;
}
.lgrid { display: grid; grid-template-columns: repeat(5, 8px); gap: 2px; flex: none; }
.lt { width: 8px; height: 8px; border-radius: 2px; display: block; }
.lt--g { background: #19d2c4; }
.lt--y { background: #f7a24b; }
.lt--x { background: #2f2f37; }
.lt--w { background: #e7e9ea; }

@media (prefers-reduced-motion: reduce) {
  .lcard { opacity: 1; transform: none; transition: none; }
}

/* Running annotation under the demo — explains the animation as it plays. */
.demo-caption {
  grid-column: 1 / -1;
  margin-top: var(--sp-3);
  min-height: 2.6em;
  font-size: var(--step--1);
  color: var(--text-mute);
  text-align: center;
  opacity: 0;
  transition: opacity 0.28s var(--ease);
  max-width: 44ch;
  margin-inline: auto;
  line-height: 1.5;
}
.demo-caption.on { opacity: 1; }
.demo-caption::before {
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--cyan);
  margin-right: 0.5rem;
  vertical-align: 0.18em;
}

/* ---- demo v3: phone left, bubbles right; taller screen; roomier bubbles ---- */
@media (min-width: 620px) {
  .demo { grid-template-columns: minmax(0, 262px) 1fr; }
}
.lscreen { height: 560px; }
.lcards { gap: 0.32rem; }
.lcard { padding: 0.4rem 0.5rem; min-height: 0; }
.lcard--none { background: #0e0e15; border-color: #191922; }
.lnone {
  align-self: flex-start;
  font-size: 0.58rem;
  font-weight: 600;
  color: #5d6167;
}
.lscore.is-good { color: var(--cyan);   background: rgba(0,232,218,0.15); }
.lscore.is-mid  { color: var(--orange); background: rgba(255,166,77,0.15); }
.lscore.is-fail { color: #9aa0a6;       background: rgba(154,160,166,0.15); }
.lcard.flash { animation: cardFlash 1.1s var(--ease); }
@keyframes cardFlash {
  0%   { background: rgba(0,232,218,0.2); border-color: rgba(0,232,218,0.5); }
  100% { background: #12121a; border-color: #1e1e28; }
}

/* bubbles: room for a real Wordle post, grid included */
.demo-bubbles { min-height: 420px; justify-content: center; gap: 0.7rem; }
.demo-bubbles .bub { max-width: 300px; padding: 0.6rem 0.8rem 0.7rem; border-radius: 16px 16px 16px 6px; }
.demo-bubbles .bub--mine { border-radius: 16px 16px 6px 16px; }
.demo-bubbles .bub-txt { font-size: 0.88rem; }
.demo-bubbles .bub-who { font-size: 0.64rem; margin-bottom: 0.25rem; }
.demo-bubbles .lgrid { grid-template-columns: repeat(5, 11px); gap: 2.5px; margin-top: 0.45rem; }
.demo-bubbles .lt { width: 11px; height: 11px; border-radius: 2.5px; }

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

/* Cards persist now and change state in place, so they must not start hidden —
   the old opacity:0-until-.in rule left the whole screen blank. */
.lcard { opacity: 1; transform: none; }

/* ---- explainer callouts (right of the phone) ----------------------------
   Brighter and larger than the old chat bubbles: these are the point being
   made, not background texture. They arrive one beat at a time. */
.demo-bubbles { justify-content: center; gap: 1.1rem; min-height: 420px; }
.callout {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  max-width: 340px;
  background: linear-gradient(180deg, rgba(0,232,218,0.13), rgba(0,232,218,0.06));
  border: 1px solid rgba(0,232,218,0.32);
  border-radius: 16px;
  padding: 0.95rem 1.1rem;
  box-shadow: 0 18px 40px -26px rgba(0,232,218,0.55);
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}
.callout.in { opacity: 1; transform: none; }
.callout p {
  margin: 0;
  font-size: 0.97rem;
  line-height: 1.45;
  color: #eaf4f3;
  font-weight: 500;
}
.callout p b { color: var(--cyan); font-weight: 750; }
.callout-dot {
  flex: none;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--cyan);
  margin-top: 0.42rem;
  box-shadow: 0 0 0 4px rgba(0,232,218,0.16);
}
@media (prefers-reduced-motion: reduce) {
  .callout { opacity: 1; transform: none; transition: none; }
}

/* More of the hero's vertical real estate given to the phone. */
.lscreen { height: 648px; }
.demo-bubbles { min-height: 500px; }

/* ============================================================
   HERO v4 — headline across the top, demo full width beneath it
   ============================================================ */
.hero-top { display: grid; gap: var(--sp-3) var(--sp-5); align-items: end; margin-bottom: var(--sp-5); }
@media (min-width: 900px) { .hero-top { grid-template-columns: 1.05fr 0.95fr; } }
.hero-top h1 { font-size: clamp(2.4rem, 1.5rem + 4.2vw, 4.6rem); }
.hero-side .hero-sub { margin-top: 0; max-width: 46ch; }

/* three columns: phone, the thread, what it means */
.demo { grid-template-columns: 1fr; gap: var(--sp-4); align-items: start; }
@media (min-width: 760px)  { .demo { grid-template-columns: minmax(0, 300px) 1fr; } }
@media (min-width: 1040px) { .demo { grid-template-columns: minmax(0, 300px) minmax(0, 1fr) minmax(0, 1fr); } }

/* phone: wider and a bit shorter — was 2.55:1, which overshot a real handset */
.lscreen { height: 592px; }
.lphone { border-radius: 34px; padding: 0.6rem 0.5rem; }
.lname { font-size: 0.85rem; }
.lscore, .lnone { font-size: 0.65rem; }
.lgrid { grid-template-columns: repeat(5, 9px); }
.lt { width: 9px; height: 9px; }
.lhead .lleague { font-size: 1.2rem; }
.lpill { font-size: 0.6rem; padding: 0.34rem 0.1rem; }
.lwordle { font-size: 0.62rem; }

/* chat bubbles: the cyan glow treatment, no border */
.demo-bubbles { min-height: 0; gap: 0.75rem; justify-content: flex-start; }
.demo-bubbles .bub {
  max-width: 320px;
  border: 0;
  background: linear-gradient(180deg, rgba(0,232,218,0.15), rgba(0,232,218,0.05));
  box-shadow: 0 18px 44px -26px rgba(0,232,218,0.75);
  border-radius: 18px 18px 18px 6px;
  padding: 0.7rem 0.95rem 0.8rem;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.42s var(--ease), transform 0.42s var(--ease);
}
.demo-bubbles .bub.in { opacity: 1; transform: none; }
.demo-bubbles .bub--mine { align-self: flex-end; border-radius: 18px 18px 6px 18px; }
.demo-bubbles .bub-who { color: var(--cyan); font-size: 0.66rem; }
.demo-bubbles .bub-txt { font-size: 0.92rem; color: #eaf4f3; }

/* the explanation column sits alongside */
.demo-notes { display: flex; flex-direction: column; gap: 1.1rem; justify-content: flex-start; }
.demo-notes .callout { max-width: none; }

@media (prefers-reduced-motion: reduce) {
  .demo-bubbles .bub { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   HERO DEMO v5 — two matching phones, realistic card size, typed notes
   ============================================================ */
.demo { grid-template-columns: 1fr; gap: var(--sp-4); align-items: stretch; }
@media (min-width: 760px)  { .demo { grid-template-columns: repeat(2, minmax(0, 288px)); justify-content: center; } }
@media (min-width: 1100px) { .demo { grid-template-columns: minmax(0,288px) minmax(0,288px) minmax(0,1fr); justify-content: start; } }

.lphone { border-radius: 34px; padding: 0.55rem 0.45rem; }
.lscreen { height: 600px; }

/* --- thread phone --- */
.lscreen--thread { padding: 0.55rem 0.4rem 0.4rem; }
.tbar {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0 0.35rem 0.5rem;
  border-bottom: 1px solid #1a1a22;
  margin-bottom: 0.45rem;
}
.tbar-dot { width: 20px; height: 20px; border-radius: 50%; background: linear-gradient(140deg, var(--cyan), #0a7f78); flex: none; }
.tbar-name { font-size: 0.78rem; font-weight: 700; color: #e9ecee; }
.tbar-sub { font-size: 0.6rem; color: var(--text-mute); margin-left: auto; }
.tscroll {
  flex: 1; min-height: 0;
  overflow: hidden;
  display: flex; flex-direction: column; gap: 0.5rem;
  padding: 0.2rem 0.3rem 0;
  scroll-behavior: smooth;
}
.tscroll .bub {
  max-width: 88%;
  align-self: flex-start;
  border: 0;
  background: linear-gradient(180deg, rgba(0,232,218,0.16), rgba(0,232,218,0.06));
  box-shadow: 0 14px 34px -24px rgba(0,232,218,0.8);
  border-radius: 15px 15px 15px 5px;
  padding: 0.5rem 0.7rem 0.6rem;
  opacity: 0; transform: translateY(10px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
  flex: none;
}
.tscroll .bub.in { opacity: 1; transform: none; }
.tscroll .bub--mine {
  align-self: flex-end;
  border-radius: 15px 15px 5px 15px;
  background: linear-gradient(180deg, rgba(0,232,218,0.3), rgba(0,232,218,0.14));
}
.tscroll .bub-who { font-size: 0.6rem; color: var(--cyan); margin-bottom: 0.15rem; }
.tscroll .bub-txt { font-size: 0.82rem; color: #eef6f5; }
.tscroll .lgrid { grid-template-columns: repeat(5, 10px); gap: 2px; margin-top: 0.4rem; }
.tscroll .lt { width: 10px; height: 10px; border-radius: 2px; }

/* --- latest scores phone: real card size, ~4.5 visible, scrolls --- */
.lscroll { flex: 1; min-height: 0; overflow: hidden; }
.lcards { gap: 0.45rem; }
.lcard {
  padding: 0.65rem 0.6rem;
  border-radius: 13px;
  align-items: center;
  min-height: 74px;
}
.lcard-who { gap: 0.3rem; }
.lname { font-size: 1.02rem; font-weight: 780; }
.lscore { font-size: 0.8rem; padding: 0.1rem 0.42rem; border-radius: 5px; }
.lnone { font-size: 0.78rem; }
.lgrid { grid-template-columns: repeat(5, 13px); gap: 2.5px; }
.lt { width: 13px; height: 13px; border-radius: 3px; }
.lcard { transition: background 0.4s var(--ease), border-color 0.4s var(--ease); }

/* --- notes: no box, typed out, spread top / middle / bottom --- */
.demo-notes {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: 0.5rem 0 0.5rem var(--sp-2);
  min-height: 600px;
}
.note {
  margin: 0;
  font-size: var(--step-1);
  line-height: 1.45;
  color: #e7f3f2;
  font-weight: 500;
  max-width: 30ch;
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  text-wrap: pretty;
}
.note.on { opacity: 1; }
.note[data-slot="1"] { align-self: center; }
.note[data-slot="2"] { align-self: flex-start; }
.note span::after {
  content: "";
  display: inline-block;
  width: 2px; height: 1.05em;
  background: var(--cyan);
  margin-left: 2px;
  vertical-align: -0.18em;
  animation: caret 1s step-end infinite;
}
.note.done span::after { display: none; }
@keyframes caret { 50% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .tscroll .bub { opacity: 1; transform: none; transition: none; }
  .note span::after { animation: none; }
}

/* ============================================================
   HERO v5 — a real photo up top, the live demo in its own section below
   Container widened to 1280 (was 1120). Text measures stay capped so line
   length does not grow with it — wider layout, same readability.
   ============================================================ */
.hero { padding-block: clamp(2.5rem, 1.4rem + 4.5vw, 5rem); }
.hero-grid { display: grid; gap: clamp(2rem, 1rem + 4vw, 4rem); align-items: center; }
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.06fr 0.94fr; } }
.hero-copy h1 { font-size: clamp(2.4rem, 1.5rem + 4.2vw, 4.6rem); }
.hero-copy .hero-sub { max-width: 44ch; }
.hero-shot img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--elev), 0 0 0 1px rgba(0,232,218,0.08), 0 0 70px -30px rgba(0,232,218,0.4);
}

/* the demo now has its own section, so it sits below the fold */
.sec--demo { background: var(--bg-2); border-block: 1px solid var(--line-soft); }
.sec--demo .sec-head h2 { max-width: 24ch; }

/* notes: start at the top with even spacing, not spread over the full height */
.demo-notes {
  justify-content: flex-start;
  gap: var(--sp-5);
  padding-top: 0.25rem;
  min-height: 0;
}
.note[data-slot="1"], .note[data-slot="2"] { align-self: flex-start; }
.note { max-width: 32ch; }

/* The headline is two sentences now, and longer than the old one — ease the
   size and let it run wider so it stays two lines rather than four. */
.hero-copy h1 { font-size: clamp(2.1rem, 1.3rem + 3.4vw, 3.9rem); max-width: 17ch; }

/* ============================================================
   STAT TILES — the numbers set in Wordle tiles that flip to reveal
   ============================================================ */
.proof { padding-block: var(--sp-5); }
.stats {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-4) var(--sp-3);
}
@media (min-width: 820px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat { display: flex; flex-direction: column; align-items: center; gap: 0.7rem; text-align: center; }
.stat-tiles { display: flex; gap: 5px; }
.stile {
  --t: clamp(34px, 2.1rem + 1vw, 48px);
  width: var(--t); height: var(--t);
  display: grid; place-items: center;
  font-family: var(--data);
  font-size: calc(var(--t) * 0.52);
  font-weight: 800;
  font-style: normal;
  color: #0c1f1e;
  background: var(--cyan);
  border-radius: 7px;
  box-shadow: 0 10px 26px -14px rgba(0, 232, 218, 0.8);
  transform-style: preserve-3d;
}
/* every fourth tile picks up the orange, so a row is not a solid cyan block */
.stat:nth-child(2) .stile:nth-child(2),
.stat:nth-child(3) .stile:nth-child(1),
.stat:nth-child(4) .stile:nth-child(3),
.stat:nth-child(1) .stile:nth-child(3) {
  background: var(--orange);
  box-shadow: 0 10px 26px -14px rgba(255, 166, 77, 0.75);
}
.stile.flip { animation: tileFlip 0.62s var(--ease) both; }
@keyframes tileFlip {
  0%   { transform: rotateX(-90deg); opacity: 0; }
  55%  { transform: rotateX(12deg);  opacity: 1; }
  100% { transform: rotateX(0);      opacity: 1; }
}
.stat-label {
  font-family: var(--data);
  font-size: 0.72rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-soft);
}
@media (prefers-reduced-motion: reduce) { .stile.flip { animation: none; } }

/* ---- stats as individual cards ------------------------------------------
   Not a slim strip and not the old dull boxes: each number gets its own card
   with an accent rail, so four separate facts read as four separate facts. */
.proof { padding-block: var(--sp-6); background: var(--bg); }
.stats { gap: var(--sp-3); }
.stat {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: var(--sp-4) var(--sp-3) var(--sp-3);
  gap: 0.9rem;
  overflow: hidden;
  transition: transform 0.28s var(--ease), border-color 0.28s var(--ease),
              box-shadow 0.28s var(--ease);
}
.stat::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--cyan), rgba(0,232,218,0));
}
.stat:nth-child(2)::before { background: linear-gradient(90deg, var(--orange), rgba(255,166,77,0)); }
.stat:nth-child(4)::before { background: linear-gradient(90deg, var(--orange), rgba(255,166,77,0)); }
.stat::after {
  content: "";
  position: absolute;
  inset: auto -30% -60% -30%;
  height: 120px;
  background: radial-gradient(60% 100% at 50% 100%, rgba(0,232,218,0.14), transparent 70%);
  pointer-events: none;
}
.stat:hover {
  transform: translateY(-4px);
  border-color: rgba(0,232,218,0.4);
  box-shadow: var(--elev);
}
.stat-label { color: var(--text-soft); font-size: 0.7rem; }
.stile {
  --t: clamp(32px, 1.6rem + 1.4vw, 46px);
  border-radius: 8px;
  box-shadow: 0 12px 24px -14px rgba(0,0,0,0.9), inset 0 -2px 0 rgba(0,0,0,0.18);
}

/* ---- notes back in the cyan panel, popping in rather than typing --------- */
.note {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  max-width: 360px;
  background: linear-gradient(180deg, rgba(0,232,218,0.14), rgba(0,232,218,0.05));
  border: 1px solid rgba(0,232,218,0.3);
  border-radius: 16px;
  padding: 1rem 1.15rem;
  box-shadow: 0 20px 46px -28px rgba(0,232,218,0.75);
  font-size: var(--step-0);
  line-height: 1.5;
  color: #eaf4f3;
  opacity: 0;
  transform: translateY(12px) scale(0.97);
  transition: opacity 0.42s var(--ease), transform 0.42s var(--ease);
}
.note.on { opacity: 1; transform: none; }
.note::before {
  content: "";
  flex: none;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--cyan);
  margin-top: 0.46rem;
  box-shadow: 0 0 0 4px rgba(0,232,218,0.16);
}
.note span::after { display: none; }   /* caret retired with the typewriter */
@media (prefers-reduced-motion: reduce) {
  .note { opacity: 1; transform: none; transition: none; }
}

/* All digits cyan. The mixed orange made the numbers harder to read — the
   colour was decorating at the expense of the thing being decorated. */
.stat:nth-child(1) .stile,
.stat:nth-child(2) .stile,
.stat:nth-child(3) .stile,
.stat:nth-child(4) .stile {
  background: var(--cyan);
  box-shadow: 0 12px 24px -14px rgba(0,0,0,0.9), inset 0 -2px 0 rgba(0,0,0,0.18);
}

/* Same specificity as the rule that introduced the orange, or it does not win. */
.stat:nth-child(1) .stile:nth-child(3),
.stat:nth-child(2) .stile:nth-child(2),
.stat:nth-child(3) .stile:nth-child(1),
.stat:nth-child(4) .stile:nth-child(3) {
  background: var(--cyan);
  box-shadow: 0 12px 24px -14px rgba(0,0,0,0.9), inset 0 -2px 0 rgba(0,0,0,0.18);
}

/* ---- the phone's two tab views ------------------------------------------ */
.lview { display: flex; flex-direction: column; flex: 1; min-height: 0;
         transition: opacity 0.45s var(--ease); }
.lview--hidden { display: none; }
.lnote { font-size: 0.6rem; color: var(--text-soft); margin: 0 0 0.5rem; line-height: 1.4; }
.lnote b { color: var(--cyan); }
.ldiv { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.02em; margin: 0 0 0.35rem; }
.ldiv--one { color: var(--cyan); }
.ldiv--two { color: var(--orange); margin-top: 0.8rem; }
.ltable { width: 100%; border-collapse: collapse; background: #12121a;
          border: 1px solid #1e1e28; border-radius: 10px; overflow: hidden; }
.ltable th { font-size: 0.52rem; letter-spacing: 0.06em; text-transform: uppercase;
             color: #8f949b; font-weight: 700; padding: 0.4rem 0.4rem; text-align: left;
             border-bottom: 1px solid #1e1e28; line-height: 1.15; }
.ltable td { font-size: 0.78rem; color: #e9ecee; padding: 0.42rem 0.4rem;
             border-bottom: 1px solid rgba(255,255,255,0.045); }
.ltable tbody tr:last-child td { border-bottom: 0; }
.ltable td.n { font-family: var(--data); font-weight: 700; font-variant-numeric: tabular-nums;
               text-align: center; width: 27%; }
.ltable tbody tr:first-child td { background: rgba(0,232,218,0.07); }
.ltable tr.is-new td:first-child { color: var(--orange); }
.lrel { font-size: 0.58rem; color: var(--cyan); font-style: italic; margin: 0.45rem 0 0; }

/* ============================================================
   BACKGROUND — a flared grid behind the dark sections
   A fine line grid masked by a radial gradient, so it reads as structure
   catching the light in one corner rather than wallpaper. Carried over from
   the earlier homepage concept, tinted to our cyan.
   ============================================================ */
.hero, .sec--demo { position: relative; isolation: isolate; }
.hero > .wrap, .sec--demo > .wrap { position: relative; z-index: 1; }

.hero::after, .sec--demo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(0, 232, 218, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 232, 218, 0.07) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(118% 88% at 78% 4%, #000 14%, transparent 68%);
  mask-image: radial-gradient(118% 88% at 78% 4%, #000 14%, transparent 68%);
}
/* the demo section flares from the other side, so the two do not look stamped */
.sec--demo::after {
  -webkit-mask-image: radial-gradient(100% 80% at 12% 10%, #000 12%, transparent 66%);
  mask-image: radial-gradient(100% 80% at 12% 10%, #000 12%, transparent 66%);
}

/* the colour wash sits under the grid */
.hero::before { z-index: -1; }
.sec--demo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(50% 40% at 8% 6%, rgba(0, 232, 218, 0.10), transparent 64%),
    radial-gradient(44% 38% at 92% 92%, rgba(255, 166, 77, 0.07), transparent 66%);
}

/* Grid was too faint to register. Stronger lines, and the mask pulled wider
   so the flare covers more of the section before it dissolves. */
.hero::after, .sec--demo::after {
  background-image:
    linear-gradient(rgba(0, 232, 218, 0.13) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 232, 218, 0.13) 1px, transparent 1px);
  background-size: 72px 72px;
}
.hero::after {
  -webkit-mask-image: radial-gradient(125% 100% at 72% 0%, #000 22%, transparent 76%);
  mask-image: radial-gradient(125% 100% at 72% 0%, #000 22%, transparent 76%);
}
.sec--demo::after {
  -webkit-mask-image: radial-gradient(115% 95% at 14% 6%, #000 18%, transparent 74%);
  mask-image: radial-gradient(115% 95% at 14% 6%, #000 18%, transparent 74%);
}

/* ---- free trial: an offer, not a footnote -------------------------------
   Was a 74px image beside muted grey text, which read as small print. */
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.95rem;
  margin-top: var(--sp-4);
  padding: 0.8rem 1.25rem 0.8rem 0.9rem;
  background: linear-gradient(180deg, rgba(0,232,218,0.12), rgba(0,232,218,0.04));
  border: 1px solid rgba(0,232,218,0.3);
  border-radius: 14px;
  box-shadow: 0 18px 40px -28px rgba(0,232,218,0.7);
}
.hero-badge img {
  width: 104px;
  height: auto;
  flex: none;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,0.5));
}
.hero-badge p {
  margin: 0;
  font-size: var(--step-0);
  line-height: 1.4;
  color: #eaf4f3;
}
.hero-badge strong {
  color: var(--cyan);
  font-weight: 780;
  font-size: 1.1em;
  letter-spacing: -0.01em;
}
.hero-badge span { color: var(--text-mute); font-size: var(--step--1); }
@media (max-width: 420px) {
  .hero-badge { gap: 0.7rem; padding: 0.7rem 0.9rem; }
  .hero-badge img { width: 78px; }
}

/* Pages whose content is a panel rather than prose — the reading measure is
   the wrong constraint there, the board should use the room it has. */
.prose--wide .wrap { max-width: var(--wrap); }
.prose--wide .prose-head { max-width: 50rem; }
.prose--wide .embed-frame { margin-top: var(--sp-4); }
.prose--wide .embed-frame iframe { height: 900px; }
@media (max-width: 700px) { .prose--wide .embed-frame iframe { height: 680px; } }

/* ============================================================
   ATMOSPHERE — drifting particles over a faint grid, site-wide
   Same field the league pages use, so the site and the product share an
   atmosphere. Both layers are decoration and sit behind everything.
   ============================================================ */
body {
  background-color: var(--bg);
  background-image:
    linear-gradient(rgba(0, 232, 218, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 232, 218, 0.035) 1px, transparent 1px);
  background-size: 72px 72px;
  background-attachment: fixed;
}
#wpl-particles {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
/* content rides above the field; sections keep their own backgrounds opaque
   enough to read against it */
.site-head, main, .site-foot { position: relative; z-index: 1; }
.sec--alt, .proof { background: rgba(32, 32, 34, 0.82); }
.sec--demo { background: rgba(32, 32, 34, 0.72); }

/* ============================================================
   RULES — the app's glass cards
   ============================================================ */
.prose--cards .wrap { max-width: 58rem; }
.rcard {
  background: rgba(16, 16, 36, 0.7);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  box-shadow: 0 6px 32px rgba(0, 0, 0, 0.45);
  padding: 1.4rem 1.5rem;
  margin-bottom: 1.1rem;
}
.rcard h2 {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: var(--step-1);
  color: var(--cyan);
  margin: 0 0 0.7rem;
  padding: 0;
  border: 0;
  letter-spacing: -0.015em;
}
.rcard h2 span { font-size: 1.05em; line-height: 1; }
.rcard h3 {
  font-size: calc(var(--step-0) * 1.02);
  color: var(--orange);
  margin: 1.3rem 0 0.45rem;
}
.rcard p { color: var(--text); margin-bottom: 0.8rem; line-height: 1.6; }
.rcard p:last-child { margin-bottom: 0; }
.rcard b { color: var(--cyan); font-weight: 700; }
.rcard .rnote { color: var(--text-mute); font-size: var(--step--1); line-height: 1.55; }
.rcard .rnote b { color: var(--text-soft); }
.rlist, .rrank { margin: 0 0 0.8rem 1.1rem; padding: 0; color: var(--text); }
.rlist li, .rrank li { margin-bottom: 0.4rem; line-height: 1.55; }
.rrank li b { color: var(--cyan); }

/* the 3-7 selector, shown as a range rather than one league's setting */
.rseg { display: flex; gap: 8px; margin: 0.9rem 0 1rem; }
.rseg div {
  flex: 1;
  text-align: center;
  padding: 0.6rem 0.3rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 9px;
}
.rseg em { display: block; font-style: normal; font-size: 1.3em; font-weight: 800; color: var(--text); }
.rseg span { display: block; font-size: 0.7rem; color: var(--text-mute); line-height: 1.25; margin-top: 0.15rem; }
@media (max-width: 560px) { .rseg { gap: 5px; } .rseg div { padding: 0.5rem 0.15rem; } .rseg span { font-size: 0.6rem; } }

/* ============================================================
   ATMOSPHERE, turned up — stronger grid, stronger colour flares
   ============================================================ */
body {
  background-image:
    linear-gradient(rgba(0, 232, 218, 0.085) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 232, 218, 0.085) 1px, transparent 1px);
  background-size: 76px 76px;
}

/* A fixed flare layer behind everything, so the colour follows you down the
   page rather than only living in the hero. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(58% 46% at 82% -4%, rgba(0, 232, 218, 0.22), transparent 62%),
    radial-gradient(48% 42% at 2% 36%, rgba(255, 166, 77, 0.14), transparent 64%),
    radial-gradient(52% 44% at 96% 82%, rgba(139, 124, 246, 0.12), transparent 66%);
}

/* Section flares get stronger to match. */
.hero::before {
  background:
    radial-gradient(60% 48% at 78% 2%, rgba(0, 232, 218, 0.24), transparent 62%),
    radial-gradient(48% 42% at 4% 86%, rgba(255, 166, 77, 0.16), transparent 64%);
}
.sec--demo::before {
  background:
    radial-gradient(54% 44% at 10% 2%, rgba(0, 232, 218, 0.2), transparent 64%),
    radial-gradient(48% 42% at 94% 94%, rgba(255, 166, 77, 0.13), transparent 66%);
}
.hero::after, .sec--demo::after {
  background-image:
    linear-gradient(rgba(0, 232, 218, 0.2) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 232, 218, 0.2) 1px, transparent 1px);
  background-size: 76px 76px;
}

/* Let the field show through the panelled sections instead of sealing it off. */
.sec--alt, .proof { background: rgba(32, 32, 34, 0.55); }
.sec--demo { background: rgba(32, 32, 34, 0.42); }
.embed-frame { background: rgba(20, 20, 26, 0.55); }

/* One grid, not two.
   The body grid starts at the top of the page; .hero::after and
   .sec--demo::after each started a second copy at the top of their own
   section, so on the homepage two identical grids sat about a nav-height
   apart and beat against each other. The section grids go; the body grid
   covers the whole page on its own, and the sections keep their colour
   flares (::before), which is what was doing the real work anyway.
   Strength pulled back from 0.085 — it only needed to be legible. */
.hero::after, .sec--demo::after { display: none; }

body {
  background-image:
    linear-gradient(rgba(0, 232, 218, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 232, 218, 0.05) 1px, transparent 1px);
  background-size: 72px 72px;
}

/* ============================================================
   WIDE PAGE SHELL — leagues and rules match the message board
   Same outer width and the same heading measure, so the three
   content pages share one silhouette. The content goes into
   columns rather than stretching: a 1280px-wide paragraph is
   unreadable, a 1280px-wide pair of columns is not.
   ============================================================ */

/* .prose--cards came later in the file and was winning on 58rem. */
.prose--cards.prose--wide .wrap { max-width: var(--wrap); }

/* Rules: two columns of cards, with the intro and the closing line
   spanning the full width so the page still reads top to bottom. */
@media (min-width: 900px) {
  /* Balanced columns rather than a grid: the cards are very different
     lengths, and a grid row sized to the taller one left a block of dead
     space under the shorter. Columns let each card hug its own content. */
  .prose--cards.prose--wide .wrap {
    columns: 2;
    column-gap: var(--sp-3);
  }
  .prose--cards.prose--wide .prose-head,
  .prose--cards.prose--wide .wrap > p { column-span: all; }
  .prose--cards.prose--wide .rcard {
    break-inside: avoid;
    margin: 0 0 var(--sp-3);
  }
}

/* Live leagues: three across once there is room, instead of two
   stretched cards. */
@media (min-width: 980px) {
  .prose--wide .league-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ============================================================
   LIVE LEAGUES — cards beside the network records
   Two equal halves at the same column width as the Rules cards, so the
   three content pages share one silhouette. League cards go two-up in
   the left half; the Best Average and Most Perfect Games widgets stack
   in the right. Both are the app's own /embed routes, so the figures
   are always the live ones and can never drift from the product.
   ============================================================ */
.league-cols { display: block; }
.league-rail { display: grid; gap: var(--sp-3); margin-top: var(--sp-4); }
.rail-card {
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  background: rgba(20, 20, 26, 0.55);
}
.rail-card iframe { display: block; width: 100%; height: 542px; border: 0; }

@media (min-width: 1040px) {
  .league-cols {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
    align-items: start;
  }
  .league-rail { margin-top: 0; }
  /* two narrow cards per half, matching the Rules rhythm */
  .prose--wide .league-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* the card's single line of stats will not fit at this width */
  .league-card .meta { white-space: normal; line-height: 1.5; }
}

/* Side by side once there is room but before the halves kick in, so a
   tablet does not get one very tall stacked pair. */
@media (min-width: 700px) and (max-width: 1039px) {
  .league-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* At half-width the stats line was wrapping "SCORES" onto its own row. */
@media (min-width: 1040px) {
  .prose--wide .league-card .meta { letter-spacing: 0.035em; font-size: 0.71rem; }
}
/* ...and once it is that narrow, the channel reads better on its own line
   than wrapping mid-phrase. */
@media (min-width: 1040px) {
  .prose--wide .league-card .chan { display: block; }
  .prose--wide .league-card .dot { display: none; }
}

/* ============================================================
   STAR PANELS — the message board's look, on our own pages
   The app's embeds sit on #06060e with two faint radial washes and the
   drifting particle field over the top. Our pages already run that field
   site-wide, so a panel only has to be dark and translucent enough to
   let it through. The old .rcard had backdrop-filter: blur(16px), which
   blurred the stars behind it into nothing — that is why the cards read
   as flat slabs. Dropped.
   ============================================================ */
.rcard, .starpanel {
  position: relative;
  isolation: isolate;
  background: rgba(6, 6, 14, 0.58);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  box-shadow: 0 6px 32px rgba(0, 0, 0, 0.45);
}
/* the two washes the embeds use: sky blue in, violet out */
.rcard::before, .starpanel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background:
    radial-gradient(ellipse 60% 40% at 10% -10%, rgba(56, 189, 248, 0.10), transparent 70%),
    radial-gradient(ellipse 60% 40% at 90% 110%, rgba(168, 85, 247, 0.10), transparent 70%);
}

.starpanel {
  padding: clamp(1.4rem, 1rem + 2vw, 2.4rem);
  margin-top: var(--sp-4);
}
.starpanel > :first-child { margin-top: 0; }
.starpanel > :last-child  { margin-bottom: 0; }
/* the keyline rules read as double borders inside a panel */
.starpanel .keyline { opacity: 0.5; }

/* Leagues: the app's directory embed is the full left half. Fixed height so
   the two halves end together; it scrolls itself once the list outgrows it. */
.rail-card--dir iframe { height: 1126px; }
@media (max-width: 1039px) { .rail-card--dir iframe { height: 760px; } }

/* Panels carry their own field (starfield.js), so they can be solid again —
   same #06060e as the embeds, with the stars over the top rather than dimly
   behind. Translucency was letting the page grid through as well. */
.rcard, .starpanel {
  background-color: #06060e;
  background-image:
    radial-gradient(ellipse 60% 40% at 10% -10%, rgba(56, 189, 248, 0.07), transparent 70%),
    radial-gradient(ellipse 60% 40% at 90% 110%, rgba(168, 85, 247, 0.07), transparent 70%);
  overflow: hidden;   /* keep the canvas inside the rounded corners */
}
.rcard::before, .starpanel::before { display: none; }
.panel-stars {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.rcard > *:not(.panel-stars),
.starpanel > *:not(.panel-stars) { position: relative; z-index: 1; }

/* One reading width for the three content pages. Rules already sat at 58rem
   and reads well; App for Slack was narrower and the message board was the
   full 1280, which left a wide black band either side of the board's own
   700px posts. */
.prose--read .wrap { max-width: 58rem; }
.prose--read .prose-head { max-width: 50rem; }
.prose--read .embed-frame { margin-top: var(--sp-4); }
.prose--read .embed-frame iframe { height: 900px; }

/* The default minimum. The app highlights whatever the league is set to;
   here there is no league, so it marks the value a new one starts on. */
.rseg .is-on {
  border-color: rgba(0, 232, 218, 0.5);
  background: rgba(0, 232, 218, 0.08);
}
.rseg .is-on em { color: var(--cyan); }
.rseg .is-on span { color: var(--text-soft); }

/* Leagues directory: tall enough for the whole list, so the panel never
   grows its own scrollbar. The embed paginates at 20, and 20 cards need
   about 1950px — bump this if the directory outgrows it. */
.rail-card--dir iframe { height: 1160px; }
@media (max-width: 1039px) { .rail-card--dir iframe { height: 1160px; } }
/* The board is two posts long right now and a fixed 900px frame left most of
   it empty. Sized to the content with room for a few more; like the leagues
   directory this is a fixed number and needs raising as the board grows. */
.prose--read .embed-frame iframe { height: 620px; }
