/* ============================================================
   Blue Tees Usage — shared chrome
   Rail, brand, nav, product switch, page frame, mobile header, theme
   toggle. Loaded by ALL FOUR pages.

   This is the third and last copy of the rail to be eliminated: the two
   dashboards shared theirs in PR #30, and methodology.html / guide.html
   kept private duplicates until now. One definition, four pages.

   Dashboard-only controls (presets, granularity, date fields, delta,
   empty-note) live in app.css, which only the dashboards load.
   ============================================================ */

* {
  box-sizing: border-box;
  letter-spacing: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  color: var(--text-primary);
  background: var(--surface-page);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

button {
  cursor: pointer;
}

/* The pre-existing focus ring, kept as a visible 2px offset ring but now
   token-driven so it stays AA in both themes. */
button:focus-visible,
input:focus-visible,
a:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset-width);
}

/* ---------- Brand ---------- */

/* The mark is the real Blue Tees logo — the crossed tees, same artwork the
   favicons are cut from, so the tab icon and the rail cannot drift. It is a
   raster because the plate is baked into the supplied file: 200x200 covers a
   30px box well past @2x, and `cover` clips it to the chip radius.

   It is drawn as a background on an empty `aria-hidden` span rather than an
   `<img>` on purpose — "Blue Tees" sits next to it as real text in every
   place the mark appears, so an alt string would only repeat the wordmark to
   a screen reader. Decorative here means decorative.

   The plate is a constant near-black (#171A23) in both themes: in light it
   reads as an object against the rail, and in dark it sits within a few
   points of --surface-raised, so what reads is the white mark itself rather
   than the chip. That is the artwork's own composition, not a token, which
   is why no theme-swapped --mark-bg survives. */
.brand-mark {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: var(--radius-md);
  background: url("blue-tees-mark.png") center / cover no-repeat;
  box-shadow: var(--shadow-xs);
}

.brand-name {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--weight-black);
  letter-spacing: var(--type-wordmark-track);
  line-height: 1;
  color: var(--text-primary);
  text-transform: uppercase;
}

/* ---------- Rail ----------
   Now a light surface with a hairline right edge, not a near-black slab.
   These rules were previously duplicated in both dashboards with trivial
   differences (a 1px gap here, a 1px margin there); porting them made the
   two copies identical, so they live here now. */

.rail {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 20;
  width: var(--rail-width);
  padding: var(--space-10) var(--space-7) var(--space-8);
  color: var(--text-primary);
  background: var(--surface-raised);
  border-right: 1px solid var(--border-default);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 40px;
  margin: 0 6px 28px;
}

.brand-sub {
  display: block;
  margin-top: 4px;
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 9px;
  font-weight: var(--weight-bold);
  letter-spacing: var(--type-wordmark-sub-track);
  text-transform: uppercase;
}

.nav {
  display: grid;
  gap: 3px;
}

.nav a {
  min-height: 40px;
  padding: 9px 11px;
  color: var(--text-secondary);
  text-decoration: none;
  border-left: 2px solid transparent;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  gap: 10px;
  transition: var(--transition-color);
}

.rail-label {
  margin: 0 10px 8px;
  color: var(--text-faint);
  font-size: var(--type-overline-size);
  font-weight: var(--weight-bold);
  letter-spacing: var(--type-overline-track);
  text-transform: uppercase;
}

.rail-label.section-label {
  margin-top: 21px;
}

.nav a:hover {
  color: var(--text-primary);
  background: var(--surface-hover);
  border-left-color: transparent;
}

/* Active nav is the one place brand blue is allowed to mark state. */
.nav a.active {
  color: var(--text-primary);
  background: var(--accent-soft);
  border-left-color: var(--brand);
}

.nav svg {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
}

/* ---------- Product switch (segmented) ---------- */

.product-switch {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px;
  padding: 3px;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
}

.product-switch a {
  min-height: 34px;
  padding: 8px 6px;
  color: var(--text-secondary);
  border: 0;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-decoration: none;
  text-transform: uppercase;
  transition: var(--transition-color);
}

.product-switch a:hover {
  color: var(--text-primary);
}

.product-switch a.active {
  color: var(--text-primary);
  background: var(--surface-raised);
  font-weight: var(--weight-bold);
  box-shadow: var(--shadow-inset-control);
}

.rail-note {
  margin-top: auto;
  padding: 12px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-inset);
  color: var(--text-muted);
  font-size: 11px;
  line-height: 1.55;
}

.rail-note strong {
  display: block;
  margin-bottom: 3px;
  color: var(--text-primary);
  font-size: 11px;
  font-weight: var(--weight-bold);
}

/* Sign-out block, token treatment for the PORTED light rail.
   auth-gate.css gives it an inherit-based baseline so it stays legible on the
   still-dark rails in methodology.html and guide.html; this is scoped under
   .rail so it outranks that baseline regardless of stylesheet order, and only
   applies on the two pages that load app.css. */
.rail .rail-auth {
  color: var(--text-muted);
}

.rail .rail-auth .rail-user {
  color: var(--text-secondary);
  opacity: 1;
}

.rail .rail-auth button {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--text-secondary);
  opacity: 1;
  transition: var(--transition-color);
}

.rail .rail-auth button:hover {
  border-color: var(--border-strong);
  color: var(--text-primary);
  opacity: 1;
}

/* ---------- Page frame ---------- */

main {
  margin-left: var(--rail-width);
  min-width: 0;
}

