/* ─────────────────────────────────────────────────────────────────────────
   My Teams — web parity with the mobile app's organizer "My Teams" feature
   (app/(app)/teams.tsx + app/(app)/team-editor.tsx).

   Two visually separate screens:
     1. The list screen (#my-teams — tmRenderList in teams.js): a full-bleed
        light SaaS-dashboard workspace modeled closely on a reference
        (light neutral canvas, centered 3-up card grid, tall white cards
        with a centered identity block + a divided footer-stats row).
        `.tm-list-page` (full-bleed background) > `.tm-list-inner` (the
        actual max-width header+grid content) > `.tm-head`/`.tm-cta`/
        `.tm-grid`/`.tm-card*`/`.tm-status-card`. See section 1 below.
     2. The create/edit roster editor (#my-teams/new, #my-teams/{id} —
        tmRenderEditor in teams.js): `.tm-page`/`.tm-ed-*`/`.tm-modal-*`,
        UNCHANGED by this pass — out of scope, left exactly as it was. The
        single exception is `.tm-member-order`, kept below because
        Tournament Manager's own read-only Team Round Robin structure view
        (app.js, around `d.membersByTeam`) reuses that one class inside its
        dark `.mgmt-row`.
   ───────────────────────────────────────────────────────────────────────── */

/* ═══════════════════════════════════════════════════════════════════════
   1. LIST SCREEN — full-bleed light dashboard, 3-up card grid
   ═══════════════════════════════════════════════════════════════════════ */

/* Full-bleed on purpose: this paints the workspace canvas edge to edge,
   independent of the page's own content max-width, so the light background
   is never "a light box sitting inside a darker page" — there is no dark
   layer anywhere in this screen's ancestor chain (body → .shell → .main →
   .view.active → .tm-list-page) for it to sit inside of in the first
   place, but painting full-bleed here removes any doubt and matches the
   reference's own edge-to-edge workspace canvas.

   The background itself is deliberately more present than a flat neutral:
   two soft green radial washes for atmosphere, laid over a vertical
   gradient that starts and ends at the site's own --bg (matching the
   sticky topnav above and the footer below) and only turns clearly green
   in the middle — so the page reads as "a green workspace" rather than a
   hard-edged green rectangle dropped between two off-white bars. */
.tm-list-page {
  --tm-workspace-bg: #E7F4EC;
  width: 100%;
  min-height: 70vh;
  background:
    radial-gradient(1100px 560px at 10% 0%, rgba(20, 122, 61, 0.16), transparent 62%),
    radial-gradient(900px 520px at 100% 25%, rgba(20, 122, 61, 0.12), transparent 58%),
    linear-gradient(180deg, var(--bg) 0%, var(--tm-workspace-bg) 160px, var(--tm-workspace-bg) calc(100% - 200px), var(--bg) 100%);
  color: var(--text);
}
.tm-list-inner {
  max-width: 1360px;
  margin: 0 auto;
  width: 100%;
  padding: var(--space-6) var(--space-5) calc(var(--space-6) * 1.5);
}

/* ── Workspace split — ~3/4 main (teams grid) + ~1/4 side panel (Club
   Players), the primary new layout for this pass. Stacks to one column
   below 900px; desktop is the priority. ─────────────────────────────── */
.tm-workspace {
  display: grid;
  grid-template-columns: 3fr 1fr;
  gap: var(--space-6);
  align-items: start;
}
.tm-workspace-main { min-width: 0; }
.tm-workspace-side { min-width: 0; }
@media (max-width: 900px) {
  .tm-workspace { grid-template-columns: 1fr; }
}

/* ── Header: heading + short supporting copy on one side, a compact
   secondary-weight Create Team action on the other — a quiet dashboard
   toolbar, not a hero banner. The teams themselves stay the visual focus. */
.tm-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}
.tm-head-text { min-width: 0; }
/* Groups the color-mode toggle with the primary Create Team action so
   `.tm-head` stays a simple two-child flex row (text | actions) — same
   layout the full Club Players view's own header (.tm-club-full-head)
   uses for the same reason. */
.tm-head-actions { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.tm-title {
  font-size: 1.7rem;
  font-weight: 800;
  letter-spacing: -0.4px;
  color: var(--text-strong);
  margin: 0 0 4px;
}
.tm-subtitle { font-size: var(--text-sm); color: var(--muted); margin: 0; }

/* Deliberately compact/quiet — a dashboard toolbar action, not the site's
   big hero .btn-primary. */
.tm-cta {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  background: var(--green);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 700;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-out), filter var(--dur-fast) var(--ease-out);
}
.tm-cta svg { width: 15px; height: 15px; stroke: currentColor; }
.tm-cta:hover { filter: brightness(1.06); }
/* Used inline inside the empty-state card, where the outer element is
   already the clickable button — a visual echo of the CTA, not itself
   interactive (no nested <button>). */
.tm-cta-ghost { cursor: inherit; }
/* A second, equal-size CTA next to the primary one (team editor's "+ Add
   player" / "Add Keelo Player" pair) — same size/shape as .tm-cta so
   neither one reads as more important, only recolored, mirroring
   .tm-club-add-btn-keelo's own treatment of the Club Players panel's
   second entry point. */
.tm-cta-secondary { background: var(--card-tint); color: var(--text); border: 1px solid var(--border); box-shadow: none; }
.tm-cta-secondary:hover { background: var(--green-tint); border-color: var(--green-lite); color: var(--green-dark); filter: none; }

/* Global color-mode toggle (UX polish task) — same quiet secondary-button
   language as .tm-cta-secondary, appears in both the list header and the
   full Club Players view's own header (tmColorModeToggleHtml, one shared
   function, never two copies). */
.tm-color-mode-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
  padding: 9px 14px;
  border-radius: var(--radius-sm);
  background: var(--card-tint);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: 700;
  white-space: nowrap;
}
.tm-color-mode-toggle:hover { background: var(--green-tint); border-color: var(--green-lite); color: var(--green-dark); }
.tm-color-mode-toggle svg { width: 15px; height: 15px; stroke: currentColor; }

/* ── Card grid — 3 up on desktop, 2 at medium widths, 1 narrow, via
   auto-fill/minmax (no manual breakpoints needed) — sized for the main
   column's own ~3/4-width share of the workspace, not the full page. ──── */
.tm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-5);
}

/* ── Team card — tall, centered "team object" card: identity block
   (number → name → a one-line roster preview) centered top-to-middle, then
   a divided footer stats row pinned to the bottom via margin-top:auto so
   every card in a row lines up on the same footer baseline regardless of
   name length. Identity rests on the colored --team-color outline + the
   number badge (either the stable derived tmTeamColor(t.display_number), or
   a manager's own local override — see tmEffectiveTeamColor in teams.js);
   opening the editor is still one click via the nested `.tm-card-open`
   button — the outer `.tm-card` is `position: relative` so it can host the
   three-dot options button/popover as an absolutely-positioned sibling
   (never nested inside `.tm-card-open`, so it can never also trigger the
   card's own open action), plus the "Players" stat's own expand button, and
   act as a drag/drop target (`data-tm-dropzone`) — none of them nested
   interactive elements. ─────────────────────────────────────────────────── */
