/* ============================================================================
   site.css — the chrome that is the same on every page.
   Linked as /site.css (absolute) from every HTML entry point, before the page's
   own stylesheet.

   It exists because the nav used to be different on every route: the darts
   solver had a "← all tools" corner link, the tracker had "← solver", the stud
   solver had no way home at all, and /shits/, /tv/ and privacy.html were dead
   ends you could only leave with the back button. Two rules now:

     tier 1  .sitenav    where in the SITE you are   — identical on every page
     tier 2  .mode-tabs  where in the TOOL you are   — per page, same styling

   The tier-2 rules used to be copy-pasted (identically) into darts/styles.css,
   stud/styles.css and uth/styles.css; they live here once now so a tab looks
   the same whether it switches a panel or navigates to another page. That is
   deliberate: tabs are grouped by intent, not by implementation, so the reader
   should not be able to tell which is which.

   Colours are written as var(--x, literal). The app stylesheets define the
   palette on :root, but the hub, /tv/, /shits/ and privacy.html don't — the
   fallbacks are what those pages actually render.
   ========================================================================== */

/* ---------- the glass system (2026-09) ----------
   Every surface on the site is one of three materials, and the tokens below
   are the whole recipe. The app stylesheets consume them; nothing redefines
   them, so the frost, the hairline and the highlight match across routes.

     glass    top-level containers: panels, cards, docks, sheets, modals, the
              nav. Frosted — a translucent fill over a backdrop blur, a hairline
              border, a specular highlight along the top edge, and a soft drop.
              The blur only reads as glass when there is something behind it
              to refract, which is what the ambient backdrop (body::before,
              below) is for.
     inlay    surfaces INSIDE glass: stat tiles, score pills, the recorder's
              buttons, tables' hairlines. Same translucent fill and hairline,
              no blur — a blur inside a blur is invisible and costs a layer per
              element, and the dice felt alone has forty of them.
     solid    things that are physically opaque and would look wrong frosted:
              casino chips, playing cards, dice, the felt itself, the camera
              frame. They keep their own materials and just sit on the glass.

   Two things the recipe protects on purpose:
   - Legibility without blur. --g-base is opaque enough that a browser with no
     backdrop-filter (or one that drops it under memory pressure, as iOS does
     on long pages) still renders readable panels — the frost is a bonus, not
     the contrast.
   - Geometry. Nothing here changes a border width, a padding or a min-height
     that the app stylesheets set. Glass is paint, not layout: the fixed-slot
     rules that stop a landing number from nudging the button under a thumb
     are untouched. */
:root {
  --g-bg: #0a0d13;                                   /* the canvas under everything */
  --g-base: rgba(15, 19, 27, .58);                   /* glass fill, before the frost */
  --g-sheen: linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .035) 42%, rgba(255, 255, 255, .015));
  --g-line: rgba(255, 255, 255, .12);                /* hairline border */
  --g-line-strong: rgba(255, 255, 255, .20);
  --g-hi: inset 0 1px 0 rgba(255, 255, 255, .18);    /* the specular top edge */
  --g-lo: inset 0 -1px 0 rgba(0, 0, 0, .22);         /* and the shadowed bottom one */
  --g-drop: 0 14px 40px rgba(0, 0, 0, .42);
  --g-blur: blur(24px) saturate(1.55);
  --g-blur-soft: blur(14px) saturate(1.35);          /* nav, pills, docks — cheaper */
  --g-in-fill: rgba(255, 255, 255, .055);            /* inlay tiles */
  --g-in-fill-hover: rgba(255, 255, 255, .10);
  --g-in-line: rgba(255, 255, 255, .10);
  --g-well: rgba(0, 0, 0, .28);                      /* inputs, logs: recessed */
  --g-r-xl: 22px; --g-r-lg: 16px; --g-r-md: 12px; --g-r-sm: 9px;
}

