/* =========================================================
   Tokens
   ========================================================= */
:root {
  color-scheme: light dark;

  /* Brand */
  --fpl-purple-900: #17012B;
  --fpl-purple-800: #37003C;
  --fpl-purple-700: #4A0F53;
  --fpl-lime:       #00FF87;
  --fpl-cyan:       #04F5FF;
  --fpl-pink:       #E90052;

  /* Surfaces (light) */
  --surface-0: #FFFFFF;
  --surface-1: #F7F5F9;
  --surface-2: #EFECF2;
  --border: #D9D2E1;
  --border-strong: #BBAFC8;

  /* Ink (light) */
  --ink-900: #16121B;
  --ink-700: #4A4356;
  --ink-500: #736C80;
  --ink-on-dark: #F4F1F7;

  /* Semantic (text-safe, WCAG AA on white) */
  --buy-text:  #046A38; --buy-bg:  #E8FFF4; --buy-edge:  #00C46A;
  --sell-text: #A8003C; --sell-bg: #FFEDF2; --sell-edge: #E90052;
  --warn-text: #8A5300; --warn-bg: #FFF6E5; --warn-edge: #E08700;
  --info-text: #0B5A7A; --info-bg: #E8F6FB; --info-edge: #0E86B5;

  /* Rank History chart (light) - deliberately reuses the app's own accent
     colors (the tab-underline purple, the info/warn edges) rather than an
     independent palette, so the chart reads as the same component family
     as the rest of the page. */
  --chart-line: var(--fpl-purple-800);
  --chart-line-fill: rgba(55, 0, 60, 0.10);
  --chart-ma: var(--info-edge);
  --chart-grid: rgba(217, 210, 225, 0.65);
  --chart-axis: var(--ink-500);
  --chart-chip-marker: var(--warn-edge);
  --chart-tooltip-bg: var(--surface-0);
  --chart-tooltip-border: var(--border-strong);

  /* Spacing */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs:  0.75rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;

  /* Radius / shadow */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --shadow-sm: 0 1px 4px rgba(23, 1, 43, 0.12), 0 1px 2px rgba(23, 1, 43, 0.06);
  --shadow-md: 0 6px 20px rgba(23, 1, 43, 0.14);
  --shadow-lg: 0 16px 40px rgba(23, 1, 43, 0.16);

  /* Motion */
  --ease: cubic-bezier(.2, .7, .3, 1);
  --dur-fast: 140ms;
  --dur-med: 220ms;

  /* Type scale (fluid) */
  --step--1: clamp(0.80rem, 0.78rem + 0.10vw, 0.86rem);
  --step-0:  clamp(0.94rem, 0.91rem + 0.15vw, 1.00rem);
  --step-1:  clamp(1.13rem, 1.05rem + 0.35vw, 1.31rem);
  --step-2:  clamp(1.35rem, 1.20rem + 0.70vw, 1.75rem);
  --step-3:  clamp(1.62rem, 1.35rem + 1.30vw, 2.40rem);

  /* App-level aliases (used throughout) */
  --bg: var(--surface-1);
  --surface: var(--surface-0);
  --surface-alt: var(--surface-2);
  /* Popup/sheet background - deliberately same as --surface in light mode
     (already pure white, can't go lighter; shadow/backdrop carry elevation
     there) but a step lighter than --surface in dark mode, where cards and
     sheets would otherwise share the identical near-black tone. */
  --sheet-bg: var(--surface);
  --text: var(--ink-900);
  --text-secondary: var(--ink-700);
  --text-muted: var(--ink-500);
  --header-h: 64px;

  scroll-padding-top: calc(var(--header-h) + var(--space-sm));
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: var(--fpl-purple-900);
    --surface: #241238;
    --surface-alt: #2E1745;
    --sheet-bg: var(--surface-alt);
    --border: #3D2456;
    --border-strong: #4C2E68;
    --text: var(--ink-on-dark);
    --text-secondary: #CFC5DC;
    --text-muted: #9A8FAC;

    /* Light-mode pastel bg/text (e.g. --buy-bg:#E8FFF4 + --buy-text:#046A38) reads as a
       stark white patch on this near-black bg - swap to tinted-transparent bg over
       brand-accent text so chips/swap-cards on the Transfers tab sit in the theme. */
    --buy-text:  var(--fpl-lime);
    --buy-bg:    rgba(0, 255, 135, 0.12);
    --buy-edge:  var(--fpl-lime);
    --sell-text: #FF6699;
    --sell-bg:   rgba(233, 0, 82, 0.18);
    --sell-edge: var(--fpl-pink);
    --warn-text: #FFC777;
    --warn-bg:   rgba(224, 135, 0, 0.18);
    --warn-edge: #E08700;
    --info-text: var(--fpl-cyan);
    --info-bg:   rgba(4, 245, 255, 0.12);
    --info-edge: var(--fpl-cyan);

    --chart-line: var(--fpl-cyan);
    --chart-line-fill: rgba(4, 245, 255, 0.12);
    --chart-ma: var(--fpl-lime);
    --chart-grid: rgba(61, 36, 86, 0.85);
    --chart-axis: #9A8FAC;
    --chart-chip-marker: var(--warn-text);
    --chart-tooltip-bg: var(--sheet-bg);
    --chart-tooltip-border: var(--border-strong);
  }
}

:root[data-theme="dark"] {
  --bg: var(--fpl-purple-900);
  --surface: #241238;
  --surface-alt: #2E1745;
  --sheet-bg: var(--surface-alt);
  --border: #3D2456;
  --border-strong: #4C2E68;
  --text: var(--ink-on-dark);
  --text-secondary: #CFC5DC;
  --text-muted: #9A8FAC;

  --buy-text:  var(--fpl-lime);
  --buy-bg:    rgba(0, 255, 135, 0.12);
  --buy-edge:  var(--fpl-lime);
  --sell-text: #FF6699;
  --sell-bg:   rgba(233, 0, 82, 0.18);
  --sell-edge: var(--fpl-pink);
  --warn-text: #FFC777;
  --warn-bg:   rgba(224, 135, 0, 0.18);
  --warn-edge: #E08700;
  --info-text: var(--fpl-cyan);
  --info-bg:   rgba(4, 245, 255, 0.12);
  --info-edge: var(--fpl-cyan);

  --chart-line: var(--fpl-cyan);
  --chart-line-fill: rgba(4, 245, 255, 0.12);
  --chart-ma: var(--fpl-lime);
  --chart-grid: rgba(61, 36, 86, 0.85);
  --chart-axis: #9A8FAC;
  --chart-chip-marker: var(--warn-text);
  --chart-tooltip-bg: var(--sheet-bg);
  --chart-tooltip-border: var(--border-strong);
}