.tm-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  min-height: 200px;
  background: var(--card);
  border: 2px solid var(--team-color, var(--border));
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.tm-card:hover {
  box-shadow: var(--shadow-lg);
  transform: translateY(-3px);
}
/* "No border" — the manager's own explicit choice, persisted server-side
   as organizer_teams.border_color = 'none' (teams.js's tmSetTeamBorderColor):
   a transparent border keeps the card's box size and
   padding identical to every bordered card in the same row/grid, rather
   than switching border-width to 0 and shifting layout. --team-color stays
   set (untouched) so the number badge keeps a real, visible color either
   way — only the outline itself disappears. */
.tm-card.tm-card-no-border { border-color: transparent; }
/* Active drop target while a player chip is being dragged over this card. */
.tm-card.tm-drop-hover {
  background: var(--green-tint);
  box-shadow: 0 0 0 4px var(--green-lite), var(--shadow-lg);
  transform: translateY(-3px);
}

.tm-card-open {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.tm-card-open:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; border-radius: var(--radius-md); }

.tm-card-top {
  display: flex;
  align-items: center;
  /* Leaves clear space start-side of the number for the absolutely-
     positioned three-dot button that now occupies the old hero-image slot
     (see .tm-team-menu-btn below) — kept as its own row rather than
     removing this wrapper, in case a second badge/affordance joins the
     number here later. */
  justify-content: space-between;
  width: 100%;
  margin-bottom: var(--space-3);
}
.tm-card-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  padding: 0 9px;
  border-radius: var(--radius-pill);
  font-size: 0.92rem;
  font-weight: 900;
  color: #fff;
  background: var(--team-color, var(--muted));
  flex-shrink: 0;
}

/* ── Three-dot "Team options" button — replaces the old small hero-image
   thumbnail in the same top corner. On a full card it's absolutely
   positioned (a plain sibling of `.tm-card-open`, never nested inside it —
   see the file-header comment above `.tm-card`); on a collapsed row
   (`.tm-team-row`) it flows normally instead. Sized well above the old 32px
   image for a comfortable touch/click target. ─────────────────────────── */
.tm-team-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  flex-shrink: 0;
}
.tm-team-menu-btn svg { width: 18px; height: 18px; }
.tm-team-menu-btn:hover, .tm-team-menu-btn[aria-expanded="true"] { background: var(--card-tint); color: var(--text); }
.tm-team-menu-btn:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.tm-card > .tm-team-menu-btn {
  position: absolute;
  top: var(--space-4);
  inset-inline-end: var(--space-4);
  z-index: 2;
}

/* ── Team options popover — anchored to the card/row that owns it (no JS
   position math), clamped to a max-width that fits inside even a narrow
   single-column card so it never overflows the viewport. ──────────────── */
.tm-team-menu {
  position: absolute;
  top: 46px;
  inset-inline-end: var(--space-4);
  z-index: 30;
  min-width: 210px;
  max-width: min(240px, calc(100vw - 32px));
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
/* Player 3-dot menu portal (UX polish task) — the SAME .tm-team-menu visual
   styling above, just switched from "absolute, anchored via CSS to a
   positioned ancestor" to "fixed, positioned via JS" (see teams.js's
   tmPositionMenuPortal, which sets top/left inline once appended to
   <body>). inset-inline-end/right are reset to auto so they can't compete
   with the inline `left` that positioning sets. z-index sits above the
   sticky top nav (50) and everything else in the page, but below the modal
   overlay (300) so a modal opened from the menu is never covered by it. */
.tm-menu-portal {
  position: fixed;
  top: 0;
  left: 0;
  right: auto;
  inset-inline-end: auto;
  z-index: 120;
}
.tm-team-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border: none;
  background: none;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text);
  text-align: start;
  cursor: pointer;
}
.tm-team-menu-item svg { width: 16px; height: 16px; stroke: currentColor; flex-shrink: 0; }
.tm-team-menu-item:hover { background: var(--card-tint); }
.tm-team-menu-item.selected { background: var(--green-tint); color: var(--green-dark); }
.tm-team-menu-item.danger { color: var(--red); }
.tm-team-menu-item.danger:hover { background: rgba(220, 38, 38, 0.08); }
.tm-team-menu-sep { height: 1px; margin: 4px 2px; background: var(--border-soft); }
.tm-team-menu-back {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 6px 10px;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: none;
  font-size: var(--text-sm);
  font-weight: 800;
  color: var(--text-strong);
  cursor: pointer;
  margin-bottom: 4px;
}
.tm-team-menu-back svg { width: 15px; height: 15px; stroke: currentColor; }
.tm-team-menu-hint { font-size: var(--text-xs); color: var(--faint); text-align: center; margin: 6px 2px 2px; }

.tm-color-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  padding: 4px 6px 8px;
}
.tm-color-swatch {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
}
.tm-color-swatch:hover { transform: scale(1.08); }
.tm-color-swatch.selected { border-color: var(--text-strong); box-shadow: 0 0 0 2px var(--card); }
.tm-color-swatch:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
/* While set_organizer_team_border_color is in flight for this team
   (tmColorSavingTeamId) — guards against a double-submit and shows that
   the pick isn't applied yet. */
.tm-color-swatch:disabled { opacity: 0.45; cursor: wait; pointer-events: none; }
.tm-team-menu-item:disabled { opacity: 0.45; cursor: wait; pointer-events: none; }

/* Team title — still the strongest text on the card, but the card's overall
   identity no longer depends on reading it (number + color carry that now
   at a glance). */
.tm-card-name {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--text-strong);
  line-height: 1.25;
  width: 100%;
  /* Long names wrap onto a second line instead of being cut off. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tm-card-preview {
  font-size: var(--text-xs);
  color: var(--faint);
  margin-top: 6px;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tm-card-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  width: 100%;
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-soft);
}
.tm-card-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.tm-card-stat b { font-size: 1.05rem; font-weight: 900; color: var(--text-strong); line-height: 1.2; }
.tm-card-stat span {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.tm-card-stat-sep { width: 1px; align-self: stretch; background: var(--border-soft); flex-shrink: 0; }

/* The Players stat doubles as the expand toggle — reset its button chrome
   and give it its own hover/focus cue distinct from the plain FIDE-IDs
   stat next to it. */
button.tm-card-stat-clickable {
  background: none;
  border: none;
  padding: 3px 8px;
  margin: -3px 0;
  border-radius: var(--radius-sm);
  font: inherit;
  color: inherit;
  cursor: pointer;
}
button.tm-card-stat-clickable:hover { background: var(--green-tint); }
button.tm-card-stat-clickable:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* ── In-card expand — names only, per spec, each row draggable onto any
   other team card. Scrolls internally past a handful of rows rather than
   growing the card without bound. ──────────────────────────────────────── */
.tm-card-expand {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px dashed var(--border-soft);
  max-height: 220px;
  overflow-y: auto;
}
.tm-card-expand-empty { font-size: var(--text-xs); color: var(--muted); text-align: center; margin: 4px 0; }

