/* ─────────────────────────────────────────────────────────────────────────────
   team-stats.css — THE ownership-stats page skin, shared by IPL and PL.
   Ported from the WC golden (public/vc/wc/team-stats.html's inline <style>),
   which is the design standard for this page (docs/parity-build-method.md rule
   #1: golden = wc-golden-archive `golden-b`, team-stats).

   ── WHY A FILE AND NOT TWO INLINE BLOCKS ────────────────────────────────────
   IPL and PL each grew their own inline copy of "the ownership page", and they
   diverged into two different products: a 6-card fixed summary vs a 4-card
   auto-fit one, `.vc-table` vs `.pl-table`, one chip table vs two, an
   always-open roster vs a collapsed one. Every one of those was a copy that
   drifted, not a decision. So the skin lives here ONCE and both pages link it;
   `shared/team-stats-view.js` owns the markup that wears it. Two pages cannot
   look different if they share the stylesheet AND the DOM builder.

   ⚠ EVERY SELECTOR HERE IS SCOPED TO `.ts-page`. This file is linked by two
   pages that also load vc-theme.css and (on PL) the graphics-admin bar; an
   unscoped `.summary-card` or `.table-card` would reach into anything else on
   the shell that happens to share a class name. The wrapper is emitted by the
   view module, so the scope cannot be forgotten by a caller.
   ───────────────────────────────────────────────────────────────────────────── */

/* ── Source (fantasy-game) toggle caption ────────────────────────────────────
   The control itself is `shared/fantasy-game-toggle.js` (.vc-game-toggle /
   .vc-seg-toggle from vc-theme.css) — the SAME control the planner and the xPts
   boards draw, which is what the owner asked for. WC's page-local
   `.ta-fantasy-source-toggle` is deliberately NOT ported: it was a look-alike
   built before the shared control existed. */
/* Ported VERBATIM from public/vc/{,pl/}xpts.html so the control reads as one
   control in two places (owner: "same style and exact wording as the xpts page").
   The caption text matches too — `משחק פנטזי` / `Fantasy game`. */
.ts-page .vc-game-toggle { text-align: center; margin: 0 0 12px; }
.ts-page .vc-game-toggle-caption { font-size: 0.9rem; font-weight: 700; color: var(--vc-text-sub); margin: 0 0 8px; }
.ts-page .vc-game-toggle .vc-seg-toggle { margin: 0; }

/* Source attribution — the denominator disclosure ("based on the top-N managers
   of 25/26"). Present whenever the envelope names a cohort; absent for a
   whole-population ownership source, which then hides the line. */
.ts-page .ts-attribution {
  margin: 6px 0 14px;
  font-size: 0.78rem;
  color: var(--vc-text-sub);
  font-style: italic;
  text-align: center;
}

/* ── Sample-size toggle (cohort sources only) ────────────────────────────────
   Pills UNDER a live caption that restates the choice as a sentence ("מדגם: 500
   הקבוצות המובילות"). The caption is not decoration: on mobile the pills wrap to
   their own row and a bare "100 250 500" loses the "top teams" meaning entirely. */
.ts-page .ts-sample-wrap { text-align: center; }
.ts-page .ts-sample-toggle {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--vc-text);
}
.ts-page .ts-sample-caption {
  font-size: 1.02rem;
  font-weight: 800;
  color: var(--vc-text);
}
.ts-page .ts-sample-toggle .sample-pills {
  display: inline-flex;
  gap: 5px;
  padding: 5px;
  background: var(--vc-surface);
  border: 1px solid var(--vc-border);
  border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
  flex-wrap: wrap;
  justify-content: center;
}
.ts-page .ts-sample-toggle button {
  border: 0;
  background: transparent;
  color: var(--vc-text-sub);
  padding: 9px 22px;
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  font-size: 1.02rem;
  font-weight: 700;
  transition: background .12s, color .12s;
}
.ts-page .ts-sample-toggle button:not(.active):hover { color: var(--vc-text); }
.ts-page .ts-sample-toggle button.active {
  background: var(--vc-accent);
  color: #08131f;
  font-weight: 800;
}
html[data-vc-theme="light"] .ts-page .ts-sample-toggle button.active {
  background: #dbb580;
  color: #10213a;
}

/* The cohort sentence. NOT a footnote — the owner's call, and the right one: on a
   board whose numbers only mean something once you know WHOSE picks they are,
   "the fantasy players who finished in the top 500 last season" IS the headline,
   not the small print. So it reads at body size, bold, in the accent, directly
   under the pills it explains.
   (A sampled cohort's margin-of-error text — PL's wide rank bands are cluster-
   sampled — renders in the same slot and inherits the same treatment.) */
.ts-page .ts-sample-margin {
  white-space: pre-line;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--vc-accent);
  line-height: 1.45;
  max-width: 62ch;
  text-align: center;
}
@media (max-width: 560px) { .ts-page .ts-sample-margin { font-size: 0.86rem; } }
/* The participating count, ADMIN ONLY — it never reaches a non-admin client, so
   this rule styles something most visitors' payloads do not contain. Visually
   marked as ours: dimmer than the public sentence and not in the accent, so an
   admin reading the page can never mistake it for what a subscriber sees. */
.ts-page .ts-sample-admin {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--vc-text-sub);
  opacity: 0.9;
  text-align: center;
}

/* ── Summary cards ──────────────────────────────────────────────────────────
   Four fixed columns → two on tablet → one on phone. WC's grid, not IPL's
   `repeat(6, …)`: six cards at 1fr each crush the player name on a laptop. */
.ts-page .summary-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}
@media (max-width: 900px) { .ts-page .summary-row { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .ts-page .summary-row { grid-template-columns: 1fr; } }
.ts-page .summary-card {
  background: var(--vc-surface);
  border: 1px solid var(--vc-border);
  border-radius: 10px;
  padding: 16px 12px;
  text-align: center;
  min-width: 0;
  transition: border-color 0.15s, transform 0.15s;
}
.ts-page .summary-card:hover {
  border-color: var(--vc-accent);
  transform: translateY(-1px);
}
.ts-page .summary-card .label {
  font-size: 0.75rem;
  color: var(--vc-text-sub);
  margin-bottom: 6px;
}
.ts-page .summary-card .value {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--vc-accent);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
  min-width: 0;
  max-width: 100%;
}
/* The card value is a name on cards 1-3 — let it ellipsize rather than force the
   grid column wider than its 1fr share (which is what breaks the row on a laptop). */
.ts-page .summary-card .value > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.ts-page .summary-card .sub {
  font-size: 0.72rem;
  color: var(--vc-text-sub);
  margin-top: 4px;
}

/* ── Identity cells: player face, club crest ────────────────────────────────
   The face disc is PL's (`/api/pl/face/<code>.png` → FPL headshot → initials);
   IPL now draws the same disc from its own 365Scores studio index. Both are a
   round 30px crop, so the two pages' player rows are the same object. */
.ts-page .face {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  object-fit: cover; background: var(--vc-surface2);
}
/* A SHIRT is the fallback when a player has no face. It keeps the face's BOX —
   same size, same slot, so a table row never changes height on a fallback — but
   not the face's CROP: `object-fit: cover` on a kit zooms into a patch of fabric
   and slices the sleeves off. `contain` shows the whole shirt inside the same
   circle. Same reasoning (and the same rule) as compare-tool.css. */