/* =========================================================
   Reset
   ========================================================= */
*, *::before, *::after { box-sizing: border-box; }
/* overflow-y explicit, not left to default: per spec, setting only one axis to
   a non-visible value forces the other to compute as auto, silently turning
   html into its own scroll container - a known trigger for position:sticky
   descendants (e.g. .team-bar) breaking and just scrolling away instead of
   pinning, mainly in Safari. */
html { overflow-x: clip; overflow-y: visible; }
/* Any class rule that sets `display` on an element beats the UA [hidden]{display:none}
   rule on a specificity tie (author origin always wins ties over UA origin) - so
   toggling the `hidden` DOM property silently does nothing on such elements unless
   this is forced back to the top of the cascade. */
[hidden] { display: none !important; }
body {
  margin: 0;
  min-height: 100svh;
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: var(--step-0);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img, svg { max-width: 100%; display: block; }
button, input { font: inherit; color: inherit; }

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

/* =========================================================
   Typography
   ========================================================= */
h1, h2, h3, h4 { margin: 0 0 var(--space-2xs); line-height: 1.2; font-weight: 700; }
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }
h4 { font-size: var(--step-0); font-weight: 600; color: var(--text-secondary); }
p { margin: 0 0 var(--space-sm); color: var(--text-secondary); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
a { color: var(--fpl-purple-800); text-decoration: none; }
:root[data-theme="dark"] a { color: var(--fpl-cyan); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) a { color: var(--fpl-cyan); } }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 3px solid var(--fpl-purple-700);
  outline-offset: 2px;
  border-radius: 2px;
}
:root[data-theme="dark"] :focus-visible { outline-color: var(--fpl-cyan); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) :focus-visible { outline-color: var(--fpl-cyan); } }

.skip-link {
  position: fixed; top: -100%; left: var(--space-sm); z-index: 2000;
  background: var(--fpl-purple-800); color: #fff; padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm);
}
.skip-link:focus { top: var(--space-sm); }

/* =========================================================
   Shell: header / footer
   ========================================================= */
.site-header {
  position: sticky; top: 0; z-index: 1000;
  background: color-mix(in srgb, var(--fpl-purple-800) 92%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-med) var(--ease);
}
.site-header__inner {
  max-width: 1200px; margin: 0 auto; padding: 0 var(--space-md);
  height: var(--header-h);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm);
}
.brand { display: flex; align-items: center; gap: var(--space-2xs); color: #fff; min-width: 0; }
.brand:hover { text-decoration: none; }
.brand__mark {
  flex-shrink: 0;
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--fpl-lime); color: var(--fpl-purple-900);
  font-weight: 800; font-size: 0.95rem;
}
.brand__text {
  font-weight: 700; font-size: var(--step-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.brand__accent { color: var(--fpl-lime); }
.site-header__actions { display: flex; align-items: center; gap: var(--space-2xs); flex-shrink: 0; }
.site-header .btn--ghost {
  color: #fff; border-color: rgba(255,255,255,0.35);
}
.site-header .btn--ghost:hover { background: rgba(255,255,255,0.12); }
.theme-toggle {
  background: transparent; border: 1px solid rgba(255,255,255,0.25); color: #fff;
  border-radius: var(--radius-sm); width: 36px; height: 36px; cursor: pointer;
  flex-shrink: 0;
}
.theme-toggle:hover { background: rgba(255,255,255,0.1); }

.site-footer {
  max-width: 1200px; margin: var(--space-xl) auto 0; padding: var(--space-md);
  color: var(--text-muted); font-size: var(--step--1); text-align: center;
}
.site-footer a { color: var(--text-muted); margin-left: var(--space-3xs); }

.page { max-width: 1200px; margin: 0 auto; padding: 0 var(--space-md) var(--space-xl); }

/* =========================================================
   Buttons / form controls
   ========================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-3xs);
  padding: 0.65em 1.1em; border-radius: var(--radius-md); border: 1px solid transparent;
  font-weight: 600; font-size: var(--step-0); cursor: pointer;
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn--primary { background: var(--fpl-purple-800); color: #fff; box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: var(--fpl-purple-700); }
.btn--ghost { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn--ghost:hover { background: var(--surface-alt); text-decoration: none; }

.field label, label {
  display: block; font-weight: 500; font-size: var(--step--1);
  color: var(--text-secondary); margin-bottom: var(--space-3xs);
}
input[type="search"], input[type="text"] {
  width: 100%; font-size: max(1rem, 16px); padding: 0.75em 1em;
  border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text);
}
input[type="search"]::-webkit-search-cancel-button { display: none; }

/* =========================================================
   Layout primitives
   ========================================================= */
.section { margin: var(--space-xl) 0; }
.section__title {
  border-bottom: 1px solid var(--border); padding-bottom: var(--space-2xs);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm);
}
.section__toggle {
  width: 32px; height: 32px; padding: 0; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.1rem; line-height: 1; border-radius: var(--radius-sm);
}
.section__body { margin-top: var(--space-xs); }
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: var(--space-md);
}
.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-2xs); }

/* =========================================================
   Hero (homepage)
   ========================================================= */
