/* Dashboard (index.html) — the portal home page.
   Everything here is light-DOM markup, so it is styled from this sheet rather than
   a shadow root. Colours come from tokens only (the Switcher rewrites them at
   runtime; a hardcoded hex would survive a theme change and look broken). */

/* ── Page header ──────────────────────────────────────────── */
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-block: 1rem 1.5rem;
}
.page-header-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }

.dash-eyebrow {
  margin: 0 0 0.35rem;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary);
}
.page-title {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-semibold);
  color: var(--text);
  margin: 0 0 0.35rem;
}
/* ── Link buttons ─────────────────────────────────────────────
   <app-button> renders a real <button> with no href, so every navigating
   affordance on this page is an <a> that borrows the button's look. */
.dash-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.5rem 1rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base);
  font-weight: var(--fw-medium);
  line-height: var(--lh-tight);
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}
.dash-btn:hover { background: var(--surface-hover); box-shadow: var(--shadow-md); }
.dash-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.dash-btn i { font-size: 1.1em; line-height: 1; }

.dash-btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-contrast);
}
.dash-btn-primary:hover {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
}
.dash-btn-sm { padding: 0.25rem 0.65rem; font-size: var(--fs-sm); }
.dash-btn-block { width: 100%; justify-content: flex-start; }

/* ── Overdue-payment banner ───────────────────────────────── */
.dash-alert {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  margin-block-end: var(--space-5);
  border: 1px solid rgba(var(--warning-rgb), 0.35);
  border-radius: var(--radius-lg);
  background: rgba(var(--warning-rgb), 0.1);
  color: var(--text);
}
.dash-alert-icon { color: var(--warning); font-size: 1.15rem; line-height: 1; flex: none; }
.dash-alert-text { margin: 0; flex: 1 1 14rem; font-size: var(--fs-base); }
.dash-alert-actions { display: flex; align-items: center; gap: var(--space-2); }
/* The banner's own surface is already tinted, so the button sits on it as a solid
   card rather than another translucent layer. */
.dash-btn-onwarning { background: var(--surface); border-color: rgba(var(--warning-rgb), 0.5); }

/* Pending-invitations notice — same top-of-page treatment as the payment banner,
   but tinted with the primary colour: it is an invitation to act, not a warning,
   and the two must not read as the same kind of message. Its icon and its rows sit
   in a column, so it aligns to the top rather than centring like the one-line one. */
.dash-alert-invite {
  align-items: flex-start;
  border-color: rgba(var(--primary-rgb), 0.35);
  background: var(--primary-01);
}
.dash-alert-invite .dash-alert-icon { color: var(--primary); margin-block-start: 0.15rem; }
.dash-alert-body { flex: 1 1 14rem; min-width: 0; }
.dash-alert-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin: 0 0 var(--space-3);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--text);
}
/* Rows sit on the tinted surface, so their separator has to be the tint's own
   border rather than --border, which would disappear against it. */
.dash-alert-invite .dash-list-item { border-block-end-color: rgba(var(--primary-rgb), 0.25); }

/* ── Metric cards ─────────────────────────────────────────── */
.dash-metrics {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  margin-block-end: var(--space-5);
}
.dash-metrics app-card { width: 100%; }

.dash-metric-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-end: var(--space-5);
}
.dash-icon-tile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: var(--radius-lg);
  background: var(--primary-01);
  color: var(--primary);
  font-size: 1.15rem;
}
.dash-metric-label {
  margin: 0 0 0.3rem;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.dash-metric-value {
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  color: var(--text);
  overflow-wrap: anywhere;
}
/* The unit/denominator inside the value ("/ 12 séances") — same line, quieter. */
.dash-metric-unit { font-size: var(--fs-base); font-weight: var(--fw-normal); color: var(--text-muted); }
.dash-metric-note {
  margin: var(--space-3) 0 0;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.dash-metric-note:empty { display: none; }
.dash-metric-note strong { color: var(--text); font-weight: var(--fw-medium); }
.dash-metric-note.is-error { color: var(--danger); }

.dash-metric-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-block-start: var(--space-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--primary);
  text-decoration: none;
}
.dash-metric-cta:hover { text-decoration: underline; }
.dash-metric-cta:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* ── Status badges ────────────────────────────────────────── */
.dash-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  background: var(--surface-2);
  color: var(--text-muted);
}
.dash-badge::before {
  content: "";
  width: 0.4rem; height: 0.4rem;
  border-radius: 50%;
  background: currentColor;
}
.dash-badge-success { background: rgba(var(--success-rgb), 0.15); color: var(--success); }
.dash-badge-warning { background: rgba(var(--warning-rgb), 0.15); color: var(--warning); }
.dash-badge-danger  { background: rgba(var(--danger-rgb), 0.15);  color: var(--danger); }
.dash-badge-primary { background: var(--primary-01); color: var(--primary); }

