/* ============================================================
   ASEC Mimosas — Phase 3 site layout
   Uses tokens from design-system.css. Mobile-first throughout.
   ============================================================ */

/* ---------- Nav ---------- */
.nav-ds {
  position: sticky; top: 0; z-index: 100;
  background: var(--color-inverse-bg);
  border-bottom: 1px solid var(--c-black-700);
  color: var(--color-inverse-ink);
}
.nav-ds__bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); padding-block: var(--sp-3); }
.nav-ds__brand { display: flex; align-items: center; gap: var(--sp-2); font-weight: 800; color: #fff; }
.nav-ds__brand img { height: 40px; width: 40px; object-fit: contain; }
.nav-ds__toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border: 1px solid var(--c-black-700); border-radius: var(--radius-sm);
  background: none; cursor: pointer; color: inherit;
}
.nav-ds__links { display: none; }
.nav-ds__links.is-open {
  display: flex; flex-direction: column; gap: var(--sp-1);
  position: absolute; left: 0; right: 0; top: 100%;
  background: var(--color-inverse-bg); border-bottom: 1px solid var(--c-black-700);
  padding: var(--sp-3) var(--sp-4) var(--sp-5);
  max-height: calc(100vh - var(--nav-height)); overflow-y: auto;
}
.nav-ds__links a { padding: var(--sp-3) var(--sp-2); font-weight: 700; font-size: var(--fs-sm); text-transform: uppercase; border-radius: var(--radius-sm); }
.nav-ds__links a:hover, .nav-ds__links a:focus-visible, .nav-ds__links a[aria-current="page"] { color: var(--c-yellow-300); }
.nav-ds__cta { margin-top: var(--sp-2); }
@media (min-width: 992px) {
  .nav-ds__toggle { display: none; }
  .nav-ds__links {
    display: flex !important; position: static; flex-direction: row; align-items: center;
    padding: 0; border: 0; max-height: none; overflow: visible; background: none;
  }
  .nav-ds__links a { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-xs); }
  .nav-ds__cta { margin-top: 0; margin-left: var(--sp-3); }
}

/* ---------- Hero ---------- */
.hero-ds {
  position: relative;
  min-height: 62vh;
  background-color: var(--c-black-900);
  background-size: cover; background-position: center;
  display: flex; align-items: flex-end;
  padding-block: var(--sp-7) var(--sp-6);
  color: var(--color-inverse-ink);
}
.hero-ds::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0,0,0,.15), rgba(0,0,0,.65)); }
.hero-ds__inner { position: relative; z-index: 1; max-width: 720px; }
.hero-ds .eyebrow { color: var(--c-yellow-300); }
@media (min-width: 992px) { .hero-ds { min-height: 78vh; } }

/* ---------- Live Match Centre placement: directly under hero,
   visible on first screen on mobile without scrolling ---------- */
.mc-slot { position: relative; margin-top: calc(-1 * var(--sp-7)); z-index: 2; }
.mc-slot .container-ds { display: flex; justify-content: center; }

.mc-card {
  background: var(--color-surface); color: var(--color-ink);
  border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  padding: var(--sp-5); width: 100%; max-width: 420px;
  border-top-width: 3px; border-top-style: solid;
}
.mc-card--live { border-top-color: var(--c-live); }
.mc-card--ft { border-top-color: var(--c-black-900); }
.mc-card--pre { border-top-color: var(--c-yellow-500); }
.mc-card-top { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.mc-status-group { display: flex; align-items: baseline; gap: var(--sp-2); }
.mc-minute { font-weight: 800; font-size: var(--fs-h6); font-variant-numeric: tabular-nums; }
.mc-updated { white-space: nowrap; }

.mc-team { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); font-weight: 700; font-size: var(--fs-sm); flex: 1; text-align: center; }
.mc-crest { object-fit: contain; }
.mc-vs {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: var(--radius-pill);
  background: var(--color-surface-alt); font-size: 10px; color: var(--color-ink-muted); font-weight: 800;
}
.mc-countdown { font-size: var(--fs-xs); font-weight: 800; color: var(--c-yellow-700); }
.mc-meta { margin-block: var(--sp-2) 0; }

/* "Flyer" poster panel (pre-match state): dark inset panel with the
   matchup in bold type — meant to build anticipation, distinct from the
   light, data-oriented look of the rest of the card. */
.mc-poster {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-4);
  background: var(--c-black-900); border-radius: var(--radius-md);
  padding: var(--sp-4); margin-block: var(--sp-3);
}
.mc-poster .mc-team { color: var(--color-inverse-ink); }
.mc-poster .mc-crest { background: #fff; border-radius: var(--radius-sm); padding: 4px; }
.mc-poster .mc-vs { background: var(--c-yellow-500); color: var(--c-black-900); }

/* ---- Man of the match (terminé state) ---- */
.mc-motm {
  display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--sp-2); row-gap: var(--sp-1);
  background: var(--color-surface-alt); border-left: 3px solid var(--c-black-900); border-radius: var(--radius-sm);
  padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); font-size: var(--fs-xs);
}
.mc-motm--away { border-left-color: var(--c-yellow-500); }
.mc-motm-label { flex: 0 0 100%; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; color: var(--color-ink-muted); }
.mc-motm strong { font-size: var(--fs-sm); }
.mc-motm-note { flex: 1 0 100%; color: var(--color-ink-muted); }

/* ---- Head-to-head (Face à face tab) ---- */
.mc-h2h-summary { font-size: var(--fs-xs); font-weight: 700; color: var(--c-yellow-700); margin: 0 0 var(--sp-3); }
.mc-h2h-list { list-style: none; margin: 0; padding: 0; }
.mc-h2h-row {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--sp-2);
  padding-block: var(--sp-2); border-bottom: 1px solid var(--color-border); font-size: var(--fs-xs);
}
.mc-h2h-row:last-child { border-bottom: none; }
.mc-h2h-date { color: var(--color-ink-muted); flex: 0 0 auto; }
.mc-h2h-score { font-weight: 700; flex: 1 1 auto; text-align: center; }
.mc-h2h-comp { color: var(--color-ink-muted); flex: 0 0 auto; }

.mc-score-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: var(--sp-3); }
.mc-score-row .mc-team { flex-direction: row; gap: var(--sp-2); }
.mc-score-row .mc-team:nth-child(1) { justify-content: flex-end; }
.mc-score-row .mc-team:nth-child(3) { justify-content: flex-start; }
.mc-score {
  display: flex; align-items: baseline; gap: var(--sp-2); font-variant-numeric: tabular-nums;
  font-size: var(--fs-h2); font-weight: 800; white-space: nowrap;
  background: var(--color-surface-alt); border-radius: var(--radius-md); padding: var(--sp-2) var(--sp-4);
}
.mc-score-sep { font-size: var(--fs-h6); font-weight: 700; color: var(--color-ink-muted); }

.mc-scorers { display: flex; justify-content: space-between; gap: var(--sp-3); font-size: var(--fs-xs); color: var(--color-ink-muted); margin-block: var(--sp-3); }
.mc-scorers > div:last-child { text-align: right; }

.mc-stats, .mc-cards-row { display: flex; flex-direction: column; gap: var(--sp-3); margin-top: var(--sp-4); }
.mc-stat-row { display: flex; flex-direction: column; gap: var(--sp-1); }
.mc-stat-nums { display: flex; justify-content: space-between; font-size: var(--fs-xs); font-weight: 700; }
.mc-stat-label { color: var(--color-ink-muted); font-weight: 600; text-transform: uppercase; letter-spacing: .02em; }
.mc-stat-bar { display: flex; height: 6px; border-radius: var(--radius-pill); overflow: hidden; background: var(--color-border); }
.mc-stat-bar-home { background: var(--c-black-900); }
.mc-stat-bar-away { background: var(--c-yellow-500); }

/* Connected vertical timeline: one continuous line with a small circular
   icon "node" per event, bordered by team color. Replaces the old per-row
   left-border segments, which looked like a broken/notched line rather
   than a single continuous timeline. */
