/* ==========================================================================
   TRACKY — design system
   Palette pulled directly from the app's own QSS/source (see build notes).
   ========================================================================== */

:root {
  /* --- Backgrounds (verified in-app) --- */
  --bg-base: #1e1e1e;
  --bg-alt: #262626;
  --bg-elevated: #2a2a2a;
  --bg-inset: #161616;
  --bg-hover: #333333;
  --border-subtle: #3a3a3a;
  --border-strong: #505050;

  /* --- Text (verified in-app) --- */
  --text-primary: #e0e0e0;
  --text-secondary: #d0d0d0;
  --text-muted: #949494;
  --text-faint: #6f6f6f;

  /* --- Primary accent (verified in-app button/UI blue) --- */
  --accent: #4a8abf;
  --accent-strong: #115588;
  --accent-soft: rgba(74, 138, 191, 0.14);
  --accent-glow: rgba(74, 138, 191, 0.35);

  /* --- Warning / danger (timer running low) --- */
  --danger: #d64545;

  /* --- Game accents ---
     Each game gets its own 2-color pairing (Smite gets a 4-color set) per
     direct request, not the app's internal theming colors anymore. */
  --lol: #2563c7;
  --lol-2: #f2ac2e;
  --lol-soft: rgba(37, 99, 199, 0.16);
  --lol-soft-2: rgba(242, 172, 46, 0.16);
  --lol-on: #ffffff;
  --lol-on-2: #1e1e1e;

  --dota: #a855f7;
  --dota-2: #d64545;
  --dota-soft: rgba(168, 85, 247, 0.14);
  --dota-soft-2: rgba(214, 69, 69, 0.14);
  --dota-on: #ffffff;
  --dota-on-2: #ffffff;

  --smite: #3dc9d1;
  --smite-2: #e8c547;
  --smite-white: #f4f6f8;
  --smite-red: #d64545;
  --smite-soft: rgba(61, 201, 209, 0.14);
  --smite-soft-2: rgba(232, 197, 71, 0.14);
  --smite-on: #1e1e1e;
  --smite-on-2: #1e1e1e;
  --smite-gradient: linear-gradient(90deg, var(--smite-2), var(--smite-white), var(--smite), var(--smite-red));

  --mc: #69a83f;
  --mc-2: #6b4423;
  --mc-soft: rgba(105, 168, 63, 0.15);
  --mc-soft-2: rgba(107, 68, 35, 0.24);
  --mc-on: #ffffff;
  --mc-on-2: #ffffff;

  /* "Add any game" — not a real game, so no single hue fits; a magenta +
     cyan pair carries the accent/border/marker roles the same way every
     other game's pair does, and --any-gradient (used just for the hero
     badge) is the actual rainbow. */
  --any: #d6409f;
  --any-2: #38bdf8;
  --any-soft: rgba(214, 64, 159, 0.16);
  --any-soft-2: rgba(56, 189, 248, 0.16);
  --any-on: #ffffff;
  --any-on-2: #1e1e1e;
  --any-gradient: linear-gradient(90deg, #e6494f, #f2932e, #e8d23a, #4dc26a, #3d9be0, #a855f7);

  /* --- Semantic (verified in-app) --- */
  --success: #2ecc71;
  --warn: #ffaa00;
  --danger: #ff4444;

  /* --- Type --- */
  --font-display: "Chakra Petch", "Segoe UI", sans-serif;
  --font-body: "IBM Plex Sans", "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", monospace;

  /* --- Scale --- */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 18px;
  --container: 1180px;
  --container-narrow: 760px;

  --space-xs: 0.5rem;
  --space-sm: 1rem;
  --space-md: 1.75rem;
  --space-lg: 2.75rem;
  --space-xl: 4.5rem;
  --space-2xl: 7rem;

  --shadow-card: 0 4px 28px rgba(0, 0, 0, 0.4);
  --shadow-pop: 0 12px 40px rgba(0, 0, 0, 0.5);
}

/* ==========================================================================
   Reset / base
   ========================================================================== */

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

html {
  background: var(--bg-base);
  color-scheme: dark;
}

/* The whole site was designed to read comfortably at ~90% browser zoom on a
   typical desktop monitor (verified on a 1440p 27" screen) — rather than
   ask every visitor to zoom out manually, bake that scale in directly so
   full-height elements like the hero's 16:9 background video fit a 16:9
   display without it. Scoped to the desktop layout only (matches the
   breakpoint below where the two-column hero switches to single-column);
   mobile keeps its own already-tuned sizing at 100%. */
@media (min-width: 961px) {
  html { zoom: 0.9; }
}

body {
  margin: 0;
  background: var(--bg-base);
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.018) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.018) 1px, transparent 1px);
  background-size: 42px 42px;
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

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

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  color: #6fa5d6;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--text-primary);
  font-weight: 600;
  line-height: 1.15;
  margin: 0 0 0.6em;
  letter-spacing: 0.01em;
}

h1 { font-size: clamp(2.4rem, 4.4vw, 3.6rem); font-weight: 700; }
h2 { font-size: clamp(1.7rem, 2.6vw, 2.3rem); }
h3 { font-size: 1.3rem; }
h4 { font-size: 1.05rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-secondary); }

p { margin: 0 0 1em; }

ul, ol { padding-left: 1.25em; }
li { margin-bottom: 0.4em; }

code, kbd, .mono { font-family: var(--font-mono); }

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

::selection {
  background: var(--accent-strong);
  color: #fff;
}

.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;
}

/* ==========================================================================
   Layout helpers
   ========================================================================== */

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 1.5rem;
}

.container-narrow {
  max-width: var(--container-narrow);
  margin: 0 auto;
  padding: 0 1.5rem;
}

main { display: block; overflow-x: hidden; }

.section {
  padding: var(--space-2xl) 0;
}

.section-tight {
  padding: var(--space-xl) 0;
}

.section-alt {
  background: var(--bg-alt);
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}

.section-head {
  max-width: 640px;
  margin: 0 0 var(--space-lg);
}

.section-head.center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.9em;
}

.eyebrow::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: currentColor;
  display: inline-block;
}

.lede {
  font-size: 1.15rem;
  color: var(--text-secondary);
  max-width: 54ch;
}

.center { text-align: center; }
.mt-0 { margin-top: 0 !important; }
.mt-sm { margin-top: var(--space-sm); }
.mt-md { margin-top: var(--space-md); }
.mt-lg { margin-top: var(--space-lg); }
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.accent-text { color: var(--accent); }
.balance { text-wrap: balance; }

.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-sm { gap: 0.75rem; }
.gap-md { gap: 1.5rem; }