.hero {
  position: relative; overflow: hidden; border-radius: var(--radius-lg);
  margin-top: var(--space-lg);
  padding: var(--space-xl) var(--space-md);
  background:
    radial-gradient(circle at 85% 15%, rgba(4, 245, 255, 0.12) 0%, transparent 45%),
    radial-gradient(circle at 15% 85%, rgba(0, 255, 135, 0.15) 0%, transparent 50%),
    linear-gradient(135deg, var(--fpl-purple-800) 0%, var(--fpl-purple-900) 100%);
  color: #fff; text-align: center;
  box-shadow: 0 12px 32px -8px rgba(37, 8, 58, 0.5), inset 0 1px 0 0 rgba(255, 255, 255, 0.1);
}
/* Brand-gradient top edge - agy's suggestion for a sleeker finish, per
   user's "looks good, make it ~20% better" ask. */
.hero::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, var(--fpl-lime), var(--fpl-cyan), var(--fpl-pink));
  opacity: 0.85;
}
.hero__pitch {
  position: absolute; inset: 0; opacity: 0.22; pointer-events: none;
  background:
    repeating-linear-gradient(135deg, transparent 0 35px, rgba(255,255,255,0.03) 35px 70px),
    repeating-linear-gradient(0deg, transparent 0 40px, rgba(255,255,255,0.06) 40px 41px),
    radial-gradient(circle at 50% 100%, rgba(0,255,135,0.3), transparent 65%);
}
.hero__inner { position: relative; max-width: 640px; margin: 0 auto; }
.hero h1 {
  color: #fff;
  background: linear-gradient(180deg, #FFFFFF 30%, var(--fpl-lime) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  text-shadow: 0 2px 20px rgba(0, 255, 135, 0.25);
  letter-spacing: -0.02em;
}
.hero__subhead {
  color: rgba(244,241,247,0.88); font-size: 1.125rem; line-height: 1.6;
  max-width: 540px; margin-left: auto; margin-right: auto;
}
@supports (text-wrap: balance) {
  .hero h1, .hero__subhead { text-wrap: balance; }
}

.search-field {
  position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2xs);
  background: var(--surface-0); border-radius: var(--radius-md); padding: var(--space-2xs);
  box-shadow: var(--shadow-md);
  /* This pill is a fixed white surface regardless of app theme (matches the
     .hero it sits on, which is always the dark-purple brand gradient) - stop
     the browser's own dark-mode auto-theming of native form-control chrome
     (:root sets color-scheme:light dark) from fighting that on OS/browser
     dark mode, where it was rendering the <input> with a dark native
     background under our still-dark --ink-900 text (illegible). */
  color-scheme: light;
}
.search-field__icon { padding-left: var(--space-2xs); color: var(--ink-500); }
.search-field input {
  flex: 1 1 12rem; border: none; padding: 0.6em 0.4em; color: var(--ink-900);
  background: var(--surface-0);
}
.search-field input:focus { outline: none; }
.search-field__clear {
  border: none; background: transparent; color: var(--ink-500); cursor: pointer; font-size: 1rem;
  padding: 0 var(--space-2xs); min-width: 44px; min-height: 44px;
}
.search-field__submit { flex: 0 0 auto; }

/* =========================================================
   Status / empty / error / skeleton
   ========================================================= */
.empty-state {
  text-align: center; padding: var(--space-lg); color: var(--text-muted);
}
.empty-state__hint { font-size: var(--step--1); }
.search-status[data-variant="error"] {
  background: var(--sell-bg); color: var(--sell-text); border-radius: var(--radius-md);
  padding: var(--space-sm); display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm);
}
.result-count { color: var(--text-muted); font-size: var(--step--1); margin-bottom: var(--space-2xs); }

.skeleton-row {
  height: 2.5rem; border-radius: var(--radius-sm); margin-bottom: var(--space-2xs);
  background: linear-gradient(90deg, var(--surface-alt) 25%, var(--surface) 37%, var(--surface-alt) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* =========================================================
   Explainer cards
   ========================================================= */
.explainer__grid { display: grid; gap: var(--space-md); grid-template-columns: repeat(3, 1fr); }
.explainer__card h3 { color: var(--fpl-purple-800); }
:root[data-theme="dark"] .explainer__card h3 { color: var(--fpl-cyan); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .explainer__card h3 { color: var(--fpl-cyan); } }

/* =========================================================
   Chips (signal states)
   ========================================================= */
.chip {
  display: inline-flex; align-items: center; gap: 0.35em;
  padding: 0.2em 0.65em; border-radius: 999px; font-size: var(--step--1); font-weight: 600;
  white-space: nowrap;
}
.chip--buy       { background: var(--buy-bg);  color: var(--buy-text); }
.chip--buy-muted { background: var(--buy-bg);  color: var(--buy-text); opacity: 0.75; }
.chip--sell      { background: var(--sell-bg); color: var(--sell-text); }
.chip--warn      { background: var(--warn-bg); color: var(--warn-text); }
.chip--neutral   { background: var(--surface-alt); color: var(--text-secondary); }
.chip--info      { background: var(--info-bg); color: var(--info-text); }
.recent-chip {
  display: inline-flex; flex-direction: column; padding: var(--space-2xs) var(--space-sm);
  border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface);
}
.recent-chip small { color: var(--text-muted); }

/* =========================================================
   Team bar (transfers page)
   ========================================================= */
.team-bar {
  position: sticky; top: var(--header-h); z-index: 900;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-sm);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--space-sm) var(--space-md); margin-top: var(--space-md);
  box-shadow: var(--shadow-sm);
}
.team-bar__team { margin: 0; font-size: var(--step-2); }
.team-bar__manager { margin: 0; color: var(--text-muted); }
.team-bar__identity { min-width: 0; }
.team-bar__kpis { display: flex; flex-wrap: wrap; gap: var(--space-sm); min-width: 0; }
.kpi { text-align: center; min-width: 4.5rem; }
.kpi__value { display: block; font-size: var(--step-1); font-weight: 700; }
.kpi__label { display: block; font-size: var(--step--1); color: var(--text-muted); }

/* =========================================================
   Tabs / segmented controls
   ========================================================= */