.mc-timeline { position: relative; list-style: none; margin: 0; padding: 0; }
.mc-timeline::before {
  content: ""; position: absolute; left: 13px; top: 14px; bottom: 14px; width: 2px;
  background: var(--color-border);
}
.mc-ev { position: relative; display: flex; align-items: center; gap: var(--sp-3); padding-block: var(--sp-2); font-size: var(--fs-xs); }
.mc-ev-min { font-weight: 800; min-width: 2.2em; color: var(--color-ink-muted); font-variant-numeric: tabular-nums; }
.mc-ev-node {
  position: relative; z-index: 1; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  background: var(--color-surface); border: 2px solid var(--color-border);
}
.mc-ev--home .mc-ev-node { border-color: var(--c-black-900); }
.mc-ev--away .mc-ev-node { border-color: var(--c-yellow-500); }
.mc-ev-desc { flex: 1; }

.mc-cta { margin-top: var(--sp-4); width: 100%; }
.mc-stale-note { margin-top: var(--sp-2); }
.mc-live-region { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---- Detail card tabs (Fil du match / Statistiques / Compositions) ----
   Segmented-pill control rather than underline tabs: a filled selected
   segment reads faster at a glance than a thin border, and feels more
   like a tactile control than a row of text links. */
.mc-tabs { margin-top: var(--sp-4); border-top: 1px solid var(--color-border); padding-top: var(--sp-4); }
.mc-tablist {
  display: flex; gap: 2px; background: var(--color-surface-alt);
  border-radius: var(--radius-pill); padding: 3px;
}
.mc-tablist [role="tab"] {
  appearance: none; background: none; border: none; border-radius: var(--radius-pill);
  flex: 1; min-width: 0; padding: var(--sp-2) var(--sp-1);
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0;
  color: var(--color-ink-muted); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background .15s ease, color .15s ease;
}
@media (max-width: 400px) {
  .mc-tablist [role="tab"] { font-size: 10px; padding-inline: 2px; }
}
.mc-tablist [role="tab"][aria-selected="true"] { background: var(--c-black-900); color: var(--color-inverse-ink); }
.mc-tablist [role="tab"]:not([aria-selected="true"]):hover { color: var(--color-ink); }
.mc-tablist [role="tab"]:focus-visible { outline: 2px solid var(--c-yellow-500); outline-offset: 2px; }
.mc-tabpanel { padding-top: var(--sp-4); }
.mc-tabpanel[hidden] { display: none; }

/* ---- Lineups / formation panel ---- */
.mc-lineups { display: flex; justify-content: space-between; gap: var(--sp-4); text-align: center; }
.mc-lineup-col { display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); flex: 1; }
.mc-lineup-col strong { font-size: var(--fs-sm); }
.mc-formation { font-size: var(--fs-h6); font-weight: 800; color: var(--c-yellow-700); }
.mc-xi-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; font-size: var(--fs-xs); color: var(--color-ink-muted); }

/* ============================================================
   MATCH RAIL (homepage) — horizontal strip of matches showing
   live, upcoming and recent results side by side.
   ============================================================ */
.mc-rail-section { background: var(--color-surface); border-bottom: 1px solid var(--color-border); }

/* Small fixed gutter shared by the section heading and the rail, instead of
   .container-ds's centered max-width — that would add a large, growing empty
   margin on wide screens (up to (100vw-1200px)/2) just to stay aligned with
   the rest of the page; a flat gutter keeps both flush near the edge at any
   viewport width, which is the point of bleeding this section full-width. */
.mc-rail-gutter { padding-inline: var(--sp-4); }
@media (min-width: 768px) { .mc-rail-gutter { padding-inline: var(--sp-6); } }

#match-centre-root {
  position: relative;
  padding-left: var(--sp-4);
  padding-right: var(--sp-4);
}
@media (min-width: 768px) {
  #match-centre-root { padding-left: var(--sp-6); padding-right: var(--sp-6); }
}
/* Static edge-fade hint that the strip scrolls further — the rail always
   overflows its container (5 match cards + CTA tile), so a scroll-position-
   aware version isn't worth the extra JS. */
#match-centre-root::after {
  content: "";
  position: absolute; top: 0; right: 0; bottom: 0;
  width: 32px;
  background: linear-gradient(to right, transparent, var(--color-surface));
  pointer-events: none;
}

.mc-rail {
  display: flex; gap: var(--sp-3);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-block: var(--sp-2) var(--sp-3);
  /* let cards breathe at the edges without clipping shadows */
  margin-inline: calc(-1 * var(--sp-1)); padding-inline: var(--sp-1);
  scrollbar-width: thin;
}
.mc-rail::-webkit-scrollbar { height: 4px; }
.mc-rail::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: var(--radius-pill); }

.mc-rail-card {
  scroll-snap-align: start;
  /* 82% on xs leaves the next card peeking, signalling the strip scrolls */
  flex: 0 0 82%;
  max-width: 330px;
  /* Without this, a flex item's default min-width:auto lets its min-content
     (here the nowrap venue line) override flex-basis, so cards with longer
     venue names render wider than the rest. */
  min-width: 0;
  display: flex; flex-direction: column; gap: var(--sp-3);
  background: var(--color-surface); color: var(--color-ink);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  padding: var(--sp-5);
  box-shadow: var(--shadow-sm);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.mc-rail-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.mc-rail-card[data-state="live"] { border-color: var(--c-live); box-shadow: 0 0 0 1px var(--c-live) inset; }
.mc-rail-card[data-state="pre"] { border-color: var(--c-yellow-300); }
@media (min-width: 480px) { .mc-rail-card { flex-basis: 66%; } }
@media (min-width: 768px) { .mc-rail-card { flex-basis: 44%; } }
@media (min-width: 992px) { .mc-rail-card { flex-basis: 288px; } }

.mc-rail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-2); }
.mc-rail-comp {
  font-size: var(--fs-xs); font-weight: 700; line-height: 1.25;
  color: var(--color-ink); display: flex; flex-direction: column; gap: 2px;
}
.mc-rail-sport {
  align-self: flex-start;
  font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--c-yellow-700); background: var(--c-yellow-50);
  padding: 1px var(--sp-2); border-radius: var(--radius-pill);
}
.mc-rail-meta {
  display: flex; flex-direction: column; gap: 1px;
  font-size: var(--fs-xs); color: var(--color-ink-muted);
}
.mc-rail-meta strong { font-size: var(--fs-h6); color: var(--color-ink); font-weight: 800; }
.mc-rail-period { color: var(--color-ink-muted); }

.mc-rail-teams { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-1); }
.mc-rail-team { display: flex; align-items: center; gap: var(--sp-2); }
.mc-rail-team .mc-crest {
  flex-shrink: 0; object-fit: cover;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
}
.mc-rail-name { flex: 1; min-width: 0; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mc-rail-team.is-asec .mc-rail-name { font-weight: 800; }
.mc-rail-score {
  flex-shrink: 0; min-width: 26px; text-align: center;
  font-weight: 800; font-size: var(--fs-sm);
  background: var(--color-surface-alt); color: var(--color-ink);
  border-radius: var(--radius-sm); padding: 1px var(--sp-2);
}
.mc-rail-score.is-win { background: var(--c-yellow-500); color: var(--c-black-900); }

.mc-rail-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  border-top: 1px solid var(--color-border); padding-top: var(--sp-2); margin-top: auto;
}
.mc-rail-venue { flex: 1; min-width: 0; font-size: 11px; color: var(--color-ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mc-rail-cta { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--c-yellow-700); white-space: nowrap; }
.mc-rail-empty { padding: var(--sp-4); }

.mc-rail-cta-tile {
  scroll-snap-align: start;
  flex: 0 0 82%;
  max-width: 330px;
  min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2);
  text-align: center;
  background: var(--c-black-900); color: var(--color-inverse-ink);
  border: 1px solid var(--c-black-900); border-radius: var(--radius-md);
  padding: var(--sp-5);
  font-weight: 800; text-transform: uppercase; letter-spacing: .02em; font-size: var(--fs-sm);
  transition: box-shadow .18s ease, transform .18s ease, background-color .18s ease;
}
.mc-rail-cta-tile:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); background: var(--c-black-800); }
.mc-rail-cta-tile .arrow { font-size: var(--fs-h4); line-height: 1; }
@media (min-width: 480px) { .mc-rail-cta-tile { flex-basis: 66%; } }
@media (min-width: 768px) { .mc-rail-cta-tile { flex-basis: 44%; } }
@media (min-width: 992px) { .mc-rail-cta-tile { flex-basis: 288px; } }

