/*
 * base.css - single source of truth for the design-system tokens.
 *
 * Loaded globally by fragments/head.html BEFORE nav.css and the per-page stylesheet, so every page
 * that uses the head fragment inherits these tokens. Page stylesheets may still declare additional,
 * page-specific tokens (e.g. --gold, --tier1, --live) in their own :root block.
 *
 * NOT loaded by standalone surfaces, which keep their own :root token block:
 *   - OBS overlay widgets (static/widget-*.css, served via static/widget-*.html / overlay.html)
 *   - the operator console (operator.css)
 *   - the error pages (error-404.css / error-500.css)
 */
:root {
  /* Core palette */
  --bg: #0e0e10;
  --text: #efeff1;
  --accent: #9146ff;
  --accent-text: #a970ff;
  --muted: #adadb8;
  --card: #18181b;
  --border: #26262c;
  --danger: #e53935;
  --green: #43b581;

  /* Shared semantic/accent colors (previously duplicated across page stylesheets). */
  --red: #e53935;     /* alias of --danger; some pages reference --red */
  --gold: #f5a623;    /* 1st-place / featured accent (leaderboard, redemptions, sub tiers) */
  --silver: #c0c0c0;  /* 2nd-place medal */
  --bronze: #cd7f32;  /* 3rd-place medal */
  --tier1: #9146ff;   /* sub tier 1 badge */
  --tier2: #00aeef;   /* sub tier 2 badge */
  --tier3: #f5a623;   /* sub tier 3 badge */
}

/* ── Accessibility helpers ── */

/* Visually hidden but available to screen readers (for labels on icon-only controls, etc.). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Skip-to-content link: off-screen until focused, then visible at the top-left. */
.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 1000;
  background: var(--accent); color: #fff; padding: 8px 14px; border-radius: 6px;
  font-size: 0.875rem; font-weight: 600; text-decoration: none;
  transform: translateY(-150%); transition: transform 0.15s;
}
.skip-link:focus { transform: translateY(0); outline: 2px solid #fff; outline-offset: 2px; }

/* Consistent keyboard-focus ring for links/buttons/custom-focusable elements (mouse focus is
   unaffected; inputs keep their own accent-border focus style from their page stylesheet). */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent-text); outline-offset: 2px;
}

/* ── Buttons ── */
/* Shared button base + the common `primary` and `sm` modifiers (identical across the dashboard and
   overlay pages). Pages may still add their own modifiers (e.g. .btn-danger, .btn-ghost), and the
   marketing home page intentionally overrides .btn-primary with larger hero-CTA styling. */
.btn { border: none; border-radius: 6px; cursor: pointer; font-size: 0.82rem; font-weight: 600; padding: 8px 14px; transition: opacity .15s; }
.btn:hover { opacity: .85; }
.btn-primary { background: var(--accent); color: #fff; }
.btn-sm { padding: 5px 10px; font-size: 0.75rem; }

/* ── Loading skeletons ── */
/* Reusable shimmer placeholder. Uses translucent-white overlays so it works on any dark surface.
   Apply `.skeleton` to a sized element; pages add their own size/shape classes alongside it. */
.skeleton {
  background: linear-gradient(90deg, rgba(255,255,255,0.04) 25%, rgba(255,255,255,0.11) 37%, rgba(255,255,255,0.04) 63%);
  background-size: 400% 100%;
  animation: skeleton-loading 1.4s ease infinite;
  border-radius: 4px;
}
@keyframes skeleton-loading {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* ── Layout / spacing / text utilities ──
   Atomic helpers that back the inline-style sweep (replacing CSP-blocked `style=` attributes).
   Generic enough to be shared by every page that loads base.css (dashboard, overlay-editor,
   overlay-alerts, account). Page stylesheets keep their own semantic classes (e.g. .form-row,
   .muted-text). The operator console does not load base.css and keeps its own copies in operator.css.

   Declarations use `!important` on purpose: base.css loads BEFORE the per-page stylesheets, so
   without it a utility would lose to an equally-specific page rule (e.g. `.form-row { gap: 10px }`).
   The inline `style=` attributes these replace always won the cascade, so the utilities must win too
   to keep rendering identical. Keep this layer single-purpose so `!important` stays predictable. */

/* flex / grid */
.flex { display: flex !important; }
.flex-col { display: flex !important; flex-direction: column !important; }
.grid-2 { display: grid !important; grid-template-columns: 1fr 1fr !important; }
.items-center { align-items: center !important; }
.items-start { align-items: flex-start !important; }
.items-end { align-items: flex-end !important; }
.self-start { align-self: flex-start !important; }
.justify-between { justify-content: space-between !important; }
.justify-end { justify-content: flex-end !important; }
.flex-wrap { flex-wrap: wrap !important; }
.flex-nowrap { flex-wrap: nowrap !important; }
.flex-1 { flex: 1 !important; }
.flex-2 { flex: 2 !important; }
.flex-3 { flex: 3 !important; }

/* gaps */
.gap-4 { gap: 4px !important; }
.gap-6 { gap: 6px !important; }
.gap-8 { gap: 8px !important; }
.gap-12 { gap: 12px !important; }

/* margins */
.m-0 { margin: 0 !important; }
.mt-4 { margin-top: 4px !important; }
.mt-8 { margin-top: 8px !important; }
.mt-10 { margin-top: 10px !important; }
.mt-12 { margin-top: 12px !important; }
.mt-14 { margin-top: 14px !important; }
.mt-16 { margin-top: 16px !important; }
.mt-20 { margin-top: 20px !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-4 { margin-bottom: 4px !important; }
.mb-6 { margin-bottom: 6px !important; }
.mb-8 { margin-bottom: 8px !important; }
.mb-12 { margin-bottom: 12px !important; }
.mb-14 { margin-bottom: 14px !important; }
.mb-16 { margin-bottom: 16px !important; }
.pt-8 { padding-top: 8px !important; }
.pt-12 { padding-top: 12px !important; }
.pt-14 { padding-top: 14px !important; }

/* text */
.muted { color: var(--muted) !important; }
.text-danger { color: var(--danger) !important; }
.fw-normal { font-weight: normal !important; }
.fw-600 { font-weight: 600 !important; }
.nowrap { white-space: nowrap !important; }
.block { display: block !important; }
.fs-75 { font-size: 0.75rem !important; }
.fs-78 { font-size: 0.78rem !important; }
.fs-80 { font-size: 0.8rem !important; }
.fs-82 { font-size: 0.82rem !important; }
.fs-85 { font-size: 0.85rem !important; }
.fs-875 { font-size: 0.875rem !important; }
.fs-100 { font-size: 1rem !important; }

/* sizing */
.w-full { width: 100% !important; }
.w-auto { width: auto !important; }
.resize-y { resize: vertical !important; }

/* misc */
.text-center { text-align: center !important; }
.cursor-pointer { cursor: pointer !important; }
.border-top { border-top: 1px solid var(--border); }
.mt-6 { margin-top: 6px !important; }
.ml-8 { margin-left: 8px !important; }
.py-8 { padding-top: 8px !important; padding-bottom: 8px !important; }
.mono { font-family: ui-monospace, Menlo, Consolas, monospace !important; }
.wrap-pre { white-space: pre-wrap !important; word-break: break-word !important; }
.col-span-full { grid-column: 1 / -1 !important; }