/* The ambient backdrop: a deep canvas with a few soft colour fields the glass
   can blur — felt green, a little gold, the accent blue. A fixed pseudo rather
   than background-attachment:fixed because iOS Safari ignores the latter and
   scrolls the gradient away on any page taller than the screen. It sits at
   z-index -1 in the root stacking context, above the canvas colour (which the
   body background propagates to) and below every in-flow box, so the column-
   flex bodies on the hub, /tv/ and /shits/ never see it as a flex item —
   position:fixed takes it out of flow. */
body::before {
  content: "";
  position: fixed;
  inset: -12%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38% 34% at 12% 8%, rgba(11, 107, 58, .55), transparent 72%),
    radial-gradient(30% 28% at 88% 4%, rgba(240, 196, 25, .14), transparent 72%),
    radial-gradient(42% 38% at 74% 92%, rgba(74, 168, 255, .20), transparent 72%),
    radial-gradient(28% 30% at 18% 84%, rgba(124, 58, 237, .14), transparent 72%),
    radial-gradient(60% 50% at 50% 50%, rgba(22, 32, 43, .9), transparent 100%);
}

/* A utility for the odd one-off container (the /tv/ code card, the privacy
   sheet) that has no app stylesheet to carry the recipe. */
.glass {
  background: var(--g-sheen), var(--g-base);
  border: 1px solid var(--g-line);
  box-shadow: var(--g-hi), var(--g-lo), var(--g-drop);
  -webkit-backdrop-filter: var(--g-blur);
  backdrop-filter: var(--g-blur);
}

/* ---------- tier 1: the site bar ---------- */

/* Not sticky, on purpose. It scrolls away with the page header: the Match
   scoreboard and the tracker's live view need every vertical pixel on a phone,
   and a pinned bar is 44px of permanent cost for a control you use twice a
   session. */
.sitenav {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 44px;
  width: 100%;
  flex: 0 0 auto;   /* the hub, /shits/ and /tv/ are column flex bodies — don't let it squash */
  padding: 0 12px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .02)), rgba(10, 13, 19, .55);
  border-bottom: 1px solid var(--g-line);
  box-shadow: var(--g-hi);
  -webkit-backdrop-filter: var(--g-blur-soft);
  backdrop-filter: var(--g-blur-soft);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: .85rem;
  font-weight: 650;
  line-height: 1;
  /* narrow phones scroll the row rather than wrapping it — a wrapped nav
     changes the page's height and shoves the content below it down */
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.sitenav::-webkit-scrollbar { display: none; }
.sitenav a { text-decoration: none; white-space: nowrap; }

