/* ==========================================================================
   Design tokens
   ==========================================================================
   One scale for spacing, one for type, one for radius. Before this, every
   component picked its own values - 7px here, 9px there, four different
   corner radii on the same screen - which is what made the app read as
   "assembled" rather than "designed".

   The palette keeps the dark, military feel but demotes the red. It used to
   mean five different things at once (active tab, primary button, section
   label, group heading, card border), so nothing it touched stood out. It
   now means exactly one: "this is the action, or the place you are".
   Meaning otherwise comes from the semantic colours below.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* Surfaces, from furthest back to nearest front. */
  --bg: #0c0f13;
  --surface: #14181e;
  --surface-2: #1a1f26;
  --surface-3: #212832;
  --border: #2a323c;
  --border-soft: #1f262e;

  /* Text, three weights of presence. */
  --text: #e9ecef;
  --text-2: #b6bfc9;
  --muted: #8b95a1;

  /* One accent, used sparingly. */
  --accent: #e0503f;
  --accent-hover: #ec6553;
  --accent-soft: rgba(224, 80, 63, 0.14);
  --accent-line: rgba(224, 80, 63, 0.45);

  /* Semantic. Each has a soft variant for backgrounds. */
  --ok: #46c25c;
  --ok-soft: rgba(70, 194, 92, 0.13);
  --gold: #e3a92f;
  --gold-soft: rgba(227, 169, 47, 0.13);
  --danger: #f4584f;
  --danger-soft: rgba(244, 88, 79, 0.13);
  --info: #5e9bf0;
  --info-soft: rgba(94, 155, 240, 0.13);
  --discord: #5865f2;

  /* Spacing: a 4px base, named by use rather than by number. */
  --gap-1: 4px;
  --gap-2: 8px;
  --gap-3: 12px;
  --gap-4: 16px;
  --gap-5: 24px;
  --gap-6: 32px;
  --gap-7: 48px;

  /* Type scale (1.2 ratio from 0.78rem). */
  --fs-micro: 0.7rem;
  --fs-small: 0.78rem;
  --fs-body: 0.875rem;
  --fs-lead: 0.95rem;
  --fs-h3: 1.05rem;
  --fs-h2: 1.2rem;
  --fs-h1: 1.45rem;

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-2: 0 6px 18px rgba(0, 0, 0, 0.35);
  --shadow-3: 0 20px 48px rgba(0, 0, 0, 0.5);

  --ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent-line);

  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* Older names, kept so the 1700 lines written against them keep working. */
:root {
  --panel: var(--surface);
  --panel-alt: var(--surface-2);
}

/* Keyboard users get a visible ring everywhere. It was missing entirely,
   which made the app impossible to operate without a mouse. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background:
    radial-gradient(1200px 400px at 50% -100px, rgba(214, 72, 58, 0.08), transparent),
    var(--bg);
  color: var(--text);
  padding-inline: max(16px, env(safe-area-inset-left, 0px));
  min-height: 100vh;
}

/* ---------- header / nav ---------- */

header.app-header {
  padding: 18px 4px 14px;
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
  max-width: 1200px;
  margin: 0 auto;
}

.header-actions { display: flex; gap: 8px; align-items: center; }

header.app-header h1 {
  margin: 0 0 3px;
  font-size: 1.35rem;
  letter-spacing: 0.01em;
}

header.app-header h1 .accent { color: var(--accent); }

header.app-header p { margin: 0; color: var(--muted); font-size: 0.82rem; }

.admin-link {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 14px;
  white-space: nowrap;
}

.admin-link:hover { color: var(--text); border-color: var(--muted); }

nav.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--border);
  max-width: 1200px;
  margin: 0 auto;
}

nav.tabs button {
  background: var(--panel);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 15px;
  font-size: 0.83rem;
  cursor: pointer;
  transition: all 0.15s ease;
}

nav.tabs button:hover { color: var(--text); }

nav.tabs button.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

main {
  padding: 18px 4px 48px;
  max-width: 1200px;
  margin: 0 auto;
}

section.tab-panel { display: none; }
section.tab-panel.active { display: block; }

/* ---------- panels ---------- */

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 16px;
}

.panel h2 { margin: 0 0 12px; font-size: 1rem; letter-spacing: 0.01em; }
.panel h3 { font-size: 0.88rem; color: var(--muted); margin: 16px 0 8px; }

.login-panel { max-width: 460px; }

/* ---------- forms / buttons ---------- */

.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 10px;
}

input[type="text"], input[type="password"], input[type="number"], select {
  flex: 1 1 200px;
  min-width: 0;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 9px 12px;
  border-radius: 8px;
  font-size: 0.88rem;
  font-family: inherit;
}

input:focus, select:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }

/* input[type=...] is an attribute selector, which outranks a plain class -
   so this needs the element qualifier to actually win. */
input.small-input { flex: 0 0 90px; }

button.btn {
  background: var(--accent);
  color: #fff;
  border: none;
  padding: 9px 16px;
  border-radius: 8px;
  font-size: 0.83rem;
  cursor: pointer;
  white-space: nowrap;
  font-family: inherit;
}

button.btn:hover { filter: brightness(1.1); }

button.btn.secondary {
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--text);
}

button.btn.ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
}

button.btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* The Discord sign-in is an <a>, not a <button>: without this it inherited
   the link colour and read as grey text on blurple. */
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  border: none;
  padding: 9px 16px;
  border-radius: 8px;
  font-size: 0.83rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
a.btn:hover { filter: brightness(1.1); }

.action-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }

.auto-refresh {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
  font-size: 0.85rem;
}

.auto-refresh label { display: flex; align-items: center; gap: 6px; }

/* ---------- tiles ---------- */

.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}

.tile {
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
}

.tile-value { font-size: 1.25rem; font-weight: 650; letter-spacing: -0.01em; }
.tile-label { color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; margin-top: 3px; }

.bar { height: 5px; background: var(--border); border-radius: 999px; overflow: hidden; margin-top: 8px; }
.bar > span { display: block; height: 100%; background: var(--gold); }
.bar.ok > span { background: var(--ok); }
.bar.warn > span { background: var(--gold); }
.bar.danger > span { background: var(--danger); }

/* ---------- player cards ---------- */

.roster-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.roster-header h2 { margin: 0 0 6px; }

.toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin: 12px 0;
  padding: 10px;
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
}

.toolbar .filter-input { flex: 2 1 220px; }
.toolbar .sort-select { flex: 1 1 170px; }
.toolbar .count { margin-left: auto; font-size: 0.8rem; white-space: nowrap; }

