/* ============================================================================
   revibed-chrome.css — the shared Revibed Games shell.

   SOURCE OF TRUTH. Edit here, then run scripts/sync-chrome.sh to vendor it into
   each game. Never edit a vendored copy — the sync script will overwrite it and
   `--check` will fail the drift test.

   THE ONE RULE: this file contains NO literal colours. Every value comes from a
   --rvb-* token the game defines in its own theme file. Games share a shell,
   never a skin. If you are tempted to write a hex here, you want the theme file.

   Structure, states and anatomy live here. Palette, fonts and mood live there.
   Spec: docs/DESIGN-LANGUAGE.md
   ============================================================================ */

/* ---- [hidden] must win --------------------------------------------------
   The chrome sets `display` on a lot of classes, and an author rule beats the UA stylesheet's
   [hidden] — so `<label class="rvb-field" hidden>` stayed visible. Any consumer toggling an
   element with the hidden attribute would hit this, so the shared file owns the fix rather than
   each game rediscovering it. (Both games already carried a local copy of this rule.) */
[hidden] { display: none !important; }

/* ---- panel: the base primitive everything floats in ---------------------- */
.rvb-panel {
  background: var(--rvb-panel);
  border: 1px solid var(--rvb-edge-dim);
  border-radius: var(--rvb-radius-lg);
}

/* ---- buttons ------------------------------------------------------------
   Padding is in em so a game sizes a button by setting font-size alone. */
.rvb-btn {
  font: inherit;
  letter-spacing: var(--rvb-track-label);
  color: var(--rvb-text);
  background: var(--rvb-panel-2);
  border: 1px solid var(--rvb-edge);
  border-radius: var(--rvb-radius);
  padding: 0.45em 0.9em;
  cursor: pointer;
}
.rvb-btn:hover:not(:disabled):not(.active) { background: var(--rvb-panel-hover); }
.rvb-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.rvb-btn.primary,
.rvb-btn.active {
  background: var(--rvb-primary);
  border-color: var(--rvb-primary);
  color: var(--rvb-on-primary);
}
.rvb-btn.primary:hover:not(:disabled) { background: var(--rvb-primary-hover); border-color: var(--rvb-primary-hover); }

/* danger stays an outline until hover — destructive actions should not shout
   as loudly as the thing you actually came to do */
.rvb-btn.danger { color: var(--rvb-danger); border-color: var(--rvb-danger); background: transparent; }
.rvb-btn.danger:hover:not(:disabled) { background: var(--rvb-danger); color: var(--rvb-on-primary); }

.rvb-btn.ghost { background: transparent; }
.rvb-btn.accent { color: var(--rvb-success); border-color: var(--rvb-success); background: transparent; }

.rvb-btn.sm { font-size: 0.85em; }

/* ---- tabs ---------------------------------------------------------------
   Active tab is the solid primary. A .action tab is pushed to the far end —
   the "+ Create" affordance that belongs with the tabs but isn't one. */
.rvb-tabs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4em; }
.rvb-tab {
  font: inherit;
  letter-spacing: var(--rvb-track-label);
  color: var(--rvb-text);
  background: var(--rvb-panel-2);
  border: 1px solid var(--rvb-edge);
  border-radius: var(--rvb-radius);
  padding: 0.45em 1em;
  cursor: pointer;
}
.rvb-tab:hover:not(.active) { background: var(--rvb-panel-hover); }
.rvb-tab.active { background: var(--rvb-primary); border-color: var(--rvb-primary); color: var(--rvb-on-primary); }
.rvb-tab.action { margin-left: auto; color: var(--rvb-success); border-color: var(--rvb-success); }

/* ---- card ---------------------------------------------------------------
   Anatomy is fixed: title (bright) → uppercase micro-label (semantic colour)
   → dim description → optional action row. Hover raises the border to primary. */
.rvb-card {
  font: inherit;
  display: flex;
  flex-direction: column;
  gap: 0.35em;
  padding: 0.9em 0.85em;
  text-align: left;
  color: var(--rvb-text);
  background: var(--rvb-panel-2);
  border: 1px solid var(--rvb-edge);
  border-radius: var(--rvb-radius-lg);
}
.rvb-card.clickable { cursor: pointer; }
.rvb-card.clickable:hover:not(.locked) { border-color: var(--rvb-primary); }
.rvb-card.locked { opacity: 0.4; cursor: not-allowed; }

/* The card's parts are NOT scoped to .rvb-card on purpose: the same title/description pairing
   appears inside modals and panels too, and scoping it made a heading render as unstyled body
   text (invisible, in one case) the moment it was used outside a card. A class should mean the
   same thing wherever it is written — that is the entire point of the shell. */
.rvb-card-title { color: var(--rvb-text-bright); }
.rvb-card-label { text-transform: uppercase; letter-spacing: var(--rvb-track-label); font-size: 0.8em; }
.rvb-card-desc { color: var(--rvb-text-dim); line-height: 1.5; }
.rvb-card-actions { display: flex; flex-wrap: wrap; gap: 0.4em; margin-top: 0.3em; }

/* ---- badge: no chrome, the colour is the whole signal -------------------- */
.rvb-badge {
  font-size: 0.8em;
  letter-spacing: var(--rvb-track-label);
  padding: 0 0.35em;
  border-radius: var(--rvb-radius);
}
.rvb-badge.official { color: var(--rvb-gold); }
.rvb-badge.new { color: var(--rvb-success); }
.rvb-badge.warn { color: var(--rvb-warn); }

/* ---- modal: scrim + centred panel, backdrop-click closes -----------------
   The modal sets its own font because it is almost always appended to <body>,
   outside whatever element a game scopes its typography to. Relay's auth dialog
   rendered in Times for exactly this reason until the shell took it over. */