/* ============================================================
   EDITORIAL NEWS BLOCK — lead story, secondary list, card row
   ============================================================ */
.news-hero {
  position: relative; display: block; overflow: hidden;
  border-radius: var(--radius-md); min-height: 320px; height: 100%;
  color: var(--color-inverse-ink); background: var(--c-black-900);
}
.news-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.news-hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.12) 30%, rgba(0,0,0,.85) 100%);
}
.news-hero__body { position: relative; z-index: 1; padding: var(--sp-5); display: flex; flex-direction: column; justify-content: flex-end; height: 100%; min-height: 320px; }
.news-hero__body h2, .news-hero__body h3 { font-size: var(--fs-h3); line-height: 1.12; margin-block: var(--sp-2); }
.news-hero__dek { font-size: var(--fs-sm); color: rgba(255,255,255,.88); max-width: 46ch; }
@media (min-width: 992px) { .news-hero, .news-hero__body { min-height: 440px; } }

.news-list { display: flex; flex-direction: column; gap: var(--sp-3); }
.news-list__item {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding-bottom: var(--sp-3); border-bottom: 1px solid var(--color-border);
}
.news-list__item:last-child { border-bottom: 0; padding-bottom: 0; }
.news-list__item img {
  flex: 0 0 92px; width: 92px; height: 68px; object-fit: cover;
  border-radius: var(--radius-sm); background: var(--color-surface-alt);
}
.news-list__item h4 { font-size: var(--fs-sm); line-height: 1.3; margin-block: var(--sp-1); font-weight: 700; }

.cat-badge {
  display: inline-block; font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  background: var(--c-yellow-100); color: var(--c-yellow-700);
  padding: 2px var(--sp-2); border-radius: var(--radius-sm);
}
.news-hero .cat-badge { background: var(--c-yellow-500); color: var(--c-black-900); }

/* On mobile keep the trailing card row short so the section does not
   turn into an endless scroll after the hero and the list. */
@media (max-width: 767px) {
  .news-row__item:nth-child(n+3) { display: none; }
}

/* ---------- Round-fixtures grid (match.html "Autres matchs") ----------
   One flat row of fixed-size square cards (no per-date grouping), so the
   whole round reads as a single scannable set instead of stacked blocks.
   Each card carries its own compact date tag in the corner since there's
   no shared group header to hang it on. Reading order: kickoff/score
   badge at the top (fastest thing to scan across a row of cards), home
   and away team in the middle, venue at the bottom — shown for every card
   so the layout stays consistent even where the exact venue isn't
   confirmed (see the JS comment above roundFixtureCard). */
.rf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 220px)); gap: var(--sp-3); justify-content: start; }
.rf-card {
  position: relative; aspect-ratio: 1 / 1; display: flex; flex-direction: column; gap: var(--sp-2);
  background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md);
  padding: var(--sp-4);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.rf-card:hover { border-color: var(--c-grey-400); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.rf-date-tag {
  position: absolute; top: var(--sp-3); left: var(--sp-4);
  font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--color-ink-muted);
}
.rf-badge {
  position: absolute; top: var(--sp-3); right: var(--sp-4);
  font-weight: 800; font-size: var(--fs-xs); letter-spacing: .02em; font-variant-numeric: tabular-nums;
  background: var(--c-black-900); color: var(--color-inverse-ink);
  border-radius: var(--radius-pill); padding: var(--sp-1) var(--sp-3);
}
.rf-card.is-final .rf-badge { color: var(--color-primary); }
.rf-teams { display: flex; flex-direction: column; justify-content: center; gap: var(--sp-2); flex: 1; margin-top: var(--sp-5); }
.rf-team { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
/* Crests are placeholder shields until real club crest URLs are wired in
   (see ASSUMPTIONS.md); kept small and quiet on purpose so eight identical
   icons on screen read as a background team-marker, not repeated clutter. */
.rf-team img { width: 20px; height: 20px; object-fit: contain; border-radius: 50%; background: var(--color-surface-alt); opacity: .85; flex-shrink: 0; }
.rf-team span { flex: 1 1 auto; min-width: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--color-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rf-venue {
  display: flex; align-items: center; gap: var(--sp-1); min-width: 0;
  font-size: 11px; color: var(--color-ink-muted);
}
.rf-venue.is-tbc { font-style: italic; opacity: .75; }
.rf-venue svg { flex-shrink: 0; width: 12px; height: 12px; }
.rf-venue span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================================================
   MATCH PAGE (match.html) — widget in a two-column layout with
   contextual sidebar, plus a clearly-boxed internal demo switcher.
   ============================================================ */
.match-page__main .mc-card { max-width: none; width: 100%; }

.match-sidebar { display: flex; flex-direction: column; gap: var(--sp-5); }
.side-card {
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-sm); padding: var(--sp-4);
}
.side-card h2 { margin-bottom: var(--sp-3); }

.side-infos-list { margin: 0; }
.side-infos-row { display: flex; justify-content: space-between; gap: var(--sp-3); padding-block: var(--sp-2); border-bottom: 1px solid var(--color-border); font-size: var(--fs-sm); }
.side-infos-row:last-child { border-bottom: none; }
.side-infos-row dt { color: var(--color-ink-muted); margin: 0; }
.side-infos-row dd { margin: 0; font-weight: 700; text-align: right; }
.side-infos-row a { color: var(--c-yellow-700); font-weight: 800; }

.side-standings { list-style: none; margin: 0; padding: 0; }
.side-standings li { display: flex; align-items: center; gap: var(--sp-2); padding-block: var(--sp-2); border-bottom: 1px solid var(--color-border); font-size: var(--fs-sm); }
.side-standings li:last-child { border-bottom: none; }
.side-standings .club { flex: 1; display: flex; align-items: center; gap: var(--sp-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-standings .club img { width: 20px; height: 20px; object-fit: contain; flex-shrink: 0; }
.side-standings li.is-asec { font-weight: 800; background: var(--c-yellow-50); margin-inline: calc(-1 * var(--sp-2)); padding-inline: var(--sp-2); border-radius: var(--radius-sm); }
.side-standings .pts { font-weight: 800; }
.side-standings-label { font-size: var(--fs-xs); color: var(--color-ink-muted); margin: calc(-1 * var(--sp-2)) 0 var(--sp-3); }

.side-form-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding-block: var(--sp-2); border-bottom: 1px solid var(--color-border); }
.side-form-row:last-child { border-bottom: none; }
.side-form-team { font-weight: 700; font-size: var(--fs-sm); }
.side-form-pills { display: flex; gap: 4px; }
.form-pill {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--radius-pill);
  font-size: 10px; font-weight: 800; color: var(--color-inverse-ink);
}
.form-pill.is-win { background: var(--c-yellow-500); color: var(--c-black-900); }
/* --c-grey-400 read at ~2.8:1 for white text on this small a pill — below
   the 4.5:1 small-text floor. --c-grey-600 clears ~5.3:1, same neutral
   the rest of the system already uses for muted text. */
.form-pill.is-draw { background: var(--c-grey-600); }
.form-pill.is-loss { background: var(--c-black-900); }

.demo-box { border: 1px dashed var(--color-border); border-radius: var(--radius-md); padding: var(--sp-4); background: var(--color-surface); }
.demo-box__label { font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--color-ink-muted); margin-bottom: var(--sp-3); }

/* ---------- Footer ----------
   The footer is the largest near-black surface on the page, so by the Trophy
   Cabinet north star it IS cabinet backing: its job is to recede. Yellow is
   spent only on link hover and the focus ring (Rarity Rule); separation is
   1px --c-black-700 hairlines with no resting shadow (Border-First Rule).

   Hierarchy is deliberately inverted from the old footer: column headings are
   muted grey and the LINKS are white and bold. The previous version made its
   headings white and its actual navigation the quietest thing in the block. */
.footer-ds { background: var(--c-black-900); color: var(--color-inverse-muted); border-top: 1px solid var(--c-black-700); }