.tm-roster-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--card-tint);
  border: 1px solid var(--border-soft);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text);
  cursor: grab;
  transition: opacity var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.tm-roster-chip:hover { border-color: var(--green-lite); }
.tm-roster-chip:active { cursor: grabbing; }
.tm-roster-chip.tm-dragging { opacity: 0.35; }
.tm-roster-chip-handle { display: inline-flex; color: var(--green); flex-shrink: 0; }
.tm-roster-chip-handle svg { width: 14px; height: 14px; stroke: currentColor; }
.tm-roster-chip-name {
  min-width: 0;
  text-align: start;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Collapsed-card mode — a compact row per team (number, name, three-dot
   menu only, per spec), used instead of the full grid of `.tm-card`s while
   tmCardsCollapsed is true. Reuses `.tm-card`'s own border/color treatment
   (same --team-color custom property) so a colored/no-border choice reads
   identically whether a team is currently shown compact or full. Spans the
   grid's full width so rows stack one per line instead of tiling into
   columns like the card grid does. ──────────────────────────────────────── */
.tm-team-row {
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
  min-height: 0;
  padding: var(--space-3) var(--space-4);
  gap: var(--space-2);
}
.tm-team-row:hover { box-shadow: var(--shadow-sm); transform: none; }
.tm-team-row-open {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  padding: 4px;
  margin: -4px;
  border-radius: var(--radius-sm);
  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
}
.tm-team-row-open:hover { background: var(--card-tint); }
.tm-team-row-open:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.tm-team-row-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-base);
  font-weight: 800;
  color: var(--text-strong);
}
/* Inside a row the menu button just flows in the flex row, not absolute. */
.tm-team-row > .tm-team-menu-btn { position: static; }

/* ── Reorder mode — replaces the whole grid area with a plain vertical
   list + Up/Down controls (see teams.js's tmRenderReorderPanel for why not
   drag-and-drop). Spans the grid's full width like the collapsed rows
   above. ─────────────────────────────────────────────────────────────── */
.tm-reorder-panel { grid-column: 1 / -1; }
.tm-reorder-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.tm-reorder-hint { font-size: var(--text-sm); color: var(--muted); margin: 0; max-width: 480px; }
/* Player-reorder's own hint (task 1) reuses this class but, unlike the
   plain-text team-list hint above, prefixes an icon — sized explicitly so
   icon('gripVertical')'s bare <svg> (no width/height of its own) never
   falls back to the browser's oversized default replaced-element size
   (the exact bug already fixed once for .mgmt-notice svg elsewhere). */
.tm-reorder-hint svg { display: inline-block; vertical-align: -3px; width: 15px; height: 15px; margin-inline-end: 4px; }
.tm-reorder-actions { display: flex; gap: var(--space-3); flex-shrink: 0; }
.tm-reorder-actions .tm-btn-outline, .tm-reorder-actions .tm-cta { margin-top: 0; }
.tm-reorder-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.tm-reorder-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--card);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
.tm-reorder-row-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-base);
  font-weight: 800;
  color: var(--text-strong);
}
.tm-reorder-row-controls { display: flex; gap: 4px; flex-shrink: 0; }
.tm-reorder-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--card-tint);
  color: var(--text);
  cursor: pointer;
}
.tm-reorder-btn svg { width: 16px; height: 16px; stroke: currentColor; }
.tm-reorder-btn-up svg { transform: rotate(-90deg); }
.tm-reorder-btn-down svg { transform: rotate(90deg); }
.tm-reorder-btn:hover:not(:disabled) { border-color: var(--green); color: var(--green); }
.tm-reorder-btn:disabled { opacity: 0.35; cursor: default; }

/* ── Empty state (zero teams) — one light card that sits naturally in the
   grid; kept intentionally simple, this pass's focus is the populated
   state. The primary Create Team action in .tm-head stays visible above
   it either way. ────────────────────────────────────────────────────── */
.tm-card-empty {
  align-items: center;
  justify-content: center;
  text-align: center;
  cursor: pointer;
  padding: var(--space-6) var(--space-5);
  border-style: dashed;
  border-width: 1.5px;
  border-color: var(--border);
  background: var(--card-tint);
  box-shadow: none;
}
.tm-card-empty:hover { border-color: var(--green-lite); background: var(--card); box-shadow: var(--shadow-sm); }
.tm-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--green-tint);
  color: var(--green);
  margin: 0 auto var(--space-3);
}
.tm-empty-icon svg { width: 26px; height: 26px; stroke: currentColor; }
.tm-empty-title { font-size: 1.1rem; font-weight: 800; color: var(--text-strong); margin-bottom: 6px; }
.tm-empty-text { font-size: var(--text-sm); color: var(--muted); margin: 0 auto var(--space-4); max-width: 320px; }

/* ── Loading skeleton — quiet placeholder cards, not a spinner box ──────── */
.tm-card-skeleton {
  height: 360px;
  cursor: default;
  background: linear-gradient(100deg, var(--card) 30%, var(--card-tint) 50%, var(--card) 70%);
  background-size: 200% 100%;
  animation: tmShimmer 1.4s ease-in-out infinite;
}
@keyframes tmShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── Error status card ───────────────────────────────────────────────────── */
.tm-status-card {
  text-align: center;
  padding: var(--space-6) var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  color: var(--muted);
}
.tm-btn-outline {
  margin-top: var(--space-3);
  padding: 10px 18px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-weight: 700;
  font-size: var(--text-sm);
}
.tm-btn-outline:hover { border-color: var(--green); color: var(--green); }
.tm-btn-outline:disabled { opacity: 0.6; cursor: not-allowed; }

/* Reused wherever a button needs the same in-flight state as create-
   tournament.js's own .ct-spinner (data-tm-reorder-save while
   reorder_organizer_teams is in flight) — a local copy, not a shared
   class, matching this file's existing convention of not reaching into
   another module's CSS (see create.css's own .ct-modal comment). */
.tm-spinner {
  width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.4);
  border-top-color: currentColor; animation: tm-spin 0.7s linear infinite; display: inline-block;
}
@keyframes tm-spin { to { transform: rotate(360deg); } }

/* ── Club Players — the side panel. A quieter green-bordered card that
   echoes the team cards' own border language without competing with the
   grid for attention. Rows are drag sources onto any team card. ───────── */
.tm-club-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  background: var(--card);
  border: 1.5px solid rgba(20, 122, 61, 0.18);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.tm-club-panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.tm-club-title { font-size: 1.05rem; font-weight: 900; color: var(--text-strong); margin: 0; }
/* The heading is now a real button (task requirement — opens the dedicated
   full Club Players view, data-tm-open-club-players) rather than plain
   text: same size/weight/color as before so the panel's own visual weight
   doesn't change, plus a small trailing chevron and a hover state so it
   reads as clickable. icon('arrow') points "forward" (away from the panel,
   toward the fuller view) — the mirror image of the same icon used
   rotated -90/90deg elsewhere for up/down, here left as drawn since RTL's
   own natural mirroring already points it the correct reading direction. */