.topbar {
  min-height: 72px;
  padding: 16px clamp(20px, 3vw, 42px);
  border-bottom: 1px solid var(--border-default);
  background: var(--surface-raised);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  position: sticky;
  top: 0;
  z-index: 15;
}

.page {
  width: min(100%, 1560px);
  margin: 0 auto;
  padding: 24px clamp(20px, 3vw, 42px) 48px;
}

/* "Data is live" indicator beside the page title. Was a per-product accent
   (cyan on LAUNCH, lime on GAME) that themed badly and meant nothing — the
   dot says "fresh", so it is the positive token on both. */
.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--positive);
  box-shadow: 0 0 0 4px var(--positive-soft);
}

.title-wrap h1 {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-page-title-size);
  font-weight: var(--weight-black);
  letter-spacing: var(--type-page-title-track);
  line-height: var(--type-page-title-line);
  color: var(--text-primary);
}

.title-wrap p {
  margin: 3px 0 0;
  color: var(--text-secondary);
  font-size: 12.5px;
}

/* The selected segment is a raised thumb, not a filled block — it reads as
   "this one is on top" rather than "this one is a button". */
.preset.active,
.gran-btn.active {
  color: var(--text-primary);
  background: var(--surface-raised);
  font-weight: var(--weight-bold);
  box-shadow: var(--shadow-inset-control);
}

/* Marks panels whose numbers are all-time and do NOT follow the date range.
   This is the snapshot marker from the design system: a point-in-time metric
   the date picker cannot move. */
.static-badge {
  flex-shrink: 0;
  align-self: flex-start;
  padding: 3px 9px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--snapshot-soft);
  /* --text-secondary, not --snapshot: the two are the same grey family, but
     --snapshot on --snapshot-soft measures 4.49:1 and this text is 10px, so it
     needs the full 4.5. See the note on --text-muted in tokens.css. */
  color: var(--text-secondary);
  font-size: 10px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.table-wrap {
  overflow-x: auto;
}

th:first-child,
td:first-child {
  text-align: left;
}

.method a {
  color: var(--text-link);
  text-decoration: none;
  border-bottom: 1px solid var(--accent-soft-border);
  transition: var(--transition-color);
}

.method a:hover {
  color: var(--text-link-hover);
  border-bottom-color: currentColor;
}

/* ---------- Mobile header ----------
   Below 980px the rail is hidden, so the product switch and the sign-out
   both have to live here. This block is shared, so the two dashboards
   cannot collapse differently.

   The row wraps, and that is the whole small-screen story. The brand links
   (LAUNCH / GAME / MCP / DATA) measure ~254px and cannot shrink; the auth
   group needs ~107px before the email even appears. Sum plus the 12px gap
   and the topbar's 32px of padding: one row needs a ~404px viewport, so
   without wrapping the sign-out hangs off the right edge on every phone up
   to and including a 390px iPhone — not only the 320px class. Wrapping is
   self-triggering, so no breakpoint is involved: the auth group drops to a
   second row exactly when it stops fitting (~543px and below, once the
   email is measured in), and above that the header is one row as before.

   Wrapping rather than hiding or collapsing is deliberate. Sign-out is
   destructive, so it keeps its label and stays visible at every width
   instead of shrinking to a glyph or moving behind an avatar tap. */
.topbar-mobile {
  display: none;
  flex-wrap: wrap;
}

/* Insurance below ~286px (Galaxy Fold cover screen), where the four links
   alone outrun the viewport. No effect at any width where they fit. */
.mobile-brand {
  display: none;
  flex-wrap: wrap;
}

.mobile-brand a {
  padding: 6px 8px;
  color: var(--text-secondary);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: var(--transition-color);
}

.mobile-brand a.active {
  color: var(--text-primary);
  border-bottom-color: var(--brand);
}

.topbar-auth {
  display: none;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Only meaningful once signed in, same as the sidebar's .rail-auth. */
body.app-ready .topbar-auth {
  display: flex;
}

.topbar-user {
  max-width: 38vw;
  overflow: hidden;
  color: var(--text-muted);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar-auth button {
  height: 32px;
  padding: 0 10px;
  color: var(--text-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  font-family: inherit;
  font-size: 11px;
  font-weight: var(--weight-bold);
  white-space: nowrap;
  transition: var(--transition-color);
}

.topbar-auth button:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
}

/* Right-hand group in the page header. On the dashboards the theme toggle sits
   in .range-controls beside the presets; on the text pages, which have no range
   controls, it lives here. Either way it is the LAST item in a space-between
   topbar, so page identity stays on the left. */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex: 0 0 auto;
}

/* ---------- Theme toggle ----------
   Sits in the page header next to the range controls. The button writes
   data-theme on <html>; absence of the localStorage key means "follow the
   OS", which is the default. */
.theme-toggle {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  transition: var(--transition-color);
}

.theme-toggle:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
  background: var(--surface-hover);
}

.theme-toggle svg {
  width: 15px;
  height: 15px;
}

/* Only one of the two glyphs is ever shown: a moon in light theme (tap to go
   dark), a sun in dark theme. light-dark() cannot express this — it takes
   colors only, not `none`/`inline` — so this is the one place the theme has
   to be matched with selectors. Both branches are needed: the media query
   covers "following a dark OS", the attribute covers an explicit toggle. */
.theme-toggle .icon-sun { display: none; }

.theme-toggle .icon-moon { display: inline; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: inline; }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: none; }
}

[data-theme="dark"] .theme-toggle .icon-sun { display: inline; }

[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
