/* ═══════════════════════════════════════════════════════════════════════════
   Public site
   ═══════════════════════════════════════════════════════════════════════════
   The landing page, the legal pages, the 404, and the shell a shared match or
   player sits inside.

   This was the last 140 lines of styles.css, which meant the landing page —
   a headline and a badge — waited on 133 KB of scoring-app CSS it never used.
   It is its own file now, and the only stylesheet the landing page loads.

   The scorecard is still drawn by styles.css: the batting table, the innings
   blocks and the award badges are rendered by markup lifted straight out of
   the scoring app. index.html asks for that file only when the address is a
   shared link, and puts it *ahead* of this one, so what is here still has the
   last word exactly as it did when both lived in one file.

   Two rules follow from sharing a page with that stylesheet. Nothing here
   styles a bare element beyond the reset, because a rule for `h2` would reach
   into the scorecard. And a token that styles.css also defines keeps the
   value it has there — the ones that differ have their own names.
   ═════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;

  /* ── Shared with styles.css, value for value ── */
  --bg:             #FAFAF8;
  --surface:        #FFFFFF;
  --surface-raised: #F5F4F0;
  --ink:            #1A1A18;
  --ink-soft:       #5B6066;
  --line:           rgba(0, 0, 0, 0.09);
  --accent-glow:    rgba(22, 163, 74, 0.18);
  --font-display:   "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body:      "Inter", -apple-system, system-ui, sans-serif;
  --font-mono:      "Space Mono", "Courier New", monospace;

  /* ── This file's own ──
     The brand green is 3.2:1 on the page ground: fine for a score readout,
     failing for 12px text. `--accent-strong` is the text-safe partner the
     phone app uses for the same reason, and `--ink-quiet` is its muted text.
     Both are named apart from `--accent` and `--ink-muted` so that loading
     this file after styles.css does not recolour the scorecard. */
  --accent-strong:  #15803D;
  --ink-quiet:      #686D75;

  /* The pair the launcher icon and the Play feature graphic are built from. */
  --navy:           #091B2D;
  --lime:           #ACE426;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--ink);
  /* The glow is given a box of its own rather than the whole page. Sized to
     the body it grew with the document, so a long scorecard or a long landing
     page had a green wash running most of the way down the left edge. */
  background:
    radial-gradient(circle at 15% 0%, var(--accent-glow) 0%, transparent 45%)
      top / 100% 900px no-repeat,
    var(--bg);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

/* ── One screen at a time ──────────────────────────────────────────────────
   index.html holds three and settles which one the address is for in an
   inline script, before first paint. The landing page is the one that shows
   with no script at all, so a visitor with JavaScript off still gets it.

   `animation: none` because styles.css fades a `.screen` up when it appears.
   That stylesheet arrives after the shell has already painted, and gaining an
   animation mid-load replays it: the header would blink out and slide back. */
.screen { display: none; animation: none; }
#screen-landing { display: block; }
html[data-screen="match"] #screen-landing,
html[data-screen="player"] #screen-landing { display: none; }
html[data-screen="match"] #screen-match,
html[data-screen="player"] #screen-player { display: block; }

/* === Shell === */
.public-shell {
  max-width: 940px;
  margin: 0 auto;
  padding: clamp(16px, 4vw, 40px) clamp(16px, 4vw, 32px) 64px;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

/* The landing page spaces its own sections, and has more to lay side by side
   than a scorecard does. */
.public-shell--landing { max-width: 1080px; gap: 0; }

/* Running text is easier to read in a narrower column than a scorecard is. */
.public-shell--legal { max-width: 760px; }

.public-shell a:focus-visible,
.public-shell summary:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 3px;
  border-radius: 6px;
}

/* === Mast === */
.public-mast { display: flex; align-items: center; gap: 10px; }
.public-back {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit;
}
/* A fraction rather than a length, so the corner is the same shape at 44px on
   the landing page and at 36px above a scorecard. */
.public-mark { display: block; border-radius: 22.7%; }

/* The app's name over who makes it. Stacked rather than run together on one
   line, so "Bat & Ball" stays the thing being read and the publisher sits
   under it — at a phone width the two side by side wrap mid-phrase. */
.public-brand { display: flex; flex-direction: column; line-height: 1.15; }
.public-wordmark {
  font-family: var(--font-display); font-weight: 800; font-size: 17px;
  letter-spacing: -0.015em; color: var(--ink);
}
.public-byline { font-size: 12px; color: var(--ink-quiet); letter-spacing: 0.01em; }