.tm-club-title-link {
  display: inline-flex; align-items: center; gap: 5px;
  border: none; background: none; padding: 0; cursor: pointer;
  font: inherit; text-align: start;
}
.tm-club-title-link:hover { color: var(--green-dark); }
.tm-club-title-link svg { width: 15px; height: 15px; stroke: currentColor; flex-shrink: 0; opacity: 0.6; }
/* Sits directly above .tm-club-list (not up in .tm-club-panel-head next to
   the section title) so it visually belongs to the list it acts on. */
.tm-club-list-actions { display: flex; align-items: center; gap: var(--space-4); margin-bottom: 8px; }
.tm-club-select-all {
  flex-shrink: 0; border: none; background: none; padding: 0;
  font-size: 0.72rem; font-weight: 800; color: var(--green); cursor: pointer;
}
.tm-club-select-all:hover { text-decoration: underline; }
.tm-club-add-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 11px;
  border-radius: var(--radius-pill);
  background: var(--green-tint);
  color: var(--green);
  font-size: 0.72rem;
  font-weight: 800;
}
.tm-club-add-btn svg { width: 13px; height: 13px; stroke: currentColor; }
.tm-club-add-btn:hover { background: var(--green-lite); }
/* Two entry points (Add Guest / Add Keelo Player) — both create the exact
   same organizer_club_players row shape, just via a different modal; kept
   visually equal-weight (no "primary vs secondary" hierarchy) since
   neither is the default path. */
.tm-club-add-row { display: flex; gap: 8px; flex-wrap: wrap; }
.tm-club-add-row .tm-club-add-btn { flex: 1; justify-content: center; }
.tm-club-add-btn-keelo { background: var(--card-tint); color: var(--text); border: 1px solid var(--border); }
.tm-club-add-btn-keelo:hover { background: var(--green-tint); border-color: var(--green-lite); color: var(--green-dark); }

.tm-club-search {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  background: var(--card-tint);
}
.tm-club-search svg { width: 15px; height: 15px; stroke: var(--muted); flex-shrink: 0; }
.tm-club-search input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  outline: none;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--text);
}

.tm-club-list { display: flex; flex-direction: column; gap: 8px; max-height: 620px; overflow-y: auto; }
.tm-club-row {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  background: var(--card-tint);
  border: 1px solid var(--border-soft);
  cursor: grab;
  position: relative;
  transition: opacity var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.tm-club-row:hover { border-color: var(--green-lite); }
.tm-club-row:active { cursor: grabbing; }
.tm-club-row.tm-dragging { opacity: 0.35; }
.tm-club-row-selected { background: var(--green-tint); border-color: var(--green-lite); }
.tm-club-row-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
/* The card's own 3-dot menu button — a normal (non-absolute) flex sibling
   of the checkbox/body above, so it naturally lands at the row's "end" edge
   (correct RTL positioning for free, no inset-inline math needed) and never
   overlaps the row text. Reuses .tm-team-menu-btn's own sizing/hover style
   wholesale (see teams.css's Team options popover section). The popover
   itself is no longer nested here at all (UX polish task — see teams.js's
   tmOpenPlayerMenuPortal) — it's a JS-positioned .tm-menu-portal appended
   to <body>, so no CSS anchoring rule is needed for it any more. */
.tm-club-row .tm-team-menu-btn { position: static; }
/* A real button, not a native checkbox — same small square-with-checkmark
   language as the TRR Check-in tab's own row control, for one consistent
   "checkbox" idiom across the newer parts of this codebase. Grabbing it
   never starts a drag (it isn't draggable itself; the row is) and its own
   click handler runs before the row's edit-click handler (see
   tmInstallListeners), so it never opens the edit modal by accident. */
.tm-club-checkbox {
  flex-shrink: 0; margin-top: 1px;
  width: 20px; height: 20px; border-radius: 6px;
  border: 1.5px solid var(--border); background: var(--card);
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: #fff;
}
.tm-club-checkbox svg { width: 12px; height: 12px; stroke: currentColor; }
.tm-club-checkbox.checked { background: var(--green); border-color: var(--green); }
.tm-club-name { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); }
/* Shared by both the collapsed card's one-line identity (Israeli Federation
   ID only — tmClubPlayerCollapsedMetaHtml) and the expanded disclosure
   section's optional-field grid (tmClubPlayerExpandedMetaHtml). Collapsed
   cards are now substantially shorter than before this task: the old
   always-visible rating/age/player-number/gender 2x2 grid moved into the
   expanded state, and each field there is only ever rendered when a real
   value exists — never a blank/"Not defined" placeholder. */
.tm-club-meta {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px 10px;
  font-size: 0.66rem; color: var(--muted);
}
.tm-club-meta-cell b { color: var(--text); font-weight: 700; margin-inline-end: 4px; }
/* Expanded state's own "nothing else to show" fallback — a single quiet
   line, never a grid of empty-looking cells. */
.tm-club-meta-empty { font-size: 0.7rem; color: var(--faint); font-style: italic; }
/* Disclosure chevron (task: "feel like a disclosure/details section") —
   same rotate-on-expand language as the TRR Rounds accordion's own chevron
   (trr-manage.css's .trrmgmt-round-header-chevron), reused here rather than
   inventing a second expand/collapse visual idiom. A plain flex sibling
   (not absolutely positioned) so it never overlaps the 3-dot menu next to
   it, and pointer-events:none so a click that lands exactly on it still
   toggles the card via the row's own click handler instead of being eaten
   by a non-interactive decoration. */
.tm-club-row-chevron {
  flex-shrink: 0; align-self: center; display: flex; color: var(--muted);
  transition: transform var(--dur-fast) var(--ease-out); pointer-events: none;
}
.tm-club-row-chevron svg { width: 14px; height: 14px; stroke: currentColor; }
.tm-club-row-chevron.expanded { transform: rotate(90deg); }
.tm-club-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.tm-club-tag {
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--green);
  background: var(--green-tint);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
}
/* Subtle Keelo identity indicator for a linked real user — same row,
   same tag styling language as the team tags next to it (not a visually
   separate roster category), just a distinct accent color + a tiny icon. */