.tabs { margin-top: var(--space-lg); }
.tabs__list {
  display: flex; gap: var(--space-2xs); overflow-x: auto; scroll-snap-type: x proximity;
  border-bottom: 1px solid var(--border); margin-bottom: var(--space-md);
  /* scroll-padding-inline-end shifts where a snap point settles, not just
     scroll extent - a snapped tab now stops with ~2.25rem of the next tab
     still peeking past the edge instead of flush, so "there's more" is
     visible even before the mask-image fade above kicks in. Works
     regardless of tab count/label length (unlike a fixed per-tab width),
     since it's a snap-stop offset, not a size constraint on the tabs
     themselves. */
  scroll-padding-inline-end: 2.25rem;
}
/* Edge-fade "more tabs offscreen" hint - mask-image fades content to
   transparent rather than overlaying a solid/gradient color, so it works
   unchanged against any --surface value in either theme (see fplApp.initTabs
   in app.js for the scroll-position toggle driving these classes). */
.tabs__list.has-scroll-right {
  -webkit-mask-image: linear-gradient(to right, black 88%, transparent 100%);
  mask-image: linear-gradient(to right, black 88%, transparent 100%);
}
.tabs__list.has-scroll-left {
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 12%);
  mask-image: linear-gradient(to right, transparent 0%, black 12%);
}
.tabs__list.has-scroll-left.has-scroll-right {
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 12%, black 88%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 12%, black 88%, transparent 100%);
}
.tabs__tab {
  scroll-snap-align: start; background: transparent; border: none; cursor: pointer;
  padding: var(--space-sm) var(--space-sm); font-weight: 600; color: var(--text-muted);
  border-bottom: 4px solid transparent; white-space: nowrap; border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.tabs__tab[aria-selected="true"] {
  color: var(--fpl-purple-800); border-bottom-color: var(--fpl-purple-800); background: var(--surface-alt);
}
:root[data-theme="dark"] .tabs__tab[aria-selected="true"] { color: var(--fpl-cyan); border-bottom-color: var(--fpl-cyan); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .tabs__tab[aria-selected="true"] { color: var(--fpl-cyan); border-bottom-color: var(--fpl-cyan); } }

.segmented {
  display: inline-flex; gap: 2px; padding: 3px; background: var(--surface-alt);
  border-radius: var(--radius-md); margin-bottom: var(--space-md); flex-wrap: wrap;
}
.segmented__option {
  background: transparent; border: none; cursor: pointer; padding: 0.5em 0.9em;
  border-radius: calc(var(--radius-md) - 3px); font-weight: 600; color: var(--text-secondary);
  display: inline-flex; align-items: center; gap: 0.4em;
}
.segmented__option[aria-selected="true"] { background: var(--surface); box-shadow: var(--shadow-sm); color: var(--text); }
.segmented__count {
  font-size: var(--step--1); background: var(--surface-alt); border-radius: 999px; padding: 0 0.5em;
  flex-shrink: 0; white-space: nowrap;
}
.segmented__option[aria-selected="true"] .segmented__count { background: var(--border); }

/* =========================================================
   Options tab
   ========================================================= */
.options-group__columns { display: grid; gap: var(--space-md); grid-template-columns: 1fr 1fr; }
.options-group__label { margin-bottom: var(--space-2xs); }
.options-group__label--sell { color: var(--sell-text); }
.options-group__label--buy { color: var(--buy-text); }

/* =========================================================
   Swap compare sheet (Transfers tab)
   ========================================================= */
.compare-heads {
  display: grid; grid-template-columns: 1fr minmax(48px, auto) 1fr;
  align-items: start; gap: var(--space-2xs); margin-bottom: var(--space-sm);
}
.compare-heads__vs { text-align: center; color: var(--text-muted); font-size: var(--step--1); font-weight: 700; align-self: center; }
.compare-heads__side--sell { text-align: right; }
.compare-heads__side--buy { text-align: left; }
.compare-heads__tag { font-size: var(--step--1); margin-bottom: var(--space-3xs); }
.compare-heads__name {
  font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.compare-heads__meta { font-size: var(--step--1); color: var(--text-muted); margin-top: var(--space-3xs); }
.compare-heads__badges { margin-top: var(--space-3xs); }

.compare-table { display: flex; flex-direction: column; margin: var(--space-sm) 0; }
.compare-table__row {
  display: grid; grid-template-columns: 1fr minmax(48px, auto) 1fr;
  align-items: center; gap: var(--space-2xs);
  padding: var(--space-2xs) 0; border-bottom: 1px solid var(--border);
}
.compare-table__row:last-child { border-bottom: none; }
.compare-table__label {
  font-size: var(--step--1); color: var(--text-muted); text-align: center; white-space: nowrap;
}
.compare-table__val { font-weight: 600; }
.compare-table__val--sell { text-align: right; }
.compare-table__val--buy { text-align: left; }
/* Only applied to rows where sell/buy are on the same scale (Value, xP,
   points, ownership%) - never on Rating, whose sell/buy NPV pools are
   calibrated on different bands (see SELL_RATING_BUCKETS in transfers.js),
   so a numeric "higher wins" comparison there would be meaningless. */
.compare-table__val--better { color: var(--buy-text); }

.compare-fixtures { margin-top: var(--space-sm); }
.compare-fixtures__title { text-align: center; }
.compare-fixtures__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-xs); }
.compare-fixtures__side--sell .chip-row { justify-content: flex-end; }
.compare-fixtures__side--buy .chip-row { justify-content: flex-start; }

/* =========================================================
   Squad / pitch
   ========================================================= */