/* Google's badge, sized by height and never restyled: their brand terms ask
   for the supplied artwork unmodified, and the clear space around the
   wordmark is already part of the image.

   That clear space is why it is pulled left by 10px. At 60px tall the file
   carries 10px of transparent margin on every side, so the black badge sat
   visibly indented from the text it belongs under. The margin is still all
   there — it now overlaps the page gutter, which is empty anyway. */
.public-badge {
  align-self: flex-start; display: inline-block;
  margin: 2px 0 0 -10px; text-decoration: none;
}
.public-badge img { display: block; height: 60px; width: auto; }

.public-link {
  color: var(--accent-strong); font-weight: 600;
  text-underline-offset: 3px;
}

/* === Landing: hero === */
.public-hero {
  display: flex; flex-direction: column; align-items: flex-start; gap: 16px;
  padding-top: clamp(32px, 7vw, 84px);
}
.public-eyebrow {
  margin: 0; font-size: 12px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--accent-strong);
}
/* Archivo, as on the app's own titles and on the Play listing. This was set
   in Inter only because nothing had said otherwise: the heading inherited the
   body face, and the display face the page was already downloading the
   stylesheet for went unused. */
/* The size is worked back from the longer line. "Share every scorecard." is
   10.8 times the font size wide in this face, so 8.3vw keeps it at about 89%
   of the viewport — inside the gutters at every width, and on one line down
   to a 360px phone. A little larger and it breaks after "every", which turns
   a two-line headline into three ragged ones on exactly the screens most of
   the audience holds. */
.public-hero h1 {
  margin: 0;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(30px, 8.3vw, 72px); line-height: 0.98;
  letter-spacing: -0.035em; text-wrap: balance;
}
.public-lede {
  margin: 4px 0 0; max-width: 56ch;
  font-size: clamp(16px, 2vw, 18.5px); line-height: 1.6;
  color: var(--ink-soft);
}
.public-fineprint { margin: 0; font-size: 13px; color: var(--ink-quiet); }

/* One entrance, on load, and nothing after it. Inside the 320ms the phone
   app holds its own motion to. */