.segmented { display: flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.segmented button {
  background: transparent;
  border: none;
  color: var(--muted);
  padding: 8px 13px;
  font-size: 0.8rem;
  cursor: pointer;
  font-family: inherit;
}
.segmented button.active { background: var(--accent); color: #fff; }

.player-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
  gap: 10px;
}

.player-card {
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.player-card:hover { border-color: var(--accent); transform: translateY(-1px); }

.player-head { display: flex; align-items: center; gap: 10px; }

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.85rem;
  border: 1px solid;
  flex-shrink: 0;
}

.player-id { min-width: 0; flex: 1; }

.player-name {
  font-weight: 600;
  font-size: 0.92rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.player-meta {
  color: var(--muted);
  font-size: 0.72rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

.rank {
  color: var(--muted);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  align-self: flex-start;
}

.stat-row {
  display: flex;
  gap: 6px;
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--border-soft);
}

.stat { flex: 1; min-width: 0; text-align: center; }
.stat-value { font-size: 0.92rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat-label { color: var(--muted); font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.04em; margin-top: 1px; }

.power-bar { height: 3px; background: var(--border); border-radius: 999px; overflow: hidden; margin-top: 10px; }
.power-bar > span { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--gold)); }

.player-foot {
  margin-top: 9px;
  font-size: 0.72rem;
  color: var(--muted);
  display: flex;
  justify-content: space-between;
}

.card-details { margin-top: 8px; }
.card-details summary { cursor: pointer; color: var(--muted); font-size: 0.7rem; }
.card-details dl {
  margin: 4px 0 0;
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 3px 10px;
  font-size: 0.71rem;
}

.card-details dt { color: var(--muted); }

.card-details dd {
  margin: 0;
  overflow-wrap: anywhere;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.card-details dd.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.66rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  overflow-wrap: normal;
}

.detail-group-title {
  margin-top: 10px;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--accent);
  border-bottom: 1px solid var(--border-soft);
  padding-bottom: 3px;
}

.detail-group-title:first-of-type { margin-top: 8px; }

.detail-hint { color: var(--muted); font-size: 0.65rem; }

/* ---------- chips / freshness ---------- */

.chip {
  display: inline-block;
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 0.7rem;
  border: 1px solid var(--border);
  background: var(--panel-alt);
  color: var(--muted);
  white-space: nowrap;
}

.chip.fresh { color: var(--ok); border-color: rgba(63, 185, 80, 0.35); background: rgba(63, 185, 80, 0.1); }
.chip.aging { color: var(--gold); border-color: rgba(224, 165, 39, 0.35); background: rgba(224, 165, 39, 0.1); }
.chip.stale { color: var(--danger); border-color: rgba(248, 81, 73, 0.35); background: rgba(248, 81, 73, 0.1); }

.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }

.chip-btn {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 0.82rem;
  cursor: pointer;
  font-family: inherit;
}

.chip-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.chip-btn .mine { opacity: 0.7; font-size: 0.7rem; }

.freshness-list { display: flex; flex-direction: column; gap: 6px; }

.freshness-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  flex-wrap: wrap;
}

.fr-label { font-size: 0.86rem; font-weight: 500; }
.fr-key { font-size: 0.72rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ---------- tracked rows / jobs ---------- */

.tracked-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }

.tracked-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 12px;
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}

.row-actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

.job {
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--muted);
  border-radius: 8px;
  padding: 11px 13px;
  margin-bottom: 8px;
  font-size: 0.85rem;
}

.job-running { border-left-color: var(--gold); }
.job-done { border-left-color: var(--ok); }
.job-failed { border-left-color: var(--danger); }

.job-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }

.job-steps { margin: 8px 0 0; padding-left: 18px; font-size: 0.78rem; color: var(--muted); }
.job-steps li { margin-bottom: 2px; }
.job-steps .step-ok { color: var(--ok); }
.job-steps .step-error { color: var(--danger); }
/* Not an error: an endpoint this key is not entitled to. Showing it in red
   invites a retry that can only be refused again. */
.job-steps .step-skipped { color: var(--gold); }
.job-steps .step-pending { color: var(--gold); }

/* ---------- versus ---------- */

.versus {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 12px;
  align-items: center;
  text-align: center;
}

.versus-side {
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
}

.versus-side.lead { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-soft); }
.versus-name { font-size: 0.85rem; color: var(--muted); margin-bottom: 4px; }
.versus-power { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.versus-mid { color: var(--accent); font-weight: 700; font-size: 0.9rem; }
.verdict-line { text-align: center; font-size: 0.87rem; margin: 12px 0 0; color: var(--muted); }
.vs { color: var(--accent); font-weight: 700; }

.compare-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

@media (max-width: 800px) {
  .compare-grid { grid-template-columns: 1fr; }
  .versus { grid-template-columns: 1fr; }
}

/* ---------- tables ---------- */

.table-scroll {
  overflow-x: auto;
  max-width: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
}

table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }

table th, table td {
  text-align: left;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border-soft);
  white-space: nowrap;
}

table th {
  color: var(--muted);
  font-weight: 600;
  position: sticky;
  top: 0;
  background: var(--panel);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

table tbody tr:hover { background: rgba(255, 255, 255, 0.02); }

/* ---------- states ---------- */

.muted { color: var(--muted); }
.empty { color: var(--muted); font-size: 0.85rem; }

.loading { color: var(--muted); font-size: 0.85rem; display: flex; align-items: center; gap: 8px; }

.spinner {
  width: 12px;
  height: 12px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  display: inline-block;
  animation: spin 0.7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.empty-state {
  text-align: center;
  padding: 36px 20px;
  color: var(--muted);
}

.empty-state h3 { margin: 0 0 6px; color: var(--text); font-size: 0.95rem; }
.empty-state p { margin: 0; font-size: 0.85rem; max-width: 460px; margin-inline: auto; }
.empty-icon { font-size: 1.6rem; opacity: 0.4; margin-bottom: 6px; }

.error-box {
  background: rgba(248, 81, 73, 0.1);
  border: 1px solid rgba(248, 81, 73, 0.35);
  color: #ffb4af;
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 0.84rem;
}

.error-box p { margin: 0; }

.note-box {
  background: rgba(224, 165, 39, 0.08);
  border: 1px solid rgba(224, 165, 39, 0.3);
  color: #edd39a;
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 0.82rem;
  margin-bottom: 14px;
}

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  background: var(--panel);
  padding: 1px 5px;
  border-radius: 4px;
}

footer.app-footer {
  text-align: center;
  color: var(--muted);
  font-size: 0.76rem;
  padding: 24px 4px calc(24px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border-soft);
}

footer.app-footer a { color: var(--gold); }

.coords { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.68rem; opacity: 0.75; }

/* ---------- pickers (zones de guerre, annuaire d'alliances) ---------- */

.step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 0.72rem;
  margin-right: 7px;
  vertical-align: middle;
}

.picker select {
  width: 100%;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 6px;
  font-size: 0.83rem;
  font-family: inherit;
}

.picker select option { padding: 5px 6px; }
.picker select option:checked { background: var(--accent); color: #fff; }

.picker-actions { margin-top: 10px; margin-bottom: 0; }

.fallback { margin-top: 14px; border-top: 1px solid var(--border-soft); padding-top: 12px; }
.fallback summary { cursor: pointer; color: var(--muted); font-size: 0.8rem; margin-bottom: 10px; }

.error-details {
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
  padding: 8px;
  font-size: 0.72rem;
  overflow-x: auto;
  margin: 8px 0 0;
}

/* ---------- enrichissement joueur ---------- */

.enriched-badge {
  margin-top: 8px;
  font-size: 0.68rem;
  color: var(--ok);
  background: rgba(63, 185, 80, 0.1);
  border: 1px solid rgba(63, 185, 80, 0.3);
  border-radius: 999px;
  padding: 2px 9px;
  display: inline-block;
}

button.btn.enrich-btn {
  margin-top: 8px;
  width: 100%;
  font-size: 0.72rem;
  padding: 6px 10px;
}

.toolbar .quota-label { font-size: 0.75rem; white-space: nowrap; }

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 50;
}

.overlay-box {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px;
  max-width: 620px;
  width: 100%;
  max-height: 80vh;
  overflow-y: auto;
}

.overlay-box h3 { margin: 0 0 6px; font-size: 1rem; }
.candidate-list { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; }