.squad-view { display: flex; flex-direction: column; gap: var(--space-md); align-items: flex-start; }
.pitch {
  width: 100%; max-width: 50rem; margin-inline: auto;
  display: flex; flex-direction: column; gap: var(--space-sm);
  padding: var(--space-md); border-radius: var(--radius-lg);
  background:
    repeating-linear-gradient(0deg, #1f7a3f 0 40px, #1c7239 40px 80px);
  border: 2px solid rgba(255,255,255,0.6);
  box-shadow: var(--shadow-lg);
}
.pitch__row {
  display: flex; flex-direction: column; gap: var(--space-2xs);
}
.pitch__row-label {
  color: rgba(255,255,255,0.85); font-weight: 700; font-size: var(--step--1);
  text-transform: uppercase; letter-spacing: 0.04em; text-align: center;
}
.pitch__row-cards {
  display: flex; flex-wrap: nowrap; gap: var(--space-2xs); justify-content: center;
  overflow-x: auto; scroll-snap-type: x proximity; scroll-padding-inline: var(--space-sm);
}
.player-card {
  position: relative;
  flex: 1 1 0; min-width: max(4.25rem, min-content); max-width: 8.5rem;
  min-height: 5.5rem; background: rgba(255,255,255,0.94); border-radius: var(--radius-md);
  padding: var(--space-2xs); text-align: center; cursor: pointer; border: none;
  box-shadow: inset 4px 0 0 var(--border-strong), var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease);
  display: flex; flex-direction: column; justify-content: space-between; align-items: center;
  scroll-snap-align: center;
  /* Same fixed-white-on-dark-pitch design as .search-field above - opt this
     native <button> out of the browser's own dark-mode auto-theming too. */
  color-scheme: light;
}
.player-card:hover { transform: translateY(-2px); }
.player-card--buy       { box-shadow: inset 4px 0 0 var(--buy-edge), var(--shadow-sm); }
.player-card--buy-muted { box-shadow: inset 4px 0 0 var(--buy-edge), var(--shadow-sm); opacity: 0.85; }
.player-card--sell      { box-shadow: inset 4px 0 0 var(--sell-edge), var(--shadow-sm); }
.player-card--warn      { box-shadow: inset 4px 0 0 var(--warn-edge), var(--shadow-sm); }
.player-card--neutral   { box-shadow: inset 4px 0 0 var(--border-strong), var(--shadow-sm); }
/* Elite-divergence: signal disagrees with heavy elite-cohort ownership (see
   fplApp.isEliteDivergent) - layered on top of the existing sell/buy edge
   color (which keeps meaning "raw flow direction") rather than replacing it,
   so a glance under deadline pressure still reads sell-vs-buy at a glance,
   with the amber outline as a secondary "treat with caution" cue. */
.player-card--divergent { outline: 2px solid var(--warn-edge); outline-offset: 1px; }
.player-card__name {
  font-weight: 700; font-size: var(--step--1); color: var(--ink-900);
  overflow-wrap: normal; word-break: normal; max-width: 100%; line-height: 1.15;
}
.player-card__price { font-size: var(--step--1); color: var(--ink-500); }
.player-card__bar {
  width: 100%; height: 4px; border-radius: 4px; background: var(--border); margin: var(--space-3xs) 0; overflow: hidden;
}
.player-card__bar span { display: block; height: 100%; min-width: 4px; border-radius: 4px; background: var(--fpl-purple-800); }
.player-card__captain {
  position: absolute; top: 2px; right: 2px; width: 1.1rem; height: 1.1rem;
  border-radius: 50%; background: var(--fpl-purple-800); color: #fff;
  font-size: 0.6rem; font-weight: 700; line-height: 1.1rem; text-align: center;
}
.player-card__captain--vice { background: var(--ink-500); }
.pitch__row--bench {
  margin-top: var(--space-2xs); padding-top: var(--space-sm);
  border-top: 1px dashed rgba(255,255,255,0.4);
}
.pitch__row--bench .player-card { opacity: 0.85; }