.divider {
  border: none;
  border-top: 1px solid var(--border-subtle);
  margin: var(--space-lg) 0;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.98rem;
  padding: 0.85em 1.6em;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
  white-space: nowrap;
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary {
  background: var(--accent-strong);
  color: #fff;
  box-shadow: 0 2px 0 rgba(0,0,0,0.25), 0 8px 24px var(--accent-glow);
}
.btn-primary:hover { background: #14639c; color: #fff; }

.btn-ghost {
  background: transparent;
  color: var(--text-primary);
  border-color: var(--border-strong);
}
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }

.btn-game {
  background: var(--game-accent, var(--accent-strong));
  color: var(--game-on-accent, #fff);
}
.btn-game:hover { filter: brightness(1.12); color: var(--game-on-accent, #fff); }

.btn-sm { padding: 0.55em 1.1em; font-size: 0.86rem; }
.btn-block { width: 100%; }
.btn-row { display: flex; gap: 0.9rem; flex-wrap: wrap; }

/* ==========================================================================
   Header / Nav
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(30, 30, 30, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-subtle);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.5rem;
  max-width: var(--container);
  margin: 0 auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}
.brand:hover { color: var(--text-primary); }
.brand .mark { width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  color: var(--text-secondary);
  font-size: 0.94rem;
  font-weight: 500;
}
.nav-links a:hover { color: var(--text-primary); }
.nav-links a.active { color: var(--accent); font-weight: 600; }

.nav-right { display: flex; align-items: center; gap: 1.4rem; }

.nav-dropdown { position: relative; }
.nav-dropdown > a { display: flex; align-items: center; gap: 0.3em; }
.nav-dropdown-menu {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(6px);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 0.5rem;
  min-width: 200px;
  box-shadow: var(--shadow-pop);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}
.nav-dropdown:hover .nav-dropdown-menu,
.nav-dropdown:focus-within .nav-dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(2px);
}
.nav-dropdown-menu a {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.55em 0.7em;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  white-space: nowrap;
}
.nav-dropdown-menu a:hover { background: var(--bg-hover); color: var(--text-primary); }
.nav-dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }

/* "Add any game" gets an animated rainbow square instead of one fixed
   color. A continuous hue-rotate on a solid base color gives a genuinely
   smooth cycle (no discrete jumps to look choppy) while still reading as
   "constantly changing" at a glance. (Plays whatever the visitor's motion
   setting says, on purpose: see the end of this file.) */
.nav-dot-rainbow { background: #e6494f; animation: nav-dot-rainbow-cycle 1.6s linear infinite; }
@keyframes nav-dot-rainbow-cycle {
  from { filter: hue-rotate(0deg); }
  to   { filter: hue-rotate(360deg); }
}

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  width: 40px; height: 40px;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/* ==========================================================================
   Hero + signature timer-grid widget
   ========================================================================== */

.hero {
  /* top/bottom padding kept equal on purpose: hero-visual is locked (see
     main.js) to the tallest grid shape and centered via .hero-grid's
     align-items, so symmetric section padding is what actually centers the
     grid card between the top and bottom edges of the background video —
     asymmetric padding here was pushing it down toward the bottom edge. */
  padding: calc((var(--space-2xl) + var(--space-xl)) / 2) 0;
  position: relative;
  overflow: hidden;
}

/* Background video: fills the hero section behind everything else.
   Absent a source (or before JS attaches one), this is just an empty,
   transparent box — the section quietly falls back to its normal
   background, so nothing looks broken without a video file in place. */
.hero-bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* top-anchored: the section is wider than 16:9, so the video loses some of its bottom
     (the game's HUD, which fades into the page anyway) and keeps the Tracky window at its top */
  object-position: center top;
  z-index: 0;
  pointer-events: none;
}

/* Two gradients doing two different jobs:
   1) a horizontal scrim so hero-copy stays readable over bright footage
   2) a vertical fade that dissolves the video into --bg-base at the
      bottom, so it blends into the rest of the page instead of ending
      in a hard edge (the blitz.gg effect). */
.hero-bg-fade {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(100deg, rgba(18, 18, 18, 0.86) 0%, rgba(18, 18, 18, 0.62) 34%, rgba(18, 18, 18, 0.2) 60%, rgba(18, 18, 18, 0.06) 80%),
    linear-gradient(180deg, rgba(18, 18, 18, 0.12) 0%, rgba(18, 18, 18, 0) 20%, rgba(18, 18, 18, 0) 42%, var(--bg-base) 96%);
}

.hero-grid {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--space-lg);
  align-items: center;
}

.hero h1 { margin-bottom: 0.45em; }
.hero .lede { margin-bottom: var(--space-md); font-size: 1.2rem; }

.stat-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 1.6rem;
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--border-subtle);
}
.stat-strip .stat-num {
  font-family: var(--font-mono);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--text-primary);
  display: block;
}
.stat-strip .stat-label {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.hero-visual {
  display: flex;
  align-items: center;
  justify-content: center;
}

.overlay-frame {
  --cols: 3;
  /* The per-cell size the original fixed 380px/3-column design implied,
     reverse-engineered from that same math. Used both here (so the frame
     shrinks by exactly one cell's width + gap per hidden column) and by
     .timer-btn's max-width below — so shrinking the frame for fewer
     columns keeps cells the exact same size as always, just fewer of
     them, instead of growing them to fill the freed-up space. */
  --cell: calc((380px - 2 * 1.75rem - 20px - 0.6rem - 2 * 0.85rem) / 3);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
  box-shadow: var(--shadow-pop);
  width: 100%;
  /* 2x frame padding + the row-toggle rail + its gap, then N cells at
     --cell width plus (N-1) gaps between them. JS updates --cols to
     match however many columns the active/previewed profile shows. */
  max-width: calc(2 * 1.75rem + 20px + 0.6rem + var(--cols) * var(--cell) + (var(--cols) - 1) * 0.85rem);
  transition: max-width 0.42s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.6s ease;
  position: relative;
}

.overlay-frame .frame-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 1.1rem;
  display: flex;
  justify-content: space-between;
}

/* Profile bar — mirrors the real app's profile-switching strip. Tabs are
   genuinely clickable (and keyboard-focusable): hovering/focusing previews
   a tab via .is-filling, a click/Enter commits it via .is-active. The
   automatic cursor tour pauses on any of that and resumes after 5s idle. */
.profile-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1.15rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
}

.profile-tabs { display: flex; align-items: center; gap: 0.4rem; }

.profile-tabs .save-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 0.2rem;
  color: var(--text-faint);
}
.profile-tabs .save-icon svg { width: 14px; height: 14px; display: block; }

.profile-tab {
  position: relative;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  border: 1px solid var(--border-subtle);
  background: var(--bg-inset);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
  transition: border-color 0.3s ease;
}
.profile-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.profile-tab .tab-fill {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.48s cubic-bezier(0.4, 0, 0.2, 1), background 0.25s ease;
}

.profile-tab .tab-num {
  position: relative;
  z-index: 1;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--text-faint);
  transition: color 0.3s ease;
}

.profile-tab.is-filling .tab-fill,
.profile-tab.is-active .tab-fill { transform: scaleY(1); }

/* The tab that's actually loaded turns green (not the in-progress blue
   fill) — same green whether it got there via the auto-tour's simulated
   click or a real one, since both converge on adding .is-active once the
   fill-in completes (see markActiveTab in main.js). */
.profile-tab.is-active .tab-fill { background: var(--success); }
.profile-tab.is-active { border-color: var(--success); }
.profile-tab.is-active .tab-num { color: var(--bg-base); font-weight: 700; }

/* Brief green ring specifically on a real user click — the auto-tour's
   own "cursor click" bounce already announces its simulated clicks, so
   this ring stays the signal that YOU just clicked this one. */
.profile-tab.is-confirmed { animation: tab-confirm-ring 0.6s ease-out; }
@keyframes tab-confirm-ring {
  0% { box-shadow: 0 0 0 0 rgba(46, 204, 113, 0.6); }
  70% { box-shadow: 0 0 0 7px rgba(46, 204, 113, 0); }
  100% { box-shadow: 0 0 0 0 rgba(46, 204, 113, 0); }
}