.footer-ds__cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-7);
  padding-block: var(--sp-8) var(--sp-7);
}
@media (min-width: 768px) { .footer-ds__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Desktop mirrors the reference: three link columns, a wider contact column,
   then the crest anchored hard right. */
@media (min-width: 992px) { .footer-ds__cols { grid-template-columns: repeat(3, minmax(0, 1fr)) 1.5fr auto; gap: var(--sp-6); } }

.footer-ds__col h2 {
  font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--c-grey-400);              /* 6.9:1 on --c-black-900 */
  margin-bottom: var(--sp-4);
}
.footer-ds__col ul { list-style: none; margin: 0; padding: 0; }
.footer-ds__col li + li { margin-top: var(--sp-1); }
.footer-ds__col li a {
  display: block; padding-block: var(--sp-2);
  font-size: var(--fs-sm); font-weight: 700;
  color: var(--color-inverse-ink);
  transition: color .15s ease;
}
/* --c-yellow-300 (not --color-primary) is the system's dark-surface accent:
   same choice as .nav-ds__links a and .section-ds--inverse .section-head .more.
   --c-yellow-700/800 are the light-background golds and must not appear here. */
.footer-ds__col li a:hover { color: var(--c-yellow-300); }

/* Contact column: label/value pairs reusing the .04em uppercase label idiom
   from .form-ds label, so the footer doesn't invent a new small-caps voice. */
.footer-ds__contact { display: flex; flex-direction: column; gap: var(--sp-4); margin: 0; }
.footer-ds__contact dt {
  font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--c-grey-400); margin-bottom: var(--sp-1);
}
.footer-ds__contact dd { margin: 0; font-size: var(--fs-sm); color: var(--color-inverse-muted); }
.footer-ds__contact dd a { color: var(--color-inverse-ink); font-weight: 700; transition: color .15s ease; }
.footer-ds__contact dd a:hover { color: var(--c-yellow-300); }
.footer-ds__contact .num { font-variant-numeric: tabular-nums; }

.footer-ds__social { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
.footer-ds__social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid var(--c-black-700); border-radius: var(--radius-pill);
  color: var(--color-inverse-muted);
  transition: color .15s ease, border-color .15s ease, transform .15s ease;
}
.footer-ds__social a:hover { color: var(--c-yellow-300); border-color: var(--c-yellow-300); transform: translateY(-1px); }
.footer-ds__social svg { width: 20px; height: 20px; fill: currentColor; display: block; }

.footer-ds__crest { justify-self: start; }
@media (min-width: 992px) { .footer-ds__crest { justify-self: end; align-self: start; } }
.footer-ds__crest img { width: 96px; height: 96px; opacity: .9; }

/* Oversized wordmark band. Purely decorative (aria-hidden in the markup), so
   it is not held to a contrast floor. Hollow letters with a thin yellow stroke:
   it reads as a line drawing scribed into the backing rather than a filled word,
   so the footer keeps receding instead of becoming the loudest surface.

   This still honours the Rarity Rule. The rule bans yellow as a large *surface*,
   and a 1.5px outline on hollow glyphs covers almost no area — the ink here is a
   fraction of what a single filled button spends. It also follows the
   Border-First Rule's logic: define the shape with a rule, not a fill.

   nowrap + overflow:hidden lets the line be clipped by the container edge
   instead of wrapping into a second line on narrow screens. */
.footer-ds__wordmark {
  border-block: 1px solid var(--c-black-700);
  padding-block: var(--sp-5);
  overflow: hidden;
}
.footer-ds__wordmark span {
  display: block;
  font-size: clamp(2.2rem, 12.2vw, 9.2rem);
  font-weight: 800;
  line-height: .8;
  letter-spacing: -.02em;
  white-space: nowrap;
  /* Fallback for engines without text-stroke: a ghosted fill, never invisible. */
  color: rgba(255, 255, 255, .07);
  user-select: none;
}
/* Gated so `color: transparent` is only applied where a stroke can actually
   render it — otherwise the wordmark would vanish entirely. */
@supports (-webkit-text-stroke: 1px currentColor) {
  .footer-ds__wordmark span {
    color: transparent;
    -webkit-text-stroke: 1.5px rgba(245, 196, 0, .42);   /* --c-yellow-500 @ 42% */
  }
  /* At mobile sizes the glyphs are ~3x smaller, so a 1.5px stroke reads much
     heavier relative to the letterform. Thin it to keep the weight consistent. */
  @media (max-width: 767px) {
    .footer-ds__wordmark span { -webkit-text-stroke-width: 1px; }
  }
}

.footer-ds__bottom { color: var(--c-grey-400); font-size: var(--fs-xs); padding-block: var(--sp-5); }

@media (prefers-reduced-motion: reduce) {
  .footer-ds__social a:hover { transform: none; }
}

/* ---------- Demo switcher (match.html only) ---------- */
.demo-switcher { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.demo-switcher button { cursor: pointer; }
.demo-switcher button[aria-pressed="true"] { background: var(--color-primary); color: var(--color-primary-ink); }

/* ============================================================
   SQUAD PAGE (season/team.html)
   ============================================================ */

/* Facts strip: coach / ground / squad size — three real facts, not a
   trophy-ds clone (those are for honours counts, this is context). */
.squad-facts {
  display: flex; flex-wrap: wrap; gap: var(--sp-5) var(--sp-7);
  padding-block: var(--sp-4);
  border-top: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border);
}
.squad-facts__item { display: flex; flex-direction: column; gap: 2px; }
.squad-facts__item .label { font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--color-ink-muted); }
.squad-facts__item .value { font-size: var(--fs-sm); font-weight: 700; }

/* Position filter: same segmented-pill recipe as .mc-tablist, kept as its
   own class since this filters page sections (show/hide), not ARIA
   tabpanels — see the demo-switcher precedent on match.html. */
.squad-tablist {
  display: inline-flex; flex-wrap: wrap; gap: 2px; background: var(--color-surface-alt);
  border-radius: var(--radius-pill); padding: 3px;
}
.squad-tablist button {
  appearance: none; background: none; border: none; border-radius: var(--radius-pill);
  padding: var(--sp-2) var(--sp-4); font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: .03em; color: var(--color-ink-muted); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.squad-tablist button[aria-pressed="true"] { background: var(--c-black-900); color: var(--color-inverse-ink); }
.squad-tablist button:not([aria-pressed="true"]):hover { color: var(--color-ink); }
.squad-tablist button:focus-visible { outline: 2px solid var(--c-yellow-500); outline-offset: 2px; }

.squad-group { margin-top: var(--sp-6); }
.squad-group__label { font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--c-yellow-700); margin-bottom: var(--sp-4); }

/* Fixed column counts, not auto-fit: auto-fit's 1fr tracks stretch to fill
   the row when a group has fewer players than the row can hold (e.g. a
   4-player group next to a 6-player one), making cards a different size
   per group. A fixed track count keeps every card the same size across
   every group; an under-full last row just leaves trailing space. */
.squad-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-5); }
@media (min-width: 480px) { .squad-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 768px) { .squad-grid { grid-template-columns: repeat(4, 1fr); } }

/* Roster cards adopt the homepage "feature" treatment (see .player-feature
   in design-system.css): taller 3:5 crop, a solid offset block stepping out
   behind the card, and a slow photo zoom on hover.

   Two deliberate differences from the homepage. (1) The offset is always
   near-black, never the homepage's alternating yellow — 15 yellow blocks
   down a 30-card grid turns the accent into a wash and breaks the Rarity
   Rule; the homepage teaser stays the one place yellow appears in this
   component. (2) The offset is a hard-edged box-shadow rather than the
   homepage's extra .player-feature__offset div — same geometry (it follows
   the card's border-radius, and an outer shadow isn't clipped by the card's
   own overflow:hidden), without wrapping 30 static articles.

   Grid gap above is --sp-5 rather than the roster's old --sp-4 so the 8px
   offset keeps clear of the neighbouring card. */
.squad-grid .player-card-ds { box-shadow: 8px 8px 0 0 var(--c-black-900); }
.squad-grid .player-card-ds:hover,
.squad-grid .player-card-ds:focus-within { box-shadow: 12px 12px 0 0 var(--c-black-900); }
.squad-grid .player-card-ds img { aspect-ratio: 3/5; transition: transform .4s ease; }
.squad-grid .player-card-ds:hover img,
.squad-grid .player-card-ds:focus-within img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
  .squad-grid .player-card-ds img { transition: none; }
  .squad-grid .player-card-ds:hover img,
  .squad-grid .player-card-ds:focus-within img { transform: none; }
}

/* ============================================================
   SHOP PAGE (shop.html)
   ============================================================ */