.chip-status-grid { display: grid; gap: var(--space-sm); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.chip-status-card {
  background: var(--surface-alt); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: var(--space-sm);
  display: flex; flex-direction: column; gap: var(--space-3xs);
}
.chip-status-card__name { font-weight: 700; font-size: var(--step-0); color: var(--text); }
.chip-status-card__pct {
  font-size: var(--step-2); font-weight: 700; color: var(--text); line-height: 1;
  display: flex; align-items: baseline; gap: var(--space-2xs);
}
.chip-status-card__pct-label { font-size: var(--step--1); font-weight: 500; color: var(--text-muted); }
.chip-status-card__bar {
  width: 100%; height: 6px; border-radius: 4px; background: var(--border); overflow: hidden;
  margin: var(--space-3xs) 0;
}
.chip-status-card__bar span { display: block; height: 100%; min-width: 4px; border-radius: 4px; background: var(--fpl-purple-800); }
.chip-status-card__detail { font-size: var(--step--1); color: var(--text-muted); line-height: 1.35; }
.chip-status-card--locked { opacity: 0.7; }

/* =========================================================
   Dialog / sheet
   ========================================================= */
.sheet {
  border: none; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: var(--space-md);
  width: min(32rem, 100%); max-width: 100%; margin: auto auto 0;
  max-height: 85vh; overflow-y: auto; overscroll-behavior: contain;
  background: var(--sheet-bg); color: var(--text); box-shadow: var(--shadow-lg);
}
.sheet::backdrop { background: rgba(23, 1, 43, 0.45); }
.sheet__close {
  position: absolute; top: var(--space-sm); right: var(--space-sm); border: none; background: var(--surface-alt);
  width: 44px; height: 44px; border-radius: 50%; cursor: pointer;
}
#player-sheet-content { padding-right: 2.5rem; }
@media (min-width: 640px) {
  .sheet { border-radius: var(--radius-lg); margin: auto; }
}
.sheet-field { display: flex; justify-content: space-between; padding: var(--space-2xs) 0; border-bottom: 1px solid var(--border); }
.sheet-field:last-child { border-bottom: none; }

/* =========================================================
   GridJS adapter layer
   (element-qualified to match/beat the mermaid theme's specificity —
    styles.css loads after the mermaid stylesheet)
   ========================================================= */
/* mermaid.min.css (the gridjs CDN theme, loaded before this file) sets
   .gridjs-container{color:#000} with nothing here overriding it - fine on the
   light-mode white background it was designed for, illegible dark-on-dark once
   --text flips to a light color. */
.fpl-grid.gridjs-container { width: 100% !important; margin: 0; color: var(--text); }
.gridjs-wrapper {
  overflow: auto; overscroll-behavior-x: contain; border-radius: var(--radius-md);
  border: 1px solid color-mix(in srgb, var(--border) 75%, transparent); scrollbar-width: thin;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
table.gridjs-table { width: 100%; border-collapse: collapse; background: var(--surface); }
/* mermaid.min.css sets `.gridjs-tbody{background-color:#fff}`, unmatched by anything
   here - shows through wherever a child (a card-mode row's margin, a grid gap) exposes
   the tbody itself rather than a td/tr we already re-theme. */
tbody.gridjs-tbody { background: transparent; }
thead.gridjs-thead, .gridjs-thead th.gridjs-th {
  background: var(--surface-alt); color: var(--text-muted);
  text-transform: uppercase; font-size: var(--step--1); letter-spacing: 0.04em;
}
th.gridjs-th { padding: var(--space-xs) var(--space-sm); border-bottom: 1px solid var(--border); }
/* mermaid.min.css hardcodes `td.gridjs-td{background-color:#fff}` - our zebra
   rule below only overrides even rows (higher specificity via the tr.gridjs-tr
   ancestor), so odd rows fell through to that raw white in dark mode, i.e.
   every other row appearing in "opposite colours". Set the base background
   explicitly so both odd and even rows are themed. */
td.gridjs-td { padding: var(--space-sm) var(--space-sm); border-bottom: 1px solid color-mix(in srgb, var(--border) 50%, transparent); vertical-align: middle; background: var(--surface); }
.gridjs-td__value { display: inline-block; max-width: 100%; vertical-align: middle; }
td.gridjs-td { font-variant-numeric: tabular-nums; transition: background 0.15s ease-in-out; }
tr.gridjs-tr:nth-child(even) td.gridjs-td { background: color-mix(in srgb, var(--surface-alt) 25%, transparent); }
tr.gridjs-tr:hover td.gridjs-td { background: color-mix(in srgb, var(--surface-alt) 70%, transparent); }
td.gridjs-td .btn {
  background: var(--fpl-purple-800); color: #fff; border: 1px solid var(--fpl-purple-800);
  padding: var(--space-3xs) var(--space-xs); font-size: var(--step--1); transition: opacity 0.15s ease;
}
td.gridjs-td .btn:hover { opacity: 0.9; text-decoration: none; }
td.gridjs-td .btn--ghost {
  padding: var(--space-3xs) var(--space-xs); font-size: var(--step--1);
}
/* --fpl-purple-800 (#37003C) is a near-black purple - a solid fill of it reads
   as a clear CTA against a light-mode white card, but goes almost invisible
   against dark mode's --surface (#241238, itself a near-black purple). Swap to
   a semi-transparent fill with the cyan accent already used for dark-mode
   emphasis elsewhere (e.g. .explainer__card h3) so the button stays visible.
   .btn--ghost is unaffected - it already uses --border-strong/--text, which
   are theme-aware, so it stays legible in both modes without an override. */
:root[data-theme="dark"] td.gridjs-td .btn {
  background: rgba(255, 255, 255, 0.1); color: var(--fpl-cyan); border-color: var(--fpl-cyan);
}
:root[data-theme="dark"] td.gridjs-td .btn:hover {
  background: rgba(255, 255, 255, 0.18); opacity: 1;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) td.gridjs-td .btn {
    background: rgba(255, 255, 255, 0.1); color: var(--fpl-cyan); border-color: var(--fpl-cyan);
  }
  :root:not([data-theme="light"]) td.gridjs-td .btn:hover {
    background: rgba(255, 255, 255, 0.18); opacity: 1;
  }
}
input.gridjs-input {
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface); color: var(--text);
}
.gridjs-pagination { color: var(--text-secondary); }
.gridjs-pagination .gridjs-pages button {
  border: 1px solid var(--border); background: var(--surface); border-radius: var(--radius-sm); color: var(--text);
}
.gridjs-pagination .gridjs-pages button:hover { background: var(--surface-alt); }
.gridjs-pagination .gridjs-pages button.gridjs-currentPage { background: var(--fpl-purple-800); color: #fff; border-color: var(--fpl-purple-800); }
/* mermaid.min.css sets `.gridjs-footer{background-color:#fff;border-top:1px
   solid #e5e7eb}` - unmatched by anything above, so any grid using built-in
   pagination (e.g. the homepage search results) showed a solid white bar
   with light-gray border under the table in dark mode. Same leak on
   .gridjs-loading-bar (briefly shown during sort/search/page changes). */
.gridjs-footer { background: var(--surface); border-top: 1px solid var(--border); }
.gridjs-loading-bar { background: var(--surface); }


/* Card-mode grids on narrow screens, opt-in per grid */
@media (max-width: 639px) {
  .grid--cards thead.gridjs-thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
  }
  .grid--cards table.gridjs-table,
  .grid--cards tbody.gridjs-tbody,
  .grid--cards tr.gridjs-tr,
  .grid--cards td.gridjs-td { display: block; width: auto; }
  .grid--cards .gridjs-wrapper { overflow: visible; border: none; }
  .grid--cards tr.gridjs-tr {
    border: 1px solid color-mix(in srgb, var(--border) 80%, transparent); border-radius: var(--radius-md);
    margin-block-end: var(--space-2xs); padding: var(--space-xs); background: var(--surface);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  }
  .grid--cards td.gridjs-td {
    display: flex; justify-content: space-between; align-items: center; gap: var(--space-sm);
    padding: var(--space-2xs); border: none;
    border-bottom: 1px solid color-mix(in srgb, var(--border) 40%, transparent);
  }
  .grid--cards td.gridjs-td:last-child { border-bottom: none; padding-top: var(--space-xs); }
  .grid--cards td.gridjs-td::before {
    /* --text-muted read as low-contrast against the dark surfaces on a real
       phone (flagged via a Gemini UI review, confirmed present site-wide,
       not just on the new /insights page) - --text-secondary is lighter
       while still reading as secondary below the bold value text. */
    content: attr(data-label); color: var(--text-secondary); font-weight: 500; font-size: var(--step--1);
    flex-shrink: 0;
  }
  .grid--cards td.gridjs-td .gridjs-td__value {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
  }
}

/* =========================================================
   Responsive breakpoints
   ========================================================= */