.profile-icons { display: flex; align-items: center; gap: 0.55rem; color: var(--text-faint); }
.profile-icons svg { width: 15px; height: 15px; display: block; }

.demo-cursor {
  position: absolute;
  top: 0;
  left: 0;
  width: 15px;
  height: 15px;
  z-index: 5;
  opacity: 0;
  pointer-events: none; /* purely visual — must never swallow clicks on
    whatever tab it's sitting over, including while "hidden" at opacity 0 */
  transition: transform 0.55s cubic-bezier(0.65, 0, 0.35, 1), opacity 0.3s ease;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
}
.demo-cursor.is-visible { opacity: 1; }
.demo-cursor svg { width: 100%; height: 100%; display: block; }
.demo-cursor.is-clicking svg { animation: cursor-click 0.32s ease; }
@keyframes cursor-click {
  0% { transform: scale(1); }
  40% { transform: scale(0.7); }
  100% { transform: scale(1); }
}

/* Timer grid — a column of rows so JS can grow/shrink it by toggling a
   class per row; height/opacity/margin all animate together, so a
   collapsed row leaves no gap behind. Column count is fixed at 3. */
.timer-grid {
  display: flex;
  flex-direction: column;
}

.timer-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-height: 100px;
  margin-bottom: 0.85rem;
  opacity: 1;
  transform: scaleY(1);
  transform-origin: top;
  overflow: hidden;
  transition: max-height 0.42s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease, margin-bottom 0.42s cubic-bezier(0.4, 0, 0.2, 1), transform 0.42s cubic-bezier(0.4, 0, 0.2, 1);
}

.timer-row.is-collapsed {
  max-height: 0;
  margin-bottom: 0;
  opacity: 0;
  transform: scaleY(0.7);
  pointer-events: none;
}

.timer-grid.no-anim .timer-row { transition: none !important; }

.row-toggle {
  width: 20px;
  height: 20px;
  border-radius: 5px;
  border: 1.5px solid var(--border-strong);
  flex-shrink: 0;
  cursor: pointer;
  background-size: cover;
  background-position: center;
  transition: border-color 0.4s ease, background 0.4s ease, box-shadow 0.25s ease;
}
.row-toggle:hover { border-color: var(--text-faint); }
.row-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Active multiplier item loaded into the square — a thin gold ring marks
   it as "buffed" distinctly from .just-entered's blue reveal flash. */
.row-toggle.has-multiplier {
  border-color: #b5590d;
  box-shadow: 0 0 0 0.5px #b5590d;
}

.timer-row.just-entered .row-toggle {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.timer-cells {
  display: flex;
  gap: 0; /* spacing is per-cell margin below so it can collapse away cleanly */
  flex: 1;
  min-width: 0;
}

.timer-btn {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius-md);
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  cursor: pointer;
  isolation: isolate;
  flex: 1 1 0;
  min-width: 0;
  /* Caps how wide (and, via aspect-ratio, how tall) a cell can grow —
     pinned to --cell (set on .overlay-frame), the exact per-cell size the
     original fixed-width 3-column design implied. Now that the frame
     itself shrinks to match the visible column count (see .overlay-frame),
     this never actually has to clamp anything in normal use; it's just a
     safe ceiling plus a real numeric transition target for the collapse
     animation below. */
  max-width: var(--cell, 92px);
  margin-right: 0.85rem;
  transition: max-width 0.42s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease, margin-right 0.42s cubic-bezier(0.4, 0, 0.2, 1), transform 0.42s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.3s ease;
}
.timer-cells > .timer-btn:last-child { margin-right: 0; }

/* Whichever cell is currently the last VISIBLE one in its row (set by JS,
   since that isn't always the actual last DOM child once columns are
   hidden) also needs its own trailing margin zeroed, or a lone gap's
   worth of blank space would sit between it and the collapsed cell(s)
   after it. */
.timer-btn.col-last-visible { margin-right: 0; }

/* Column collapse (used by the 5x2 profile to hide 1 of the 3 cells per
   row) — same technique as the row collapse below, just horizontal: the
   cell shrinks to zero width/margin instead of zero height. */
.timer-btn.col-collapsed {
  flex: 0 0 auto;
  max-width: 0;
  margin-right: 0;
  opacity: 0;
  transform: scaleX(0.7);
  pointer-events: none;
}

.timer-grid.no-anim .timer-btn { transition: none !important; }

.timer-btn .tint {
  position: absolute;
  inset: 0;
  background: var(--t-accent, var(--accent));
  opacity: 0.16;
  z-index: 0;
  transition: opacity 0.3s ease;
}

/* Populated by JS with a per-game image once assets/grid/<game>/ has files;
   sits over .tint (which stays as the fallback look until then). */
.timer-btn .icon-img {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.timer-btn.has-icon-img .tint { opacity: 0; }
.timer-btn.has-icon-img .icon-img { opacity: 1; }
.timer-btn.has-icon-img .key,
.timer-btn.has-icon-img .num { text-shadow: 0 1px 3px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.7); }

/* Low-opacity black scrim over the image so the key/timer stay readable
   without hiding the art underneath. Sits above .icon-img, below the
   warning wash and the text. Faded out while paused (see .is-paused below)
   — a stopped timer shows a clean, unscrimmed image with no overlay. */
.timer-btn.has-icon-img::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #000;
  opacity: 0.4;
  transition: opacity 0.25s ease;
  pointer-events: none;
}
.timer-btn.has-icon-img.is-paused::before { opacity: 0; }

/* Click toggles a timer off: cooldown stops, scrim clears, key label and
   pulse/adjust affordances still work so it can be clicked back on. */
.timer-btn.is-paused .warn-wash { display: none; }

.timer-btn .warn-wash {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--danger);
  opacity: 0;
  pointer-events: none;
}
.timer-btn.is-warning { border-color: var(--danger); }
.timer-btn.is-warning .warn-wash { animation: warning-pulse 0.9s ease-in-out infinite; }
@keyframes warning-pulse {
  0%, 100% { opacity: 0.12; }
  50% { opacity: 0.52; }
}

.timer-btn .key {
  position: absolute;
  top: 5px; left: 7px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--text-faint);
  z-index: 3;
}

.timer-btn .num {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 1.12rem;
  color: var(--text-primary);
  z-index: 3;
  text-shadow: 0 2px 6px rgba(0,0,0,0.7);
  transition: color 0.25s ease;
}

