/* ============================================================================
   athlete/css/theme.css — static CSS counterpart to athlete/modules/theme.js.
   Owns three concerns that used to be runtime-injected via createElement/
   appendChild from theme.js:

     1. Team-branded surfaces (.stat-block / .gbg-row / .am-row.active accent)
     2. Motion polish + athlete-menu positioning (.athlete-menu, press states,
        @keyframes for live pulse + image fade-in, prefers-reduced-motion)
     3. View transitions (@view-transition + per-direction slide animations)

   Cascade contract: loaded AFTER each page's CSS + athlete-switcher.css on
   every athlete page. Loading position alone guarantees this stylesheet wins
   over page-specific .athlete-menu rules -- NO !important required. Previous
   version (in theme.js) needed 14 !important declarations to fight per-page
   .athlete-menu drift; killing the JS injection + leveraging cascade order
   is the same enterprise fix that was applied to athlete-switcher in v284.

   What does NOT live here:
     - First-paint theme attribute stamping (stays in theme.js -- has to
       read localStorage, which CSS can't do)
     - swapLogosForTheme runtime listener (theme.js, JS-only concern)
     - SCv2.setTheme / SCv2.getTheme / SCv2.applyTeamTheme (theme.js, JS)

   Visual parity vs the previous JS-injected rules: byte-equivalent minus
   the !important keyword. Reviewed May 20 2026 alongside the athlete-switcher
   tokenize PR.
   ========================================================================== */

/* ─── 1. Team-branded surfaces ────────────────────────────────────────────── */

/* Season Stats card headers -- were a flat white-to-grey gradient. Now use the
   team's gradient so each card feels "Raiders" or "Chiefs" branded. White
   text on the gradient reads in both themes. */