.tm-club-tag-keelo { display: inline-flex; align-items: center; gap: 3px; color: var(--blue); background: #E6F1FA; }
.tm-club-tag-keelo svg { width: 10px; height: 10px; stroke: currentColor; }
/* A club player not currently on any team — a quiet, distinct tone so it
   reads as "no membership yet" rather than as a real team name. */
.tm-club-tag-none { color: var(--muted); background: var(--border-soft); }
/* Missing Israeli Federation ID (legacy player) — same amber pair the rest
   of the manager surfaces already use for "needs attention, never blocks"
   notices (trr-manage.css's .trrmgmt-badge.amber / manage.css's --mgmt-amber),
   reused here by value rather than inventing a third color for the same
   meaning. Clearly visible, not alarming — no icon, just a quiet pill. */
.tm-club-tag-warning { color: #9A6B12; background: #FCF1DC; }
/* Add-from-Club-Players picker only — "already on a DIFFERENT team", a
   plain informational disclosure (not a warning/blocker: this player stays
   fully selectable, see tmRenderAddFromClubModal's own header comment), so
   it uses the same quiet, neutral tone as .tm-club-tag-none rather than the
   amber "needs attention" treatment above. */
.tm-club-tag-other-team { color: var(--muted); background: var(--border-soft); }
/* Team-membership badge, now colored per-team (task requirement) — same
   solid-background-plus-white-text idiom the team's own number badge
   already uses (.tm-card-number, teams.css section 1 below), reading the
   SAME --team-color custom property set inline by tmClubPlayerTeamTagsHtml
   (from tmEffectiveTeamColor — never a separate color source). Kept as the
   pill's only distinguishing style (same size/padding/radius as every
   other .tm-club-tag) so several team badges on one card stay easy to
   tell apart by color/label without changing shape. */
.tm-club-tag-team { background: var(--team-color); color: #fff; }
.tm-club-empty { font-size: var(--text-sm); color: var(--muted); text-align: center; margin: var(--space-3) 0; }

/* ── Global "no colors" display mode (UX polish task) — a presentation-only
   override, toggled by adding/removing .tm-neutral-colors on the page's own
   `.tm-list-page` root (tmApplyNeutralColorsDom in teams.js). Every element
   that carries an INLINE --team-color (the team card itself, its collapsed-
   row twin, a club-player team-membership tag, the reorder-row preview
   number) gets it forced to one neutral gray via !important here — that
   beats the inline declaration for that exact element (CSS cascade:
   author !important outranks an inline author-normal style), while every
   OTHER element that only ever INHERITS --team-color from one of these
   (e.g. a normal team card's own .tm-card-number) picks up the override
   automatically, with nothing else to touch. The underlying inline style
   attribute (and therefore organizer_teams.border_color / tmEffectiveTeam
   Color's own computation) is completely untouched — turning this back off
   is just removing the class, and every color reappears exactly as it was.
   Semantic colors (danger/warning/Keelo/etc.) never use --team-color, so
   none of them are affected by this rule. Reuses the same slate-gray hex
   the "Gray" border preset already uses (TM_BORDER_PRESET_HEX.gray in
   teams.js) — neutral mode reads as "every team using that existing Gray
   option," not an invented new color. */
.tm-neutral-colors .tm-card,
.tm-neutral-colors .tm-club-tag-team,
.tm-neutral-colors .tm-reorder-row .tm-card-number {
  --team-color: #475569 !important;
}

.tm-club-selection-bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: 7px 10px; border-radius: var(--radius-sm);
  background: var(--green-tint); color: var(--green-dark);
}
/* Keeps the bar's own height reserved in the layout even at 0 selected
   (see tmClubSelectionBarHtml's own header comment in teams.js) — visibility
   (not display:none) so the slot never changes height as the count goes
   to/from zero, which is what actually stops the organizer's scroll
   position from shifting on Clear Selection/the last checkbox unchecking. */
.tm-club-selection-bar-hidden { visibility: hidden; }
.tm-club-selection-count { font-size: 0.78rem; font-weight: 800; }
.tm-club-selection-clear {
  border: none; background: none; padding: 0; cursor: pointer;
  font-size: 0.72rem; font-weight: 700; color: var(--green-dark); text-decoration: underline;
}
/* Bulk "Remove from club" (Club Players full-list page only — see
   tmClubSelectionBarHtml's own header comment in teams.js). Destructive
   styling, distinct from the plain-text Clear Selection link next to it. */
.tm-club-selection-remove {
  display: inline-flex; align-items: center; gap: 6px;
  border: none; border-radius: var(--radius-sm); cursor: pointer;
  padding: 5px 10px; font-size: 0.74rem; font-weight: 800;
  background: var(--red); color: #fff;
}
.tm-club-selection-remove svg { width: 14px; height: 14px; }
.tm-club-selection-remove:disabled { opacity: 0.6; cursor: not-allowed; }
.tm-club-selection-remove .tm-spinner { width: 13px; height: 13px; }

/* "Select by category" — Team tab (follow-up task). */
.tm-cat-tabs { display: flex; gap: 6px; margin-bottom: var(--space-3); }
.tm-cat-tab {
  flex: 1; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card); color: var(--text-muted);
  padding: 7px 10px; font-size: 0.8rem; font-weight: 700; cursor: pointer;
}
.tm-cat-tab.active { border-color: var(--green); background: var(--green-tint); color: var(--green-dark); }
.tm-cat-team-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 280px; overflow-y: auto;
}
.tm-cat-team-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card); padding: 9px 12px; cursor: pointer; text-align: start;
}
.tm-cat-team-row:hover { border-color: var(--green); background: var(--green-tint); }
.tm-cat-team-name { font-weight: 700; font-size: 0.88rem; }
.tm-cat-team-count { font-size: 0.74rem; color: var(--text-muted); }

/* The floating "N players" drag-image badge (setDragImage target) — never
   actually visible in the layout itself (positioned off-screen, only
   rendered into the drag ghost), so it just needs to look right in
   isolation: a small, high-contrast pill. */
.tm-drag-count-badge {
  display: inline-flex; align-items: center;
  padding: 6px 12px; border-radius: var(--radius-pill);
  background: var(--green); color: #fff;
  font-size: 0.8rem; font-weight: 800;
  box-shadow: var(--shadow-md);
}

/* ── Dedicated full-width Club Players view (task requirement) — same
   `.tm-list-page` shell/max-width as the normal list screen (see
   tmRender's own branch), just its own wrapper instead of the 3-column
   teams+panel layout, so it can give the whole width to player cards. ── */
.tm-club-full-wrap { max-width: 1120px; margin: 0 auto; }
/* Title/subtitle on one side, the color-mode toggle on the other — same
   two-child flex-row pattern as the list screen's own `.tm-head`. */
.tm-club-full-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.tm-club-full-head-text { min-width: 0; }
.tm-club-full-title { font-size: 1.75rem; font-weight: 900; color: var(--text-strong); letter-spacing: -0.4px; margin: 0; }
.tm-club-full-subtitle { font-size: var(--text-sm); color: var(--muted); margin: 4px 0 0; }
/* 2-3 up on a wide desktop, collapsing on its own via auto-fill/minmax —
   same no-manual-breakpoints convention as .tm-grid above, just a wider
   minmax since these cards are deliberately "large rectangular" (task
   requirement) rather than the team grid's own more-square shape. */
.tm-club-full-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  gap: var(--space-4);
}
/* One large player card — same internal anatomy as the side panel's own
   .tm-club-row (checkbox → body → chevron → 3-dot menu, same
   data-tm-toggle-club-player/data-tm-club-select/tmRenderClubPlayerMenuButton
   hooks, same expand/collapse), just roomier padding/gap and a taller name
   so it reads as a proper card instead of a compact list row. */
.tm-club-card {
  display: flex; align-items: flex-start; gap: var(--space-4);
  background: var(--card); border: 1px solid var(--border-soft); border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
  cursor: grab;
  position: relative;
  transition: opacity var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.tm-club-card:hover { border-color: var(--green-lite); box-shadow: var(--shadow-md); }
.tm-club-card:active { cursor: grabbing; }
.tm-club-card.tm-dragging { opacity: 0.35; }
.tm-club-card-selected { background: var(--green-tint); border-color: var(--green-lite); }
.tm-club-card-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1; }
.tm-club-card-name { font-size: 1.1rem; font-weight: 800; color: var(--text-strong); }
/* Same button-positioning fix the side panel's own row already needed (see
   .tm-club-row .tm-team-menu-btn above) — the popover itself is a portal
   now, not nested here, so no anchoring rule for it is needed. */