.timer-btn.is-warning .num { color: #ffdcdc; }

/* Hover "+10 / +30" (top) and "-10 / -30" (bottom) strips, mirroring the
   real app's quick-adjust buttons. Hidden until hover/focus so they don't
   clutter the grid; a real <button> each so they're independently
   clickable/tabbable without triggering the cell's own pause/resume click
   (see stopPropagation in main.js). */
.timer-btn .adj-row {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 4;
  display: flex;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.timer-btn .adj-row.adj-row-top { top: 0; }
.timer-btn .adj-row.adj-row-bot { bottom: 0; }
.timer-btn:hover .adj-row,
.timer-btn:focus-within .adj-row { opacity: 1; pointer-events: auto; }

.timer-btn .adj-btn {
  flex: 1;
  min-width: 0;
  border: none;
  background: rgba(18, 18, 18, 0.88);
  color: #e5e5e5;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  font-weight: 700;
  line-height: 1;
  padding: 3px 0;
  cursor: pointer;
}
.timer-btn .adj-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.timer-btn .adj-row-top .adj-btn:hover,
.timer-btn .adj-row-top .adj-btn:focus-visible { background: rgba(30, 160, 60, 0.95); color: #fff; }
.timer-btn .adj-row-bot .adj-btn:hover,
.timer-btn .adj-row-bot .adj-btn:focus-visible { background: rgba(190, 30, 30, 0.95); color: #fff; }
.timer-btn .adj-row .adj-btn + .adj-btn { border-left: 1px solid rgba(255, 255, 255, 0.18); }

/* The upload slot only behaves like a real timer once actually running —
   no adjust strips during the empty/armed pre-start states. */
.timer-btn.custom-slot:not(.timer-running) .adj-row { display: none; }

.timer-btn.custom-slot .num { font-size: 0.62rem; color: var(--text-muted); font-weight: 500; text-align: center; padding: 0 4px; }

.timer-btn.custom-slot { flex-direction: column; gap: 0.3rem; }
.timer-btn.custom-slot .custom-upload-icon,
.timer-btn.custom-slot .custom-start-icon {
  position: relative;
  z-index: 3;
  width: 15px;
  height: 15px;
  color: var(--text-faint);
  transition: color 0.25s ease, opacity 0.2s ease;
}
.timer-btn.custom-slot .custom-upload-icon svg,
.timer-btn.custom-slot .custom-start-icon svg { width: 100%; height: 100%; display: block; }
.timer-btn.custom-slot:hover .custom-upload-icon,
.timer-btn.custom-slot:hover .num { color: var(--text-secondary); }
.timer-btn.custom-slot:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Three states for this cell, driven by JS toggling .has-custom-image and
   .timer-running:
     1. empty            — upload icon + "Upload your image" (default look above)
     2. armed            — has-custom-image only: image showing, green pulse,
                            hand icon + "Click to start timer"
     3. timer-running     — behaves like a normal timer cell: plain live
                            countdown, no icons, no pulse */
.timer-btn.custom-slot .custom-start-icon { display: none; }

.timer-btn.custom-slot.has-custom-image:not(.timer-running) {
  animation: custom-slot-armed-pulse 1.6s ease-in-out infinite;
}
.timer-btn.custom-slot.has-custom-image:not(.timer-running) .custom-upload-icon { display: none; }
.timer-btn.custom-slot.has-custom-image:not(.timer-running) .custom-start-icon { display: block; }
.timer-btn.custom-slot.has-custom-image:not(.timer-running) .custom-start-icon,
.timer-btn.custom-slot.has-custom-image:not(.timer-running) .num { color: var(--success); }
.timer-btn.custom-slot.has-custom-image:not(.timer-running) .num { font-weight: 600; }
@keyframes custom-slot-armed-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(46, 204, 113, 0.45); }
  50% { box-shadow: 0 0 0 6px rgba(46, 204, 113, 0); }
}

.timer-btn.custom-slot.timer-running .custom-upload-icon,
.timer-btn.custom-slot.timer-running .custom-start-icon { display: none; }
.timer-btn.custom-slot.timer-running .num {
  font-size: 1.12rem;
  font-weight: 600;
  color: var(--text-primary);
  padding: 0;
}
/* Once running, a low-time warning should still read the same red as any
   other cell — needs to explicitly out-rank the rule just above it. */
.timer-btn.custom-slot.timer-running.is-warning .num { color: #ffdcdc; }

/* Once the visitor has picked their own image, hide the default upload
   prompt (the states above take over what's shown instead). */
.timer-btn.custom-slot.has-custom-image .custom-upload-icon { display: none; }

.timer-btn:hover { border-color: var(--border-strong); }
.timer-btn.pulse { animation: pulse-reset 0.35s ease; }
@keyframes pulse-reset {
  0% { transform: scale(0.9); }
  60% { transform: scale(1.04); }
  100% { transform: scale(1); }
}

.overlay-frame .frame-hint {
  margin-top: 1.1rem;
  font-size: 0.76rem;
  color: var(--text-faint);
  text-align: center;
}

/* ==========================================================================
   Cards / grids
   ========================================================================== */

.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.25rem; }

.card {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 1.75rem;
}

.feature-card { transition: border-color 0.15s ease, transform 0.15s ease; }
.feature-card:hover { border-color: var(--border-strong); transform: translateY(-2px); }
.feature-card .ico {
  width: 42px; height: 42px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 1.1rem;
}
.feature-card h3 { margin-bottom: 0.5em; font-size: 1.1rem; }
.feature-card p { color: var(--text-muted); font-size: 0.94rem; margin-bottom: 0; }

/* Game pack cards */
.game-card {
  display: block;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--gc-accent, var(--accent));
  border-radius: var(--radius-md);
  padding: 1.6rem 1.75rem;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow .15s ease;
}
.game-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-card); border-color: var(--border-strong); border-left-color: var(--gc-accent, var(--accent)); }
.game-card .gc-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.9rem; }
.game-card .gc-icon {
  width: 40px; height: 40px;
  border-radius: var(--radius-sm);
  background: var(--gc-soft, var(--accent-soft));
  color: var(--gc-accent, var(--accent));
  display: flex; align-items: center; justify-content: center;
}
.game-card .gc-count {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--gc-accent2, var(--gc-accent, var(--accent)));
  background: var(--gc-soft2, var(--gc-soft, var(--accent-soft)));
  padding: 0.3em 0.65em;
  border-radius: 100px;
}
.game-card h3 { margin-bottom: 0.4em; }
.game-card p { color: var(--text-muted); font-size: 0.92rem; margin-bottom: 0.9rem; }
.game-card .gc-link { font-size: 0.88rem; font-weight: 600; color: var(--gc-accent, var(--accent)); }

/* ==========================================================================
   Video carousel (homepage "see it running" feature clips)
   ========================================================================== */

.video-carousel {
  position: relative;
  /* The video is the single largest contributor to this section's height,
     so capping its width (instead of the full container) is what got the
     section to fit on screen without cropping any frame. 840px landed
     after feedback that the initial narrower pass (the site's shared
     "narrow content" token, 760px) read a bit small — this is close to a
     10% bump from that, still well short of full-bleed. */
  max-width: 840px;
  margin: 0 auto;
}

/* Only the sliding track gets clipped. The dots live outside this wrapper
   now so their own hover/active transform (see .vc-dot.is-active) never
   gets cut off by an overflow boundary sitting flush against them. */
.vc-viewport {
  overflow: hidden;
}

.vc-track {
  display: flex;
  transition: transform 0.55s cubic-bezier(0.65, 0, 0.35, 1);
}

.vc-slide {
  flex: 0 0 100%;
  min-width: 0;
}

.vc-video-wrap {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-subtle);
  background: var(--bg-inset);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}

.vc-video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  background: var(--bg-inset);
}

/* A scripted animation in place of a video (assets/js/anim/): the canvas
   sits on top of its poster picture, which shows until the first frame is
   drawn and whenever scripts can't run. */
.vc-anim {
  position: relative;
  z-index: 1;
  background: transparent;
}
.vc-anim-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Left/right "shadow" zones on the video itself — a gradient that doubles
   as a click target for prev/next, same as the dots below. Hidden until
   the cursor is actually over the video, so the clip reads clean at rest;
   focus-visible still reveals it for keyboard users regardless of hover. */