@media (max-width: 1024px) {
  .options-group__columns { grid-template-columns: 1fr; }
  .explainer__grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .page { padding: 0 var(--space-sm) var(--space-lg); }
  .site-header__inner { padding: 0 var(--space-sm); }
  .hero { padding: var(--space-lg) var(--space-sm); }
  /* .search-field input's flex-basis (12rem, set for the row layout above)
     becomes a HEIGHT basis under flex-direction:column - a 192px-tall input,
     plus the icon forced onto its own full-width row, is what actually
     produced the oversized/broken-looking mobile search box (confirmed via
     agy). Force a single row instead - icon/input/button all inline, input
     shrinks via min-width:0, button sizes to its own label. Scoped to
     #player-form specifically (not the bare .search-field class) - login.html
     reuses .search-field for its password-entry form, which has no icon and
     genuinely wants the existing full-width stacked mobile layout. */
  #player-form.search-field { flex-wrap: nowrap; }
  #player-form.search-field input { min-width: 0; }
  #player-form .search-field__submit { width: auto; flex-shrink: 0; }
  .team-bar { flex-direction: column; align-items: flex-start; }
  .theme-toggle { width: 44px; height: 44px; }
  .tabs__list { scroll-snap-type: x mandatory; }
  .pitch { padding: var(--space-sm); }
  .pitch__row-cards { padding-inline: var(--space-sm); padding-bottom: var(--space-2xs); }
}

@media (max-width: 400px) {
  .card { padding: var(--space-sm); }
}

/* =========================================================
   Options tab: buy/sell candidates as tap-to-expand badges.
   Detail lives in the shared #player-sheet dialog (see openOptionSheet
   in transfers.js), not inline, so this stays compact for 10-40 rows.
   ========================================================= */
.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-xs);
}

.option-badge {
  display: flex; align-items: center; gap: var(--space-xs);
  width: 100%; padding: var(--space-2xs) var(--space-xs);
  background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--border-strong);
  border-radius: var(--radius-md); cursor: pointer; text-align: left;
  font: inherit; color: inherit;
  transition: background 0.15s ease, transform 0.1s ease;
}
.option-badge:hover { background: var(--surface-alt); transform: translateY(-1px); }
.option-badge--sell { border-left-color: var(--sell-edge); }
.option-badge--buy { border-left-color: var(--buy-edge); }

.option-badge__avatar {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--surface-alt); color: var(--text-muted);
  font-size: var(--step--1); font-weight: 700;
}
.option-badge__body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.option-badge__name {
  font-size: var(--step-0); font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.option-badge__sub { font-size: var(--step--1); color: var(--text-muted); white-space: nowrap; }
.option-badge__signal { font-size: var(--step--1); font-weight: 700; flex-shrink: 0; }

/* =========================================================
   Transfers tab: suggested transfer combo cards (.grid--swaps)
   ========================================================= */
.grid--swaps thead.gridjs-thead {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
}
.grid--swaps .gridjs-wrapper { overflow: visible; border: none; background: transparent; }
.grid--swaps table.gridjs-table { display: block; background: transparent; width: 100%; }
.grid--swaps tbody.gridjs-tbody {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); gap: var(--space-md);
}
.grid--swaps tr.gridjs-tr {
  display: flex; flex-direction: column; gap: var(--space-xs);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: var(--space-sm); box-shadow: var(--shadow-sm);
  margin: 0; width: auto;
}
.grid--swaps td.gridjs-td {
  padding: 0; width: auto; border: none; background: transparent !important;
}
.grid--swaps td.gridjs-td::before { display: none; }

.grid--swaps td[data-label="In"],
.grid--swaps td[data-label="In #1"],
.grid--swaps td[data-label="Out #2"],
.grid--swaps td[data-label="In #2"],
.grid--swaps td[data-label="Bank left"],
.grid--swaps td[data-label="Rating gain"],
.grid--swaps td[data-label="Next GW xP"] {
  display: none !important;
}

.swap-card__pairs {
  display: flex; flex-direction: column; gap: var(--space-2xs);
}
.swap-card__pair {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-xs); border-radius: var(--radius-sm);
  background: var(--surface-alt); border: 1px solid var(--border);
  width: 100%; font: inherit; text-align: left; cursor: pointer;
}
.swap-card__pair--clickable:hover, .swap-card__pair--clickable:focus-visible {
  border-color: var(--info-edge);
}
/* --surface-alt sits too close to --surface/--border in dark mode to read as its own
   card against the .grid--swaps row behind it - bump to --border-strong there. */