.tm-club-card .tm-team-menu-btn { position: static; }

@media (max-width: 560px) {
  .tm-list-inner { padding: var(--space-5) var(--space-4) var(--space-6); }
  .tm-head { flex-direction: column; align-items: stretch; }
  .tm-head-actions { flex-direction: column; align-items: stretch; }
  .tm-cta { justify-content: center; }
  .tm-color-mode-toggle { justify-content: center; }
  .tm-title { font-size: 1.5rem; }
  .tm-reorder-head { flex-direction: column; align-items: stretch; }
  .tm-reorder-actions { flex-direction: row; }
  .tm-reorder-actions .tm-btn-outline, .tm-reorder-actions .tm-cta { flex: 1; justify-content: center; }
  .tm-team-menu { min-width: 190px; }
  .tm-club-full-head { flex-direction: column; align-items: stretch; }
  .tm-club-full-grid { grid-template-columns: 1fr; }
  .tm-club-full-title { font-size: 1.4rem; }
}


/* ═══════════════════════════════════════════════════════════════════════
   2. TEAM EDITOR (create/edit team) — same light Keelo workspace as the
   list screen above, wrapped in the same `.tm-page` shell (see tmRender()
   in teams.js) plus its own narrower `.tm-ed-wrap` so a roster of short
   rows doesn't stretch edge-to-edge on the page's full 1120px width.
   ═══════════════════════════════════════════════════════════════════════ */

.tm-ed-wrap { max-width: 860px; margin: 0 auto; }

/* Now a real, obviously-clickable button (task requirement — the previous
   version was small muted text, easy to miss) instead of a plain inline
   link: its own border/background/padding, same pill language the rest of
   this screen's quiet secondary actions already use (.tm-club-add-btn-keelo
   below). Same destination/handler as before (data-tm-back-to-list,
   unchanged) — only presentation changed. */
.tm-ed-back {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--text-sm); font-weight: 800; color: var(--text);
  margin-bottom: var(--space-5);
  padding: 8px 14px; border: 1.5px solid var(--border); border-radius: var(--radius-pill);
  background: var(--card);
}
.tm-ed-back:hover { color: var(--green-dark); border-color: var(--green-lite); background: var(--green-tint); }
.tm-ed-back svg { width: 16px; height: 16px; stroke: currentColor; }

/* ── "New team" card ─────────────────────────────────────────────────── */
.tm-ed-create-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: var(--space-6); max-width: 460px;
}
.tm-ed-create-title {
  font-size: 1.5rem; font-weight: 900; letter-spacing: -0.4px;
  color: var(--text-strong); margin: 0 0 var(--space-5);
}

.tm-field { margin-bottom: var(--space-5); }
.tm-field label {
  display: block; font-size: var(--text-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--muted); margin-bottom: 6px;
}
.tm-field input[type="text"] {
  width: 100%; background: var(--card); border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  padding: 12px 14px; color: var(--text); font-size: var(--text-base); font-family: inherit;
}
.tm-field input[type="text"]:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px var(--green-lite); }

.tm-cta-block { width: 100%; justify-content: center; }
.tm-cta:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }

/* ── Header — team name/count on one side, the primary Add Player CTA on
   the other, same two-column pattern as the list screen's `.tm-head`, so
   it's always easy to find near the top. ───────────────────────────────── */
.tm-ed-header {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-4); margin-bottom: var(--space-5);
}
.tm-ed-header-text { min-width: 0; flex: 1 1 auto; }
.tm-ed-title-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.tm-ed-title {
  font-size: 1.7rem; font-weight: 900; letter-spacing: -0.5px; color: var(--text-strong);
  margin: 0; min-width: 0; max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tm-ed-subtitle { font-size: var(--text-sm); color: var(--muted); margin: 4px 0 0; }

/* Team Rating (task 4) — a quiet secondary metric pill, deliberately NOT
   styled like a tournament result/standings badge (task's own explicit
   instruction). */
.tm-team-rating {
  display: inline-flex; align-items: baseline; gap: 6px;
  margin-top: 8px; padding: 4px 12px;
  background: var(--bg-sunk); border-radius: var(--radius-pill);
}
.tm-team-rating-label { font-size: var(--text-xs); font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.tm-team-rating-value { font-size: var(--text-base); font-weight: 900; color: var(--text-strong); }

/* A quiet inline affordance next to the title — not a competing action,
   just a way to fix a typo in the team name without leaving the page. */
.tm-icon-btn-ghost {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 30px; height: 30px; border-radius: var(--radius-sm); border: none; background: transparent;
  color: var(--faint);
}
.tm-icon-btn-ghost svg { width: 15px; height: 15px; stroke: currentColor; }
.tm-icon-btn-ghost:hover:not(:disabled) { background: var(--green-tint); color: var(--green); }
.tm-icon-btn-ghost:disabled { opacity: 0.4; cursor: not-allowed; }

/* ── Roster — the main focus of the page: a lineup of clean rows, board
   order first and most prominent, reorder/edit/remove kept secondary.
   One row per player today; the row is already its own self-contained
   flex item so a future drag handle can slot in without restructuring. ── */
.tm-roster { display: flex; flex-direction: column; gap: 10px; margin-bottom: var(--space-6); }

.tm-roster-row {
  display: flex; align-items: center; gap: var(--space-4);
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: 14px var(--space-4); box-shadow: var(--shadow-sm);
}
.tm-roster-board {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--green-tint); color: var(--green); font-weight: 900; font-size: 0.95rem;
}
.tm-roster-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tm-roster-name {
  font-weight: 800; font-size: var(--text-base); color: var(--text-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tm-roster-sub { font-size: var(--text-xs); color: var(--muted); }
.tm-roster-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }

.tm-roster-btn {
  width: 32px; height: 32px; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--card); color: var(--muted); display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0;
}
.tm-roster-btn svg { width: 14px; height: 14px; stroke: currentColor; }
.tm-roster-btn:hover:not(:disabled) { border-color: var(--green-lite); color: var(--green); background: var(--green-tint); }
.tm-roster-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.tm-roster-btn-danger:hover:not(:disabled) { border-color: rgba(220, 38, 38, 0.35); color: var(--red); background: rgba(220, 38, 38, 0.06); }
/* Bulk-select checkbox (reuses .tm-club-checkbox's own square-with-
   checkmark styling wholesale) + the row's own selected state — same green
   highlight language as the Club Players list's .tm-club-row-selected. */
.tm-roster-row-selected { border-color: var(--green-lite); background: var(--green-tint); }
.tm-roster-bulk-remove-btn { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; font-size: 0.78rem; }
.tm-roster-bulk-remove-btn svg { width: 14px; height: 14px; stroke: currentColor; }

/* ── Player reorder — drag & drop "Edit order" mode (task 1). The old
   one-step Move up/down arrow buttons are removed entirely (not hidden) —
   this is the only order-editing UX now. The banner/actions row reuses
   the existing .tm-reorder-head/.tm-reorder-hint/.tm-reorder-actions/
   .tm-btn-outline/.tm-cta/.tm-spinner classes from the team-LIST's own
   (arrow-based) team-reorder feature above — same visual language, no
   duplicated layout rules; only the row/handle/dragging-state rules below
   are genuinely new. ─────────────────────────────────────────────────── */
.tm-roster-reorder { margin-top: var(--space-4); }
.tm-roster-row-reorder { cursor: default; }
.tm-roster-drag-handle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex-shrink: 0;
  color: var(--muted); background: none; border: none; padding: 0;
  cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none;
}
.tm-roster-drag-handle:hover { color: var(--green); }
.tm-roster-drag-handle svg { width: 18px; height: 18px; }
/* Every reorder-mode row transitions smoothly when it's shifted to "make
   space" for the one actually being dragged; the dragged row itself gets
   no transition (it must track the pointer 1:1, with no lag) plus a
   raised, shadowed look so it clearly reads as "lifted" above its
   neighbors while in motion. */