.vc-edge {
  position: absolute;
  top: 0;
  bottom: 0;
  width: clamp(40px, 14%, 84px);
  display: flex;
  align-items: center;
  border: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
  background: none;
  z-index: 2;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.vc-video-wrap:hover .vc-edge,
.vc-edge:focus-visible {
  opacity: 1;
}
/* Hover doesn't exist on touch, so this affordance is never discoverable
   there — and left active, its invisible hit-zone could double-fire
   alongside the swipe gesture added for touch below. Removed from
   hit-testing entirely rather than just staying invisible. */
@media (hover: none), (pointer: coarse) {
  .vc-edge {
    display: none;
  }
}
.vc-edge-prev {
  left: 0;
  justify-content: flex-start;
  background: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0) 100%);
}
.vc-edge-next {
  right: 0;
  justify-content: flex-end;
  background: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0) 100%);
}
.vc-edge-arrow {
  width: 20px;
  height: 20px;
  margin: 0 0.6rem;
  color: #fff;
  opacity: 0.8;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.6));
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.vc-edge:hover .vc-edge-arrow,
.vc-edge:focus-visible .vc-edge-arrow {
  opacity: 1;
  transform: scale(1.15);
}
.vc-edge:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -3px;
}

.vc-caption {
  max-width: 62ch;
  margin: var(--space-sm) auto 0;
  text-align: center;
}
.vc-caption h3 { margin-bottom: 0.4em; }
.vc-caption p { color: var(--text-muted); font-size: 0.96rem; margin-bottom: 0; }

.vc-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.78rem;
  margin-top: var(--space-md);
  padding: 4px 0;
}
.vc-dot {
  /* 30% bigger than the original 9px, with room above/below (via .vc-dots
     padding and moving overflow:hidden onto .vc-viewport, see above) so
     the is-active transform never gets clipped. */
  width: 11.7px; height: 11.7px;
  border-radius: 50%;
  background: var(--border-strong);
  border: none;
  padding: 0;
  cursor: pointer;
  transition: background-color 0.25s ease, transform 0.25s ease;
}
.vc-dot:hover { background: var(--text-faint); }
.vc-dot.is-active { background: var(--accent); transform: scale(1.25); }
.vc-dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* This section runs taller than its siblings (heading block + 16:9 video +
   caption + dots stacked together), enough that on common 1440p/100%-zoom
   setups it clipped past the bottom of the viewport. Tightening its own
   vertical rhythm — reusing existing spacing tokens, just smaller ones —
   claws back real height without touching .section/.section-head defaults
   used by every other section on the site.
   Desktop-only (min-width matches the site's own mobile breakpoint): the
   "doesn't fit in one screen" problem this solves is specific to a
   fixed-height desktop browser viewport. On mobile there's no such
   pressure — people scroll continuously through stacked content — so this
   used to also override the mobile-specific .section padding (an ID beats
   a class regardless of media query) and left this one section with
   noticeably less breathing room than its neighbors. Scoping it here lets
   mobile fall back to the same rhythm every other section already uses. */
@media (min-width: 721px) {
  #feature-videos {
    padding: var(--space-lg) 0 var(--space-xl);
  }
  #feature-videos .section-head {
    margin-bottom: var(--space-md);
  }
  #feature-videos .vc-dots {
    margin-top: var(--space-sm);
  }
}

/* Owner, 25 Oct (package 1037): a smaller heading and intro text here, so after the wheel snap the carousel's dots
   are on screen too. The intro may run wider, so it takes two lines instead of four. */
#feature-videos .section-head { max-width: none; }
#feature-videos .section-head h2 { font-size: clamp(1.45rem, 2vw, 1.8rem); }
#feature-videos .section-head .lede { font-size: 1rem; max-width: none; margin-bottom: 0; }

/* ==========================================================================
   Filmstrip (customization demo)
   ========================================================================== */

.filmstrip {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  justify-content: center;
  padding: 2rem 1rem;
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}
.filmstrip .frame { text-align: center; }
.filmstrip .frame .slot {
  width: 64px; height: 64px;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 0.6rem;
  color: var(--fs-accent, var(--text-muted));
}
.filmstrip .frame .cap { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-faint); }
.filmstrip .arrow { color: var(--text-faint); font-size: 1.2rem; }

/* ==========================================================================
   Chat mock (clipboard-to-chat demo)
   ========================================================================== */

.chat-mock {
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 1.25rem 1.4rem;
  font-family: var(--font-mono);
  font-size: 0.88rem;
}
.chat-mock .chat-line { display: flex; gap: 0.6em; padding: 0.3em 0; color: var(--text-muted); }
.chat-mock .chat-line .who { color: var(--accent); flex-shrink: 0; }
.chat-mock .chat-line.paste { color: var(--text-primary); background: rgba(74,138,191,0.1); border-radius: 4px; padding: 0.35em 0.5em; margin: 0.2em -0.5em; }
.chat-mock .caret { display: inline-block; width: 7px; height: 1em; background: var(--accent); vertical-align: middle; animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ==========================================================================
   Hotkey badges (kbd)
   ========================================================================== */

.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.8em;
  padding: 0.28em 0.55em;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--text-primary);
  background: var(--bg-inset);
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: 5px;
}

.hotkey-row { display: flex; align-items: center; justify-content: space-between; padding: 0.85em 0; border-bottom: 1px solid var(--border-subtle); gap: 1rem; }
.hotkey-row:last-child { border-bottom: none; }
.hotkey-row .hk-label { color: var(--text-secondary); font-size: 0.94rem; }
.hotkey-row .hk-tip { color: var(--text-faint); font-size: 0.82rem; margin-top: 0.15em; }
.hotkey-row .hk-keys { display: flex; gap: 0.35rem; flex-shrink: 0; }

/* ==========================================================================
   Pricing
   ========================================================================== */

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1.1rem;
  align-items: stretch;
}

.price-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 1.6rem 1.35rem;
  display: flex;
  flex-direction: column;
  position: relative;
}
.price-card.featured {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), var(--shadow-card);
}
.price-card .badge-tag {
  position: absolute;
  top: -12px; left: 50%;
  transform: translateX(-50%);
  background: var(--accent-strong);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.3em 0.8em;
  border-radius: 100px;
  white-space: nowrap;
}
.price-card .tier-name { font-family: var(--font-display); font-size: 1.05rem; color: var(--text-primary); font-weight: 600; margin-bottom: 0.6rem; }
.price-card .tier-price { font-family: var(--font-mono); font-size: 1.9rem; color: var(--text-primary); font-weight: 600; line-height: 1; }
.price-card .tier-per { font-size: 0.76rem; color: var(--text-faint); margin-bottom: 0.3rem; }
.price-card .tier-effective { font-size: 0.78rem; color: var(--accent); margin-bottom: 1.2rem; min-height: 1.2em; }
.price-card ul { list-style: none; padding: 0; margin: 0 0 1.4rem; flex-grow: 1; }
.price-card li { display: flex; gap: 0.5em; font-size: 0.85rem; color: var(--text-secondary); margin-bottom: 0.6em; }
.price-card li .ck { color: var(--success); flex-shrink: 0; }
.price-card li .xk { color: var(--text-faint); flex-shrink: 0; }

.compare-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.compare-table th, .compare-table td { padding: 0.9em 1em; text-align: center; border-bottom: 1px solid var(--border-subtle); }
.compare-table th:first-child, .compare-table td:first-child { text-align: left; color: var(--text-secondary); }
.compare-table thead th { font-family: var(--font-display); color: var(--text-primary); font-weight: 600; font-size: 0.88rem; }
.compare-table td.yes { color: var(--success); }
.compare-table td.no { color: var(--text-faint); }