.king-badge {
  margin-top: 6px;
  font-size: 0.68rem;
  color: var(--gold);
  background: rgba(224, 165, 39, 0.12);
  border: 1px solid rgba(224, 165, 39, 0.35);
  border-radius: 999px;
  padding: 2px 9px;
  display: inline-block;
}

/* ---------- train d'alliance ---------- */

.train-settings { gap: 14px; align-items: flex-end; }
.train-settings label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.75rem;
  color: var(--muted);
}
/* The base rule gives inputs `flex: 1 1 200px`. Inside a column-direction
   label that basis becomes a HEIGHT, so it is reset here. */
.train-settings input, .train-settings select { flex: 0 0 auto; min-width: 150px; }
.train-settings #train-status { font-size: 0.78rem; }

.train-pool { margin-top: 4px; }
.pool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(165px, 1fr));
  gap: 4px 10px;
}
.pool-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  padding: 3px 0;
  cursor: pointer;
}

.train-week-label {
  color: var(--muted);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 14px 0 6px;
}

.train-day {
  display: grid;
  grid-template-columns: 120px 1fr 1fr 1fr;
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  background: var(--panel-alt);
  margin-bottom: 6px;
}
.train-day.weekend { border-color: rgba(224, 165, 39, 0.3); }
.train-day.weekend .train-weekday { color: var(--gold); }

.train-weekday { font-size: 0.85rem; font-weight: 600; text-transform: capitalize; }
.train-daynum { font-size: 0.72rem; font-variant-numeric: tabular-nums; }

.train-slot-label {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 3px;
}
.slot-driver .train-slot-label { color: var(--accent); }
.slot-vip .train-slot-label { color: var(--gold); }
.train-slot select { width: 100%; flex: 0 0 auto; padding: 6px 9px; font-size: 0.82rem; }
.train-slot-name { font-size: 0.85rem; font-weight: 600; }
.train-slot-name.empty { color: var(--muted); font-weight: 400; }
.train-note input { width: 100%; flex: 0 0 auto; padding: 6px 9px; font-size: 0.78rem; }

.balance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
  gap: 6px;
}
.balance-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 7px;
  background: var(--panel-alt);
  font-size: 0.8rem;
}
.balance-name { font-weight: 600; }

.train-text {
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  padding: 12px 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1.6;
  overflow-x: auto;
  margin: 0;
  color: var(--text);
}
.train-export-status { font-size: 0.78rem; }

@media (max-width: 760px) {
  .train-day { grid-template-columns: 1fr 1fr; }
  .train-date { grid-column: 1 / -1; }
  .train-note { grid-column: 1 / -1; }
}

/* ---------- escouades, historique, courbes ---------- */

.small-note { font-size: 0.75rem; margin: 4px 0 0; }
.warn-box { border-color: var(--gold); background: rgba(224, 165, 39, 0.08); }

.card-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.card-actions .card-action { flex: 1 1 auto; font-size: 0.72rem; padding: 6px 8px; }

.squads-block, .history-block { margin-top: 12px; }