@media (prefers-reduced-motion: no-preference) {
  .public-hero > * { animation: public-rise 300ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
  .public-hero > :nth-child(2) { animation-delay: 40ms; }
  .public-hero > :nth-child(3) { animation-delay: 80ms; }
  .public-hero > :nth-child(4) { animation-delay: 120ms; }
  .public-hero > :nth-child(5) { animation-delay: 160ms; }
}
@keyframes public-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* === Landing: the stage ===
   The top of the landing page, set at night: the icon's navy, edge to edge,
   with the ground js/ground.js draws lying across it. On a wide screen the
   copy stands to the left and the ground to the right; on a narrow one the
   copy is on top and the ground has the space underneath.

   The three `--ground-*` properties say where that ground is. The script
   reads the same split from the stage's width, and the still backdrop below
   uses them, so the picture a visitor gets with no WebGL is in the same place
   as the one they get with it. */
.public-stage {
  --ground-x: 79%;
  --ground-y: 58%;
  --ground-w: min(56vw, 860px);

  position: relative; isolation: isolate; overflow: hidden;
  color: #fff;
  background:
    radial-gradient(110% 80% at var(--ground-x) var(--ground-y), #11314B 0%, var(--navy) 52%, #050F1A 100%);
}

/* Three layers, bottom to top: a still outline of the ground, the canvas,
   and a scrim that keeps the copy legible whatever passes behind it. */
.public-stage__scene { position: absolute; inset: 0; z-index: -1; }

/* What is there before the scene, and instead of it if the scene never
   comes: the rope, as a flat ellipse, where the ground will be. It is drawn
   at the same tilt the camera settles to, so the real thing fades up through
   it rather than replacing it with something a different shape. */
.public-stage__scene::before {
  content: ""; position: absolute;
  left: var(--ground-x); top: var(--ground-y);
  width: var(--ground-w); aspect-ratio: 2 / 1;
  /* Nudged down by a fraction of its own width. The camera looks at the
     middle of the pitch, but in perspective the near half of the rope is
     drawn larger than the far half, so the shape it makes sits lower than
     the point it is centred on. */
  margin-top: calc(var(--ground-w) * 0.07);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 1.5px solid rgba(172, 228, 38, 0.45);
  background: radial-gradient(closest-side, rgba(20, 96, 60, 0.5), rgba(12, 58, 43, 0.32) 72%, rgba(12, 58, 43, 0) 100%);
  box-shadow: 0 0 48px rgba(172, 228, 38, 0.1);
  transition: opacity 900ms ease;
}
.public-stage__scene.is-live::before { opacity: 0; }

.public-stage__scene canvas {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%;
  opacity: 0; transition: opacity 1200ms ease;
}
.public-stage__scene.is-live canvas { opacity: 1; }

.public-stage__scene::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(
    90deg,
    rgba(9, 27, 45, 0.92) 0%, rgba(9, 27, 45, 0.66) 30%, rgba(9, 27, 45, 0) 54%
  );
}

.public-stage > .public-shell {
  position: relative;
  min-height: clamp(600px, 100svh, 840px);
  padding-bottom: clamp(32px, 6vw, 64px);
}
/* The copy takes the height the mast leaves and sits in the middle of it. */
.public-stage .public-hero {
  flex: 1; justify-content: center;
  max-width: 560px; padding-top: 0;
}
/* Sized for the column rather than the window: 51px is the largest at which
   the longer line still fits the 560px the copy is given, and 560px is as far
   right as the copy can reach before it is standing on the rope. */
.public-stage .public-hero h1 { font-size: clamp(30px, 8.3vw, 51px); }

.public-stage .public-wordmark { color: #fff; }
.public-stage .public-byline { color: rgba(255, 255, 255, 0.62); }
.public-stage .public-eyebrow { color: var(--lime); }
.public-stage .public-lede { color: rgba(255, 255, 255, 0.8); }
.public-stage .public-fineprint { color: rgba(255, 255, 255, 0.6); }
.public-stage a:focus-visible { outline-color: var(--lime); }

/* The sections under the stage start from its edge, not from a second top
   margin. */
.public-stage + .public-shell { padding-top: 0; }

/* ── The over ──
   The chips the scene adds as each ball is bowled: the glyphs a scorer's pad
   carries, in the colours the app gives them. A four is blue and a wicket is
   red on every scorecard, and here.

   The row holds its height from the start and is merely invisible until the
   scene is running. Appearing later would push the copy up by its own height
   a second or two after the page had settled. */
.public-over {
  display: flex; align-items: center; gap: 12px;
  min-height: 34px; margin-top: 6px;
  visibility: hidden;
}
.public-stage__scene.is-live ~ .public-shell .public-over { visibility: visible; }
.public-over__label {
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  transition: opacity 400ms ease;
}
/* Between overs there is nothing to label. */
.public-over:not(:has(.public-ball)) .public-over__label { opacity: 0; }
.public-over__balls { display: flex; gap: 6px; }
.public-ball {
  display: grid; place-items: center;
  min-width: 32px; height: 32px; padding: 0 5px;
  border-radius: 9px;
  border: 1.5px solid rgba(255, 255, 255, 0.34);
  font-family: var(--font-mono); font-weight: 700; font-size: 13px;
  color: #fff;
}
.public-ball--four   { background: #2563EB; border-color: #2563EB; }
.public-ball--six    { background: #7E22CE; border-color: #7E22CE; }
.public-ball--wicket { background: #DC2626; border-color: #DC2626; }
.public-ball--wide   { background: #B45309; border-color: #B45309; }
/* Space Mono is for numerals. A W is not one, and in that face at this size
   it reads as three upright strokes. */
.public-ball--wicket, .public-ball--wide {
  font-family: var(--font-display); font-weight: 800; letter-spacing: -0.01em;
}
@media (prefers-reduced-motion: no-preference) {
  .public-ball { animation: public-ball-in 240ms cubic-bezier(0.2, 0.9, 0.3, 1.25) both; }
}
@keyframes public-ball-in {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: none; }
}

/* Under 900px there is no room for copy and ground side by side, so the
   ground goes below: the shell leaves a square-ish space under the copy and
   the scene is drawn into it. */
@media (max-width: 899px) {
  .public-stage {
    --ground-x: 50%;
    --ground-y: calc(100% - min(44vw, 235px));
    --ground-w: min(112vw, 620px);
  }
  .public-stage__scene::after {
    background: linear-gradient(
      180deg,
      rgba(9, 27, 45, 0.92) 0%, rgba(9, 27, 45, 0.72) 44%, rgba(9, 27, 45, 0) 64%
    );
  }
  .public-stage > .public-shell { min-height: 0; padding-bottom: min(88vw, 470px); }
  .public-stage .public-hero {
    flex: none; max-width: none;
    padding-top: clamp(28px, 7vw, 56px);
  }
}

/* === Landing: sections === */
.public-section { margin-top: clamp(64px, 10vw, 120px); }
.public-section > h2 {
  margin: 0 0 clamp(22px, 3.2vw, 36px); max-width: 20ch;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(26px, 4vw, 40px); line-height: 1.05;
  letter-spacing: -0.028em; text-wrap: balance;
}

/* ── What it does ──
   Surfaces are a hairline and a soft shadow, as in the app, rather than a
   tinted block. */
.public-features {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.public-feature {
  padding: 20px 22px 22px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 14px rgba(0, 0, 0, 0.03);
}
/* Space Mono is for numerals and nothing else — the same rule the app keeps. */
.public-feature__no {
  display: block; margin-bottom: 16px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.04em;
  color: var(--accent-strong);
}
.public-feature h3 {
  margin: 0 0 6px;
  font-family: var(--font-display); font-weight: 700; font-size: 17.5px;
  letter-spacing: -0.012em;
}
.public-feature p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); }

/* ── One link ──
   Three steps under a single rule, each marked the way a delivery is marked
   in the over strip: a numeral in a ball. */
.public-steps {
  list-style: none; margin: 0; padding: clamp(22px, 3vw, 30px) 0 0;
  border-top: 2px solid var(--ink);
  display: grid; gap: 28px clamp(24px, 4vw, 48px);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.public-step__no {
  display: grid; place-items: center;
  width: 38px; height: 38px; margin-bottom: 16px;
  border-radius: 50%;
  border: 1.5px solid var(--ink);
  font-family: var(--font-mono); font-weight: 700; font-size: 15px;
}
/* The last ball of the three is the one that scores. */
.public-step:last-child .public-step__no {
  background: var(--accent-strong); border-color: var(--accent-strong); color: #fff;
}
.public-step h3 {
  margin: 0 0 6px;
  font-family: var(--font-display); font-weight: 700; font-size: 19px;
  letter-spacing: -0.015em;
}
.public-step p { margin: 0; max-width: 34ch; font-size: 15px; line-height: 1.55; color: var(--ink-soft); }

/* ── Questions ── */
.public-faq { max-width: 760px; border-top: 1px solid var(--line); }
.public-faq details { border-bottom: 1px solid var(--line); }
.public-faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 2px; cursor: pointer; list-style: none;
  font-weight: 600; font-size: 16px; line-height: 1.35;
}
.public-faq summary::-webkit-details-marker { display: none; }
.public-faq summary::after {
  content: "+"; flex: none;
  font-family: var(--font-mono); font-size: 20px; line-height: 1;
  color: var(--accent-strong);
  transition: transform 180ms ease;
}
.public-faq details[open] summary::after { transform: rotate(45deg); }
.public-faq p {
  margin: 0; padding: 0 2px 20px; max-width: 62ch;
  font-size: 15px; line-height: 1.6; color: var(--ink-soft);
}

/* ── The closing band ──
   The Play feature graphic's ground — navy, lifted towards one side, with the
   icon's rising diagonal run faintly across it — so the last thing on the
   page and the first thing on the listing are visibly the same product. */
.public-band {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 24px 40px;
  padding: clamp(28px, 6vw, 60px);
  border-radius: 22px;
  background: var(--navy); color: #fff;
}
.public-band::before {
  content: ""; position: absolute; inset: -20% -10%; z-index: -1;
  background: repeating-linear-gradient(
    58deg, transparent 0 26px, rgba(172, 228, 38, 0.05) 26px 28px
  );
}
.public-band::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(60% 90% at 14% 50%, rgba(172, 228, 38, 0.16), transparent 62%),
    radial-gradient(80% 120% at 105% 8%, rgba(172, 228, 38, 0.09), transparent 60%);
}
.public-band h2 {
  margin: 0;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(28px, 4.6vw, 46px); line-height: 1.02;
  letter-spacing: -0.03em; text-wrap: balance;
}
.public-band h2 em { font-style: normal; color: var(--lime); }
.public-band p {
  margin: 12px 0 0; font-size: 15.5px; line-height: 1.5;
  color: rgba(255, 255, 255, 0.82); text-wrap: balance;
}
/* No optical pull here: the badge is its own flex item, not under a column of
   text it has to line up with. */
.public-band .public-badge { margin: 0; align-self: center; }
.public-band a:focus-visible { outline-color: var(--lime); }

/* === Footer === */
.public-foot {
  margin-top: clamp(40px, 6vw, 64px); padding-top: 20px;
  display: flex; flex-wrap: wrap; gap: 10px 18px;
  font-size: 13px; color: var(--ink-quiet);
  border-top: 1px solid var(--line);
}
.public-foot a { color: inherit; text-underline-offset: 3px; }
.public-foot p { flex-basis: 100%; margin: 0; font-size: 12px; }

/* === A match, a player === */
.public-head { display: flex; flex-direction: column; gap: 4px; }
.public-head h1 {
  margin: 0;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(22px, 4vw, 30px); letter-spacing: -0.02em; text-wrap: balance;
}
.public-sub { margin: 0; font-size: 14px; color: var(--ink-quiet); }

.public-note { padding: 40px 4px; font-size: 15px; line-height: 1.6; color: var(--ink-soft); }
.public-note p { margin: 0; }

.pcard { margin-top: 18px; }
.pcard h3 {
  margin: 0 0 10px; font-size: 12px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-quiet);
}
.pstats { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); }
.pstat {
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 16px; border-radius: 10px;
  background: var(--surface-raised);
}
.pstat__value { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.pstat__label { font-size: 12px; color: var(--ink-quiet); }

/* Where a spectator finds out what drew the scorecard they are reading. It
   was one line of text and a text link; it is most of the reason anybody who
   was sent a match ends up scoring one, so it now carries the icon they will
   look for in the store and the badge that takes them there. */
.public-install {
  margin-top: 36px; padding: 18px 20px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 16px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 14px rgba(0, 0, 0, 0.03);
}
.public-install__text { flex: 1 1 220px; min-width: 0; }
.public-install__text strong {
  display: block;
  font-family: var(--font-display); font-weight: 700; font-size: 16.5px;
  letter-spacing: -0.012em;
}
.public-install__text span {
  display: block; margin-top: 2px;
  font-size: 14px; line-height: 1.5; color: var(--ink-soft);
}
.public-install .public-badge { margin: 0; align-self: center; }
.public-install .public-badge img { height: 54px; }

/* === Legal pages === */
.legal { font-size: 16px; line-height: 1.7; }
.legal h1 {
  margin: 0 0 4px;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(28px, 5vw, 38px); line-height: 1.05; letter-spacing: -0.028em;
}
.legal h2 {
  margin: 34px 0 8px;
  font-family: var(--font-display); font-weight: 700; font-size: 19px;
  letter-spacing: -0.012em;
  /* A heading reached by its fragment — `#account-deletion` is the address
     the Play data-safety form points at — should not land flush against the
     top edge of the window. */
  scroll-margin-top: 20px;
}
.legal p, .legal li { margin-top: 0; color: var(--ink-soft); }
.legal strong { color: var(--ink); }
.legal ul { padding-left: 1.4rem; }
.legal li { margin-bottom: 0.35rem; }
.legal a { color: var(--accent-strong); text-underline-offset: 3px; }
.legal__meta { margin-bottom: 28px; font-size: 13px; color: var(--ink-quiet); }
.legal__card {
  margin-bottom: 1rem; padding: 20px 22px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
}
.legal__card p:last-child { margin-bottom: 0; }
.legal__highlight {
  margin: 1.25rem 0; padding: 14px 18px;
  border-left: 3px solid var(--accent-strong);
  border-radius: 0 12px 12px 0;
  background: var(--surface);
}
.legal__highlight p { margin: 0; font-size: 15px; }

/* ── The landing page on a phone ───────────────────────────────────────────
   The layout is already mobile-first and does not overflow. What changes at
   this width is weight: a full-size feature card is too much padding for a
   single column, and the closing band's badge belongs under its heading
   rather than squeezed beside it. */
@media (max-width: 559px) {
  .public-shell { padding-bottom: 40px; }
  .public-shell:not(.public-shell--landing) { gap: 20px; }

  .public-features { gap: 10px; }
  .public-feature { padding: 16px 18px 18px; }
  .public-feature__no { margin-bottom: 10px; }

  .public-band { border-radius: 18px; }

  /* The badge drops to a row of its own here, where its built-in clear space
     reads as a hole between it and the text above, and as an indent against
     the icon. Close the first and pull back the second. */
  .public-install { gap: 2px 14px; }
  .public-install .public-badge { margin: 0 0 -6px -9px; }

  .public-foot { gap: 10px 18px; }
}