/* ==========================================================================
   FAQ accordion
   ========================================================================== */

.faq-list { border-top: 1px solid var(--border-subtle); }
.faq-item { border-bottom: 1px solid var(--border-subtle); }
.faq-q {
  width: 100%;
  background: none;
  border: none;
  text-align: left;
  padding: 1.35rem 0;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  cursor: pointer;
}
.faq-q .plus { flex-shrink: 0; font-family: var(--font-mono); color: var(--accent); transition: transform 0.2s ease; font-size: 1.1rem; }
.faq-item.open .faq-q .plus { transform: rotate(45deg); }
.faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
  color: var(--text-muted);
  font-size: 0.94rem;
}
.faq-a p { padding-bottom: 1.3rem; margin: 0; }
.faq-item.open .faq-a { max-height: 600px; }

/* ==========================================================================
   Steps
   ========================================================================== */

.steps { list-style: none; padding: 0; margin: 0; counter-reset: step; }
.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 2.4rem 1fr;
  gap: 1.1rem;
  padding-bottom: var(--space-md);
  margin-bottom: var(--space-md);
  border-bottom: 1px solid var(--border-subtle);
}
.steps li:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
.steps li::before {
  content: counter(step);
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  width: 2.4rem; height: 2.4rem;
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  font-size: 1rem;
}
.steps h3 { margin-bottom: 0.3em; font-size: 1.05rem; }
.steps p { color: var(--text-muted); margin-bottom: 0; font-size: 0.94rem; }

/* ==========================================================================
   Forms
   ========================================================================== */

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; margin-bottom: 1.1rem; }
.field { margin-bottom: 1.1rem; display: flex; flex-direction: column; gap: 0.45rem; }
.field label { font-size: 0.86rem; font-weight: 600; color: var(--text-secondary); }
.field .hint { font-size: 0.78rem; color: var(--text-faint); }
.field input, .field select, .field textarea {
  background: var(--bg-inset);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.75em 0.9em;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 0.95rem;
  width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field textarea { resize: vertical; min-height: 110px; }
.form-note { font-size: 0.82rem; color: var(--text-faint); margin-top: 0.9rem; }

/* ==========================================================================
   Notices / callouts
   ========================================================================== */

.notice {
  border-radius: var(--radius-md);
  padding: 1.1rem 1.35rem;
  border: 1px solid var(--border-subtle);
  background: var(--bg-elevated);
  font-size: 0.92rem;
  color: var(--text-secondary);
  display: flex;
  gap: 0.8rem;
}
.notice .ico { flex-shrink: 0; color: var(--accent); margin-top: 0.15em; }
.notice.warn { border-color: rgba(255,170,0,0.35); background: rgba(255,170,0,0.06); }
.notice.warn .ico { color: var(--warn); }
.notice strong { color: var(--text-primary); }

/* ==========================================================================
   Prose (long-form: docs / blog / legal)
   ========================================================================== */

.prose { max-width: 720px; }
.prose h2 { margin-top: 2.2em; font-size: 1.5rem; }
.prose h3 { margin-top: 1.6em; font-size: 1.1rem; }
.prose p, .prose li { color: var(--text-secondary); }
.prose a { text-decoration: underline; text-underline-offset: 2px; }
.prose blockquote {
  margin: 1.5em 0;
  padding: 0.2em 0 0.2em 1.2em;
  border-left: 3px solid var(--accent);
  color: var(--text-muted);
  font-style: italic;
}
.prose code {
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  padding: 0.15em 0.4em;
  font-size: 0.88em;
  color: var(--text-primary);
}

.page-hero {
  padding: var(--space-xl) 0 var(--space-lg);
  border-bottom: 1px solid var(--border-subtle);
}
.page-hero .lede { margin-top: 0.6rem; }

.doc-nav {
  position: sticky;
  top: 90px;
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 0.88rem;
}
.doc-nav li { margin-bottom: 0.15rem; }
.doc-nav a { display: block; padding: 0.5em 0.8em; border-radius: var(--radius-sm); color: var(--text-muted); }
.doc-nav a:hover { background: var(--bg-elevated); color: var(--text-primary); }
.doc-layout { display: grid; grid-template-columns: 200px 1fr; gap: var(--space-lg); align-items: start; }

.updated-date { font-size: 0.82rem; color: var(--text-faint); margin-bottom: 2rem; }

/* ==========================================================================
   Blog
   ========================================================================== */

.blog-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; }
.blog-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 1.6rem;
  display: flex;
  flex-direction: column;
}
.blog-card .tag { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); margin-bottom: 0.8rem; }
.blog-card h3 { margin-bottom: 0.5rem; font-size: 1.15rem; }
.blog-card p { color: var(--text-muted); font-size: 0.9rem; flex-grow: 1; }
.blog-card .meta { font-size: 0.78rem; color: var(--text-faint); margin-top: 1rem; }
.blog-card.soon { opacity: 0.6; }
.blog-card.soon .tag { color: var(--text-faint); }

/* ==========================================================================
   Account
   ========================================================================== */

.license-box {
  background: var(--bg-inset);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  padding: 1.2rem 1.4rem;
  font-family: var(--font-mono);
  font-size: 1.1rem;
  color: var(--text-primary);
  letter-spacing: 0.03em;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.data-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.data-table th { text-align: left; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-faint); padding: 0 0 0.7em; border-bottom: 1px solid var(--border-subtle); font-weight: 600; }
.data-table td { padding: 0.9em 0; border-bottom: 1px solid var(--border-subtle); color: var(--text-secondary); }
.pill { display: inline-flex; align-items: center; gap: 0.4em; font-size: 0.78rem; padding: 0.3em 0.7em; border-radius: 100px; background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.pill.on { background: rgba(46,204,113,0.14); color: var(--success); }

/* ==========================================================================
   Toast
   ========================================================================== */

.toast {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
  padding: 0.9rem 1.4rem;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
  font-size: 0.9rem;
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  max-width: 90vw;
  text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-alt);
  padding: var(--space-xl) 0 var(--space-md);
  margin-top: var(--space-2xl);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(4, 1fr);
  gap: 2rem;
  padding-bottom: var(--space-lg);
}
.footer-brand .brand { margin-bottom: 0.8rem; }
.footer-brand p { color: var(--text-faint); font-size: 0.86rem; max-width: 28ch; }
.footer-col h4 { font-size: 0.78rem; margin-bottom: 1.1rem; }
.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin-bottom: 0.65rem; }
.footer-col a { color: var(--text-muted); font-size: 0.9rem; }
.footer-col a:hover { color: var(--text-primary); }
.footer-bottom {
  border-top: 1px solid var(--border-subtle);
  padding-top: var(--space-md);
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  font-size: 0.8rem;
  color: var(--text-faint);
}
.footer-social { display: flex; gap: 0.8rem; }
.footer-social a {
  width: 36px; height: 36px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
}
.footer-social a:hover { color: var(--text-primary); border-color: var(--accent); }

.nav-icon-btn {
  width: 34px; height: 34px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  flex-shrink: 0;
}
.nav-icon-btn:hover { color: var(--text-primary); border-color: var(--accent); }
.footer-disclaimer { max-width: var(--container); margin: 0 auto; padding: 0 1.5rem; font-size: 0.76rem; color: var(--text-faint); line-height: 1.6; }

