/* ============================================================================
 * team-contrast.css — legibility corrections for the ACTIVE team's palette.
 *
 * Why this file exists
 * --------------------
 * The engine names its two brand ramps "navy" (primary) and "gold" (secondary)
 * after predsfan, whose secondary is a light gold that reads well on the navy
 * field. Every rule of the form "accent colour on the brand field" was written
 * against that assumption.
 *
 * A team whose secondary is DARK breaks all of them at once. Rangers red
 * #CE1126 on Rangers blue #0038A8 is 1.75:1 — the two colours have almost the
 * same relative luminance, so no per-rule tweak can rescue the pair. They are
 * simply not usable as foreground/background for each other, in either
 * direction. The site had ~10 distinct failing combinations per page, including
 * three page titles rendered blue-on-blue (1:1 — literally invisible).
 *
 * The correction, therefore, is structural rather than cosmetic:
 *   - the brand field carries WHITE text, never the accent;
 *   - the accent survives as a SOLID FILL with white text on it, and as a light
 *     tint where something must read as "the accent" while sitting on the field;
 *   - muted greys that fell under 4.5:1 move one step down their own ramp.
 *
 * Every colour below comes from a contrast ROLE that frontend/build.js computes
 * from the active team's own ramps (--on-primary, --on-secondary,
 * --accent-on-primary, --muted-on-primary). That keeps this file team-neutral:
 * for a light-secondary team like predsfan the roles resolve back to the
 * original gold-on-navy and these rules are a no-op.
 *
 * Load order
 * ----------
 * build.js injects this as the LAST stylesheet in every view. It has to win over
 * blog.css / players.css / stats.css / news.css / schedule.css, which set colour
 * after bundle-core.css; anywhere earlier and it would lose the cascade. The
 * `var(--role, fallback)` forms keep the page sane if the generator has not run.
 * ========================================================================== */

/* ── muted text tokens ───────────────────────────────────────────────────────
 * Text-only tokens (their own comments in design-tokens say so) that measured
 * under 4.5:1 on white. Corrected here rather than in the ramp so the
 * border/divider steps keep the lightness they were chosen for. */
:root {
    --neutral-gray-400: #5d6f86;  /* was #9ca3af — 2.19–2.54:1 on white */
}

/* ── text ON the brand field ─────────────────────────────────────────────────
 * The global `h1…h6 { color: var(--brand-navy-900) }` in bundle-core.css is
 * correct on white and catastrophic on the brand field: it is what made the
 * Roster / Statistics / Latest News titles invisible. */
/* All six *-page-header blocks paint the brand field as their background, so the
 * suffix selector is safe here and picks up any future page for free. */