/* Featured spotlight — the source photography is a set of square
   Instagram promo cards (own baked-in header/footer text bands), not
   clean product photography, so a 3:2 crop + object-position isolates
   just the jersey-in-locker artwork. See .product-ds__media below for
   the exact math; both share the same source template. */
.shop-spotlight {
  position: relative; border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid var(--color-border); box-shadow: var(--shadow-sm);
}
.shop-spotlight img { width: 100%; aspect-ratio: 3/2; object-fit: cover; object-position: center 18%; display: block; }
.shop-spotlight__tag {
  position: absolute; left: var(--sp-4); bottom: var(--sp-4);
  background: var(--c-yellow-500); color: var(--c-black-900);
  font-weight: 800; font-size: var(--fs-sm); padding: var(--sp-2) var(--sp-4);
  border-radius: var(--radius-pill);
}

/* Order steps ("Comment commander") */
.order-steps { display: flex; flex-direction: column; gap: var(--sp-5); }
.order-step { display: flex; gap: var(--sp-4); }
.order-step__num {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
  background: var(--c-yellow-500); color: var(--c-black-900);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: var(--fs-sm);
}
.order-step h3 { font-size: var(--fs-h6); margin-bottom: var(--sp-1); }
.order-step p { font-size: var(--fs-sm); color: var(--color-ink-muted); margin: 0; }
.order-step__phone { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-3); }
.order-step__phone strong { font-variant-numeric: tabular-nums; font-size: var(--fs-sm); }
.copy-feedback { font-size: var(--fs-xs); font-weight: 700; color: var(--c-yellow-700); }

/* Category filter — same segmented-pill recipe as .squad-tablist
   (season/team.html), kept as its own class since this page doesn't
   share that page's markup and shouldn't couple to it. */
.shop-filter {
  display: inline-flex; flex-wrap: wrap; gap: 2px; background: var(--color-surface-alt);
  border-radius: var(--radius-pill); padding: 3px; margin-bottom: var(--sp-5);
}
.shop-filter button {
  appearance: none; background: none; border: none; border-radius: var(--radius-pill);
  padding: var(--sp-2) var(--sp-4); font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: .03em; color: var(--color-ink-muted); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.shop-filter button[aria-pressed="true"] { background: var(--c-black-900); color: var(--color-inverse-ink); }
.shop-filter button:not([aria-pressed="true"]):hover { color: var(--color-ink); }
.shop-filter button:focus-visible { outline: 2px solid var(--c-yellow-500); outline-offset: 2px; }

/* Product grid */
.product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--sp-4); }
.product-ds {
  display: flex; flex-direction: column; height: 100%;
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); overflow: hidden;
  transition: box-shadow .2s ease, transform .2s ease;
}
.product-ds:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.product-ds__media { aspect-ratio: 3/2; background: var(--color-surface-alt); }
/* object-position: center 18% crops out the source image's own baked-in
   "PRODUIT OFFICIEL" header band and price/promo footer band (real
   Instagram assets, not clean product photography) so only the
   jersey-in-locker artwork is visible; our own type system carries the
   name/price below instead of trusting the (sometimes promo, possibly
   stale) price printed into the image itself. */
.product-ds__media img { width: 100%; height: 100%; object-fit: cover; object-position: center 18%; }
.product-ds__body { padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2); flex: 1; }
.product-ds__tags { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.product-ds h3 { font-size: var(--fs-h6); margin: 0; }
.product-ds__price { font-size: var(--fs-h5); font-weight: 800; font-variant-numeric: tabular-nums; margin: 0; }
.product-ds__price span { font-size: var(--fs-xs); font-weight: 700; color: var(--color-ink-muted); margin-left: var(--sp-1); }
.product-ds__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: auto; padding-top: var(--sp-2); }

.shop-note { border-top: 1px solid var(--color-border); margin-top: var(--sp-7); padding-top: var(--sp-6); }

/* ============================================================
   CALENDRIER (season/results.html)
   Card grid: a light-grey head (crest + name) on a white body — kept
   deliberately quiet (no black surface, no yellow accent) so the crests
   and score are the only visual weight; ASEC's own name stays plain like
   the opponent's rather than picked out in yellow, matching the
   reference the card head was built against.
   ============================================================ */

.calendar-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.calendar-head svg { width: 14px; height: 14px; }

/* Filter — a full-width, evenly-distributed pill bar (every button gets
   equal flex width) rather than a left-hugging chip cluster, so it reads
   as one continuous control spanning the page like the month scrubber
   it's replacing. Active/pressed keeps this site's own black-fill
   convention (matching .squad-tablist / .mc-tablist) rather than
   borrowing an accent color for what is, elsewhere on this site, always
   a black-on-white toggle state. */
.calendar-filter {
  display: flex; gap: 2px; background: var(--color-surface-alt);
  border-radius: var(--radius-pill); padding: 4px; margin-bottom: var(--sp-3);
}
.calendar-filter button {
  flex: 1; appearance: none; background: none; border: none; border-radius: var(--radius-pill);
  padding: var(--sp-3) var(--sp-4); font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: .03em; color: var(--color-ink-muted); cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.calendar-filter button[aria-pressed="true"] { background: var(--c-black-900); color: var(--color-inverse-ink); }
.calendar-filter button:not([aria-pressed="true"]):hover { color: var(--color-ink); }
.calendar-filter button:focus-visible { outline: 2px solid var(--c-yellow-500); outline-offset: 2px; }

/* Month bar covers a full season (12 pills: "Tous" + Août-Juin, short
   form since the season dropdown above already carries the year).
   Equal flex-grow on every button, wrapped rather than scrolled: on wide
   viewports all 12 sit in one full-width, evenly-spaced row; on narrow
   ones flexbox wraps to further rows and each row still stretches its
   own buttons to fill the full width evenly, so the bar never needs a
   scrollbar at any size. */
.calendar-filter--months { flex-wrap: wrap; }
.calendar-filter--months button { flex: 1 1 84px; }

/* Season dropdown — a bordered pill matching the rest of the page's
   button vocabulary (Border-First Rule: 1px border at rest, no shadow
   until hover), rather than bare text floating with no affordance that
   it's clickable. Open state reuses the site's one black-fill "pressed"
   convention (same as the filter pills below it) instead of introducing
   a second active-state treatment. This feed only has one season of
   real fixtures, so picking next/previous surfaces the calendar's own
   "no data yet" empty state rather than fabricated matches. */
.season-select { position: relative; display: inline-block; margin-bottom: var(--sp-4); }
.season-select__trigger {
  display: inline-flex; align-items: center; gap: var(--sp-2); appearance: none; cursor: pointer;
  background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-pill);
  padding: var(--sp-2) var(--sp-4); font-size: var(--fs-sm); font-weight: 800; color: var(--color-ink);
  line-height: 1.2; transition: background .15s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.season-select__trigger:hover { box-shadow: var(--shadow-sm); }
.season-select__trigger[aria-expanded="true"] {
  background: var(--c-black-900); border-color: var(--c-black-900); color: var(--color-inverse-ink);
}
.season-select__trigger svg { width: 12px; height: 12px; flex-shrink: 0; transition: transform .15s ease; }
.season-select__trigger[aria-expanded="true"] svg { transform: rotate(180deg); }
.season-select__trigger:focus-visible { outline: 2px solid var(--c-yellow-500); outline-offset: 2px; }
.season-select__menu {
  position: absolute; top: calc(100% + var(--sp-2)); left: 0; z-index: 20;
  min-width: 140px; margin: 0; padding: var(--sp-2) 0; list-style: none;
  background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.season-select__menu[hidden] { display: none; }
.season-select__menu li { padding: var(--sp-3) var(--sp-4); font-weight: 700; font-size: var(--fs-sm); color: var(--color-ink); cursor: pointer; }
.season-select__menu li:hover { background: var(--color-surface-alt); }
.season-select__menu li[aria-selected="true"] { background: var(--color-surface-alt); font-weight: 800; }

/* Secondary (competition) bar reads a step quieter than the primary month
   bar above it: border instead of a filled track, left-hugging chips
   instead of full-width equal-flex segments, since it's a refinement of
   the month selection rather than an equally-weighted second axis. */
.calendar-filter--competition {
  background: none; padding: 0; gap: var(--sp-2); margin-bottom: var(--sp-5); flex-wrap: wrap;
}
.calendar-filter--competition button {
  flex: 0 0 auto; border: 1px solid var(--color-border);
  padding: var(--sp-2) var(--sp-4); font-weight: 700;
}
.calendar-filter--competition button[aria-pressed="true"] {
  background: var(--c-black-900); border-color: var(--c-black-900);
}

.fixtures-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-4); align-items: start; }