.squad-source { margin-bottom: 8px; }
.squad-source-label {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  margin-bottom: 4px;
}
.squad-row {
  border: 1px solid var(--border-soft);
  border-radius: 7px;
  padding: 6px 9px;
  margin-bottom: 5px;
  background: var(--panel);
}
.squad-main { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
.squad-power { font-weight: 700; font-size: 0.88rem; font-variant-numeric: tabular-nums; }
.squad-meta { font-size: 0.7rem; }
.squad-heroes { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 5px; }
.squad-hero {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.66rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  color: var(--muted);
}
.squad-hero.named { font-family: inherit; color: var(--text); border-color: var(--border-soft); }
.squad-seen { font-size: 0.66rem; margin-top: 4px; }

.history-list { display: flex; flex-direction: column; gap: 4px; }
.history-item {
  display: grid;
  grid-template-columns: 88px 1fr;
  gap: 8px;
  align-items: baseline;
  padding: 4px 0;
  border-bottom: 1px solid var(--border-soft);
}
.history-item:last-child { border-bottom: none; }
.history-when { font-size: 0.68rem; }
.history-what { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; font-size: 0.75rem; }
.history-type {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  white-space: nowrap;
}
.history-change { color: var(--muted); }
.history-change strong { color: var(--text); }

/* ---------- duel des escouades ---------- */

.verdict-basis { font-size: 0.75rem; text-align: center; margin: 8px 0 0; }
.duel-summary { font-size: 0.8rem; margin: 0 0 12px; }
.duel-list { display: flex; flex-direction: column; gap: 4px; }

.duel-row {
  display: grid;
  grid-template-columns: 1fr 150px 1fr;
  gap: 10px;
  align-items: center;
  padding: 5px 8px;
  border-radius: 7px;
  background: var(--panel-alt);
  font-size: 0.78rem;
}
.duel-side { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.duel-side.right { justify-content: flex-end; }
.duel-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.duel-side.wins .duel-name { color: var(--text); font-weight: 600; }
.duel-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
.duel-side.wins .duel-value { color: var(--gold); font-weight: 700; }

.duel-bar { display: flex; align-items: center; gap: 6px; }
.duel-rank { color: var(--muted); font-size: 0.68rem; width: 26px; text-align: center; }
.duel-track {
  position: relative;
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--border);
}
/* The centre line is the tie; the fill grows from it towards the winner. */
.duel-track::after {
  content: '';
  position: absolute;
  left: 50%;
  top: -2px;
  bottom: -2px;
  width: 1px;
  background: var(--muted);
  opacity: 0.5;
}
.duel-fill { position: absolute; top: 0; bottom: 0; border-radius: 999px; }
.duel-fill.to-a { background: var(--accent); }
.duel-fill.to-b { background: #4c7fd6; }
.duel-delta { font-size: 0.66rem; width: 34px; text-align: right; font-variant-numeric: tabular-nums; }
.duel-delta.a { color: var(--accent); }
.duel-delta.b { color: #6f9ce6; }

/* ---------- courbes ---------- */

.chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.chart-col { min-width: 0; }
.chart-title { font-size: 0.82rem; font-weight: 600; margin-bottom: 6px; }
.power-chart { background: var(--panel-alt); border: 1px solid var(--border-soft); border-radius: 9px; padding: 8px; }
.power-chart svg { display: block; }
/* Named chart-axis, not chart-grid: the layout class of the same name would
   also match these <line> elements and set display:grid on them. */
.power-chart .chart-axis { stroke: var(--border); stroke-width: 1; }
.power-chart .chart-label { fill: var(--muted); font-size: 10px; }
.chart-caption { font-size: 0.76rem; margin-top: 6px; text-align: right; font-variant-numeric: tabular-nums; }
.chart-caption.up { color: var(--ok); }
.chart-caption.down { color: var(--danger); }

@media (max-width: 760px) {
  .duel-row { grid-template-columns: 1fr; gap: 4px; }
  .duel-side.right { justify-content: flex-start; }
  .chart-grid { grid-template-columns: 1fr; }
}

/* ---------- branche d'armee ---------- */

.army-icon { fill: currentColor; display: block; flex: 0 0 auto; }

.army-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 3px 8px 3px 6px;
  border-radius: 999px;
  border: 1px solid;
  white-space: nowrap;
}
.army-tank     { color: #e0a527; border-color: rgba(224, 165, 39, 0.45); background: rgba(224, 165, 39, 0.10); }
.army-missile  { color: #d6483a; border-color: rgba(214, 72, 58, 0.45);  background: rgba(214, 72, 58, 0.10); }
.army-aircraft { color: #6f9ce6; border-color: rgba(111, 156, 230, 0.45);background: rgba(111, 156, 230, 0.10); }

/* ---------- portraits de heros ---------- */

.hero-portrait {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  border: 1px solid;
  font-weight: 700;
  overflow: hidden;
  flex: 0 0 auto;
  line-height: 1;
  user-select: none;
}
.hero-portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-portrait.has-img { background: var(--panel-alt) !important; }
/* A thin ring repeats the branch, so a line-up reads at a glance. */
.hero-portrait.ring-tank     { box-shadow: inset 0 0 0 2px rgba(224, 165, 39, 0.75); }
.hero-portrait.ring-missile  { box-shadow: inset 0 0 0 2px rgba(214, 72, 58, 0.75); }
.hero-portrait.ring-aircraft { box-shadow: inset 0 0 0 2px rgba(111, 156, 230, 0.75); }

.hero-row { display: flex; flex-wrap: wrap; gap: 6px; }
.hero-cell { display: flex; flex-direction: column; align-items: center; gap: 3px; max-width: 64px; }
.hero-cell-name {
  font-size: 0.62rem;
  text-align: center;
  line-height: 1.15;
  word-break: break-word;
}
.hero-cell-name.unnamed { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ---------- bandeau escouade sur la carte ---------- */

.player-card.clickable { cursor: pointer; }
.player-card.clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.squad-strip {
  margin-top: 10px;
  padding: 8px 9px;
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  background: var(--panel);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.squad-strip.empty { align-items: center; padding: 7px 9px; }
.squad-strip-note { font-size: 0.72rem; }
.squad-strip-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.squad-strip-power { font-weight: 700; font-size: 0.92rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.squad-strip-src { font-size: 0.66rem; font-weight: 400; }
.squad-strip-more { font-size: 0.66rem; }

/* ---------- fenetre de detail ---------- */

body.modal-open { overflow: hidden; }

.modal-box { max-width: 720px; max-height: 86vh; padding: 0; overflow: hidden; display: flex; flex-direction: column; }

.modal-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}
.modal-avatar { width: 46px; height: 46px; font-size: 0.95rem; }
.modal-title { flex: 1; min-width: 0; }
.modal-title h3 { margin: 0; font-size: 1.05rem; }
.modal-meta { font-size: 0.75rem; margin-top: 2px; }
.modal-close {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 8px;
  width: 32px;
  height: 32px;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  flex: 0 0 auto;
}
.modal-close:hover { color: var(--text); border-color: var(--accent); }

/* Only the body scrolls, so the header stays put on a long history. */
.modal-body {
  overflow-y: auto;
  padding: 16px 18px 18px;
  flex: 1 1 auto;
  scrollbar-gutter: stable;
}
.modal-body > .modal-figures { margin-top: 0; }

.modal-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
  flex: 0 0 auto;
}
.modal-figure { background: var(--panel-alt); border: 1px solid var(--border-soft); border-radius: 9px; padding: 9px 11px; }
.modal-figure-value { font-size: 1.05rem; font-weight: 650; font-variant-numeric: tabular-nums; }
.modal-figure-label { font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin-top: 2px; }

.modal-section { margin-top: 18px; }
.modal-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.modal-section-head h4 { margin: 0; font-size: 0.85rem; letter-spacing: 0.01em; }
.modal-action { font-size: 0.68rem; padding: 4px 9px; }
.modal-raw summary { cursor: pointer; color: var(--muted); font-size: 0.8rem; margin-bottom: 8px; }

.squad-block { margin-bottom: 12px; }
.squad-block-title {
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  margin-bottom: 6px;
}
.squad-card {
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: var(--panel-alt);
  padding: 10px 12px;
  margin-bottom: 7px;
}
.squad-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; flex-wrap: wrap; }
.squad-card-power { display: flex; align-items: center; gap: 9px; }
.squad-card-value { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.squad-card-meta { font-size: 0.72rem; }
.squad-card-dates { font-size: 0.66rem; margin-top: 8px; }

@media (max-width: 620px) {
  .modal-box { max-height: 92vh; }
  .modal-figures { grid-template-columns: 1fr 1fr; }
}

.hero-edit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 6px; }

.hero-edit {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 9px;
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  background: var(--panel-alt);
}

.hero-edit-name {
  flex: 1 1 auto;
  min-width: 0;
  background: transparent;
  border: 1px solid transparent;
  padding: 5px 7px;
  font-size: 0.82rem;
  font-weight: 600;
  border-radius: 6px;
}
.hero-edit-name:hover { border-color: var(--border); }
.hero-edit-name:focus { background: var(--panel); border-color: var(--accent); font-weight: 400; }
.hero-edit-name.saved { border-color: var(--ok); }

.hero-edit-types { display: flex; gap: 3px; flex: 0 0 auto; }
.hero-type-btn {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  padding: 0;
  transition: all 0.12s ease;
}
.hero-type-btn:hover { color: var(--text); border-color: var(--muted); }
/* The active branch is the only one that takes its colour, so a row can be
   read at a glance without hunting for a checkmark. */
.hero-type-btn.active { color: #fff; }
.hero-type-btn.army-tank.active     { background: #e0a527; border-color: #e0a527; color: #1a1408; }
.hero-type-btn.army-aircraft.active { background: #6f9ce6; border-color: #6f9ce6; color: #0b1526; }
.hero-type-btn.army-missile.active  { background: var(--accent); border-color: var(--accent); }

.hero-filter-toggle { display: flex; align-items: center; gap: 6px; font-size: 0.8rem; color: var(--muted); white-space: nowrap; }

/* ---------- depot des portraits ---------- */

.hero-type-item { gap: 9px; align-items: center; }
.hero-type-text { display: flex; align-items: baseline; gap: 7px; flex: 1; min-width: 0; }

.hero-drop {
  position: relative;
  flex: 0 0 auto;
  border-radius: 10px;
  cursor: pointer;
  line-height: 0;
  transition: box-shadow 0.12s ease;
}
.hero-drop:hover { box-shadow: 0 0 0 2px var(--accent-soft); }
.hero-drop.over { box-shadow: 0 0 0 2px var(--accent); }
.hero-drop.busy { opacity: 0.5; pointer-events: none; }

.hero-drop-remove {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  font-size: 0.72rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  display: none;
}
.hero-type-item:hover .hero-drop-remove { display: block; }
.hero-drop-remove:hover { color: var(--danger); border-color: var(--danger); }

/* ---------- connexion Discord et compte ---------- */

#auth-slot { display: flex; align-items: center; }
.auth-off { font-size: 0.72rem; max-width: 170px; text-align: right; line-height: 1.25; }

/* `a.btn` (element + class) outranks a bare `.discord-btn`, so the sign-in
   button was being painted in the app's red while claiming to be Discord's.
   Matching the same specificity puts blurple back. */
a.btn.discord-btn,
.discord-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: #5865f2;
  color: #fff;
  text-decoration: none;
}
a.btn.discord-btn:hover,
.discord-btn:hover { filter: brightness(1.1); }

.auth-chip {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 7px 5px 5px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel);
}
.auth-avatar { width: 30px; height: 30px; border-radius: 50%; display: block; flex: 0 0 auto; }
.auth-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.auth-name { font-size: 0.8rem; font-weight: 600; }
.auth-sub { font-size: 0.66rem; }
.auth-sub.link-approved { color: var(--ok); }
.auth-sub.link-pending { color: var(--gold); }
.auth-sub.link-rejected, .auth-sub.link-stale { color: var(--danger); }
.auth-logout { font-size: 0.68rem; padding: 4px 9px; }

.login-banner {
  border-radius: 9px;
  padding: 10px 14px;
  margin-bottom: 14px;
  font-size: 0.85rem;
  border: 1px solid;
}
.login-banner.ok { border-color: var(--ok); background: rgba(63, 185, 80, 0.1); color: var(--ok); }
.login-banner.warn { border-color: var(--gold); background: rgba(224, 165, 39, 0.1); color: var(--gold); }

.ok-box { border-color: var(--ok); background: rgba(63, 185, 80, 0.08); }

/* ---------- choix du joueur ---------- */

.claim-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 5px;
  margin: 10px 0;
  max-height: 340px;
  overflow-y: auto;
}
.claim-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: flex-start;
  text-align: left;
  padding: 7px 10px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: var(--panel-alt);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
}
.claim-row:hover:not(:disabled) { border-color: var(--muted); }
.claim-row.selected { border-color: var(--accent); background: var(--accent-soft); }
.claim-row.taken, .claim-row:disabled { opacity: 0.45; cursor: not-allowed; }
.claim-name { font-size: 0.85rem; font-weight: 600; }
.claim-meta { font-size: 0.7rem; }
.claim-taken { font-size: 0.66rem; color: var(--danger); }
.claim-search, .claim-note { width: 100%; }
.claim-note { margin-bottom: 10px; }

/* ---------- file des officiers ---------- */

.user-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 9px 11px;
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  background: var(--panel-alt);
  margin-bottom: 6px;
}
.user-who { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1; }
.user-avatar { width: 34px; height: 34px; border-radius: 50%; display: block; flex: 0 0 auto; }
.user-name { font-size: 0.87rem; font-weight: 600; }
.user-meta { font-size: 0.72rem; margin-top: 1px; }

.avatar-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.7rem;
  border-radius: 50%;
}
.auth-avatar, .user-avatar { overflow: hidden; }
.auth-avatar img, .user-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- fiches d'identite (Discord / joueur) ---------- */

.id-card {
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: var(--panel-alt);
  padding: 12px 14px;
}
.id-head { display: flex; align-items: center; gap: 11px; margin-bottom: 10px; }
.id-avatar { width: 46px; height: 46px; border-radius: 12px; flex: 0 0 auto; overflow: hidden; }
.id-avatar-sm { width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto; overflow: hidden; }
.id-avatar img, .id-avatar-sm img { width: 100%; height: 100%; object-fit: cover; display: block; }
.id-title { min-width: 0; flex: 1; }
.id-name { font-size: 0.95rem; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.id-handle { font-size: 0.74rem; margin-top: 1px; }
.id-role { flex: 0 0 auto; }

.id-facts { margin: 10px 0 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; font-size: 0.75rem; }
.id-facts dt { color: var(--muted); }
.id-facts dd { margin: 0; text-align: right; overflow: hidden; text-overflow: ellipsis; }
.id-facts dd.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.7rem; }
.id-card .stat-row { margin: 0; }

/* ---------- demande de liaison ---------- */

.request-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel);
  padding: 14px;
  margin-bottom: 12px;
}
.request-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.request-status {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid;
}
.status-pending { color: var(--gold); border-color: rgba(224, 165, 39, 0.5); background: rgba(224, 165, 39, 0.1); }
.status-stale { color: var(--danger); border-color: rgba(248, 81, 73, 0.5); background: rgba(248, 81, 73, 0.1); }
.request-when { font-size: 0.74rem; }