.sitenav-home {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: 0 0 auto;
  padding: 6px 8px;
  border-radius: 9px;
  color: var(--ink, #e8edf2);
}
.sitenav-home:hover { background: rgba(255, 255, 255, .08); }

.sitenav-sep { flex: 0 0 auto; width: 1px; height: 20px; background: var(--g-line); }

.sitenav-links { display: flex; align-items: center; gap: 4px; }
.sitenav-links a {
  padding: 6px 11px;
  border: 1px solid transparent;
  border-radius: 999px;
  color: var(--muted, #93a1b0);
}
.sitenav-links a:hover { color: var(--ink, #e8edf2); background: rgba(255, 255, 255, .08); }
/* current page: tinted, not filled — the filled gold pill is tier 2's active
   state, and the two rows must not compete for the eye */
.sitenav-links a[aria-current="page"] {
  color: var(--gold, #f0c419);
  background: rgba(240, 196, 25, .12);
  border-color: rgba(240, 196, 25, .38);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12);
}

/* Tighten up on narrow phones — the wordmark plus three tool pills still fit
   at 390px, so nothing has to be hidden or scrolled to. */
@media (max-width: 430px) {
  .sitenav { gap: 8px; padding: 0 8px; }
  .sitenav-links a { padding: 6px 9px; }
}

/* ---------- tier 2: in-tool tabs ---------- */

.mode-tabs {
  max-width: 1180px;
  margin: 16px auto 0;
  padding: 0 16px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
/* a <button> switches a panel, an <a class="tab-link"> navigates to a sibling
   page — same pill either way. The pills sit straight on the backdrop, so a
   light blur is what makes them read as glass rather than as flat chips. */
.mode-tabs button,
.mode-tabs a.tab-link {
  background: linear-gradient(180deg, rgba(255, 255, 255, .09), rgba(255, 255, 255, .03)), rgba(15, 19, 27, .35);
  border: 1px solid var(--g-line);
  box-shadow: var(--g-hi);
  -webkit-backdrop-filter: var(--g-blur-soft);
  backdrop-filter: var(--g-blur-soft);
  color: var(--muted, #93a1b0);
  border-radius: 999px;
  padding: 7px 18px;
  font-weight: 650;
  text-decoration: none;
}
.mode-tabs button.active,
.mode-tabs a.tab-link.active {
  background: linear-gradient(180deg, #ffd955, var(--gold, #f0c419));
  border-color: rgba(255, 230, 140, .7);
  color: #241c02;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 6px 18px rgba(240, 196, 25, .28);
}
.mode-tabs button:not(.active):hover,
.mode-tabs a.tab-link:not(.active):hover {
  border-color: rgba(240, 196, 25, .55);
  color: var(--gold, #f0c419);
  background: linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, .05)), rgba(15, 19, 27, .35);
}

/* second-level nav inside a tab (stud's Practice / Strategy groups) */
.sub-tabs {
  max-width: 1180px;
  margin: 10px auto 0;
  padding: 0 16px;
  display: flex;
  gap: 8px;
  align-items: center;
}
.sub-tabs::before { content: '↳'; color: var(--muted, #93a1b0); font-size: .9rem; }
.sub-tabs button {
  background: rgba(255, 255, 255, .03);
  border: 1px solid var(--g-line);
  color: var(--muted, #93a1b0);
  border-radius: 999px;
  padding: 4px 14px;
  font-size: .85rem;
  font-weight: 600;
}
.sub-tabs button.active { border-color: rgba(240, 196, 25, .55); color: var(--gold, #f0c419); background: rgba(240, 196, 25, .10); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .10); }
.sub-tabs button:not(.active):hover { border-color: var(--g-line-strong); color: var(--ink, #e8edf2); background: rgba(255, 255, 255, .07); }

@media (max-width: 900px) {
  .mode-tabs, .sub-tabs { justify-content: center; gap: 6px; margin-top: 12px; padding: 0 10px; }
  /* fat-finger targets: these are tapped between throws */
  .mode-tabs button, .mode-tabs a.tab-link { padding: 9px 14px; font-size: .85rem; }
}

/* Phones: one row that scrolls sideways instead of wrapping to two. A wrapped
   tab row changes the page's height per tab count and costs ~44px of fold —
   the same reasoning as the sitenav's overflow-x above. */
@media (max-width: 640px) {
  .mode-tabs, .sub-tabs {
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    margin-top: 10px;
  }
  .mode-tabs::-webkit-scrollbar, .sub-tabs::-webkit-scrollbar { display: none; }
  .mode-tabs button, .mode-tabs a.tab-link, .sub-tabs button {
    flex: 0 0 auto;
    white-space: nowrap;
  }
}

/* Touch polish, everywhere the shared chrome loads: kill the grey iOS tap
   flash (each app paints its own pressed state) and the 300ms double-tap
   wait on the controls that get hammered mid-game. */
.sitenav a, .mode-tabs button, .mode-tabs a.tab-link, .sub-tabs button {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.mode-tabs button:active, .mode-tabs a.tab-link:active, .sub-tabs button:active {
  transform: scale(.96);
}
.mode-tabs button, .mode-tabs a.tab-link, .sub-tabs button { transition: transform .06s ease, background .15s ease, color .15s ease, border-color .15s ease; }
@media (prefers-reduced-motion: reduce) {
  .mode-tabs button:active, .mode-tabs a.tab-link:active, .sub-tabs button:active { transform: none; }
}