/* Month grouping — proportional to what's actually confirmed (a handful
   of fixtures spanning two months), not a full rolling year of tabs.
   grid-column spans the full row so the label reads as a section
   heading over the cards that follow, not a squeezed grid cell. */
.fixtures-month-label {
  grid-column: 1 / -1;
  font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--c-yellow-700); margin: var(--sp-3) 0 0;
}
.fixtures-month-label:first-child { margin-top: 0; }

.fixture-card {
  display: flex; flex-direction: column; height: 100%;
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); overflow: hidden;
  transition: box-shadow .2s ease, transform .2s ease;
}
.fixture-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.fixture-card[data-status="live"] { border-color: var(--c-live); box-shadow: 0 0 0 1px var(--c-live) inset; }

.fixture-card__head {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  background: var(--c-grey-200); padding: var(--sp-5) var(--sp-3);
}
.fixture-card__team { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); flex: 1; min-width: 0; text-align: center; }
/* Crest sits inside its own fixed-size white circle (background + clip
   live on the wrapper, not the <img>) so the badge is guaranteed a full
   white disc no matter how a given crest PNG handles transparency at
   its own edges — no dark bleed-through possible, since overflow:hidden
   on the wrapper clips to the circle regardless of the image's shape. */
.fixture-card__crest {
  width: 56px; height: 56px; border-radius: 50%; background: #fff;
  display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0;
}
.fixture-card__crest img { width: 68%; height: 68%; object-fit: contain; }
.fixture-card__team span {
  color: var(--color-ink); font-weight: 700; font-size: var(--fs-xs); line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.fixture-card__team.is-asec span { font-weight: 800; }

.fixture-card__center { flex-shrink: 0; display: flex; align-items: center; justify-content: center; min-width: 56px; }
.fixture-card__score { color: var(--color-ink); font-size: var(--fs-h4); font-weight: 800; font-variant-numeric: tabular-nums; }
.fixture-card__vs { color: var(--color-ink-muted); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; }

.fixture-card__body { padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2); flex: 1; }
.fixture-card__eyebrow { font-size: var(--fs-xs); color: var(--color-ink-muted); margin: 0; }
.fixture-card__status { line-height: 1; }
.fixture-card__comp { font-weight: 800; font-size: var(--fs-sm); color: var(--color-ink); margin: 0; }
.fixture-card__matchday { font-weight: 700; font-size: var(--fs-xs); color: var(--color-ink); margin: 0 0 var(--sp-1); }
.fixture-card__datetime, .fixture-card__venue {
  display: flex; align-items: center; gap: var(--sp-1); font-size: var(--fs-xs); color: var(--color-ink-muted); min-width: 0;
}
.fixture-card__datetime svg, .fixture-card__venue svg { flex-shrink: 0; width: 12px; height: 12px; }
.fixture-card__venue span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fixture-card__venue.is-tbc { font-style: italic; opacity: .8; }
.fixture-card__action { margin-top: auto; padding-top: var(--sp-2); font-size: var(--fs-xs); font-weight: 800; color: var(--c-yellow-700); }

.fixture-card-skeleton { min-height: 280px; border-radius: var(--radius-md); }
.fixtures-empty { grid-column: 1 / -1; padding: var(--sp-6); text-align: center; color: var(--color-ink-muted); }

/* ============================================================
   CLASSEMENT (season/ranking.html)
   Real ARIA tablist (not the calendar's filter-pill recipe) since each
   tab swaps in a genuinely different competition's table, the same
   relationship .mc-tablist has to the Match Centre's tabpanels. Same
   segmented-pill visual recipe, kept as its own class per this
   codebase's convention of one class per page rather than a shared
   page-crossing dependency (see .squad-tablist's own comment).
   ============================================================ */
.ranking-tablist {
  display: inline-flex; gap: 2px; background: var(--color-surface-alt);
  border-radius: var(--radius-pill); padding: 4px; margin-bottom: var(--sp-5);
}
.ranking-tablist [role="tab"] {
  appearance: none; background: none; border: none; border-radius: var(--radius-pill);
  padding: var(--sp-3) var(--sp-5); font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: .03em; color: var(--color-ink-muted); cursor: pointer; min-height: 44px;
  transition: background .15s ease, color .15s ease;
}
.ranking-tablist [role="tab"][aria-selected="true"] { background: var(--c-black-900); color: var(--color-inverse-ink); }
.ranking-tablist [role="tab"]:not([aria-selected="true"]):hover { color: var(--color-ink); }
.ranking-tablist [role="tab"]:focus-visible { outline: 2px solid var(--c-yellow-500); outline-offset: 2px; }

.ranking-form { display: inline-flex; gap: 3px; justify-content: center; }

.ranking-table-skeleton { height: 480px; border-radius: var(--radius-md); }
.ranking-empty {
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface); padding: var(--sp-8) var(--sp-5);
  text-align: center; color: var(--color-ink-muted);
}

/* ============================================================
   CLUB PAGES (club/about-asec-mimosas.html, club/palmares.html)
   ============================================================ */

/* Asymmetric page header (about-asec-mimosas.html): text column + a
   standalone founding-year panel, so the top of the page reads as a
   composed moment instead of one narrow column stranded in a much wider
   viewport. Stacks on mobile, panel pinned to the trailing edge at
   desktop widths (brand register's asymmetric-composition permission). */
.about-hero { display: grid; gap: var(--sp-6); align-items: start; }
@media (min-width: 992px) {
  .about-hero { grid-template-columns: 1.3fr 1fr; gap: var(--sp-8); }
}

/* Founding panel — the "display case" for a single fact (the founding
   year) rather than an honours count, so it borrows trophy-ds's black
   surface + yellow numeral language without reusing the trophy-ds class
   itself, keeping that class's meaning (honours) unambiguous. */
.founding-panel {
  background: var(--c-black-900); color: var(--color-inverse-ink);
  border-radius: var(--radius-lg); padding: var(--sp-8) var(--sp-6);
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--sp-2);
}
.founding-panel__num {
  font-size: clamp(3rem, 2rem + 5vw, 5.5rem); font-weight: 800; line-height: 1;
  color: var(--color-primary); font-variant-numeric: tabular-nums;
}
.founding-panel__label { font-size: var(--fs-sm); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.founding-panel__sub { font-size: var(--fs-xs); color: var(--color-inverse-muted); }

/* Facts strip — a bordered card (Border-First Rule) laid out as a fixed
   grid rather than flex-wrap: flex-wrap left a ragged trailing edge and
   no visual container, which read as loose text floating in whitespace
   rather than a considered "fact sheet" module. */
.club-facts {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-6) var(--sp-6);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  padding: var(--sp-6);
}
@media (min-width: 768px) { .club-facts { grid-template-columns: repeat(4, 1fr); } }
.club-facts__item { display: flex; flex-direction: column; gap: 2px; }
.club-facts__item .label { font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--color-ink-muted); }
.club-facts__item .value { font-size: var(--fs-sm); font-weight: 700; }

/* Milestones panel — an inset "display case" card (rounded, not a
   full-bleed slab with a hard rectangular edge) in a muted, deep gold
   rather than flat black. Scoped local custom property, not a change to
   --color-inverse-bg: this is a deliberate one-off for this one panel,
   not a revision of the sitewide Rarity Rule (DESIGN.md still holds
   everywhere else — plain black inverse sections, yellow as a rare
   accent). Text colors below are re-picked against this specific
   background, not inherited from .section-ds--inverse. */
.milestones-panel {
  --panel-gold: #6b5313;
  background: var(--panel-gold); color: var(--color-inverse-ink);
  border-radius: var(--radius-lg);
  padding: var(--sp-8) var(--sp-6);
  text-align: center;
}

/* Founding milestones — a real dated sequence (1948 to 1999), so a
   connected line + node reads as history, not decorative step numbers.
   Same "line + circular marker" recipe as .mc-timeline, restyled for the
   gold panel with the year standing in for the match-minute marker. */