.request-columns { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: stretch; }
.request-col { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.request-col-title {
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.request-col .id-card { flex: 1; }
.request-arrow { align-self: center; color: var(--accent); font-size: 1.3rem; }

.request-note {
  margin-top: 11px;
  padding: 9px 12px;
  border-left: 2px solid var(--accent);
  background: var(--panel-alt);
  border-radius: 0 8px 8px 0;
  font-size: 0.82rem;
}
.request-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 12px; }

@media (max-width: 760px) {
  .request-columns { grid-template-columns: 1fr; }
  .request-arrow { transform: rotate(90deg); }
}

.account-who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.account-avatar { width: 36px; height: 36px; border-radius: 50%; flex: 0 0 auto; overflow: hidden; }
.account-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.account-meta { font-size: 0.74rem; margin-top: 1px; }

/* ==========================================================================
   Porte d'entree : login Discord, salle d'attente, refus
   ========================================================================== */

/* The door fills what is left between the header and the footer, so the
   card sits in the middle of the screen instead of hanging from the top.
   `min-height` rather than `height`: on a short screen, or on the waiting
   screen with its four steps, the card must stay free to push the footer
   down rather than being cut off. */
.gate {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: min(68vh, 620px);
  padding: 40px 0 56px;
}

/* `display: flex` beats the `hidden` attribute, and the hidden door was
   still holding 150px of empty space above the tab bar. */
.gate[hidden] { display: none; }

.gate-card {
  width: min(460px, 100%);
  background:
    radial-gradient(420px 180px at 50% -50px, rgba(88, 101, 242, 0.14), transparent),
    var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 38px 34px 28px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}

.gate-card h2 { margin: 0; font-size: 1.3rem; letter-spacing: 0.01em; }
.gate-card p { margin: 0; line-height: 1.6; max-width: 40ch; }
.gate-card .note-box { text-align: left; width: 100%; }

/* A rule, not more whitespace: the fine print answers a different question
   ("qu'est-ce que vous lisez de mon compte") from the one the card asks. */
.gate-fine {
  font-size: 0.74rem;
  max-width: 42ch;
  line-height: 1.5;
  border-top: 1px solid var(--border-soft);
  padding-top: 14px;
  margin-top: 2px;
}

/* Blurple, not the app's red: this badge stands for Discord, and recolouring
   someone else's mark in your own palette only makes it unrecognisable. */
.gate-badge {
  width: 56px;
  height: 56px;
  border-radius: 18px;
  display: grid;
  place-items: center;
  background: #5865f2;
  color: #fff;
  box-shadow: 0 8px 22px rgba(88, 101, 242, 0.35);
}
.gate-badge svg { width: 28px; height: 28px; }

.gate-avatar {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  font-weight: 700;
}
.gate-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

.btn.big { padding: 11px 22px; font-size: 0.95rem; }

/* The four steps, so the wait has a visible end. */
.gate-steps {
  text-align: left;
  margin: 0;
  padding-left: 20px;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.9;
}
.gate-steps li.done { color: var(--ok); }
.gate-steps li.current { color: var(--text); font-weight: 600; }

.role-chip { align-self: center; }

/* ==========================================================================
   Evenements d'alliance
   ========================================================================== */

.event-card { border-left: 3px solid var(--accent); }
.event-card.closed { border-left-color: var(--muted); opacity: 0.9; }
.event-card.past { opacity: 0.75; }

.event-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.event-title { font-size: 1.05rem; font-weight: 700; }
.event-when { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; font-size: 0.85rem; margin-top: 2px; }
/* "samedi 19 septembre" -> "Samedi 19 septembre". `capitalize` would put a
   capital on every word, which is not how French dates are written. */
.event-date { display: inline-block; }
.event-date::first-letter { text-transform: uppercase; }
.event-time { color: var(--gold); font-weight: 600; }
.event-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.muted-chip { color: var(--muted); }
.event-desc { white-space: pre-wrap; line-height: 1.55; margin: 10px 0 0; }

.my-signup { margin: 14px 0; }
.signup-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 8px; }
.signup-form select, .signup-note { padding: 7px 10px; }
.signup-note { flex: 1 1 200px; min-width: 160px; }