.rvb-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 40;
  font-family: var(--rvb-font-ui);
  color: var(--rvb-text);
  background: var(--rvb-scrim);
  align-items: center;
  justify-content: center;
  padding: 1em;
}
.rvb-modal.visible { display: flex; }
.rvb-modal-panel {
  width: min(420px, 92vw);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--rvb-panel-solid);
  border: 1px solid var(--rvb-edge);
  border-radius: var(--rvb-radius-lg);
  padding: 1.2em 1.3em;
}
.rvb-modal-panel h3 {
  color: var(--rvb-text-bright);
  letter-spacing: 0.2em;
  margin-bottom: 0.7em;
}
.rvb-modal-sub { color: var(--rvb-muted); font-size: 0.75em; letter-spacing: var(--rvb-track-label); }
.rvb-modal-actions { display: flex; justify-content: flex-end; gap: 0.6em; margin-top: 1em; }

/* ---- form field ---------------------------------------------------------
   The error slot keeps its height whether or not it has text, so submitting a
   bad form never makes the dialog jump under the pointer. */
.rvb-field { display: block; color: var(--rvb-text-dim); letter-spacing: var(--rvb-track-label); margin: 0.8em 0 0.3em; }
.rvb-field input,
.rvb-field select,
.rvb-input,
.rvb-select {
  display: block;
  width: 100%;
  margin-top: 0.3em;
  padding: 0.6em 0.7em;
  font: inherit;
  color: var(--rvb-text-bright);
  background: var(--rvb-inset);
  border: 1px solid var(--rvb-edge);
  border-radius: var(--rvb-radius);
}
.rvb-field input:focus,
.rvb-field select:focus,
.rvb-input:focus,
.rvb-select:focus { outline: none; border-color: var(--rvb-primary); }
.rvb-err { color: var(--rvb-danger); min-height: 1.3em; margin-top: 0.6em; }

/* keyboard focus must always be visible, whatever a game does to :focus */
.rvb-btn:focus-visible,
.rvb-tab:focus-visible,
.rvb-card.clickable:focus-visible {
  outline: 2px solid var(--rvb-primary);
  outline-offset: 1px;
}

/* ---- rank row -----------------------------------------------------------
   rank · handle · value. One row type for leaderboards, rivalries and crew
   standings alike, so a player reads all three the same way. Your own row is
   always highlighted — you should never have to hunt for yourself. */
.rvb-rows { min-height: 120px; }
.rvb-rank-row {
  display: grid;
  grid-template-columns: 2.2em 1fr auto;
  gap: 0.6em;
  padding: 0.4em 0.45em;
  color: var(--rvb-text);
  border-bottom: 1px solid var(--rvb-edge-dim);
}
.rvb-rank-row .rvb-rank { color: var(--rvb-muted); font-variant-numeric: tabular-nums; }
.rvb-rank-row .rvb-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rvb-rank-row .rvb-value { text-align: right; color: var(--rvb-success); font-variant-numeric: tabular-nums; }
.rvb-rank-row.mine { background: var(--rvb-highlight); }
.rvb-rank-row.mine .rvb-who { color: var(--rvb-primary); }
/* medals for the top three, and nothing else — no bars, no sparklines */
.rvb-rank-row.r1 .rvb-rank { color: var(--rvb-gold); }
.rvb-rank-row.r2 .rvb-rank,
.rvb-rank-row.r3 .rvb-rank { color: var(--rvb-text-dim); }

/* a two-column variant for head-to-head, where there is no rank */
.rvb-rank-row.h2h { grid-template-columns: 1fr auto; }

/* ---- empty / loading / error state --------------------------------------
   Never a spinner. Every one of these is written copy in the game's own voice;
   the shell only decides how it sits. */
.rvb-empty { color: var(--rvb-muted); padding: 1.2em 0.3em; }

/* ---- masthead: wordmark → tagline → backlink, in that order -------------- */
.rvb-masthead { text-align: center; }
.rvb-masthead .rvb-wordmark { color: var(--rvb-text-bright); font-family: var(--rvb-font-display); }
.rvb-masthead .rvb-tagline { color: var(--rvb-muted); }
.rvb-masthead .rvb-backlink { font-size: 0.75em; letter-spacing: var(--rvb-track-label); color: var(--rvb-muted); }
.rvb-masthead .rvb-backlink a { color: var(--rvb-text-dim); text-decoration: none; }
.rvb-masthead .rvb-backlink a:hover { color: var(--rvb-text-bright); }

/* ---- account bar --------------------------------------------------------
   Signed out it is an invitation, never a gate. Games may reserve space on the
   left with padding-left for their own controls. */
.rvb-accountbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6em;
}
.rvb-accountbar .rvb-hint { color: var(--rvb-muted); }
.rvb-accountbar .rvb-handle { color: var(--rvb-success); letter-spacing: var(--rvb-track-label); }

/* ---- stat strip (profile) ------------------------------------------------ */
.rvb-stats { display: flex; gap: 1.6em; margin: 0.3em 0 1em; }
.rvb-stats span { display: flex; flex-direction: column; }
.rvb-stats b { font-size: 1.7em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.rvb-stats small { color: var(--rvb-muted); font-size: 0.75em; margin-top: 0.15em; }
.rvb-stats .good { color: var(--rvb-success); }
.rvb-stats .info { color: var(--rvb-primary); }
.rvb-stats .gold { color: var(--rvb-gold); }

@media (prefers-reduced-motion: reduce) {
  .rvb-btn, .rvb-tab, .rvb-card { transition: none; }
}