.stat-block-header {
    background: linear-gradient(135deg, var(--team-primary, #1d4ed8), var(--team-secondary, #f59e0b));
    border-bottom: 0;
}
.stat-block-title {
    color: #ffffff;
}
.stat-block-games {
    color: rgba(255, 255, 255, 0.85);
}

/* Stat block container -- subtle team-color accent on the left edge. */
.stat-block {
    position: relative;
}
.stat-block::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--team-primary, #1d4ed8), var(--team-secondary, #f59e0b));
    pointer-events: none;
    z-index: 1;
}

/* "Game by Game" rows -- left accent bar in team color. */
.gbg-row {
    position: relative;
    border-left: 3px solid color-mix(in srgb, var(--team-primary, #1d4ed8) 60%, transparent);
}

/* Athlete-menu rows -- active row gets a stronger team-color accent. */
.am-row.active {
    box-shadow: inset 3px 0 0 var(--team-primary, #1d4ed8);
}

/* ─── 2. Motion polish + athlete-menu positioning ─────────────────────────── */

/* Athlete-switcher dropdown menu -- UNIFIED positioning + fade entrance.
   Page-specific CSS used to anchor the menu differently (home/mykid centered
   with translateX(-50%), settings anchored left:0). On narrow phones the
   centered approach pulled the menu half off-screen because the button sits
   near the left edge. One anchor -- straight down from the button's left
   edge, capped at viewport width -- gives every page the same drop. */
.athlete-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: auto;
    transform: none;
    min-width: 260px;
    max-width: calc(100vw - 24px);
    z-index: 80;
    transition: opacity 0.18s ease;
}
.athlete-menu:not(.open) {
    display: block;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}
.athlete-menu.open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* Brief click-through guard: when the dropdown opens, the SAME finger tap
   can register a second click on whichever row appears under it. 250ms of
   pointer-events:none on the open menu makes that fall-through impossible
   -- the tap ends on the button, the user lifts their finger, and the menu
   becomes interactive on the NEXT tap. */
.athlete-menu.just-opened {
    pointer-events: none;
}

/* Ensure the parent of the menu is a positioning context so the absolute
   menu doesn't escape to <html>. .app-header-brand is the common shell. */
.app-header-brand {
    position: relative;
}

/* Tactile press feel on tappable cards -- iOS-grade */
.game-card,
.thread,
.gbg-row,
.athlete-card,
.settings-row {
    transition: transform 0.10s ease, background 0.15s ease, opacity 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.game-card:active,
.thread:active,
.gbg-row:active,
.athlete-card:active {
    transform: scale(0.985);
}

/* LIVE hero pulse -- for games in_progress. Catches the eye without flashing. */
.hero-card[data-state="live"] .hero-eyebrow,
.hero-card[data-state="live"] .gs-vs-badge {
    animation: sc-live-pulse 1.8s ease-in-out infinite;
}
@keyframes sc-live-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.7; }
}

/* Image loading -- fade-in real photos instead of pop-in (avatars, team logos). */
.athlete-card-logo img,
.nm-avatar img,
.am-logo img,
.athlete-switcher-dot img,
.msg-avatar img,
.gs-team-logo-placeholder img {
    animation: sc-img-fade-in 0.32s ease;
}
@keyframes sc-img-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Subtle hover lift on the New Message + Add Athlete CTAs (trackpad/mouse). */
.new-msg-btn,
.nm-group-btn,
.nm-row {
    transition: transform 0.10s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.new-msg-btn:active {
    transform: scale(0.96);
}

@media (prefers-reduced-motion: reduce) {
    .athlete-menu {
        transition: none;
    }
    .hero-card[data-state="live"] .hero-eyebrow,
    .hero-card[data-state="live"] .gs-vs-badge {
        animation: none;
    }
    .athlete-card-logo img,
    .nm-avatar img,
    .am-logo img,
    .athlete-switcher-dot img,
    .msg-avatar img,
    .gs-team-logo-placeholder img {
        animation: none;
    }
}

/* ─── 3. View transitions (SPA-style navigation) ──────────────────────────── */

@view-transition {
    navigation: auto;
}

/* iOS-style directional slide between tabs. The direction is set on <body>
   right before startViewTransition fires: sc-nav-forward (moving rightward
   in tab order) or sc-nav-back (moving leftward). The default (no class)
   falls back to a gentle fade. */
@keyframes sc-slide-in-right  { from { transform: translateX(100%);  opacity: 0.6; } to { transform: translateX(0); opacity: 1; } }
@keyframes sc-slide-out-left  { from { transform: translateX(0); opacity: 1; } to { transform: translateX(-30%); opacity: 0; } }
@keyframes sc-slide-in-left   { from { transform: translateX(-100%); opacity: 0.6; } to { transform: translateX(0); opacity: 1; } }
@keyframes sc-slide-out-right { from { transform: translateX(0); opacity: 1; } to { transform: translateX(30%); opacity: 0; } }
@keyframes sc-vt-fade-in      { from { opacity: 0; } to { opacity: 1; } }
@keyframes sc-vt-fade-out     { from { opacity: 1; } to { opacity: 0; } }

/* Default (no direction class) -- gentle fade. Covers back/forward history
   navigations + the very first router transition. */
::view-transition-old(root) { animation: sc-vt-fade-out 160ms ease forwards; }
::view-transition-new(root) { animation: sc-vt-fade-in  220ms ease forwards; }

/* Forward = new page enters from the right, old exits to the left. */
body.sc-nav-forward::view-transition-old(root) { animation: sc-slide-out-left 280ms cubic-bezier(0.32, 0.72, 0.32, 1) forwards; }
body.sc-nav-forward::view-transition-new(root) { animation: sc-slide-in-right 320ms cubic-bezier(0.32, 0.72, 0.32, 1) forwards; }

/* Back = new page enters from the left, old exits to the right. */
body.sc-nav-back::view-transition-old(root) { animation: sc-slide-out-right 280ms cubic-bezier(0.32, 0.72, 0.32, 1) forwards; }
body.sc-nav-back::view-transition-new(root) { animation: sc-slide-in-left   320ms cubic-bezier(0.32, 0.72, 0.32, 1) forwards; }

/* Persistent across navigations -- the app-header DOESN'T animate, the
   browser morphs it between snapshots. We INTENTIONALLY do NOT set
   view-transition-name on .bottom-nav: combining it with the nav's
   backdrop-filter broke position:fixed on iOS Safari / some Chrome builds
   (the implicit containing-block created by view-transition-name fought
   with backdrop-filter's own CB), so the nav scrolled with the page.
   Letting the nav cross-fade during the slide is a small visual trade for
   the stickiness win. */
.app-header {
    view-transition-name: sc-app-header;
}

/* Reduced-motion: drop the slide, keep the fade. */
@media (prefers-reduced-motion: reduce) {
    body.sc-nav-forward::view-transition-old(root),
    body.sc-nav-back::view-transition-old(root) { animation: sc-vt-fade-out 160ms ease forwards; }
    body.sc-nav-forward::view-transition-new(root),
    body.sc-nav-back::view-transition-new(root) { animation: sc-vt-fade-in 220ms ease forwards; }
}