.milestones { position: relative; list-style: none; margin: 0; padding: 0; max-width: 720px; }
.milestones::before {
  content: ""; position: absolute; left: 27px; top: 8px; bottom: 8px; width: 2px;
  /* translucent black darkens whatever panel color sits behind it,
     rather than a fixed hex tuned to one specific background */
  background: rgba(0, 0, 0, .3);
}
.milestone { position: relative; display: flex; gap: var(--sp-4); padding-block: var(--sp-4); }
.milestone:first-child { padding-top: 0; }
.milestone:last-child { padding-bottom: 0; }
.milestone__year {
  position: relative; z-index: 1; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: var(--radius-pill);
  background: var(--c-black-800); border: 2px solid var(--c-yellow-500);
  color: var(--c-yellow-500); font-weight: 800; font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.milestone__body { padding-top: var(--sp-1); }
.milestone__body h3 { font-size: var(--fs-h6); color: var(--color-inverse-ink); margin-bottom: 2px; }
/* Lighter than --color-inverse-muted (#b9b9b9): that gray was tuned for
   pure black (~9.7:1) and drops to ~3.6:1, below AA, on the lighter gold
   panel — bumped to clear 4.5:1 against --panel-gold specifically. */
.milestone__body p { font-size: var(--fs-sm); color: #d8d8d8; margin: 0; max-width: 52ch; }

/* Honours grid (club/palmares.html) — featured tiles get their own grid
   instead of a flat 4-up bootstrap row, so the two continental titles can
   span wider and read as the headline, not a peer of the domestic counts. */
.trophy-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); }
@media (min-width: 768px) {
  .trophy-grid { grid-template-columns: repeat(4, 1fr); }
  .trophy-ds--featured { grid-column: span 2; }
}
.trophy-ds--featured { padding-block: var(--sp-6); }
.trophy-ds--featured .count { font-size: var(--fs-h1); }
.trophy-ds--featured .note { margin-top: var(--sp-3); font-size: var(--fs-xs); color: var(--color-inverse-muted); max-width: 30ch; margin-inline: auto; }

/* Long inline year lists (30+ years for the domestic titles) need room to
   breathe across wrapped lines, or they read as one dense illegible
   block rather than a scannable record. */
.table-ds td.years-list { line-height: 1.85; font-variant-numeric: tabular-nums; }

/* Vision statement — a single sourced quote from the club's own charter.
   Set large enough to carry its own section on type alone (size + weight,
   no color trick): the section's only content, so it needs to read as a
   deliberate editorial pause, not a caption-sized aside. */
.club-vision {
  font-size: clamp(1.5rem, 1.2rem + 1.6vw, 2.25rem); font-weight: 700; line-height: 1.3;
  letter-spacing: -0.01em; max-width: 32ch; text-wrap: pretty;
}

/* ============================================================
   CONTACT PAGE (contacts.html)
   ============================================================ */

/* Phone call-out — reuses .about-hero's asymmetric grid for the outer
   layout (text column + standalone panel), and the founding-panel "display
   case" recipe for the panel itself, but sized for a full phone number
   instead of a 4-digit year: giant tabular-nums would wrap badly at that
   length, so the number sits at trophy-ds__count scale with its own call
   button underneath rather than standing alone as a single giant numeral. */
.contact-panel {
  background: var(--c-black-900); color: var(--color-inverse-ink);
  border-radius: var(--radius-lg); padding: var(--sp-8) var(--sp-6);
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-3);
}
.contact-panel__label { font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--color-inverse-muted); }
.contact-panel__num {
  font-size: clamp(1.6rem, 1.2rem + 2.2vw, 2.5rem); font-weight: 800; line-height: 1.1;
  color: var(--color-primary); font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
}
.contact-panel__sub { font-size: var(--fs-sm); color: var(--color-inverse-muted); max-width: 32ch; }
.contact-panel .btn-ds { margin-top: var(--sp-2); }

/* Address cards — Border-First Rule (1px border at rest, shadow only on
   hover/focus since these are links out to Maps). auto-fit keeps this
   breakpoint-free: two cards side by side once there's room, stacked below. */
.address-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-4); }
.address-card {
  padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-2);
  transition: box-shadow .2s ease, transform .2s ease;
}
.address-card:hover, .address-card:focus-within { box-shadow: var(--shadow-md); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { .address-card { transition: none; } .address-card:hover, .address-card:focus-within { transform: none; } }
.address-card h3 { font-size: var(--fs-h6); }
.address-card p { font-size: var(--fs-sm); color: var(--color-ink-muted); margin: 0; max-width: 34ch; }
.address-card .btn-ds { align-self: flex-start; margin-top: var(--sp-2); }

/* Contact form — the site's first form, so these are new tokens rather
   than a reuse: bordered inputs at the same radius/border-color as every
   other bordered surface (Border-First Rule), yellow reserved for the
   focus ring only (Rarity Rule) so a page full of empty fields never reads
   as a wash of brand color. */
.form-ds { display: flex; flex-direction: column; gap: var(--sp-5); }
.form-ds__row { display: flex; flex-direction: column; gap: var(--sp-2); }
.form-ds__row--split { display: grid; grid-template-columns: 1fr; gap: var(--sp-5); }
@media (min-width: 576px) { .form-ds__row--split { grid-template-columns: 1fr 1fr; } }
.form-ds label { font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--color-ink-muted); }
.form-ds label .req { color: var(--c-yellow-700); }
.form-ds input, .form-ds select, .form-ds textarea {
  font: inherit; font-size: var(--fs-body); color: var(--color-ink); background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius-sm);
  padding: var(--sp-3) var(--sp-4); min-height: 44px; width: 100%;
  transition: border-color .15s ease;
}
.form-ds textarea { min-height: 140px; resize: vertical; }
.form-ds input:hover, .form-ds select:hover, .form-ds textarea:hover { border-color: var(--c-grey-400); }
.form-ds input:focus-visible, .form-ds select:focus-visible, .form-ds textarea:focus-visible {
  outline: 3px solid var(--c-yellow-500); outline-offset: 1px; border-color: var(--c-yellow-600);
}
/* Native :invalid fires as soon as a required field exists, before the user
   has touched it — only show the red state once they've left the field
   with bad input (class toggled on blur by contacts.html's inline script),
   matching the "validate on blur, not on every keystroke" rule. */
.form-ds .is-touched:invalid { border-color: var(--c-live); }
.form-ds__error {
  display: none; font-size: var(--fs-xs); font-weight: 700; color: var(--c-live);
}
.form-ds .is-touched:invalid ~ .form-ds__error { display: block; }
.form-ds__foot { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
.form-ds__note { font-size: var(--fs-xs); color: var(--color-ink-muted); max-width: 52ch; }
.form-ds__status {
  font-size: var(--fs-xs); font-weight: 700; color: var(--c-yellow-700); min-height: 1em;
}

/* ============================================================
   ARTICLE DETAIL (news/<slug>.html)
   The site's first long-form reading surface. Everything above this
   point is UI type at line-height 1.5; running prose needs its own
   measure and leading, which DESIGN.md anticipates ("Max ~65-75ch
   line length where prose appears").
   ============================================================ */

/* ---- Breadcrumb: quiet by design. It orients, it does not compete
   with the cover directly beneath it. ---- */
.article-crumbs { font-size: var(--fs-xs); color: var(--color-ink-muted); }
.article-crumbs ol { display: flex; flex-wrap: wrap; gap: var(--sp-2); list-style: none; margin: 0; padding: 0; }
.article-crumbs li:not(:last-child)::after { content: "›"; margin-left: var(--sp-2); color: var(--color-border); }
.article-crumbs a { color: var(--c-yellow-800); font-weight: 700; }
.article-crumbs a:hover { text-decoration: underline; }
.article-crumbs [aria-current="page"] { color: var(--color-ink-muted); }

/* ---- Cover, two variants ------------------------------------
   Both are dark, so the overlaid type is white in either case and
   .article-cover__body needs no variant-specific color rules.

   --photo: full-bleed image + scrim, deliberately the same gradient
   language as .news-hero so arriving from a news card feels like the
   card expanded rather than like a different page.

   --type: no image slot at all. For articles the club never shot a
   photo for, an empty frame or a grey placeholder reads as breakage;
   a Match Night Black display-case panel reads as an editorial
   decision. This is DESIGN.md's Two-Job Black Rule.
   It doubles as the photo variant's failure state (see the onerror
   handler in the markup) — assets.asec.ci is a third-party host this
   build does not control, so the cover has to survive losing it. ---- */
.article-cover {
  position: relative; display: flex; align-items: flex-end;
  border-radius: var(--radius-lg); overflow: hidden; isolation: isolate;
  background: var(--c-black-900); color: var(--color-inverse-ink);
}
.article-cover--photo { min-height: 340px; }
.article-cover--type { border: 1px solid var(--c-black-700); }
@media (min-width: 768px) { .article-cover--photo { min-height: 440px; } }
@media (min-width: 992px) { .article-cover--photo { min-height: 520px; } }

.article-cover__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.article-cover--photo::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(12,12,12,.10) 25%, rgba(12,12,12,.62) 68%, rgba(12,12,12,.93) 100%);
}
.article-cover__body {
  position: relative; z-index: 2; width: 100%;
  padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-3);
}
@media (min-width: 768px) { .article-cover__body { padding: var(--sp-7) var(--sp-6); } }
/* The type variant has no photo to fill the panel, so its padding does
   the work the image would have done. */