.option-list { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.option-block {
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  padding: 12px 14px;
}
.option-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}
.option-label { font-weight: 600; }
.option-counts { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; font-size: 0.75rem; }

.count-pill {
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--muted);
}
.count-pill.accepted { color: var(--ok); border-color: rgba(63, 185, 80, 0.35); }
.count-pill.sub { color: var(--gold); border-color: rgba(224, 165, 39, 0.3); }
.count-pill.pending { color: var(--accent); border-color: rgba(214, 72, 58, 0.4); }

.signup-group { margin-top: 10px; }
.signup-group-title {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 4px;
}
.signup-group.pending .signup-group-title { color: var(--accent); }
.signup-group.accepted .signup-group-title { color: var(--ok); }

.signup-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-top: 1px solid var(--border-soft);
  flex-wrap: wrap;
}
.signup-who { display: flex; align-items: center; gap: 10px; min-width: 0; }
.signup-name { font-size: 0.88rem; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.signup-meta { font-size: 0.72rem; }
.chip.role-titulaire { color: var(--ok); border-color: rgba(63, 185, 80, 0.35); }
.chip.role-remplacant { color: var(--gold); border-color: rgba(224, 165, 39, 0.3); }

.event-officer-bar {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}
.btn.small { padding: 5px 10px; font-size: 0.78rem; }
.btn.danger { color: var(--danger); border-color: rgba(248, 81, 73, 0.35); }

.past-events { margin-top: 18px; }
.past-events summary { cursor: pointer; color: var(--muted); padding: 8px 0; }

/* --- formulaire de creation --- */

.event-form { border-left: 3px solid var(--gold); }
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
  /* Without this the grid stretches every cell to the tallest row and the
     inputs grow into big empty boxes. */
  align-items: start;
}
.form-field { display: flex; flex-direction: column; gap: 4px; }
.form-label { font-size: 0.75rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
/* Same trap as the train settings: the base rule gives inputs
   `flex: 1 1 200px`, and inside a column-direction label that basis is read
   as a HEIGHT - the fields became 200px-tall empty boxes. */
.form-field input, .form-field select { width: 100%; flex: 0 0 auto; }
/* Same skin as the inputs: a textarea that keeps the browser default reads
   as a different control from the fields right above it. */
.event-desc-input {
  width: 100%;
  padding: 9px 11px;
  resize: vertical;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}
.event-desc-input:focus { outline: none; border-color: var(--accent); }
.option-editor { margin: 14px 0; display: flex; flex-direction: column; gap: 8px; }
.option-row { align-items: center; }
.option-input { flex: 1 1 260px; }
.checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; margin: 6px 0 12px; }

/* ==========================================================================
   Journal des comptes retires
   ========================================================================== */

.removal-list { display: flex; flex-direction: column; }
.removal-row {
  display: flex;
  gap: 12px;
  justify-content: space-between;
  flex-wrap: wrap;
  padding: 6px 0;
  border-top: 1px solid var(--border-soft);
  font-size: 0.8rem;
}
.removal-name { font-weight: 600; }

/* ---------- train : mes propres passages ---------- */

.my-turns { border-left: 3px solid var(--gold); }
.my-turns-list { display: flex; flex-direction: column; }
.my-turn {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  border-top: 1px solid var(--border-soft);
  font-size: 0.88rem;
}
.my-turn:first-child { border-top: none; }
/* French dates take one capital, not one per word. */
.my-turn-date { font-weight: 600; }
.my-turn-date::first-letter { text-transform: uppercase; }
.my-turn-role { color: var(--gold); }

.train-day.mine {
  border-color: rgba(224, 165, 39, 0.45);
  background: rgba(224, 165, 39, 0.06);
}
.train-mine-tag {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gold);
  margin-top: 2px;
}

/* ---------- capacites de la cle API ---------- */

.capability-list { display: flex; flex-direction: column; margin: 12px 0; }
.capability-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-top: 1px solid var(--border-soft);
}
.capability-row:first-child { border-top: none; }
.capability-main { min-width: 0; }
.capability-label { font-size: 0.87rem; font-weight: 600; }
.capability-feature { font-size: 0.74rem; margin-top: 1px; }
.capability-message { font-size: 0.72rem; margin-top: 3px; font-style: italic; }
.capability-state { text-align: right; flex: 0 0 auto; }
.capability-when { font-size: 0.7rem; margin-top: 3px; }
.capability-row.cap-forbidden .capability-label { color: var(--danger); }
.capability-row.cap-unknown { opacity: 0.65; }

.id-problem { color: var(--danger); }

/* Une seule porte ouverte tant que la liaison n'est pas validee. */
.tabs.single { justify-content: flex-start; }

/* ==========================================================================
   Consoles (officiers, administration) : nav laterale + sections
   ========================================================================== */

/* Five quota tiles fit on one line in a console; the member site keeps the
   roomier default. */
body.console .tile-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

body.console .console-shell {
  display: grid;
  grid-template-columns: 210px minmax(0, 1fr);
  gap: 22px;
  align-items: start;
  padding: 20px 0 40px;
  max-width: 1200px;
  margin: 0 auto;
}

.console-nav {
  position: sticky;
  top: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px;
}

.console-nav button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.86rem;
  padding: 9px 12px;
  border-radius: 8px;
  cursor: pointer;
}
.console-nav button:hover { color: var(--text); background: var(--panel-alt); }
.console-nav button.active { background: var(--accent-soft); color: var(--text); font-weight: 600; }

.nav-badge {
  background: var(--accent);
  color: #fff;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  min-width: 20px;
  text-align: center;
  padding: 1px 6px;
}

.console-group {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  padding: 12px 12px 4px;
}
.console-group:first-child { padding-top: 4px; }

.console-main { min-width: 0; }
.console-section { display: none; }
.console-section.active { display: block; }

.console-section > .panel:first-child { margin-top: 0; }

/* Sur petit ecran la nav repasse au-dessus, en ligne. */
@media (max-width: 860px) {
  body.console .console-shell { grid-template-columns: 1fr; }
  .console-nav {
    position: static;
    flex-direction: row;
    overflow-x: auto;
  }
  .console-nav button { width: auto; white-space: nowrap; }
  .console-group { display: none; }
}

/* ---------- journal d'audit ---------- */

.audit-filters { margin: 14px 0 6px; }
.audit-filters input { flex: 1 1 240px; }

.audit-list { display: flex; flex-direction: column; }

.audit-day {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin: 16px 0 4px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border-soft);
}
.audit-day:first-child { margin-top: 4px; }
.audit-day::first-letter { text-transform: uppercase; }

.audit-row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
  padding: 8px 0;
  border-bottom: 1px solid var(--border-soft);
}

.audit-icon {
  width: 24px;
  height: 24px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-size: 0.7rem;
  font-weight: 700;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  color: var(--muted);
}
/* Colour by what the line is about: money, people, content. */
.audit-row.cat-quota .audit-icon { color: var(--gold); border-color: rgba(224, 165, 39, 0.4); }
.audit-row.cat-access .audit-icon,
.audit-row.cat-link .audit-icon { color: var(--ok); border-color: rgba(63, 185, 80, 0.35); }
.audit-row.cat-account .audit-icon,
.audit-row.cat-role .audit-icon { color: var(--danger); border-color: rgba(248, 81, 73, 0.35); }