[class$="-page-header"] h1,
[class$="-page-header"] h2,
.page-header h1,
.site-footer .footer-heading {
    color: var(--on-primary, #ffffff);
}

/* fan-guide.css styles these headers as `color: white` but never sets a
 * background, so they inherited the light `thead th` fill from bundle-core and
 * rendered white-on-#f4f6f8 (1.08:1 — invisible). Restore the dark header the
 * white text was written for. */
.data-table thead th {
    background-color: var(--bg-dark, #0038A8);
    color: var(--on-primary, #ffffff);
}

/* Only above 1024px does the nav sit on the brand field. At or below, it collapses
 * into a WHITE drawer — where white text is invisible and the accent at full
 * strength is already 6.7:1. Measured, not assumed: the flip is at exactly
 * 1024/1025px. Scoping this cost me a self-inflicted white-on-white regression. */
@media (min-width: 1025px) {
    .site-header .nav-link.active {
        color: var(--on-primary, #ffffff) !important;
        /* Inset rather than a border so marking the active tab costs no layout. The
         * accent TINT is used because the accent at full strength on the brand
         * field is 1.75:1 — invisible as an indicator, not just as text. */
        box-shadow: inset 0 -3px 0 var(--accent-on-primary, #ffffff);
    }
}

@media (max-width: 1024px) {
    .site-header .nav-link.active {
        color: var(--brand-gold-900) !important;
    }
}

/* Secondary/supporting text on the field. --muted-on-primary is the darkest
 * step of the primary ramp that still clears 4.5:1 against the field itself. */
.site-footer small,
.site-footer .footer-text,
.site-footer .footer-bottom p,
.quick-stats-bar .label,
.hero-card .hero-card-meta {
    color: var(--muted-on-primary, #d1dcf0);
}

/* The stat strip's values are held by an `!important` rule that also carries the
 * five ID selectors, so matching the class alone loses on specificity. This is the
 * one place worth restating them. The strip is painted with a gradient, which is
 * why a contrast audit cannot see it — it has to be checked by eye. */
.quick-stats-bar .value,
#quick-record,
#quick-points,
#quick-division,
#quick-conference,
#quick-league {
    color: var(--on-primary, #ffffff) !important;
}

/* ── panels painted with a brand GRADIENT ────────────────────────────────────
 * These were invisible to the first audit pass: the checker resolved a flat
 * background-color but bailed on gradients, so every one of these panels was
 * skipped rather than measured, and the page reported clean. They are the same
 * accent-on-field mistake as everywhere else, just on a gradient fill.
 *
 * Scoped to .fan-guide-page because a bare `.stat-card` also exists on /stats
 * over a light surface, where forcing white text would repeat the white-on-white
 * mistake this file already made once. */
.fan-guide-page :is(.dark-card, .closing-cta, .stat-card, .retired-number-banner),
.fan-guide-page :is(.dark-card, .closing-cta, .stat-card, .retired-number-banner) :is(h1,h2,h3,h4,h5,p,li,span,strong,em,a,div),
.legend-card-header,
.legend-card-header :is(h1,h2,h3,h4,p,span,div),
.starting-banner-inner,
.starting-banner-inner :is(div,span,strong),
.countdown-timer :is(div,span),
.blog-card.featured .read-more-link {
    color: var(--on-primary, #ffffff);
}

/* …and the one panel filled with the ACCENT rather than the field. For a team
 * whose secondary is light this resolves back to dark-on-light, unchanged. */
.fan-guide-page .timeline-box,
.fan-guide-page .timeline-box :is(h1,h2,h3,h4,p,li,span,strong,em,a) {
    color: var(--on-secondary, #ffffff);
}

/* fan-guide.css fades this panel from the accent into `--brand-amber` (#f5a623), a
 * fixed orange chosen to sit beside predsfan's gold. Against a red accent it is
 * both off-palette and unreadable — no single text colour clears AA across a
 * red-to-orange sweep. Keeping both stops inside the team's own accent ramp makes
 * the panel legible end to end (4.9:1 at the light stop) and on-brand for any team. */
.fan-guide-page .timeline-box {
    background: linear-gradient(135deg, var(--brand-gold-900) 0%, var(--brand-gold-800) 100%);
}

/* live.css pins this to the raw accent; on the navy countdown panel that is 1.75:1. */
.countdown-timer .time-unit .value,
.countdown-timer .time-unit .label {
    color: var(--on-primary, #ffffff);
}

/* The stat strip is a navy-900 → navy-700 gradient, so a role computed against
 * navy-900 alone lands at 3.2:1 on the light end. Judge muted text on a gradient
 * by its lightest stop, not its darkest. */
.quick-stats-bar .label {
    color: var(--brand-navy-50, #f3f5fb);
}

/* ── text ON the accent fill ─────────────────────────────────────────────────
 * `.btn, button:not(.unstyled)` paints every button with the accent and then
 * sets the brand field colour as its text — the single rule behind most of the
 * failures. White on Rangers red is 6.7:1. */
.btn,
button:not(.unstyled),
.skip-to-main,
.skip-to-content,
.skip-link,
.load-more-btn,
.load-more-btn .remaining-count,
.footer-subscribe-btn,
.add-to-calendar-btn,
.add-to-calendar-btn span,
.view-toggle-btn.active,
.view-toggle-btn.active span,
.article-source-badge,
.story-overlay span,
.small-hero-card .overlay span,
.featured-hero-card .story-overlay span,
.starting-banner-label,
.game-status-badge .status-text,
.legend-card-header .number,
.row-matchup .location-indicator.home {
    color: var(--on-secondary, #ffffff);
}

/* Mobile-only surfaces. The narrow layouts swap in their own components, so these
 * never appear in a desktop pass — they were found by auditing at 390px.
 *
 * Only the FIRST cell of the highlighted row gets the brand field as its
 * background (the rest of the row is a pale tint), so this has to match that
 * selector exactly. Colouring the whole row white put white text on the pale
 * tint for the team name — the same mistake, one row over. */
@media (max-width: 480px) {
    .standings-mini-table tbody tr.predators-row td:first-child,
    .standings-mini-table tbody tr.predators-row:hover td:first-child {
        color: var(--on-primary, #ffffff);
    }
}

.mobile-position-header .mobile-position-count,
.mobile-stats-toggle .toggle-btn {
    color: var(--neutral-700, #445566);
}

/* #ef4444 is 3.76:1 on white — fine as a fill behind white text, short of AA as
 * text itself. #dc2626 clears both. */
.perf-value.negative,
.stat-change.negative,
.trend-down {
    color: #dc2626;
}

/* ── filter chips ────────────────────────────────────────────────────────────
 * With every button painted brand-red by the rule above, the active state had
 * nothing left to signal with — and a wall of saturated chips is most of why
 * these pages read as loud. Inactive chips become chrome; the accent fill is
 * reserved for the one that is actually on. */
.filter-tab,
.filter-controls .filter-btn,
.position-filter-tabs .filter-tab,
.blog-filter-tabs .filter-tab,
.highlights-filters .filter-btn {
    background-color: var(--neutral-100, #f4f6f8);
    color: var(--neutral-800, #2d3748);
    border: 1px solid var(--neutral-300, #d1d9e2);
}

.filter-tab .tab-count,
.blog-filter-tabs .filter-tab .tab-count,
.highlights-filters .filter-btn .filter-count {
    color: var(--neutral-700, #445566);
}

.filter-tab.active,
.filter-controls .filter-btn.active,
.position-filter-tabs .filter-tab.active,
.blog-filter-tabs .filter-tab.active,
.highlights-filters .filter-btn.active {
    background-color: var(--brand-gold-900);
    border-color: var(--brand-gold-900);
    color: var(--on-secondary, #ffffff);
}

.filter-tab.active .tab-count,
.blog-filter-tabs .filter-tab.active .tab-count,
.highlights-filters .filter-btn.active .filter-count {
    color: var(--on-secondary, #ffffff);
}

/* Amber on its own pale amber surface is 3.07:1; one step down clears AA. */
.community-connection-status.reconnecting {
    color: #b45309;
}

/* ── muted text on light surfaces ────────────────────────────────────────────
 * Ramp steps 400/500 are legitimate border and divider colours; they were just
 * being used for body-adjacent text as well, at 2.0–3.3:1. These move to step
 * 600 (#5d6f86, 5.1:1) — the same family, one notch darker. */
.blog-card-reading-time,
.blog-card-meta time,
.popular-post-views,
.view-count,
.video-card .video-date,
.side-story .story-meta,
.mini-position,
.player-number-inline,
.sit-label,
.country-more,
.pagination-info,
.perf-rank {
    color: var(--neutral-600, #5d6f86);
}

/* Step 600 is measured against WHITE; these two sit on tinted chrome (#edeef0,
 * #f3f4f6) where it lands at 4.4:1. Step 700 keeps them clear of AA there. */
.player-search-wrapper .search-icon,
.view-toggle .view-toggle-btn,
.view-toggle .view-toggle-btn span {
    color: var(--neutral-700, #445566);
}

/* …but the active toggle sits on the accent fill, so it follows that role. */
.view-toggle .view-toggle-btn.active,
.view-toggle .view-toggle-btn.active span {
    color: var(--on-secondary, #ffffff);
}

/* ── success green ───────────────────────────────────────────────────────────
 * --success-500 is 2.5:1 on white as text AND 2.5:1 against white text as a
 * fill, so it failed in both roles. Step 700 (#047857) clears 4.5:1 either way. */
.schedule-game-card .home-indicator,
.context-diff.positive,
.stat-change.positive,
.trend-up {
    color: var(--success-700, #047857);
}

.streak-badge.win,
.badge-success {
    background-color: var(--success-700, #047857);
    color: #ffffff;
}