.tm-roster-row-reorder:not(.tm-roster-row-dragging) { transition: transform 120ms ease; }
.tm-roster-row-dragging {
  position: relative; z-index: 5;
  cursor: grabbing;
  box-shadow: var(--shadow-lg);
  background: var(--card);
  transition: none;
}
/* Set on <body> for the duration of any drag (task: "prevent accidental
   text-selection/ghost interactions") — belt-and-suspenders alongside the
   handle's own touch-action/user-select rules above, covering the rest of
   the page too while a drag is in progress. */
body.tm-member-reorder-active { cursor: grabbing; }
body.tm-member-reorder-active * { -webkit-user-select: none; user-select: none; }

/* ── "Add from Club Players" picker modal — reuses the Club Players list's
   own row language (.tm-club-row/.tm-club-checkbox/.tm-club-tag*) wholesale
   for every row that CAN be picked; an already-attached row gets its own
   quiet disabled treatment instead (never hidden — task's explicitly
   offered alternative), so the organizer can see their whole club roster
   in one place. ─────────────────────────────────────────────────────────── */
.tm-add-from-club-list {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 360px; overflow-y: auto; margin: var(--space-4) 0;
}
.tm-add-from-club-row, .tm-add-from-club-row:active { cursor: pointer; }
.tm-add-from-club-row-disabled, .tm-add-from-club-row-disabled:active { cursor: default; opacity: 0.6; }

/* Read-only board-order badge reused by Tournament Manager's own dark Team
   Round Robin structure view (app.js, inside `.mgmt-row`) — kept as its own
   rule, dark-themed via --mgmt-* like the rest of that screen, since it is
   NOT part of this light redesign. Do not fold into `.tm-roster-board`
   above (light-themed, a different screen entirely). */
.tm-member-order {
  width: 26px; height: 26px; border-radius: 50%; background: var(--mgmt-card);
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 0.8rem;
  color: var(--mgmt-muted); flex-shrink: 0;
}

/* ── Empty roster ─────────────────────────────────────────────────────── */
.tm-roster-empty {
  text-align: center; padding: var(--space-6) var(--space-5);
  background: var(--card-tint); border: 1.5px dashed var(--border); border-radius: var(--radius-lg);
  margin-bottom: var(--space-6);
}
.tm-roster-empty .tm-empty-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--green-tint); color: var(--green); margin: 0 auto var(--space-3);
}
.tm-roster-empty .tm-empty-icon svg { width: 24px; height: 24px; stroke: currentColor; }
.tm-roster-empty .tm-empty-title { font-size: 1.05rem; font-weight: 800; color: var(--text-strong); margin-bottom: 6px; }
.tm-roster-empty .tm-empty-text { font-size: var(--text-sm); color: var(--muted); margin: 0 auto; }

/* ── Team settings — quiet, collapsed by default (a plain <details>, no JS
   needed); rename/delete never compete with roster management above. ──── */
.tm-ed-settings { border-top: 1px solid var(--border-soft); padding-top: var(--space-4); }
.tm-ed-settings-summary {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font-size: var(--text-sm); font-weight: 700; color: var(--muted); list-style: none;
}
.tm-ed-settings-summary::-webkit-details-marker { display: none; }
.tm-ed-settings-summary svg { width: 15px; height: 15px; stroke: currentColor; }
.tm-ed-settings-summary:hover { color: var(--text); }
.tm-ed-settings-body { margin-top: var(--space-4); }
.tm-ed-danger-btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 16px; border-radius: var(--radius-sm); border: 1.5px solid var(--border);
  background: var(--card); color: var(--red); font-weight: 700; font-size: var(--text-sm);
}
.tm-ed-danger-btn svg { width: 15px; height: 15px; stroke: currentColor; }
.tm-ed-danger-btn:hover:not(:disabled) { border-color: var(--red); background: rgba(220, 38, 38, 0.06); }
.tm-ed-danger-btn:disabled { opacity: 0.5; cursor: not-allowed; }

@media (max-width: 640px) {
  .tm-ed-header { flex-direction: column; align-items: stretch; }
  .tm-ed-title { max-width: none; }
  .tm-ed-header .tm-cta { justify-content: center; }
  .tm-roster-row { flex-wrap: wrap; }
  .tm-roster-actions { width: 100%; justify-content: flex-end; }
}

/* ═══════════════════════════════════════════════════════════════════════
   3. MODALS — Add/Edit player, Rename team, Delete confirm, generic alert.
   Teams.js's own dedicated modal functions (tmAlert/tmConfirm/tmOpenRename
   Modal/tmOpenMemberModal — deliberately not app.js's mgmtAlert/mgmtConfirm,
   see this file's own header comment), styled to match this screen's light
   theme instead of app.js's/manage.css's dark `.mgmt-modal*`.
   ═══════════════════════════════════════════════════════════════════════ */
.tm-modal-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(20, 20, 20, 0.45);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-4);
}
.tm-modal {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--space-5); max-width: 420px; width: 100%; color: var(--text);
  box-shadow: 0 24px 64px rgba(20, 20, 20, 0.22);
}
.tm-modal-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 1.05rem; font-weight: 900; margin: 0 0 var(--space-4); color: var(--text-strong);
}
.tm-modal-title svg { width: 18px; height: 18px; stroke: currentColor; flex-shrink: 0; }
.tm-modal-title.danger { color: var(--red); }
.tm-modal-msg { font-size: var(--text-base); color: var(--text); margin: 0 0 var(--space-5); white-space: pre-line; line-height: 1.55; }
.tm-modal-field { margin-bottom: var(--space-4); }
.tm-modal-field label {
  display: block; font-size: var(--text-xs); font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--muted); margin-bottom: 6px;
}
.tm-modal-field input,
.tm-modal-field select,
.tm-modal-field textarea {
  width: 100%; background: var(--card); border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px; color: var(--text); font-size: var(--text-base); font-family: inherit;
}
.tm-modal-field textarea { resize: vertical; min-height: 140px; line-height: 1.6; }
.tm-modal-field input:focus,
.tm-modal-field select:focus,
.tm-modal-field textarea:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px var(--green-lite); }