.article-cover--type .article-cover__body { padding-block: var(--sp-7); }
@media (min-width: 768px) { .article-cover--type .article-cover__body { padding-block: var(--sp-9); } }

/* --fs-h1 tops out at 4rem, which overflows inside a constrained cover
   block once a headline runs past ~40 characters. The cover gets its own
   ceiling and a hard measure instead. */
.article-cover h1 {
  font-size: clamp(1.9rem, 1.4rem + 2vw, 3.1rem);
  line-height: 1.06; letter-spacing: -.015em; max-width: 20ch;
  color: var(--color-inverse-ink); text-wrap: balance;
}
.article-cover__dek { font-size: var(--fs-sm); color: rgba(255,255,255,.85); max-width: 52ch; margin: 0; }
.article-cover .cat-badge { align-self: flex-start; background: var(--c-yellow-500); color: var(--c-black-900); }

/* Cover type settles on load. Written as an animation on an already-
   visible element, never a class-gated transition: class-gated reveals
   never fire on a background tab or in a headless renderer, and the
   section ships blank. */
@keyframes article-cover-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
.article-cover__body > * { animation: article-cover-in .5s cubic-bezier(.22,1,.36,1) backwards; }
.article-cover__body > :nth-child(2) { animation-delay: .06s; }
.article-cover__body > :nth-child(3) { animation-delay: .12s; }
@media (prefers-reduced-motion: reduce) {
  .article-cover__body > * { animation: none; }
}

/* ---- Meta row: Border-First Rule. Rules, not a card, not a shadow. ---- */
.article-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-6); padding-block: var(--sp-3);
  border-top: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-xs); color: var(--color-ink-muted);
}
.article-meta time { font-weight: 700; color: var(--color-ink); }
.article-meta__share { display: flex; align-items: center; gap: var(--sp-3); margin-left: auto; }
.article-meta__share a { font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--c-yellow-800); }
.article-meta__share a:hover { text-decoration: underline; }

/* ---- Reading column + contextual rail ----
   minmax(0, 68ch) rather than 68ch so the prose track can still shrink
   below its max on mid-width screens instead of forcing overflow. */
.article-layout { display: grid; gap: var(--sp-7); align-items: start; margin-top: var(--sp-6); }
@media (min-width: 992px) {
  .article-layout { grid-template-columns: minmax(0, 68ch) 1fr; gap: var(--sp-8); }
  .article-layout > aside { position: sticky; top: calc(var(--nav-height) + var(--sp-4)); }
}

/* ---- Prose ----
   1.7 leading and 68ch are prose-specific and deliberately looser than
   the 1.5 / no-max used for UI text everywhere else in this file. */
.prose-ds { max-width: 68ch; font-size: 1.0625rem; line-height: 1.7; text-wrap: pretty; }
@media (min-width: 768px) { .prose-ds { font-size: 1.125rem; } }
.prose-ds > p { margin: 0 0 var(--sp-5); }
.prose-ds > p:last-child { margin-bottom: 0; }
.prose-ds a { color: var(--c-yellow-800); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.prose-ds strong { font-weight: 800; }

/* Standfirst. The club's own CMS ships this paragraph wrapped in
   <strong><em>, which renders as a bold-italic wall at this length.
   The emphasis is carried structurally instead: bigger, slightly
   heavier, full ink. Same signal, none of the shouting. */
.prose-ds__lead {
  font-size: 1.1875rem; line-height: 1.55; font-weight: 500;
  color: var(--color-ink); margin-bottom: var(--sp-6);
}
@media (min-width: 768px) { .prose-ds__lead { font-size: 1.3125rem; } }

/* Pull quote. No side stripe: a thick colored border-left is an
   absolute ban and always reads as a template. Full hairlines above
   and below carry the separation instead.
   No CSS-generated quote glyph either: the club's copy already carries
   French guillemets, and a decorative “ on top of them double-marks
   the quote. The guillemets stay in the text where they belong. */
.prose-ds__quote { margin: var(--sp-7) 0; padding: var(--sp-5) 0; border-top: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border); }
.prose-ds__quote p {
  font-size: 1.1875rem; line-height: 1.5; font-weight: 500; margin: 0;
}
@media (min-width: 768px) { .prose-ds__quote p { font-size: 1.3125rem; } }
.prose-ds__quote cite {
  display: block; margin-top: var(--sp-4); font-style: normal;
  font-size: var(--fs-xs); font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--color-ink);
}
.prose-ds__quote cite span { display: block; margin-top: 2px; font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--color-ink-muted); }

/* Pivot line. Same visual weight as a pull quote, but it is the
   publication's own thesis sentence rather than someone's speech, so it
   stays a <p> and never a <blockquote>. Used once per article at most:
   a second one turns a deliberate beat into a layout mannerism. */
.prose-ds__pivot {
  margin: var(--sp-7) 0; padding: var(--sp-5) 0;
  border-top: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border);
  font-size: 1.1875rem; line-height: 1.5; font-weight: 500;
}
@media (min-width: 768px) { .prose-ds__pivot { font-size: 1.3125rem; } }

/* ---- "Pour aller plus loin" rail ----
   Real links into pages that already exist, so a short article still
   lands the reader somewhere useful instead of dead-ending. */
.article-aside { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--sp-5); background: var(--color-surface); }
.article-aside h2 { font-size: var(--fs-h6); margin-bottom: var(--sp-4); }
.article-aside ul { list-style: none; margin: 0; padding: 0; }
.article-aside li { border-bottom: 1px solid var(--color-border); }
.article-aside li:last-child { border-bottom: none; }
.article-aside a { display: flex; align-items: baseline; gap: var(--sp-2); padding-block: var(--sp-3); font-size: var(--fs-sm); font-weight: 700; }
.article-aside a:hover { color: var(--c-yellow-800); }
.article-aside a::after { content: "→"; margin-left: auto; color: var(--color-ink-muted); transition: transform .15s ease; }
.article-aside a:hover::after { transform: translateX(3px); color: var(--c-yellow-800); }
@media (prefers-reduced-motion: reduce) {
  .article-aside a::after { transition: none; }
  .article-aside a:hover::after { transform: none; }
}

/* ---- "À lire aussi" ----
   Two tracks, not the usual three-card row: only the articles that
   have actually been built are linked, and the dark tile absorbs the
   remaining width rather than padding the row with cards pointing at
   pages that do not exist yet. */
.article-more { display: grid; gap: var(--sp-4); }
@media (min-width: 768px) { .article-more { grid-template-columns: 1fr 1fr; } }
.article-more__tile {
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-5);
  background: var(--c-black-900); color: var(--color-inverse-ink);
  border-radius: var(--radius-md); padding: var(--sp-5);
  transition: background .2s ease, box-shadow .2s ease, transform .2s ease;
}
.article-more__tile:hover { background: var(--c-black-800); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.article-more__tile .arrow { font-size: var(--fs-h4); line-height: 1; color: var(--c-yellow-500); }
@media (prefers-reduced-motion: reduce) {
  .article-more__tile { transition: none; }
  .article-more__tile:hover { transform: none; }
}