.ts-page .face.is-shirt {
  object-fit: contain; object-position: center;
  background: transparent; padding: 1px;
}
.ts-page .face-init {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--vc-surface2); color: var(--vc-text-sub);
  font-weight: 800; font-size: 0.72rem;
}
.ts-page .team-logo-img {
  width: 18px; height: 18px; object-fit: contain;
  vertical-align: middle; flex: 0 0 auto;
}
.ts-page .team-logo-img.lg { width: 26px; height: 26px; }
.ts-page .team-logo-fallback { color: var(--vc-text-sub); font-size: 0.8rem; flex: 0 0 auto; }
/* Crest BEFORE the club name in both directions. In RTL the default `row` already
   puts the first child at the start (right) edge — do NOT add row-reverse, which
   would flip the crest after the name and break parity with .next-opp. */
.ts-page .team-cell-content { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.ts-page .team-cell-content > span { overflow: hidden; text-overflow: ellipsis; }

/* Player cell = face + (name over club). The club line under the name is what
   lets the name column carry the club without a second column on mobile. */
.ts-page .player-cell { display: inline-flex; align-items: center; gap: 9px; text-align: start; min-width: 0; }
.ts-page .player-cell .pc-main { min-width: 0; }
.ts-page .player-cell .pc-name { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ts-page .player-cell .pc-team {
  display: flex; align-items: center; gap: 5px;
  color: var(--vc-text-sub); font-weight: 500; font-size: 0.78rem;
}

/* Next-opponent cell: crest · short name · H/A chip. The H/A chip is colour-coded
   (WC): green = home, grey = away, so the venue reads at a glance in a dense table. */
.ts-page .next-opp {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.85rem; color: var(--vc-text-sub); white-space: nowrap;
}
.ts-page .next-opp .ha {
  font-size: 0.7rem; font-weight: 700; color: var(--vc-text-sub);
  padding: 1px 4px; border-radius: 4px; background: var(--vc-surface2);
}
.ts-page .next-opp .ha.h { background: rgba(129, 199, 132, 0.22); color: #a5d6a7; }
.ts-page .next-opp .ha.a { background: rgba(176, 190, 197, 0.18); color: #b0bec5; }
.ts-page .next-opp .gw { font-size: 0.7rem; color: var(--vc-text-sub); font-weight: 500; }
html[data-vc-theme="light"] .ts-page .next-opp .ha.h { background: rgba(46, 125, 50, 0.16); color: #2e7d32; }
html[data-vc-theme="light"] .ts-page .next-opp .ha.a { background: rgba(69, 90, 100, 0.14); color: #455a64; }

/* ── Sections + table cards ─────────────────────────────────────────────────── */
.ts-page .stats-section { margin-bottom: 24px; }
.ts-page .stats-section h2 {
  font-size: 1.1rem; font-weight: 600; color: var(--vc-text);
  text-align: center; margin-bottom: 10px;
  padding-bottom: 6px; border-bottom: 1px solid var(--vc-border);
}
.ts-page .stats-section-note {
  margin: -2px 0 12px;
  font-size: 0.84rem; color: var(--vc-text-sub);
  font-weight: 500; line-height: 1.5; text-align: center;
}
/* The EO explainer is deliberately multi-line — honour its \n breaks. */
.ts-page .ts-eo-note { white-space: pre-line; }

.ts-page .data-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 16px;
  align-items: start;
}
.ts-page .table-card {
  background: var(--vc-surface);
  border: 1px solid var(--vc-border);
  border-radius: 10px;
  overflow: hidden;
}
.ts-page .table-card-header {
  padding: 12px 14px;
  background: var(--vc-surface2);
  border-bottom: 1px solid var(--vc-border);
  font-size: 0.9rem; font-weight: 600; color: var(--vc-text);
  text-align: center;
}
.ts-page .table-card-body { overflow-x: auto; }
.ts-page .table-card-footer { padding: 10px 14px 14px; display: flex; justify-content: center; }
.ts-page .table-toggle-btn {
  border: 1px solid var(--vc-border);
  background: var(--vc-surface2);
  color: var(--vc-text-sub);
  border-radius: 999px;
  padding: 6px 14px;
  font: inherit;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.ts-page .table-toggle-btn:hover { color: var(--vc-text); border-color: var(--vc-accent); }

/* ── Header alignment follows its own column, by MEANING not by position ─────
   vc-theme.css forces `.vc-table thead th { text-align: right }` globally, which
   leaves a header sitting off to one side of the numbers it names.

   ⚠ THE OLD RULE KEYED ON nth-child(2)/(3), AND THAT WAS THE BUG. It happened to
   be right for the player tables (2 = name, 3 = club) and wrong everywhere else:
   on the chips table column 2 is the CHIP NAME and column 1 is a percentage, so
   "%" was pushed right while its numbers sat centred, and "בונוס" was centred
   over left-aligned text.

   Keying on `data-col` instead means every table gets the same answer for the
   same KIND of column, and a new table inherits it for free:
     · text columns (player, club, chip)  → start-aligned, header and cells alike
     · everything else (rank, %, price…)  → centred, header and cells alike
   `text-align: start` rather than right/left, so RTL and LTR both work with no
   second rule. */
.ts-page .table-card-body .vc-table thead th { position: static; }
.ts-page .vc-table th,
.ts-page .vc-table td { text-align: center; vertical-align: middle; }
.ts-page .vc-table th[data-col="name"],  .ts-page .vc-table td[data-col="name"],
.ts-page .vc-table th[data-col="club"],  .ts-page .vc-table td[data-col="club"],
.ts-page .vc-table th[data-col="chip"],  .ts-page .vc-table td[data-col="chip"],
.ts-page .vc-table th[data-col="nextOpp"], .ts-page .vc-table td[data-col="nextOpp"] { text-align: start; }

.ts-page .vc-table tbody tr:hover { background: rgba(255, 204, 2, 0.06); }
.ts-page .vc-table td.metric-accent { font-weight: 700; color: var(--vc-accent); }
.ts-page .vc-table td.ts-empty { text-align: center; color: var(--vc-text-sub); padding: 16px; }

/* ── Capability-gated columns ───────────────────────────────────────────────
   ⭐ THE MECHANISM THE WHOLE FOUR-GAME PAGE TURNS ON.

   Not every fantasy game can fill every column: a game with no published
   captaincy has no EO and no captain%, and 9 Fantasy publishes neither TODAY
   (it is expected to, in-season). The columns are therefore BUILT AND WIRED for
   every game, and COLLAPSED — header and cells together, `display:none`, so the
   two stay aligned — until the envelope's `capabilities` says the active game
   can fill them.

   ⚠ COLLAPSE, NEVER BLANK. A rendered-but-empty column reads as "we have no
   data on these players", which is a claim about the players. A column that is
   not there reads as "this game does not publish that", which is the truth.
   The view module toggles `.has-<cap>` on `.ts-page` from the envelope, so a
   game gaining a capability is a server-side flag flip and nothing else. */
.ts-page:not(.has-eo) [data-col="eo"] { display: none; }
.ts-page:not(.has-captaincy) [data-col="cap"] { display: none; }
.ts-page:not(.has-price) [data-col="price"] { display: none; }
.ts-page:not(.has-nextopp) [data-col="nextOpp"] { display: none; }

.ts-page .vc-table td[data-col="eo"] { font-weight: 700; color: var(--vc-accent); }

/* Click-to-sort headers (Own% / EO%). The ▼/▲ is written into .sort-arrow by JS
   on the active column. Keep the implicit columnheader role — aria-sort is only
   honoured on columnheader/rowheader, so a role="button" would make the sort
   state inert for screen readers. */
.ts-page .vc-table th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.ts-page .vc-table th.sortable:hover { color: var(--vc-accent); }
.ts-page .vc-table th.sortable:focus-visible { outline: 2px solid var(--vc-accent); outline-offset: -2px; }
.ts-page .vc-table th.sortable .sort-arrow {
  display: inline-block; margin-inline-start: 0.25em; font-size: 0.8em; opacity: 0.8;
}

/* Movers delta cells. */
.ts-page .delta-up   { color: #4caf50; font-weight: 700; direction: ltr; unicode-bidi: isolate; }
.ts-page .delta-down { color: #ef5350; font-weight: 700; direction: ltr; unicode-bidi: isolate; }

/* ── The Template XI pitch ───────────────────────────────────────────────────
   Ported from public/vc/team-news.html's lineup pitch, including the two bidi
   decisions it had to work out the hard way — they are not style choices:

   · The PITCH is pinned `direction: ltr`. A pitch is a fixed-orientation diagram
     and `.ts-pitch-row` is a GRID, whose columns flow along the container's
     direction — so on this RTL page the whole eleven would be mirrored and the
     left-back would line up on the right.
   · Each DOT puts itself back to `rtl`, so a Hebrew name (or a name/number line
     mixing scripts) keeps the bidi base the page is written for. Only the
     lateral axis is pinned; nothing else. */
.ts-page .ts-pitch {
  background: linear-gradient(180deg, #1e5c28 0%, #2d7a3a 40%, #2d7a3a 60%, #1e5c28 100%);
  border-radius: 10px;
  padding: 16px 8px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
  overflow: hidden;
  /* min-height, not height: the rows flex to fill it, so a 3-4-3 and a 3-5-2 are
     the same size instead of one leaving a band of empty grass. */
  min-height: 460px;
  direction: ltr;
}
.ts-page .ts-pitch::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 84px; height: 84px;
  border: 2px solid rgba(255, 255, 255, 0.12); border-radius: 50%;
  pointer-events: none;
}
.ts-page .ts-pitch::after {
  content: ''; position: absolute; top: 50%; left: 8%; right: 8%;
  height: 2px; background: rgba(255, 255, 255, 0.10); pointer-events: none;
}
.ts-page .ts-pitch-rows {
  display: flex; flex-direction: column; gap: 10px;
  flex: 1 1 auto; min-height: 0;
}
.ts-page .ts-pitch-row {
  display: grid; width: 100%;
  justify-items: center; align-items: center;
  gap: 6px; position: relative; z-index: 1;
  flex: 1 1 auto;
}
/* ── The bench (dugout) ──────────────────────────────────────────────────────
   Inside the pitch but visibly OFF it: a darker strip below the grass, above the
   touchline rule. It is the same dot, dimmed and shrunk, because a bench player
   is the same kind of fact at a lower weight — a second visual language here
   would read as a second board rather than the rest of one squad.
   `flex: 0 0 auto` keeps the strip its natural height so the eleven above still
   flexes to fill the grass. */
.ts-page .ts-bench {
  flex: 0 0 auto; position: relative; z-index: 1;
  margin: 4px -8px -16px;            /* bleed to the pitch's padding edges */
  padding: 8px 10px 10px;
  background: rgba(0, 0, 0, 0.28);
  border-top: 2px solid rgba(255, 255, 255, 0.14);
}
.ts-page .ts-bench-label {
  direction: rtl;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.72);
  margin-bottom: 6px; text-align: center;
}
.ts-page .ts-bench-row {
  display: grid; width: 100%;
  justify-items: center; align-items: start; gap: 6px;
}
.ts-page .ts-bench .ts-dot { max-width: 78px; opacity: 0.88; }
.ts-page .ts-bench .ts-disc { width: 38px; height: 38px; }
.ts-page .ts-bench .ts-crest { width: 15px; height: 15px; }
.ts-page .ts-bench .ts-dot-name { font-size: 10px; }
.ts-page .ts-bench .ts-dot-role { font-size: 9px; }
.ts-page .ts-bench .ts-dot-val { font-size: 10px; padding: 1px 5px; }
.ts-page .ts-bench-note { margin-top: 8px; }

/* ── A locked value on the PITCH ─────────────────────────────────────────────
   `.vc-locked-val` is the site-wide paywall treatment and it is a 5px BLUR — which
   is right on a table cell at ~0.9rem and erases the text completely inside a
   0.68rem pill, leaving an empty gold chip that reads as broken rather than paid.
   The blur has to scale with the type it is blurring, so it is dialled back here
   (and again on the smaller bench pill) to the point where you can still see that
   a number is present without being able to read it. That visibility IS the
   mechanism — a blurred figure advertises what a subscription buys; an empty chip
   advertises a bug. */
.ts-page .ts-dot-val .vc-locked-val { filter: blur(2.2px); opacity: 0.85; }
.ts-page .ts-bench .ts-dot-val .vc-locked-val { filter: blur(1.8px); }
/* ── The dot, matched to the WC Best-XI graphic (src/renderer/wc/wcBestXiRenderer.js)
   Its anatomy, in its own order: a LIGHT DISC holding the face (not a bare
   photo — the disc is what makes eleven different crops read as one set), a rim
   badge for identity (WC used the nation flag; a club game uses the crest), the
   name, a role line of position + price, and the gold metric pill.
   `unicode-bidi: plaintext` on the name is WC's too: it lets each name pick its
   OWN direction, which is what keeps a Latin name inside a Hebrew pitch from
   being reordered. */
.ts-page .ts-dot {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  width: 100%; max-width: 92px; min-width: 0;
  position: relative;
  direction: rtl;
}
.ts-page .ts-disc {
  position: relative;
  width: 48px; height: 48px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.88);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
  display: flex; align-items: center; justify-content: center;
  overflow: visible; flex: none;
}
.ts-page .ts-disc .face,
.ts-page .ts-disc .face-init {
  width: 48px; height: 48px; border: 0; background: transparent;
  color: #1a3a22; font-size: 0.8rem;
}
/* Rim badge — the club crest, on the disc's edge, exactly where WC puts the flag. */
.ts-page .ts-disc .ts-crest {
  position: absolute; bottom: -2px; inset-inline-end: -4px;
  width: 18px; height: 18px; border-radius: 50%;
  object-fit: contain; background: #f7f7f7; padding: 1px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.ts-page .ts-dot-name {
  font-size: 0.7rem; font-weight: 700; color: #f7f7f7;
  text-align: center; line-height: 1.15;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  unicode-bidi: plaintext;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65);
}
.ts-page .ts-dot-role {
  font-size: 0.62rem; font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  display: flex; gap: 5px; align-items: baseline; line-height: 1;
}
.ts-page .ts-dot-role .ts-price {
  color: rgba(255, 255, 255, 0.7); font-weight: 600;
  direction: ltr; unicode-bidi: isolate;
}
.ts-page .ts-dot-val {
  font-size: 0.68rem; font-weight: 800; letter-spacing: 0.3px;
  color: #102030; background: #fcc61d;
  border-radius: 10px; padding: 1px 10px; white-space: nowrap;
}

@media (max-width: 560px) {
  .ts-page .ts-pitch { min-height: 400px; padding: 12px 4px; }
  .ts-page .ts-dot { max-width: 66px; }
  .ts-page .ts-disc { width: 36px; height: 36px; }
  .ts-page .ts-disc .face, .ts-page .ts-disc .face-init { width: 36px; height: 36px; font-size: 0.66rem; }
  .ts-page .ts-disc .ts-crest { width: 14px; height: 14px; }
  .ts-page .ts-dot-name { font-size: 0.62rem; }
  /* The role line is the first thing to go: at this width the name and the metric
     are what a reader is actually reading off the pitch. */
  .ts-page .ts-dot-role { display: none; }
  .ts-page .ts-dot-val { font-size: 0.6rem; padding: 1px 7px; }
}

/* ── Chip drill-down ────────────────────────────────────────────────────────── */
.ts-page .chip-row-clickable { cursor: pointer; }
.ts-page .chip-row-clickable:hover { background: var(--vc-surface2, rgba(255, 255, 255, 0.04)); }
.ts-page .chip-drill-btn {
  display: inline-flex; align-items: center; gap: 7px;
  background: transparent; border: 0; cursor: pointer; font: inherit;
  color: var(--vc-accent); font-weight: 700; padding: 0;
}
.ts-page .chip-drill-name { text-decoration: underline; text-underline-offset: 2px; }
.ts-page .chip-drill-caret { font-size: 1.1rem; line-height: 1; color: var(--vc-accent); }
[dir="rtl"] .ts-page .chip-drill-caret { transform: scaleX(-1); }

.ts-drill-modal {
  position: fixed; inset: 0; z-index: 1500;
  display: none; align-items: center; justify-content: center;
  background: rgba(4, 8, 18, 0.62); padding: 18px;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.ts-drill-modal .chip-drill-card {
  position: relative; width: 100%; max-width: 460px;
  max-height: 86vh; overflow-y: auto;
  background: var(--vc-bg); border: 1px solid var(--vc-border);
  border-radius: 16px; padding: 22px 20px 18px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);
}
/* A two-group chip (captain + doubled vice) gets a wider card + side-by-side columns. */
.ts-drill-modal .chip-drill-card.multi-col { max-width: 720px; }
.ts-drill-modal .chip-drill-groups { display: grid; grid-template-columns: 1fr; gap: 18px; }
.ts-drill-modal .chip-drill-card.multi-col .chip-drill-groups { grid-template-columns: 1fr 1fr; }
.ts-drill-modal .chip-drill-group { min-width: 0; }
.ts-drill-modal .chip-drill-group-title {
  font-size: 0.92rem; font-weight: 800; color: var(--vc-accent);
  margin: 0 0 6px; padding-bottom: 5px; border-bottom: 1px solid var(--vc-border);
  text-align: start;
}
.ts-drill-modal .chip-drill-close {
  position: absolute; top: 10px; inset-inline-end: 12px;
  background: transparent; border: 0; color: var(--vc-text-sub);
  font-size: 1.7rem; line-height: 1; cursor: pointer; padding: 2px 6px;
}
.ts-drill-modal .chip-drill-close:hover { color: var(--vc-text); }
.ts-drill-modal .chip-drill-title { margin: 0 0 4px; font-size: 1.12rem; font-weight: 800; padding-inline-end: 26px; }
.ts-drill-modal .chip-drill-sub { margin: 0 0 14px; font-size: 0.82rem; color: var(--vc-text-sub); }
.ts-drill-modal .chip-drill-empty { color: var(--vc-text-sub); text-align: center; padding: 18px 0; }
.ts-drill-modal .chip-drill-table { width: 100%; }
/* Don't freeze the modal's column titles — the global .vc-table makes thead
   sticky, and in this short scrolling card a static header reads cleaner (and
   avoids the transparent-sticky bleed-through). */
.ts-drill-modal .chip-drill-table thead th { position: static; font-size: 0.74rem; color: var(--vc-text-sub); }
.ts-drill-modal .chip-drill-player { display: inline-flex; align-items: center; gap: 8px; }
.ts-drill-modal .chip-drill-table td:first-child,
.ts-drill-modal .chip-drill-table th:first-child { text-align: start; }
.ts-drill-modal .chip-drill-pct { font-weight: 700; }
.ts-drill-modal .face, .ts-drill-modal .face-init { width: 24px; height: 24px; font-size: 0.64rem; }
.ts-drill-modal .team-logo-img { width: 16px; height: 16px; object-fit: contain; }

/* ── "All players" browse (collapsed by default) ────────────────────────────── */
.ts-page .roster-expander {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--vc-surface2);
  border: 1px solid var(--vc-border);
  border-radius: 10px;
  padding: 12px 16px;
  cursor: pointer;
  color: var(--vc-text);
  font-size: 1.05rem; font-weight: 600;
  text-align: start; font-family: inherit;
}
.ts-page .roster-expander:hover { background: rgba(255, 204, 2, 0.06); }
.ts-page .roster-expander .roster-chevron { transition: transform 0.18s ease; color: var(--vc-text-sub); }
.ts-page .roster-expander[aria-expanded="true"] .roster-chevron { transform: rotate(180deg); }
.ts-page .roster-panel { margin-top: 14px; }
.ts-page .roster-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; }
.ts-page .roster-controls input[type="search"],
.ts-page .roster-controls .tj-combo input {
  background: var(--vc-surface2);
  border: 1px solid var(--vc-border);
  border-radius: 8px;
  padding: 9px 12px;
  color: var(--vc-text);
  font-size: 0.92rem; font-family: inherit;
}
.ts-page .roster-controls input[type="search"] { flex: 1 1 220px; min-width: 0; }
/* Club search-combobox — the same control as the FDR jump-to-team picker. */
.ts-page .roster-controls .tj-combo { position: relative; flex: 0 1 220px; }
.ts-page .tj-combo input { width: 100%; box-sizing: border-box; }
.ts-page .tj-combo input:focus { outline: none; border-color: var(--vc-accent); }
.ts-page .tj-list {
  list-style: none; margin: 4px 0 0; padding: 4px;
  position: absolute; inset-inline-start: 0; top: 100%; z-index: 30;
  min-width: 100%; max-height: 300px; overflow-y: auto;
  border-radius: 10px; border: 1px solid var(--vc-border); background: var(--vc-bg);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
  display: none;
}
.ts-page .tj-list.open { display: block; }
.ts-page .tj-opt {
  display: flex; align-items: center; gap: 8px; padding: 7px 10px;
  border-radius: 7px; cursor: pointer;
  font-size: 0.9rem; font-weight: 600; color: var(--vc-text); white-space: nowrap;
}
.ts-page .tj-opt .ocrest { width: 18px; height: 18px; flex: none; object-fit: contain; border-radius: 2px; }
.ts-page .tj-opt:hover, .ts-page .tj-opt.active { background: var(--vc-surface2); color: var(--vc-accent); }
.ts-page .tj-empty { padding: 8px 10px; font-size: 0.84rem; color: var(--vc-text-sub); }

.ts-page .roster-pos-chips { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.ts-page .roster-pos-chips button {
  background: var(--vc-surface2);
  border: 1px solid var(--vc-border);
  border-radius: 999px;
  padding: 7px 13px;
  color: var(--vc-text-sub);
  font-size: 0.85rem; font-family: inherit;
  cursor: pointer;
}
.ts-page .roster-pos-chips button:hover { color: var(--vc-text); border-color: var(--vc-accent); }
.ts-page .roster-pos-chips button.active {
  background: var(--vc-accent); color: #1a1a1a;
  border-color: var(--vc-accent); font-weight: 700;
}
html[data-vc-theme="light"] .ts-page .roster-pos-chips button.active { background: #dbb580; color: #10213a; }

.ts-page .roster-price-filter {
  display: inline-flex; align-items: center; gap: 8px;
  flex: 1 1 220px; min-width: 160px; font-size: 0.85rem;
}
.ts-page .roster-price-filter .rpf-label { font-weight: 600; color: var(--vc-text-sub); white-space: nowrap; }
.ts-page .roster-price-filter input[type="range"] {
  flex: 1 1 90px; min-width: 80px; max-width: 220px;
  accent-color: var(--vc-accent); cursor: pointer;
  /* ⚠ LTR ON AN RTL PAGE, DELIBERATELY. A range input inherits `direction`, and in
     RTL the browser MIRRORS its axis: the maximum lands on the LEFT. The filter
     opens at its maximum ("all prices"), so on the Hebrew page the handle sat
     pinned to the far-left edge — and dragging it left, which is what "less" means
     to everyone, did nothing at all. Measured: value stayed at 15 through a
     half-width drag, while the same gesture on /en filtered immediately. It reads
     as a broken control, which is exactly how it was reported.
     A slider is a NUMBER LINE, not text — low-to-high left-to-right holds in both
     directions, the same reason media scrubbers and volume sliders are not
     mirrored either. The label and value around it still follow the page. */
  direction: ltr;
}
.ts-page .roster-price-filter .rpf-value {
  font-weight: 700; color: var(--vc-text);
  min-width: 46px; white-space: nowrap; text-align: end;
}
.ts-page .roster-count { color: var(--vc-text-sub); font-size: 0.85rem; margin: 2px 2px 10px; }
.ts-page .roster-status { color: var(--vc-text-sub); font-size: 0.9rem; padding: 14px 4px; }
.ts-page .roster-status .vc-spinner { vertical-align: middle; margin-inline-end: 6px; }

/* ── Freshness ──────────────────────────────────────────────────────────────
   `.stale` is set when the snapshot predates a deadline it should have captured,
   or is simply old. It is a WARNING on the badge, not an error state: the page
   still renders the numbers it has, and the tooltip says why they may lag. */
.ts-page .vc-updated-badge.stale { color: #ffb74d; border-color: rgba(255, 183, 77, 0.45); }
.ts-page .ts-updated-row { justify-content: space-between; gap: 12px; flex-wrap: wrap; }

/* ── Responsive ─────────────────────────────────────────────────────────────── */
@media (max-width: 600px) {
  .ts-page .data-grid { grid-template-columns: 1fr; }
  .ts-page .table-card .vc-table { font-size: 0.82rem; }
  .ts-page .table-card .vc-table th,
  .ts-page .table-card .vc-table td { padding: 9px 6px; white-space: normal; }
  .ts-page .summary-card .value { font-size: 1.25rem; }
  .ts-page .roster-controls .tj-combo { flex: 1 1 150px; }
  .ts-drill-modal .chip-drill-card.multi-col .chip-drill-groups { grid-template-columns: 1fr; }
}
/* ── Dense-table sizing ─────────────────────────────────────────────────────
   Price belongs on every player board (owner, 2026-08-15), which puts the
   most-owned table back to six columns inside a half-width card. The room comes
   from the IDENTITY CELL rather than from dropping a column: a 24px face still
   identifies a player at a glance in a table row (the 48px disc on the pitch is
   where the face has to carry the whole cell), and the club column is capped
   tighter. Measured to fit at 1024px and up; below that the club moves under the
   name, which frees far more than it costs. */
.ts-page .table-card-body .vc-table .face,
.ts-page .table-card-body .vc-table .face-init { width: 24px; height: 24px; font-size: 0.6rem; }
.ts-page .table-card-body .vc-table .player-cell { gap: 6px; }
.ts-page .table-card-body .vc-table th,
.ts-page .table-card-body .vc-table td { padding-inline: 6px; }
.ts-page .vc-table td[data-col="club"] .team-cell-content { max-width: 110px; }
.ts-page .vc-table td[data-col="name"] .player-cell { max-width: 155px; }

/* ── (retired) the six-column problem ───────────────────────────────────────
   With EO present the most-owned table wants rank · player · club · own · EO ·
   price. Measured at 1440 with the shell sidebar, the two side-by-side cards are
   ~513px each and that table needs ~579 — so it scrolled sideways INSIDE its
   card, hiding price behind a drag on a full-size desktop.

   WC hits the same wall and answers it the same way, in its own words: "when EO
   is shown (6 cols), drop Price so Own%/EO% stay readable". WC scoped that to
   narrow screens only because its player cell is plain text; ours carries a 30px
   face disc (+39px per row, the owner's explicit ask), so the squeeze is there at
   every width and the rule applies at every width.

   Price is not lost — it keeps its column on the differentials board and in the
   "All players" browser, which is where a reader is actually price-shopping. */
/* Price is no longer dropped here — see "Dense-table sizing" above. */

/* ── …and the last 20px: let long names actually ellipsize ───────────────────
   `.pc-name` and `.team-cell-content > span` already carry text-overflow, but a
   flex item does not shrink below its content unless something bounds it — so a
   long Hebrew club name ("עירוני קריית שמונה") pushed the table 10-20px past its
   card and the ellipsis never engaged. These caps are what make the truncation
   real; they are generous enough that ordinary names never hit them. */
/* These are DENSE tables in HALF-WIDTH cards, which the theme's 12px horizontal
   cell padding was never sized for: five columns spend 120px of a 513px card on
   padding alone, and that alone is the whole residual overflow. Tighten the
   HORIZONTAL padding only — the vertical rhythm (and so the row height the rest
   of the page is tuned to) is untouched. */
.ts-page .table-card-body .vc-table th,
.ts-page .table-card-body .vc-table td { padding-inline: 8px; }

.ts-page .vc-table td[data-col="club"] .team-cell-content { max-width: 150px; }
.ts-page .vc-table td[data-col="name"] .player-cell { max-width: 190px; }
/* The club boards are rank · club · opponent · value, and the opponent cell was
   the one pushing them past their card at 1280 (+33px). It now renders the
   REGISTERED SHORT club name (see nextOppCellHtml), which fits on its own — so
   the cap is a safety net for an unregistered long name, not the normal case,
   and it is loose enough that a real short name is never clipped. */
.ts-page .vc-table td[data-col="nextOpp"] .next-opp { max-width: 150px; overflow: hidden; }

/* ── The opponent in the TWO-UP boards: crest + H/A, no text ────────────────
   MEASURED. Adding the fixture to the most-owned board pushed it 66px past its
   card at 1280 — the tightest desktop width, where two cards share the row — and
   the opponent cell was 117px of the 499. Dropping just its TEXT returns ~67px,
   which is the whole overflow, and costs least: the crest is a faster identifier
   at a glance than four Hebrew characters, the H/A chip carries the half that
   actually changes the decision, and the full club name stays reachable as the
   cell's tooltip. The CLUB BOARDS keep crest + short name — they have a whole
   column for it and no six-column row to fit. */
.ts-page :is(#tsTopOwnedTable, #tsSecondTable) td[data-col="nextOpp"] .next-opp > span:first-of-type {
  display: none;
}
/* …and a little real headroom on top. After the text came out, the six-column
   row measured 435 against a 433 card at 1280 — inside tolerance but ON the line,
   and a 2px min-content overflow is a horizontal scrollbar on some rendering.
   1px off each side of six columns buys 12px, which is margin rather than luck. */
.ts-page .table-card-body :is(#tsTopOwnedTable, #tsSecondTable) th,
.ts-page .table-card-body :is(#tsTopOwnedTable, #tsSecondTable) td { padding-inline: 5px; }

.ts-page :is(#tsTopOwnedTable, #tsSecondTable) td[data-col="nextOpp"] .next-opp {
  max-width: none;
  gap: 4px;
}
/* MEASURED, not guessed. The club CELL in these boards is allocated 154px at the
   tightest desktop width (1280), and the longest Israeli club label needs 119px —
   so the old 132px cap was clipping names the table had room for: the crest and
   its gap eat ~22px of the cap, leaving the label ~108px. 150px keeps the cell
   inside the width it already gets and stops clipping anything real. */
.ts-page :is(#tsAvgPlayersTable, #tsAvgDefTable) td[data-col="club"] .team-cell-content { max-width: 150px; }
.ts-page .vc-table td[data-col="nextOpp"] .next-opp > span:first-of-type {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* ── Where the club goes: under the name, in the two-up tables ───────────────
   Measured, not guessed. The four boards that sit TWO TO A ROW get ~513px of card
   at a 1440 viewport, and with price restored they carry six columns (rank ·
   player · club · metric · EO · price). Six columns do not fit 513px — measured
   9-139px over at every desktop width — and the widest of them by far is the club
   NAME.

   So in those tables the club rides UNDER the player's name, crest and all: the
   information stays, the row stops overflowing, and it reads the way the pitch dot
   and the mobile layout already do. It is also what buys price its column back,
   which is the thing actually being asked for.

   ⚠ PLAYER tables only. The two boards that are ABOUT clubs keep their column —
   hiding it there leaves a rank beside a bare number, which is what a first pass
   shipped. The roster keeps its column too on desktop: it is a FULL-WIDTH card
   with room to spare. */
.ts-page .table-card-body
  :is(#tsTopOwnedTable, #tsSecondTable, #tsRisersTable, #tsFallersTable) [data-col="club"] { display: none; }
.ts-page .player-cell .pc-team { display: none; }
.ts-page :is(#tsTopOwnedTable, #tsSecondTable, #tsRisersTable, #tsFallersTable) .player-cell .pc-team { display: flex; }

@media (max-width: 700px) {
  /* The roster runs out of room at this width too — same treatment. */
  .ts-page .table-card-body #tsRosterTable [data-col="club"] { display: none; }
  .ts-page #tsRosterTable .player-cell .pc-team { display: flex; }
  .ts-page .vc-table td[data-col="name"] .player-cell { max-width: none; }
}

/* Small phones (360-375 is still a very live width: iPhone SE, older Androids).
   With the fixture kept on the two player boards, the six-column row measured 4px
   past its card at 360 while 390 and up were clean — so the trim is scoped to the
   band that needs it rather than charged to every phone. 1px of inline padding
   off six columns returns 12px, which is margin rather than a squeak. */
/* …and below ~340 it genuinely does not fit: measured 32px over at 320 (Fold /
   very old handsets) with every other lever already pulled. The fixture is the
   right thing to drop there — it is the only column that is context rather than
   the subject — and dropping it beats the horizontal scroll that is the only
   other outcome. 360 and up keep it. */
@media (max-width: 340px) {
  .ts-page [data-col="nextOpp"] { display: none; }
  /* ⚠ PRE-EXISTING AT THIS WIDTH, on the ADMIN view too — the sweep simply never
     tested 320 and only caught it once the free view put real mover rows there.
     The movers board ran 22px over and the roster 31px. Price is the column to
     drop on both: the roster already drops it at 560 for the same reason, and a
     mover board is read for the DELTA. */
  .ts-page :is(#tsRisersTable, #tsFallersTable) [data-col="price"] { display: none; }
  .ts-page #tsRosterTable [data-col="pos"] { display: none; }
}

@media (max-width: 400px) {
  .ts-page .table-card-body :is(#tsTopOwnedTable, #tsSecondTable) th,
  .ts-page .table-card-body :is(#tsTopOwnedTable, #tsSecondTable) td { padding-inline: 4px; }
}

@media (max-width: 560px) {
  /* Ownership is the point of this page — price is the first column to go. */
  .ts-page .roster-panel [data-col="price"] { display: none; }
  /* THE FIXTURE STAYS ON THE TWO PLAYER BOARDS AT PHONE WIDTH (owner). It can:
     those two render it as crest + H/A, ~53px, and at 390 each board has the
     FULL page width to itself instead of sharing a row — so there is more room
     per table here than at 1280, not less. The club boards and the roster still
     drop it: the club boards already NAME the club in their own column, and the
     roster is a search surface where the fixture is not what you scan for. */
  .ts-page :is(#tsAvgPlayersTable, #tsAvgDefTable, #tsRosterTable) [data-col="nextOpp"] { display: none; }
}

/* ── THE ELITE PILL ──────────────────────────────────────────────────────────
   It sits in the same row as 100/250/500 and is the one paid option, and it was
   styled as a DIMMED, locked control — which is exactly backwards. A reader has
   no independent reason to try it: unlike its neighbours it is not a bigger or
   smaller version of anything, so if it also looks disabled nobody presses it and
   the explainer behind it never opens. It is now the most inviting thing in the
   row — gold-tinted, full opacity, crowned — with the lock reduced to a small
   trailing hint rather than the headline.

   It stays clickable rather than `disabled`, because a disabled control swallows
   the very interaction the upsell needs. */
.ts-page .ts-sample-toggle button.is-locked {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--vc-accent);
  font-weight: 800;
  background: linear-gradient(180deg, rgba(252, 198, 29, 0.16), rgba(252, 198, 29, 0.07));
  border: 1px solid rgba(252, 198, 29, 0.55);
  animation: ts-pill-glow 2.8s ease-in-out infinite;
}
.ts-page .ts-sample-toggle button.is-locked:hover {
  background: linear-gradient(180deg, rgba(252, 198, 29, 0.30), rgba(252, 198, 29, 0.14));
  border-color: var(--vc-accent);
  animation: none;
}
.ts-page .ts-pill-crown { font-size: 0.95em; line-height: 1; }
.ts-page .ts-sample-toggle button.is-locked .vc-locked-badge {
  font-size: 0.72em; line-height: 1; opacity: 0.6; margin-inline-start: 1px;
}
/* A slow breath, not a blink — enough to catch the eye once, never enough to nag.
   Off entirely for readers who ask for reduced motion. */
@keyframes ts-pill-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(252, 198, 29, 0); }
  50%      { box-shadow: 0 0 12px 1px rgba(252, 198, 29, 0.35); }
}
@media (prefers-reduced-motion: reduce) {
  .ts-page .ts-sample-toggle button.is-locked { animation: none; }
}

/* ── A lock that sits IN the flow, not over the card ─────────────────────────
   `lockElement` blurs a whole card and centres an overlay on it — right when the
   entire board is paid. It is wrong for a board whose TOP IS FREE: it would blur
   the five rows we are showing off. So the depth locks (ownership tail, club
   tail) and the roster panel render the same overlay markup as an ordinary block
   in the card footer, where it reads as "…and there is more below". */
.ts-page .ts-lock-footer { position: relative; padding: 6px 0 2px; }
.ts-page .ts-lock-footer .vc-locked-overlay {
  position: static;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* A locked player on the pitch: same dot geometry so the formation is unchanged,
   with the disc reading as a lock rather than as a failed image. */
.ts-page .ts-disc-locked {
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.16);
  border: 1px dashed rgba(255, 255, 255, 0.45);
  font-size: 18px;
}
.ts-page .ts-dot-locked .ts-dot-name { opacity: 0.72; font-style: italic; }

/* ── The upgrade box, INSIDE the table, right under the free rows ────────────
   `.vc-locked-overlay` is normally absolutely positioned over a blurred region.
   Here it sits in the flow, so `position: static` and no dimming — the rows
   above it are the free ones we want fully legible. */
.ts-page .ts-lock-row > td { padding: 10px 6px 12px; background: none; }
.ts-page .ts-lock-row .vc-locked-overlay,
.ts-page .ts-lock-panel .vc-locked-overlay {
  position: static;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: 0;
}
.ts-page .ts-lock-panel { padding: 14px 0 4px; }
/* The teaser rows under the offer: present, unreadable, and not competing with
   the free rows above for attention. */
.ts-page .ts-ghost-row { opacity: 0.5; }
/* A hidden Template XI player: a blurred dot, NOT a lock badge (owner). A lock
   glyph on a pitch reads as an error; a blurred player reads as a player you
   cannot quite see — which is exactly what it is. */
.ts-page .ts-disc-locked {
  background: rgba(255, 255, 255, 0.55);
  filter: blur(3px);
}
.ts-page .ts-dot-locked .ts-dot-name,
.ts-page .ts-dot-locked .ts-dot-val { filter: blur(3px); user-select: none; }
.ts-page .ts-dot-locked .ts-dot-role { opacity: 0.85; }

/* The elite explainer: a reading modal, not a table drill — wider measure, and
   paragraphs that breathe. */
.ts-page ~ .ts-drill-modal .ts-elite-card,
.ts-elite-card { max-width: 520px; }
.ts-elite-body p { margin: 0 0 10px; line-height: 1.6; color: var(--vc-text); font-size: 0.95rem; }
.ts-elite-body p:last-child { margin-bottom: 0; }
/* ── The modal's CTA ─────────────────────────────────────────────────────────
   The shared `.vc-teaser-cta` is sized for a small inline lock card, and inside a
   520px reading modal it lands as a link-shaped afterthought under three
   paragraphs of argument. This is the end of a PITCH, so it gets button weight:
   wider, taller, its own lift on hover. Scoped to `.ts-elite-cta` so the small
   in-table locks keep the compact original. */
.ts-elite-cta { margin-top: 18px; text-align: center; }
.ts-elite-cta .vc-teaser-cta {
  display: inline-block;
  padding: 13px 34px;
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(252, 198, 29, 0.28);
  transition: transform 0.14s ease, box-shadow 0.14s ease, filter 0.14s ease;
}
.ts-elite-cta .vc-teaser-cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 7px 20px rgba(252, 198, 29, 0.42);
  filter: brightness(1.06);
}
.ts-elite-cta .vc-teaser-cta:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .ts-elite-cta .vc-teaser-cta { transition: none; }
  .ts-elite-cta .vc-teaser-cta:hover { transform: none; }
}

/* The upgrade card ships a 300px max-width, wider than a 320px phone's table cell
   once padding is counted — it pushed the movers board 22px past its card at 320
   while 360 and up were clean.

   `max-width: 0` on the cell is the load-bearing line and it is not a typo: a
   table cell is sized by its content's MIN-CONTENT width, so `max-width: 100%`
   alone is circular — 100% of a width the content is deciding. Pinning it to 0
   makes the cell take its width from the ROW instead, which lets the card and its
   text wrap into whatever the table actually has. */
.ts-page .ts-lock-row > td { max-width: 0; }
.ts-page .ts-lock-row .vc-locked-card,
.ts-page .ts-lock-panel .vc-locked-card {
  max-width: 100%;
  box-sizing: border-box;
}
.ts-page .ts-lock-row .vc-locked-sub,
.ts-page .ts-lock-panel .vc-locked-sub { overflow-wrap: anywhere; }
/* MEASURED, after `max-width: 0` on the cell did NOT bite: the card's own
   min-content is ~273px (title + sub + CTA and their padding), and a max-width
   can never shrink a box below its min-content. On a 320px phone the movers
   board — the narrowest table on the page — has ~270px to give. So the cap is an
   explicit px value at that width, small enough to fit, with the sub free to
   wrap into it. */
@media (max-width: 400px) {
  .ts-page .ts-lock-row .vc-locked-card,
  .ts-page .ts-lock-panel .vc-locked-card {
    padding-inline: 8px;
    max-width: 220px;
  }
  .ts-page .ts-lock-row .vc-locked-title,
  .ts-page .ts-lock-row .vc-locked-sub { overflow-wrap: anywhere; word-break: break-word; }
  .ts-page .ts-lock-row .vc-teaser-cta { max-width: 100%; }
}

/* ── The combos tool ─────────────────────────────────────────────────────────
   "How many of them own ALL of these players?" — slots on top, the answer under
   them, the crowd's other picks below that. Three rows, one question.

   ⚠ LOGICAL PROPERTIES ONLY. This page ships in Hebrew (RTL) and English (LTR)
   from ONE stylesheet, and every physical `left`/`margin-left`/`padding: a b c d`
   here would be a mirror bug on one of them. */
.ts-page .ts-combo { display: flex; flex-direction: column; gap: 14px; }

/* ── Slots ───────────────────────────────────────────────────────────────── */
.ts-page .tsc-slots {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
}
.ts-page .tsc-slot {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px; border-radius: 999px;
  border: 1px solid var(--vc-border); background: var(--vc-surface);
  font-size: 0.85rem; font-weight: 600; color: var(--vc-text);
  max-width: 100%;   /* the grid ITEM, not only the track — a long name must not
                        push the page sideways on a phone */
}
.ts-page .tsc-slot.is-filled { padding-inline-end: 4px; }
.ts-page .tsc-slot-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-page .tsc-slot-x {
  border: 0; background: none; cursor: pointer; line-height: 1;
  font-size: 1.05rem; color: var(--vc-text-sub); padding: 2px 6px; border-radius: 999px;
}
.ts-page .tsc-slot-x:hover { color: var(--vc-text); background: var(--vc-surface2); }
.ts-page .tsc-slot-add {
  cursor: pointer; border-style: dashed; color: var(--vc-text-sub);
  background: none;
}
.ts-page .tsc-slot-add:hover { color: var(--vc-accent); border-color: var(--vc-accent); }
.ts-page .tsc-plus {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--vc-surface2); font-size: 1rem; font-weight: 700;
}
.ts-page .tsc-clear {
  border: 0; background: none; cursor: pointer;
  font-size: 0.8rem; color: var(--vc-text-sub); text-decoration: underline;
  padding: 6px 4px;
}
.ts-page .tsc-clear:hover { color: var(--vc-text); }

/* ── Picker ──────────────────────────────────────────────────────────────── */
.ts-page .tsc-picker {
  display: flex; flex-direction: column; gap: 6px;
  max-width: 420px;
}
.ts-page .tsc-picker input[type="search"] {
  width: 100%; box-sizing: border-box;
  padding: 8px 12px; border-radius: 8px;
  border: 1px solid var(--vc-border); background: var(--vc-surface);
  color: var(--vc-text); font-size: 0.9rem; font-family: inherit;
}
.ts-page .tsc-picker input[type="search"]:focus {
  outline: none; border-color: var(--vc-accent);
}
.ts-page .tsc-results {
  list-style: none; margin: 0; padding: 4px;
  max-height: 260px; overflow-y: auto;
  border: 1px solid var(--vc-border); border-radius: 8px;
  background: var(--vc-surface);
}
.ts-page .tsc-results li {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 6px; cursor: pointer;
  font-size: 0.85rem;
}
.ts-page .tsc-results li:hover { background: var(--vc-surface2); }
.ts-page .tsc-res-main { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.ts-page .tsc-res-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-page .tsc-res-club { font-size: 0.72rem; color: var(--vc-text-sub); }
.ts-page .tsc-res-own { font-size: 0.78rem; color: var(--vc-text-sub); font-variant-numeric: tabular-nums; }
.ts-page .tsc-res-empty { color: var(--vc-text-sub); cursor: default; justify-content: center; }
.ts-page .tsc-res-empty:hover { background: none; }

/* ── Readout ─────────────────────────────────────────────────────────────── */
.ts-page .tsc-readout {
  border: 1px solid var(--vc-border); border-radius: 10px;
  background: var(--vc-surface); padding: 14px 16px;
}
.ts-page .tsc-empty {
  color: var(--vc-text-sub); font-size: 0.88rem; text-align: center; padding: 10px 0;
}
.ts-page .tsc-empty.is-error { color: var(--vc-danger, #d33); }
/* The empty state IS the add control — see renderComboReadout. It fills the
   readout so the target is the whole box, not the words in the middle of it. */
.ts-page button.tsc-empty-add {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; box-sizing: border-box; padding: 22px 12px;
  border: 1px dashed var(--vc-border); border-radius: 8px;
  background: none; cursor: pointer;
  color: var(--vc-text-sub); font-size: 0.9rem; font-weight: 600; font-family: inherit;
}
.ts-page button.tsc-empty-add:hover {
  color: var(--vc-accent); border-color: var(--vc-accent);
}
.ts-page button.tsc-empty-add:hover .tsc-plus { background: var(--vc-surface); }
.ts-page .tsc-headline {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.ts-page .tsc-big {
  font-size: 2.4rem; font-weight: 800; line-height: 1;
  color: var(--vc-accent); font-variant-numeric: tabular-nums;
}
.ts-page .tsc-pct { font-size: 1.2rem; font-weight: 700; }
.ts-page .tsc-cap { font-size: 0.9rem; color: var(--vc-text-sub); font-weight: 600; }
.ts-page .tsc-headline.is-zero .tsc-cap { color: var(--vc-text); }

/* Bars: one per selected player at his own ownership, then the combination —
   all on ONE 0-100 scale, so the collapse from "each of them" to "all of them"
   is the thing you see rather than a thing you have to work out. Rescaling to
   the biggest bar would make every combination look the same size. */
.ts-page .tsc-bars { display: flex; flex-direction: column; gap: 6px; }
.ts-page .tsc-bar {
  display: grid; grid-template-columns: 28px minmax(0, 1fr) 3fr auto;
  align-items: center; gap: 8px;
  font-size: 0.8rem;
}
.ts-page .tsc-bar-face { display: inline-flex; }
.ts-page .tsc-bar-label {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--vc-text-sub);
}
.ts-page .tsc-track {
  height: 10px; border-radius: 999px;
  background: var(--vc-surface2); min-width: 0;
}
.ts-page .tsc-fill {
  display: block; height: 100%; border-radius: 999px;
  background: var(--vc-text-sub); opacity: 0.55;
  min-width: 2px;   /* a real 0.4% must still be visible as a sliver, not as nothing */
  transition: width 180ms ease;
}
.ts-page .tsc-bar-val { font-variant-numeric: tabular-nums; color: var(--vc-text-sub); }
.ts-page .tsc-bar.is-combo { font-weight: 700; }
.ts-page .tsc-bar.is-combo .tsc-bar-label,
.ts-page .tsc-bar.is-combo .tsc-bar-val { color: var(--vc-text); }
.ts-page .tsc-bar.is-combo .tsc-track { height: 14px; }
.ts-page .tsc-bar.is-combo .tsc-fill { background: var(--vc-accent); opacity: 1; }

/* ── Partners ────────────────────────────────────────────────────────────── */
.ts-page .tsc-partners-label {
  font-size: 0.85rem; font-weight: 700; color: var(--vc-text); margin-bottom: 8px;
}
.ts-page .tsc-partner-row { display: flex; flex-wrap: wrap; gap: 8px; }
.ts-page .tsc-partner {
  display: inline-flex; align-items: center; gap: 6px;
  /* LOGICAL, not `padding: 5px 10px 5px 6px` — the tighter side is the FACE's,
     and a physical shorthand puts it on the wrong side in one of the two
     directions this stylesheet ships in. */
  padding-block: 5px; padding-inline: 6px 10px;
  border-radius: 999px; cursor: pointer;
  border: 1px solid var(--vc-border); background: var(--vc-surface);
  color: var(--vc-text); font-size: 0.8rem; font-family: inherit;
  max-width: 100%;
}
.ts-page .tsc-partner:hover { border-color: var(--vc-accent); color: var(--vc-accent); }
.ts-page .tsc-partner-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-page .tsc-partner-pct { color: var(--vc-text-sub); font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  /* The name column is CAPPED rather than dropped. Hiding it would take the
     combo row's "all together" label with it — the one label on the chart that is
     not guessable from a face — and re-showing that one row's label inside a
     3-column grid reflows every other cell. A fixed narrow column with an
     ellipsis keeps one rule for every row.

     The name sets SMALLER here and the column gap widens, because at 390px the
     name sat hard against the face and the two read as one smudge. Smaller type
     also buys back the width the extra gap costs, so the track does not shrink. */
  .ts-page .tsc-bar { grid-template-columns: 24px 78px minmax(56px, 1fr) auto; gap: 10px; }
  .ts-page .tsc-bar-label { font-size: 0.72rem; }
  .ts-page .tsc-bar-val { font-size: 0.72rem; }
  .ts-page .tsc-big { font-size: 2rem; }
  /* Same crowding in the picker list and the partner chips — the face is flush
     against the name there too. */
  .ts-page .tsc-results li { gap: 10px; }
  .ts-page .tsc-res-name { font-size: 0.8rem; }
  .ts-page .tsc-partner { gap: 8px; }
  .ts-page .tsc-partner-name { font-size: 0.76rem; }
  .ts-page .tsc-slot { gap: 10px; font-size: 0.8rem; }
}