/* ── Club Player form (Add/Edit player in the Club Players panel) — two
   fields per row so the fuller field set (rating/FIDE/number/birth date/
   gender) doesn't turn into a very long single-column form. ───────────── */
.tm-modal-club-player { max-width: 460px; }
.tm-modal-field-row { display: flex; gap: var(--space-3); }
.tm-modal-field-row .tm-modal-field { flex: 1; min-width: 0; margin-bottom: var(--space-4); }

/* ── Keelo-linked identity (migration 163) — a subtle badge for an
   already-linked player (edit modal), a quiet text-link action to link an
   existing guest, and the shared Keelo-user search modal both "Add Keelo
   Player" and "Link Keelo Account" open. ───────────────────────────────── */
.tm-cp-linked-badge {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: var(--space-4); padding: 8px 10px;
  background: var(--green-tint); border: 1px solid var(--green-lite); border-radius: var(--radius-sm);
  color: var(--green-dark); font-size: var(--text-sm); font-weight: 700;
}
.tm-cp-linked-badge svg { width: 15px; height: 15px; stroke: currentColor; flex-shrink: 0; }
.tm-modal-link-keelo-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-bottom: var(--space-4); padding: 9px 12px;
  border: 1.5px solid var(--green-lite); border-radius: var(--radius-sm);
  background: var(--green-tint); color: var(--green-dark);
  font-size: var(--text-sm); font-weight: 800;
}
.tm-modal-link-keelo-btn svg { width: 14px; height: 14px; stroke: currentColor; }
.tm-modal-link-keelo-btn:hover { background: var(--green-lite); }

/* ── Import player list — preview/review step (see teams.js's own header
   comment above tmRenderImportModal for the full phase state machine). ── */
.tm-hint { font-size: var(--text-sm); color: var(--muted); margin: 6px 0 0; line-height: 1.45; }
.tm-import-error { color: var(--red, #DC2626); font-weight: 700; }
.tm-modal-import { max-width: 560px; }
.tm-import-rows {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 320px; overflow-y: auto; margin: var(--space-3) 0;
}
.tm-import-row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px; border-radius: var(--radius-sm);
  background: var(--card-tint); border: 1px solid var(--border-soft);
}
.tm-import-row-dup { opacity: 0.72; }
.tm-import-name-input {
  flex: 1; min-width: 0; border: 1px solid transparent; background: transparent;
  font-size: var(--text-sm); font-family: inherit; color: var(--text-strong);
  padding: 3px 5px; border-radius: 6px;
}
.tm-import-name-input:hover, .tm-import-name-input:focus {
  border-color: var(--border); background: var(--card); outline: none;
}
/* Israeli Federation Player Number column — narrower than the name field,
   right next to it in the same row. */
.tm-import-fedid-input { flex: 0 0 118px; text-align: center; }
.tm-import-fedid-input.tm-import-error {
  border-color: var(--red, #DC2626); background: var(--card);
}
.tm-import-fedid-input.tm-import-error::placeholder { color: var(--red, #DC2626); }
/* Official Rating column (dual rating-source, migration 189, app repo) —
   same narrow-fixed-column treatment as the federation id input above,
   just narrower (shorter values), right next to it. */
.tm-import-rating-input { flex: 0 0 90px; text-align: center; }
.tm-import-rating-input.tm-import-error {
  border-color: var(--red, #DC2626); background: var(--card);
}
.tm-import-rating-input.tm-import-error::placeholder { color: var(--red, #DC2626); }
@media (max-width: 640px) {
  /* Two narrow-fixed-width inputs plus the name field and checkbox no
     longer fit on one line at phone width — wrap onto a second line
     instead of forcing horizontal overflow, and let the two fixed-width
     columns share the row's width evenly there rather than each claiming
     its own fixed px. */
  .tm-import-row { flex-wrap: wrap; }
  .tm-import-fedid-input, .tm-import-rating-input {
    flex: 1 1 90px;
  }
}

.tm-modal-keelo-search { max-width: 440px; }
.tm-search-results { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; margin-bottom: var(--space-3); }
.tm-search-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  background: var(--card-tint); color: var(--text); text-align: start;
  font-family: inherit; cursor: pointer;
}
.tm-search-row:hover { border-color: var(--green-lite); background: var(--green-tint); }
.tm-search-row-name { font-size: var(--text-sm); font-weight: 700; color: var(--text-strong); }
.tm-search-row-rating { font-size: var(--text-xs); font-weight: 700; color: var(--muted); flex-shrink: 0; }
.tm-search-empty { font-size: var(--text-sm); color: var(--muted); text-align: center; padding: var(--space-3) 0; }

.tm-modal-actions { display: flex; flex-direction: column; gap: 8px; }
.tm-modal-actions.row { flex-direction: row; }
.tm-modal-actions.row .tm-modal-btn { flex: 1; }
.tm-modal-btn {
  padding: 11px 16px; border-radius: var(--radius-sm); font-weight: 800; font-size: var(--text-sm);
  border: 1.5px solid var(--border); background: var(--card); color: var(--text);
}
.tm-modal-btn:hover:not(:disabled) { border-color: var(--green); }
.tm-modal-btn.primary { background: var(--green); border-color: var(--green); color: #fff; }
.tm-modal-btn.primary:hover:not(:disabled) { filter: brightness(1.08); }
.tm-modal-btn.danger { background: var(--red); border-color: var(--red); color: #fff; }
.tm-modal-btn.danger:hover:not(:disabled) { filter: brightness(1.1); }
.tm-modal-btn.ghost { background: transparent; color: var(--muted); }
.tm-modal-btn.ghost:hover:not(:disabled) { color: var(--text); border-color: var(--border); }
.tm-modal-btn:disabled { opacity: 0.6; cursor: wait; pointer-events: none; }

/* ── Post-drop action modal — the "Keep in both teams" / "Move here" /
   "View player profile" (disabled) choice shown after a player is dropped
   onto a different team card. A little wider than the base .tm-modal so
   each option's subtext has room to breathe. ────────────────────────────── */
.tm-modal-drop { max-width: 460px; }
.tm-drop-options { display: flex; flex-direction: column; gap: 10px; margin-bottom: var(--space-4); }
.tm-drop-option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--border);
  background: var(--card);
  text-align: start;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.tm-drop-option:hover:not(:disabled) { border-color: var(--green); background: var(--green-tint); }
.tm-drop-option-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--green-tint);
  color: var(--green);
}
.tm-drop-option-icon svg { width: 16px; height: 16px; stroke: currentColor; }
.tm-drop-option-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tm-drop-option-title { font-size: var(--text-sm); font-weight: 800; color: var(--text-strong); }
.tm-drop-option-sub { font-size: var(--text-xs); color: var(--muted); }
.tm-drop-option:disabled,
.tm-drop-option.tm-drop-option-disabled { opacity: 0.55; cursor: not-allowed; }
.tm-drop-option.tm-drop-option-disabled .tm-drop-option-icon { background: var(--border-soft); color: var(--muted); }