.audit-action { font-size: 0.87rem; }
.audit-target { color: var(--text); font-weight: 600; }
.audit-detail { font-size: 0.75rem; margin-top: 2px; }
.audit-meta { text-align: right; font-size: 0.75rem; white-space: nowrap; }
.audit-actor { display: block; font-weight: 600; font-size: 0.8rem; }
.audit-when { font-size: 0.72rem; }

@media (max-width: 620px) {
  .audit-row { grid-template-columns: 26px minmax(0, 1fr); }
  .audit-meta { grid-column: 2; text-align: left; margin-top: 2px; }
}

/* ==========================================================================
   Refonte : composants d'interface
   ==========================================================================
   Cette couche reprend les composants existants sur les tokens ci-dessus.
   Elle est en fin de fichier pour l'emporter sur les règles historiques,
   plutôt que de réécrire 1700 lignes à l'aveugle.
   ========================================================================== */

/* ---------- typographie et hierarchie ---------- */

body { font-size: var(--fs-body); line-height: 1.5; }

header.app-header h1 { font-size: var(--fs-h1); font-weight: 700; }
header.app-header p { font-size: var(--fs-small); color: var(--muted); }

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--gap-5);
  margin-bottom: var(--gap-4);
  box-shadow: var(--shadow-1);
}
.panel h2 {
  font-size: var(--fs-h3);
  font-weight: 650;
  margin: 0 0 var(--gap-2);
  letter-spacing: -0.01em;
}
.panel > p.muted { margin-top: 0; }

/* Les intertitres étaient en rouge et en capitales, donc plus visibles que
   les titres eux-mêmes. Ils redeviennent des étiquettes. */
.detail-group-title,
.signup-group-title,
.request-col-title,
.console-group,
.form-label,
.audit-day {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- boutons ---------- */

button.btn,
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-2);
  padding: 9px 16px;
  border-radius: var(--radius);
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.2;
  border: 1px solid transparent;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
button.btn { background: var(--accent); color: #fff; }
button.btn:hover:not(:disabled) { background: var(--accent-hover); filter: none; }
button.btn.secondary {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--text);
}
button.btn.secondary:hover:not(:disabled) { background: var(--surface-3); border-color: var(--muted); }
button.btn.ghost { background: transparent; border-color: var(--border); color: var(--text-2); }
button.btn.ghost:hover:not(:disabled) { color: var(--text); border-color: var(--muted); background: var(--surface-2); }
button.btn.danger { color: var(--danger); border-color: rgba(244, 88, 79, 0.3); }
button.btn.danger:hover:not(:disabled) { background: var(--danger-soft); border-color: var(--danger); }
button.btn.danger-solid { background: var(--danger); color: #fff; }
button.btn.danger-solid:hover:not(:disabled) { background: #ff6a61; }
button.btn:disabled { opacity: 0.5; }
button.btn.small, a.btn.small { padding: 5px 11px; font-size: var(--fs-micro); }

.spinner {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: spin 0.6s linear infinite;
  flex: 0 0 auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- champs ---------- */

input[type="text"], input[type="password"], input[type="number"],
input[type="date"], input[type="time"], select, textarea {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-size: var(--fs-small);
  transition: border-color 0.12s ease;
}
input:hover:not(:disabled), select:hover:not(:disabled) { border-color: var(--muted); }
input:focus, select:focus, textarea:focus { border-color: var(--accent); }
input::placeholder, textarea::placeholder { color: var(--muted); opacity: 0.75; }

/* ---------- chips et pastilles ---------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-micro);
  font-weight: 600;
  border: 1px solid var(--border);
  color: var(--text-2);
  background: var(--surface-2);
}
.chip.fresh { color: var(--ok); border-color: rgba(70, 194, 92, 0.3); background: var(--ok-soft); }
.chip.stale { color: var(--gold); border-color: rgba(227, 169, 47, 0.3); background: var(--gold-soft); }

/* ---------- encarts ---------- */

.note-box {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: var(--radius);
  padding: var(--gap-3) var(--gap-4);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--text-2);
}
.note-box strong { color: var(--text); }
.note-box.ok-box { border-left-color: var(--ok); background: var(--ok-soft); }
.note-box.warn-box { border-left-color: var(--gold); background: var(--gold-soft); }

/* ---------- tuiles ---------- */

.tile {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: var(--gap-4);
}
.tile-value { font-size: var(--fs-h2); font-weight: 650; letter-spacing: -0.02em; }
.tile-label {
  font-size: var(--fs-micro);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}

/* ---------- toasts ---------- */

.toast-host {
  position: fixed;
  right: max(16px, env(safe-area-inset-right, 0px));
  bottom: max(16px, env(safe-area-inset-bottom, 0px));
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: var(--gap-2);
  width: min(380px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: var(--gap-3);
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-left: 3px solid var(--muted);
  border-radius: var(--radius);
  padding: var(--gap-3) var(--gap-4);
  box-shadow: var(--shadow-2);
  font-size: var(--fs-small);
  line-height: 1.45;
  animation: toast-in 0.18s ease-out;
}
.toast.leaving { animation: toast-out 0.2s ease-in forwards; }
.toast-icon { flex: 0 0 auto; margin-top: 1px; }
.toast-text { flex: 1 1 auto; min-width: 0; }
.toast-close {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.toast-close:hover { color: var(--text); }
.toast-action {
  background: none;
  border: none;
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
}
.toast-ok { border-left-color: var(--ok); }
.toast-ok .toast-icon { color: var(--ok); }
.toast-error { border-left-color: var(--danger); }
.toast-error .toast-icon { color: var(--danger); }
.toast-warn { border-left-color: var(--gold); }
.toast-warn .toast-icon { color: var(--gold); }
.toast-info { border-left-color: var(--info); }
.toast-info .toast-icon { color: var(--info); }

@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(6px); } }

/* ---------- dialogue ---------- */

.dialog-backdrop {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(6, 8, 11, 0.72);
  backdrop-filter: blur(2px);
  display: grid;
  place-items: center;
  padding: var(--gap-4);
  animation: fade-in 0.12s ease-out;
}
body.dialog-open { overflow: hidden; }

.dialog {
  width: min(460px, 100%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  padding: var(--gap-5);
  animation: dialog-in 0.16s ease-out;
}
.dialog.danger { border-top: 3px solid var(--danger); }
.dialog-title { margin: 0 0 var(--gap-2); font-size: var(--fs-h3); font-weight: 650; }
.dialog-message { margin: 0; color: var(--text-2); font-size: var(--fs-small); line-height: 1.55; }
.dialog-message strong { color: var(--text); }
.dialog-field { display: flex; flex-direction: column; gap: var(--gap-1); margin-top: var(--gap-4); }
.dialog-field input {
  /* flex: 1 1 200px sur la règle de base des champs : dans un conteneur en
     colonne, ce 200px devient une HAUTEUR et le champ fait la taille d'une
     zone de texte. Même piège que pour les réglages du train. */
  flex: 0 0 auto;
  width: 100%;
  padding: 9px 12px;
}
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--gap-2); margin-top: var(--gap-5); }

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes dialog-in { from { opacity: 0; transform: translateY(10px) scale(0.98); } to { opacity: 1; transform: none; } }

/* ---------- squelettes de chargement ---------- */

.skeleton-wrap { display: flex; flex-direction: column; gap: var(--gap-3); padding: var(--gap-2) 0; }
.skel {
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
.skel-title { height: 15px; width: 38%; }
.skel-row { height: 42px; }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* ---------- états vides ---------- */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-3);
  text-align: center;
  padding: var(--gap-7) var(--gap-4);
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius-lg);
}
.empty-art { color: var(--muted); opacity: 0.55; }
.empty-title { margin: 0; font-size: var(--fs-lead); font-weight: 650; }
.empty-message { margin: 0; color: var(--muted); max-width: 44ch; line-height: 1.55; font-size: var(--fs-small); }
.empty-icon { display: none; }