/* ── News + quick actions row ─────────────────────────────── */
.dash-columns {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  align-items: start;
}
/* One breakpoint for the whole page: below it every multi-column row becomes a
   single full-width column — the metric cards, the news/side row, and the two news
   teasers inside the Actualités card. `auto-fit` alone isn't enough for any of
   them: the metric row still fits two 16rem tracks at ~700-900px (a cramped 2 + 1
   with a ragged last card) and the teasers still fit two 13rem tracks well below
   that. All three are stated in ONE query so the page can never end up
   half-stacked, with one row collapsed and the next not. */
@media (max-width: 900px) {
  .dash-metrics,
  .dash-columns,
  .dash-news { grid-template-columns: 1fr; }
}
.dash-columns app-card { width: 100%; }

/* The side column: cards stack with the same gap the grid uses between columns,
   so "Mes partenaires de jeu" and "Actions rapides" are never flush against each
   other. align-content:start keeps them their natural height instead of stretching
   to match the taller news card beside them. */
.dash-side {
  display: grid;
  gap: var(--space-5);
  align-content: start;
}

/* app-card's header slot is a plain bar; push the "Tout voir" link to its end. */
.dash-columns app-card > [slot="header"] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.dash-header-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--primary);
  text-decoration: none;
}
.dash-header-link:hover { text-decoration: underline; }
.dash-header-link:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.dash-news {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.dash-news:empty { display: none; }
.dash-news-item { display: flex; flex-direction: column; gap: var(--space-2); }
.dash-news-title {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}
.dash-news-title a { color: var(--text); text-decoration: none; }
.dash-news-title a:hover { color: var(--primary); }
.dash-news-date { font-size: var(--fs-xs); color: var(--text-subtle); }
.dash-news-excerpt { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.dash-news-empty { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.dash-news-empty.is-error { color: var(--danger); }

.dash-quick { display: grid; gap: var(--space-2); }

/* ── Tennis: invitations + game partners ──────────────────── */
.dash-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}
.dash-list:empty { display: none; }
.dash-list-status { margin: 0; font-size: var(--fs-sm); color: var(--text-muted); }
.dash-list-status.is-error { color: var(--danger); }

.dash-list-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding-block-end: var(--space-3);
  border-block-end: 1px solid var(--border);
}
.dash-list-item:last-child { padding-block-end: 0; border-block-end: 0; }

/* min-width:0 so a long name ellipsizes instead of pushing the buttons out of
   the card — flex items default to min-width:auto and refuse to shrink. */
.dash-list-body { flex: 1 1 10rem; min-width: 0; }
.dash-list-name {
  margin: 0;
  font-size: var(--fs-base);
  font-weight: var(--fw-medium);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-list-meta {
  margin: 0.15rem 0 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-list-actions { display: flex; align-items: center; gap: var(--space-2); flex: none; }
.dash-list-actions app-button { display: inline-block; width: auto; }

.dash-list-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  border-radius: 50%;
  background: var(--primary-01);
  color: var(--primary);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
}
/* Result line shown in place of the buttons once an invitation is answered. */
.dash-list-result { font-size: var(--fs-sm); color: var(--text-muted); flex: none; }
.dash-list-result.is-error { color: var(--danger); }