/* ==========================================================================
   Per-game theming hooks
   ========================================================================== */

[data-game="lol"]  { --game-accent: var(--lol);   --game-accent-2: var(--lol-2);   --game-soft: var(--lol-soft);   --game-soft-2: var(--lol-soft-2);   --game-on-accent: var(--lol-on);   --game-on-accent-2: var(--lol-on-2); }
[data-game="dota"] { --game-accent: var(--dota);  --game-accent-2: var(--dota-2);  --game-soft: var(--dota-soft);  --game-soft-2: var(--dota-soft-2);  --game-on-accent: var(--dota-on);  --game-on-accent-2: var(--dota-on-2); }
[data-game="smite"]{ --game-accent: var(--smite); --game-accent-2: var(--smite-2); --game-soft: var(--smite-soft); --game-soft-2: var(--smite-soft-2); --game-on-accent: var(--smite-on); --game-on-accent-2: var(--smite-on-2); --game-gradient: var(--smite-gradient); }
[data-game="mc"]   { --game-accent: var(--mc);    --game-accent-2: var(--mc-2);    --game-soft: var(--mc-soft);    --game-soft-2: var(--mc-soft-2);    --game-on-accent: var(--mc-on);    --game-on-accent-2: var(--mc-on-2); }
[data-game="any"]  { --game-accent: var(--any);   --game-accent-2: var(--any-2);   --game-soft: var(--any-soft);   --game-soft-2: var(--any-soft-2);   --game-on-accent: var(--any-on);   --game-on-accent-2: var(--any-on-2); --game-gradient: var(--any-gradient); }

/* Rainbow badge variant for the "Add any game" hero — same shape/spacing
   as .game-badge, gradient fill instead of a flat --game-accent. */
.game-badge.rainbow-badge {
  background: var(--any-gradient);
  color: #16161a;
}

.game-hero {
  background: linear-gradient(180deg, var(--game-soft), transparent 55%, var(--game-soft-2) 130%);
  padding: var(--space-xl) 0 var(--space-lg);
  border-bottom: 1px solid var(--border-subtle);
}
.game-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  background: var(--game-accent);
  color: var(--game-on-accent);
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.4em 0.9em;
  border-radius: 100px;
  margin-bottom: 1rem;
}
.game-accent-text { color: var(--game-accent); }
.game-list-mark::marker { color: var(--game-accent); }
.game-card-alt {
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-top: 3px solid var(--game-accent);
  border-radius: var(--radius-md);
  padding: 1.5rem;
}
.game-card-alt .num { font-family: var(--font-mono); font-size: 1.7rem; color: var(--game-accent); font-weight: 600; display: block; margin-bottom: 0.2rem; }
.game-card-alt:nth-child(even) { border-top-color: var(--game-accent-2, var(--game-accent)); }
.game-card-alt:nth-child(even) .num { color: var(--game-accent-2, var(--game-accent)); }

/* Mock overlay-on-screen illustration used on game pages */
.mock-screen {
  aspect-ratio: 16/9;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-subtle);
  background:
    radial-gradient(ellipse at 20% 20%, var(--game-soft), transparent 55%),
    radial-gradient(ellipse at 80% 80%, var(--game-soft-2, rgba(255,255,255,0.04)), transparent 55%),
    var(--bg-inset);
  position: relative;
  overflow: hidden;
  padding: 1.2rem;
}
.mock-screen .chrome-dots { display: flex; gap: 0.4rem; position: absolute; top: 1rem; left: 1.2rem; }
.mock-screen .chrome-dots span { width: 9px; height: 9px; border-radius: 50%; background: var(--border-strong); }
.mock-screen .mock-grid { position: absolute; bottom: 1.2rem; right: 1.2rem; display: grid; grid-template-columns: repeat(3,1fr); gap: 0.5rem; }
.mock-screen .mock-grid .timer-btn { width: 44px; height: 44px; }
.mock-screen .mock-grid .num { font-size: 0.85rem; }