/* ==========================================================================
   Refonte : en-tête, navigation et petits écrans
   ==========================================================================
   L'en-tête portait le titre, la puce de session, deux liens d'espace et,
   juste dessous, sept onglets qui passaient à trois lignes sur téléphone :
   la moitié de l'écran était consommée avant le premier contenu.
   ========================================================================== */

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

header.app-header { padding-block: var(--gap-4) var(--gap-3); }

.header-inner { align-items: center; }
.header-actions { flex-wrap: wrap; justify-content: flex-end; gap: var(--gap-2); }

.admin-link {
  font-size: var(--fs-small);
  padding: 7px 14px;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.admin-link:hover { background: var(--surface-2); border-color: var(--accent-line); color: var(--text); }

/* Une seule rangée, qui défile, plutôt qu'un pavé d'onglets repliés.
   Elle reste collée en haut pendant le défilement : sur un roster de
   soixante joueurs, l'onglet actif est la seule indication de l'endroit où
   l'on se trouve. */
nav.tabs {
  position: sticky;
  top: 0;
  z-index: 30;
  box-shadow: 0 1px 0 var(--border);
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  padding-block: var(--gap-3);
  background: var(--bg);
}
nav.tabs::-webkit-scrollbar { display: none; }
nav.tabs button {
  flex: 0 0 auto;
  scroll-snap-align: start;
  background: transparent;
  border-color: transparent;
  color: var(--text-2);
  font-weight: 550;
  padding: 8px 14px;
}
nav.tabs button:hover { background: var(--surface-2); color: var(--text); }
nav.tabs button.active {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--accent);
}
nav.tabs button.active:hover { background: var(--accent-soft); }

@media (max-width: 760px) {
  header.app-header { padding-block: var(--gap-3) var(--gap-2); }
  .header-inner { flex-wrap: nowrap; gap: var(--gap-2); }
  header.app-header h1 { font-size: 1.05rem; }
  /* La baseline explique l'application à la première visite ; sur téléphone
     elle coûte une ligne à chaque page, et le titre suffit. */
  header.app-header p { display: none; }
  .header-actions { flex-wrap: nowrap; }
  /* Les liens d'espace deviennent des pastilles : le libellé est porté par
     le title et par l'icône, pas par trois mots qui débordent. */
  .admin-link { padding: 7px 10px; font-size: 0.72rem; }
  nav.tabs { padding-inline: 0; }
  nav.tabs button { padding: 7px 12px; font-size: 0.8rem; }
  main { padding-top: var(--gap-3); }
}

/* ---------- l'accent redevient rare ---------- */
/* Le rouge de la marque servait à la fois aux onglets actifs, aux boutons
   principaux, aux intertitres, aux étiquettes de type d'escouade et aux
   types de changement d'historique : cinq sens pour une seule couleur, donc
   plus aucun. Il ne reste qu'aux éléments sur lesquels on peut agir. */
.squad-source-label,
.squad-block-title,
.history-type,
.hist-kind {
  color: var(--muted);
  font-weight: 600;
}

/* ---------- replis techniques ---------- */

.detail-more { margin-top: var(--gap-4); }
.detail-more > summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2);
  font-size: var(--fs-small);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 13px;
}
.detail-more > summary::-webkit-details-marker { display: none; }
.detail-more > summary::before {
  content: '';
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}
.detail-more[open] > summary::before { transform: rotate(45deg); }
.detail-more > summary:hover { color: var(--text); border-color: var(--muted); }

/* ---------- l'en-tête sur téléphone ---------- */
/* Avant : le titre passait sur deux lignes, la puce de session sur trois,
   et "Déconnexion" poussait le tout hors de l'écran. Sur un téléphone,
   l'en-tête ne doit dire que deux choses - où l'on est, et qui on est. */
header.app-header h1 { white-space: nowrap; }

.auth-chip { min-width: 0; }
.auth-text { min-width: 0; }
.auth-name,
.auth-sub {
  display: block;
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 760px) {
  /* Le sous-titre de la puce (le joueur lié) est déjà en toutes lettres sur
     l'onglet profil, qui est à un doigt d'ici. */
  .auth-sub { display: none; }
  .auth-name { max-width: 10ch; }
  .role-chip { display: none; }
  .auth-logout { padding: 6px 10px; }
  .auth-logout .btn-label { display: none; }
}

@media (max-width: 460px) {
  /* Les liens d'espace ne disparaissent pas : ils se raccourcissent. Un
     officier sur téléphone doit pouvoir atteindre sa file d'attente. */
  .admin-link { font-size: 0; padding: 7px 11px; }
  .admin-link::after { content: attr(data-short); font-size: 0.72rem; }
}

/* ---------- squelette de démarrage ---------- */

.boot {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--gap-5) 4px;
}
.boot .skel-row { height: 78px; }

/* ---------- remplissage progressif ---------- */

.auto-refresh {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-3);
  margin-top: var(--gap-4);
}
.switch-label { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-small); }
.field-inline { display: inline-flex; align-items: center; gap: 8px; }
/* Même piège que pour les champs de dialogue : la règle de base des inputs
   leur donne flex: 1 1 200px, ce qui les étire ici. */
.auto-refresh input[type='number'],
.auto-refresh select { flex: 0 0 auto; }
.auto-refresh input[type='number'] { width: 92px; }

.provisioning-actions { margin-top: var(--gap-4); align-items: center; }
.provisioning-next { margin-top: var(--gap-4); }
.provisioning-next ol {
  margin: var(--gap-2) 0 0;
  padding-left: 1.3em;
  color: var(--text-2);
  font-size: var(--fs-small);
  line-height: 1.7;
}
.provisioning-log {
  list-style: none;
  margin: var(--gap-3) 0 0;
  padding: 0;
  font-size: var(--fs-small);
  line-height: 1.7;
}
.provisioning-log li { border-left: 2px solid var(--border); padding-left: var(--gap-3); }
.provisioning-log li.log-ok { border-left-color: var(--ok); }
.provisioning-log li.log-error { border-left-color: var(--danger); }
.provisioning-log li.log-skipped { border-left-color: var(--gold); }

/* ---------- l'attribut hidden l'emporte ---------- */
/* Un élément porteur d'un display explicite (flex, grid, inline-flex)
   ignore l'attribut hidden, dont le display:none par défaut est moins
   spécifique qu'une règle de classe. Cela a déjà coûté un bandeau fantôme
   sur la page d'accueil et deux champs de réglage affichés en même temps.
   La règle vaut pour toute l'application, une fois pour toutes. */
[hidden] { display: none !important; }

/* ---------- bandeau d'aperçu de branche ---------- */

.instance-banner {
  margin-bottom: var(--gap-4);
  border-left-width: 3px;
}
.instance-banner code {
  background: var(--surface-3);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
  font-size: 0.85em;
}