:root[data-theme="dark"] .swap-card__pair {
  border-color: var(--border-strong);
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .swap-card__pair { border-color: var(--border-strong); } }
.swap-card__player {
  font-weight: 700; font-size: var(--step-0); padding: var(--space-3xs) var(--space-2xs);
  border-radius: var(--radius-sm); max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.swap-card__player--sell {
  background: var(--sell-bg); color: var(--sell-text); box-shadow: inset 3px 0 0 var(--sell-edge);
}
.swap-card__player--buy {
  background: var(--buy-bg); color: var(--buy-text); box-shadow: inset 3px 0 0 var(--buy-edge);
}
.swap-card__arrow {
  color: var(--text-muted); font-weight: 700; flex-shrink: 0; padding: 0 var(--space-3xs);
}
.swap-card__chips {
  display: flex; flex-wrap: wrap; gap: var(--space-2xs); align-items: center; margin-top: var(--space-3xs);
}

@media (max-width: 640px) {
  .grid--swaps tbody.gridjs-tbody {
    grid-template-columns: 1fr; gap: var(--space-sm);
  }
  .grid--swaps tr.gridjs-tr {
    padding: var(--space-xs) var(--space-sm); gap: var(--space-2xs);
  }
}

/* =========================================================
   Rank History tab (transfers page)
   Chart colors are dedicated custom properties, not read off --text/--border
   directly: Chart.js's own color parser only understands hex/rgb/rgba/hsl/
   named values and calls .alpha() on them for hover/fill derivation, so a
   var() resolving to something more exotic would pass through unparsed.
   ========================================================= */
.kpi-strip { display: flex; flex-wrap: wrap; gap: var(--space-md); min-width: 0; }
.kpi__value--good { color: var(--buy-text); }
.kpi__value--bad  { color: var(--sell-text); }

.rank-history__summary { margin-bottom: var(--space-md); }
.rank-history__note { color: var(--text-muted); font-size: var(--step--1); margin-top: var(--space-2xs); }
.rank-history__chips { margin-top: var(--space-sm); }

/* .card supplies surface/border/radius/shadow; this only adds the positioning +
   determinate height Chart.js's responsive:true needs. Don't size the <canvas>
   itself in CSS - Chart.js writes inline width/height and a CSS override with
   !important loops the ResizeObserver. */
.rank-chart { position: relative; height: clamp(18rem, 46vh, 26rem); padding: var(--space-sm); }
.rank-chart canvas { display: block; }

@media (max-width: 640px) {
  .rank-chart { height: clamp(14rem, 52vh, 20rem); padding: var(--space-2xs); }
  .kpi-strip { gap: var(--space-sm); }
}

/* =========================================================
   GW Review tab (transfers page)
   This is the first template to use fplApp.initCollapsible (app.js) - it
   drives .gw-review__toggle/.gw-review__detail below via the generic
   .collapsible marker class and an `active` class toggle, but .collapsible
   itself still carries no default styling (any future consumer that expects
   bare `.collapsible`/`.active` to look like something out of the box will
   hit the same "reads as dead code" trap this one worked around).
   ========================================================= */
.gw-review__caveat { color: var(--text-muted); font-size: var(--step--1); margin-bottom: var(--space-md); }

.gw-review__row {
  border: 1px solid var(--border); border-radius: var(--radius-md);
  margin-bottom: var(--space-sm); overflow: hidden;
}
.gw-review__toggle {
  width: 100%; display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md); background: var(--surface); border: none;
  cursor: pointer; text-align: left; font: inherit; color: var(--text);
}
.gw-review__toggle:hover { background: var(--surface-alt); }
.gw-review__summary { font-weight: 600; }
.gw-review__toggle-icon {
  margin-left: auto; flex-shrink: 0; width: 1.5rem; height: 1.5rem; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-alt); font-size: 1rem; line-height: 1;
}
.gw-review__toggle-icon::before { content: '+'; }
.gw-review__toggle[aria-expanded="true"] .gw-review__toggle-icon::before { content: '\2212'; }

.gw-review__detail { display: none; padding: var(--space-md); border-top: 1px solid var(--border); background: var(--surface-alt); }
.gw-review__detail.active { display: block; }
.gw-review__detail .kpi-strip { margin-bottom: var(--space-md); }

.gw-review__table { width: 100%; border-collapse: collapse; font-size: var(--step--1); }
.gw-review__table th, .gw-review__table td { text-align: left; padding: var(--space-2xs) var(--space-sm); border-bottom: 1px solid var(--border); }
.gw-review__table th:last-child, .gw-review__table td:last-child { text-align: right; }
.gw-review__note { color: var(--text-muted); font-size: var(--step--1); margin-top: var(--space-xs); }

@media (max-width: 640px) {
  .gw-review__toggle { padding: var(--space-sm); }
}

/* =========================================================
   Leagues tab (transfers page)
   Accordion structurally mirrors .gw-review__row/__toggle/__detail above
   (same .collapsible/.active marker classes, same +/- toggle icon) - own BEM
   names since .gw-review__* is that tab's own vocabulary, not a shared one.
   Lives inside .tabs__panel, a sibling of the horizontal-scroll-snap
   .tabs__list (the tab button strip) - expanding a row here can't perturb
   that strip's scroll position, so no scroll-snap guard is needed.
   ========================================================= */
.leagues-tab__caveat { color: var(--text-muted); font-size: var(--step--1); margin-bottom: var(--space-md); }

.league-row {
  border: 1px solid var(--border); border-radius: var(--radius-md);
  margin-bottom: var(--space-sm); overflow: hidden;
}
.league-row__toggle {
  width: 100%; display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md); background: var(--surface); border: none;
  cursor: pointer; text-align: left; font: inherit; color: var(--text);
}
.league-row__toggle:hover { background: var(--surface-alt); }
.league-row__title { font-weight: 600; }
.league-row__meta { color: var(--text-muted); font-size: var(--step--1); }
.league-row__toggle-icon {
  margin-left: auto; flex-shrink: 0; width: 1.5rem; height: 1.5rem; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-alt); font-size: 1rem; line-height: 1;
}
.league-row__toggle-icon::before { content: '+'; }
.league-row__toggle[aria-expanded="true"] .league-row__toggle-icon::before { content: '\2212'; }

.league-row__content { display: none; padding: var(--space-sm) var(--space-md); border-top: 1px solid var(--border); background: var(--surface-alt); }
.league-row__content.active { display: block; }

.league-member-list { display: flex; flex-direction: column; gap: var(--space-2xs); }
.league-member {
  display: flex; align-items: center; gap: var(--space-sm);
  padding: var(--space-2xs) var(--space-sm); border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border);
  text-decoration: none; color: inherit;
}
.league-member:hover { background: var(--surface-alt); border-color: var(--border-strong); }
.league-member__rank {
  flex-shrink: 0; min-width: 2.5rem; text-align: right; font-weight: 700; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.league-member__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.league-member__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.league-member__manager { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-muted); font-size: var(--step--1); }
.league-member__points { flex-shrink: 0; color: var(--text-muted); font-size: var(--step--1); font-variant-numeric: tabular-nums; }
.league-member--current-user { background: var(--surface-alt); border-color: var(--border-strong); }
.league-member--current-user .league-member__name { color: var(--text); }

.league-row__more { margin-top: var(--space-sm); }

@media (max-width: 640px) {
  .league-row__toggle { padding: var(--space-sm); }
  .league-member__rank { min-width: 2rem; }
}

/* =========================================================
   Print
   ========================================================= */
@media print {
  .site-header, .site-footer, .theme-toggle, .search-field, .segmented, .tabs__list { display: none !important; }
  body { background: #fff; color: #000; }
}