/* Minecraft dirt-block texture — literal pixel squares, not a gradient */
.dirt-grid {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(16, 1fr);
  grid-template-rows: repeat(9, 1fr);
  gap: 1px;
  background: #3a2513;
}
.dirt-grid span { display: block; background: #6b4423; }
.dirt-grid span:nth-child(7n+2) { background: #7d5230; }
.dirt-grid span:nth-child(7n+4) { background: #5a3b1e; }
.dirt-grid span:nth-child(7n+6) { background: #8b5a2b; }
.dirt-grid span:nth-child(11n+1) { background: #4a2f18; }
.dirt-block {
  aspect-ratio: 1;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-subtle);
  overflow: hidden;
  position: relative;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  gap: 2px;
  background: #3a2513;
}
.dirt-block span { display: block; background: #6b4423; }
.dirt-block span:nth-child(5n+2) { background: #7d5230; }
.dirt-block span:nth-child(5n+4) { background: #5a3b1e; }
.dirt-block span:nth-child(9n+1) { background: #8b5a2b; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 960px) {
  /* One-column layout (package 1020): the hero is much taller than wide here, so a video
     covering all of it would show only a thin, blurry slice. Instead the lighter -small video
     (main.js) sits as a 16:9 band at the top of the section, flush under the nav, and fades
     into the page at its bottom; the TRACKY LIVE card and the text follow below it. */
  .hero-bg-video {
    position: relative;
    inset: auto;
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    margin: calc((var(--space-2xl) + var(--space-xl)) / -2) 0 var(--space-md);
  }
  .hero-bg-fade {
    inset: 0 0 auto 0;
    height: auto;
    aspect-ratio: 16 / 9;
    background: linear-gradient(180deg, rgba(18, 18, 18, 0) 55%, var(--bg-base) 100%);
  }
  .hero-grid { grid-template-columns: 1fr; }
  .hero-visual { order: -1; max-width: 340px; margin: 0 auto var(--space-md); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: repeat(3, 1fr); }
  .pricing-grid { grid-template-columns: repeat(2, 1fr); }
  .price-card.featured { grid-column: span 2; }
  .doc-layout { grid-template-columns: 1fr; }
  .doc-nav { position: static; display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: var(--space-md); }
  .doc-nav li { margin: 0; }
  .blog-grid { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .nav-links, .nav-right .btn { display: none; }
  .nav-toggle { display: flex; }
  .nav.open .nav-links {
    display: flex;
    position: absolute;
    top: 100%; left: 0; right: 0;
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--border-subtle);
    flex-direction: column;
    align-items: flex-start;
    padding: 1rem 1.5rem 1.5rem;
    gap: 0.3rem;
  }
  .nav.open .nav-dropdown-menu { position: static; transform: none; opacity: 1; visibility: visible; box-shadow: none; border: none; padding: 0 0 0 1rem; margin-top: 0.3rem; display: none; }
  .nav.open .nav-dropdown.expanded .nav-dropdown-menu { display: block; }
  .nav-links a { padding: 0.6rem 0; width: 100%; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: repeat(2, 1fr); }
  .pricing-grid { grid-template-columns: 1fr; }
  .price-card.featured { grid-column: span 1; }
  .form-row { grid-template-columns: 1fr; }
  .compare-table { font-size: 0.8rem; }
  h1 { font-size: 2.1rem; }
  .section { padding: var(--space-xl) 0; }
  .stat-strip { gap: 1.1rem 1.6rem; }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
}

.btn-dot {
  opacity: 0;
  transition: opacity 0.15s ease;
}

/* No prefers-reduced-motion rule on purpose (owner decision, 18 Oct): the page's motion
   plays whatever the visitor's "remove animations" setting says. */

/* package 1022: company details not filled in yet (build.py, COMPANY) - easy to spot on the legal pages */
.todo { background: rgba(255,170,0,0.16); color: var(--warn); border-radius: 3px; padding: 0 0.25em; font-weight: 600; }
.footer-company { margin-bottom: 0.5rem; }
.footer-sal { display: inline-block; vertical-align: middle; }
.footer-sal img { display: block; max-width: 100%; height: auto; }
.prose table { width: 100%; border-collapse: collapse; margin: 1em 0; font-size: 0.92rem; }
.prose th, .prose td { text-align: left; vertical-align: top; padding: 0.5em 0.6em; border-bottom: 1px solid var(--border, rgba(255,255,255,0.08)); color: var(--text-secondary); }
.prose th { color: var(--text-primary); font-weight: 600; }

/* package 1022: the admin page */
.admin-wrap { max-width: 980px; margin: 0 auto; }
.admin-wrap .card { margin-bottom: var(--space-lg, 1.5rem); }
.admin-row { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.admin-row > input[type=text] { flex: 1 1 220px; }
.admin-wrap input[type=text], .admin-wrap textarea {
  background: var(--bg-inset); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 0.6em 0.8em; color: var(--text-primary); font-family: var(--font-body); font-size: 0.95rem;
}
.admin-wrap input[type=text]:focus, .admin-wrap textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.admin-wrap textarea { width: 100%; min-height: 4.5em; resize: vertical; }
.admin-wrap input[type=number], .admin-wrap input[type=email], .admin-wrap select {
  background: var(--bg-inset); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 0.6em 0.8em; color: var(--text-primary); font-family: var(--font-body); font-size: 0.95rem;
}
.admin-wrap .field input[type=number], .admin-wrap .field input[type=email] { width: 100%; }
.admin-money { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.6rem; margin: 0.8rem 0; }
.admin-money > div { border: 1px solid rgba(255,255,255,0.10); border-radius: 8px; padding: 0.55rem 0.7rem; }
.admin-money .lbl { display: block; font-size: 0.78rem; color: var(--text-muted, #8a8f98); }
.admin-money .num { display: block; font-family: var(--font-mono); font-size: 1.15rem; color: var(--text-primary); }
.admin-money .pay .num { color: #7acc7a; }
.admin-money .hold .num { color: #e0b35c; }
.admin-keys { font-family: var(--font-mono); font-size: 0.85rem; white-space: pre; overflow-x: auto; background: var(--bg-inset); border-radius: 6px; padding: 0.6rem 0.8rem; margin: 0.5rem 0; }
.admin-wrap details summary { cursor: pointer; font-size: 0.9rem; margin-top: 0.6rem; }
.admin-wrap .field label input[type=checkbox] { width: auto; margin-right: 0.4em; vertical-align: middle; }
.admin-wrap .admin-row > .field { margin-bottom: 0.6rem; }
.admin-kv { display: grid; grid-template-columns: max-content 1fr; gap: 0.25rem 1rem; font-size: 0.9rem; margin: 0.6rem 0; }
.admin-kv dt { color: var(--text-muted, #8a8f98); }
.admin-kv dd { margin: 0; word-break: break-word; }
.admin-log { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.admin-log th, .admin-log td { text-align: left; vertical-align: top; padding: 0.4em 0.5em; border-bottom: 1px solid rgba(255,255,255,0.08); }
.admin-ad-preview { max-width: 440px; width: 100%; border-radius: 6px; border: 1px solid rgba(255,255,255,0.12); background: #2a2a2a; }
.admin-msg { font-size: 0.88rem; margin-top: 0.5rem; }
.admin-msg.err { color: #e06060; }
.admin-msg.ok { color: #7acc7a; }
.admin-tag { display: inline-block; font-size: 0.75rem; padding: 0.05em 0.5em; border-radius: 999px; border: 1px solid rgba(255,255,255,0.18); margin-left: 0.4em; }

/* The animated tile background (assets/js/bg-tiles.js, package 1025): one canvas fixed to the window, above the
   sections' own backgrounds and below their content (bg-tiles.js puts that content in position: relative). */
.bg-tiles {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  /* owner, 23 Oct: the first time the canvas shows it fades in from fully transparent over 1.5 s. bg-tiles.js does
     the fade (package 1035), counting only frames the page really draws: a CSS animation ran its clock while a busy
     page had not painted yet, so it was often over before anyone saw it. */
}

/* ==========================================================================
   "The games are presets" (games/add-any-game.html, package 1036): three small Tracky windows set up for three
   different uses. The timers count down for real (initPresetGrids in main.js).
   ========================================================================== */
.pg-frames {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
  align-items: stretch;
}
.pg-frame {
  margin: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: 1.25rem 1.25rem 1.1rem;
}
.pg-label {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding-bottom: 0.7rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--border-subtle);
}
.pg-grid {
  display: grid;
  grid-template-columns: repeat(var(--pg-cols, 3), 64px);
  gap: 0.9rem 0.75rem;
  justify-content: center;
}
.pg-cell { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; min-width: 0; }
.pg-slot {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
  background: var(--bg-inset);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
}
.pg-slot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
/* running: a dark wash over the picture so the time reads; ready (0:00): the clean picture, no time */
.pg-slot::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #000;
  opacity: 0.6;
  transition: opacity 0.25s ease;
}
.pg-slot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--danger);
  opacity: 0;
  pointer-events: none;
}
.pg-slot.is-ready::before { opacity: 0; }
.pg-slot.is-warning { border-color: var(--danger); }
.pg-slot.is-warning::after { animation: warning-pulse 0.9s ease-in-out infinite; }
.pg-key {
  position: absolute;
  top: 3px;
  left: 5px;
  z-index: 3;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0,0,0,0.95);
}
.pg-num {
  position: relative;
  z-index: 3;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text-primary);
  text-shadow: 0 1px 3px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.7);
}
.pg-slot.is-warning .pg-num { color: #ffdcdc; }
.pg-name {
  font-size: 0.72rem;
  line-height: 1.25;
  color: var(--text-secondary);
  text-align: center;
  max-width: 76px;
}
.pg-tag {
  display: block;
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
.pg-frame figcaption {
  margin-top: auto;
  padding-top: 1rem;
  font-size: 0.85rem;
  color: var(--text-secondary);
  text-align: center;
}
@media (max-width: 960px) {
  .pg-frames { grid-template-columns: minmax(0, 1fr); max-width: 380px; margin: 0 auto; }
}

/* Clips on the features page (package 1037): the carousel's 16:9 frame, on its own, between a section's heading and
   its cards. They loop while on screen (initStandaloneClips in main.js). */
.feature-clip {
  max-width: 980px;
  margin: 0 auto var(--space-lg);
}

/* A game page's top box holding a real clip (package 1039): the League video, the Dota "Copy timers" animation.
   Edge to edge, no padding; the box is already 16:9 like both clips. */
.mock-screen.has-media { padding: 0; background: var(--bg-inset); }
.mock-screen .mock-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.mock-screen.has-media .vc-anim-poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mock-screen.has-media .vc-anim { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; }
