/* Cap Room — mobile-first. The builder is one screen that never scrolls as a whole;
   only the player list scrolls, so the cap bar and the team carousel stay put. */

:root {
  --bg: #0b0d12;
  --panel: #151922;
  --panel-2: #1c212c;
  --line: #262d3a;
  --text: #eef1f6;
  --muted: #98a1b3;
  --accent: #f0653a;
  --team: #f0653a;            /* overwritten per selected team */

  --under: #4ba3f2;
  --cap: #f2c14b;
  --tax: #f0853a;
  --apron1: #ef5f4c;
  --apron2: #d6336c;

  --radius: 14px;
  --pad: 14px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
}

body {
  background: var(--bg);
  color: var(--text);
  font: 15px/1.45 ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  overscroll-behavior: none;
}

button { font: inherit; color: inherit; cursor: pointer; }

/* Never let the browser drag a picture out of the page — inside the carousel it steals
   the pointer stream and the wheel stops following the cursor. */
img { -webkit-user-drag: none; user-select: none; }

/* The share view is a full-screen overlay; the builder behind it is not merely covered,
   it is not rendered. */
body.is-sharing #builder { visibility: hidden; }

/* ─── builder shell ─────────────────────────────────────────────────────── */

#builder {
  display: grid;
  /* The column MUST be minmax(0, 1fr). Left implicit it is `auto`, which sizes to
     max-content — and the carousel rail's max-content is thirty logos wide, which drags
     every other row out to ~1800px and pushes their text off the screen. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr) auto auto;
  height: 100%;
  height: 100dvh;   /* mobile browsers whose toolbars eat into 100% */
  max-width: 560px;
  margin: 0 auto;
  padding: max(10px, env(safe-area-inset-top)) 12px max(10px, env(safe-area-inset-bottom));
  gap: 10px;
  overflow: hidden;
  /* Contain the carousel's z-indexes. The badges carry z-index up to 100; without a
     stacking context here they live in the root one and paint over the share view. */
  position: relative;
  z-index: 0;
}

/* Same reason: a grid or flex item defaults to min-width:auto and refuses to shrink
   below its content. Every one of these holds something that can be wider than the
   phone it is on. */
#builder > * { min-width: 0; }

/* ─── cap bar ───────────────────────────────────────────────────────────── */

.cap {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 11px var(--pad) 9px;
}

.cap-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 9px;
}

.cap-total {
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.cap-count {
  color: var(--muted);
  font-size: 0.8rem;
  margin-left: 6px;
}

.cap-status {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
  background: color-mix(in srgb, var(--under) 18%, transparent);
  color: var(--under);
}
.cap-status[data-tier="cap"]    { background: color-mix(in srgb, var(--cap) 18%, transparent);    color: var(--cap); }
.cap-status[data-tier="tax"]    { background: color-mix(in srgb, var(--tax) 18%, transparent);    color: var(--tax); }
.cap-status[data-tier="apron1"] { background: color-mix(in srgb, var(--apron1) 20%, transparent); color: var(--apron1); }
.cap-status[data-tier="apron2"] { background: color-mix(in srgb, var(--apron2) 22%, transparent); color: var(--apron2); }

.cap-track {
  position: relative;
  height: 26px;
  background: var(--panel-2);
  border-radius: 7px;
  overflow: hidden;
}

.cap-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: 7px 0 0 7px;
  background: linear-gradient(90deg,
    var(--under) 0%, var(--cap) 42%, var(--tax) 62%, var(--apron1) 78%, var(--apron2) 100%);
  /* Sized to the whole track from JS, so the colour at any point means the same thing
     however full the bar is. Without no-repeat the gradient tiles and a wide bar grows a
     second blue section at its right-hand end. */
  background-repeat: no-repeat;
  transition: width 260ms cubic-bezier(.25,.8,.3,1);
}

.cap-mark {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background: rgba(255, 255, 255, 0.28);
  opacity: 0.9;
}

.cap-mark::after {
  content: attr(data-label);
  position: absolute;
  top: 50%;
  left: 3px;
  transform: translateY(-50%);
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  white-space: nowrap;
}

.cap-mark.is-last::after { left: auto; right: 3px; }

.cap-note {
  margin: 7px 0 0;
  font-size: 0.76rem;
  color: var(--muted);
  min-height: 1.1em;
}

/* ─── selected squad ────────────────────────────────────────────────────── */

.squad { min-height: 62px; }

.squad-empty {
  margin: 0;
  padding: 20px 0 0;
  text-align: center;
  color: var(--muted);
  font-size: 0.82rem;
}

.squad-strip {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: none;
}
.squad-strip::-webkit-scrollbar { display: none; }

.chip {
  flex: 0 0 auto;
  min-width: 74px;
  background: var(--panel);
  border: 1px solid var(--chip-color, var(--line));
  border-left: 3px solid var(--chip-color, var(--accent));
  border-radius: 10px;
  padding: 7px 9px;
  text-align: left;
  line-height: 1.25;
  animation: pop 180ms cubic-bezier(.2,1.2,.4,1);
}

.chip-name {
  display: block;
  font-size: 0.78rem;
  font-weight: 650;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 96px;
}

.chip-salary {
  display: block;
  font-size: 0.72rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

@keyframes pop { from { transform: scale(.85); opacity: 0; } }

/* ─── roster list ───────────────────────────────────────────────────────── */

.roster {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

.roster-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 0 2px 7px;
}

.roster-head h1 {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.roster-payroll {
  font-size: 0.74rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.roster-search {
  width: 100%;
  margin: 0 0 7px;
  padding: 8px 11px;
  font: inherit;
  font-size: 0.86rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  -webkit-appearance: none;
  appearance: none;
}

.roster-search::placeholder { color: var(--muted); }

.roster-search:focus {
  outline: none;
  border-color: var(--team);
  background: var(--panel-2);
}

.roster-search::-webkit-search-cancel-button {
  -webkit-appearance: none;
  height: 14px;
  width: 14px;
  border-radius: 50%;
  background: var(--muted);
  cursor: pointer;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat;
}

.roster-list {
  list-style: none;
  margin: 0;
  padding: 0 0 4px;
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  scrollbar-width: thin;
  cursor: grab;
  user-select: none;          /* a drag should scroll, not select the names */
  -webkit-user-select: none;
  overscroll-behavior: contain;
}

.roster-list.is-dragging,
.squad-strip.is-dragging { cursor: grabbing; }

.squad-strip { cursor: grab; user-select: none; -webkit-user-select: none; }

.player {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 9px 11px;
  text-align: left;
  transition: border-color 120ms, background 120ms;
}

.player:hover { background: var(--panel-2); }

.player[aria-pressed="true"] {
  border-color: var(--team);
  background: color-mix(in srgb, var(--team) 13%, var(--panel));
}

/* The circle in the sketch is the player's face. Headshots are transparent PNGs, so the
   team colour sits behind them; players we could not match show their initials instead. */
.avatar {
  --avatar-size: 34px;
  position: relative;
  flex: 0 0 auto;
  width: var(--avatar-size);
  height: var(--avatar-size);
  border-radius: 50%;
  overflow: hidden;
  background: var(--avatar-bg, var(--panel-2));
  display: grid;
  place-items: center;
}

/* No object-fit and no background-size: the files are cropped square at build time, so
   there is nothing to fit. html2canvas honours neither property and mangled the faces
   whichever one we used. The radius is on the image itself as well as the wrapper,
   because html2canvas clips unreliably. */
.avatar img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  display: block;
}

.avatar-initials {
  font-size: calc(var(--avatar-size) * 0.36);
  font-weight: 800;
  color: rgba(255, 255, 255, 0.92);
  letter-spacing: -0.02em;
}

.player[aria-pressed="true"] .avatar {
  box-shadow: 0 0 0 2px var(--team);
}

/* Shown only when the list mixes teams — all-players, or a search. */
.player-team {
  flex: 0 0 auto;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  opacity: 0.9;
}

.player-check {
  flex: 0 0 auto;
  color: var(--team);
  font-weight: 900;
  font-size: 0.9rem;
  opacity: 0;
  transition: opacity 120ms;
}

.player[aria-pressed="true"] .player-check { opacity: 1; }

.player-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.player-salary {
  flex: 0 0 auto;
  font-size: 0.85rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  padding-left: 9px;
  border-left: 1px solid var(--line);
}

.player[aria-pressed="true"] .player-salary { color: var(--text); }

/* ─── team carousel ─────────────────────────────────────────────────────── */

/* A ring, not a scroller. Every badge is absolutely positioned at the centre and pushed
   out by its cyclic distance from the selection, so the chosen team is always in the
   middle and the wheel wraps past the ends of the alphabet. */
.carousel {
  position: relative;
  height: 76px;
  overflow: hidden;
  touch-action: pan-y;          /* horizontal drags are ours */
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
  --wheel-spacing: 46px;
  --wheel-visible: 3;
}

.carousel.is-dragging { cursor: grabbing; }

.carousel::before,
.carousel::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 42px;
  pointer-events: none;
  z-index: 2;
}
.carousel::before { left: 0;  background: linear-gradient(90deg, var(--bg), transparent); }
.carousel::after  { right: 0; background: linear-gradient(270deg, var(--bg), transparent); }

.carousel-rail { position: absolute; inset: 0; }

.team {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 54px;
  height: 54px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--panel);
  display: grid;
  place-items: center;
  padding: 6px;
  /* transform and opacity are written by layoutCarousel(); do not set them here. */
  transition: transform 200ms cubic-bezier(.22, .9, .3, 1), opacity 170ms,
              border-color 170ms, background 170ms;
  will-change: transform, opacity;
}

.carousel.is-dragging .team { transition: none; }

.team img { width: 100%; height: 100%; object-fit: contain; }

.team-code {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.team[aria-selected="true"] {
  border-color: var(--team);
  background: color-mix(in srgb, var(--team) 20%, var(--panel));
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
}

.team-count {
  position: absolute;
  bottom: 2px;
  right: 3px;
  font-size: 0.56rem;
  font-weight: 800;
  color: var(--team);
}

/* ─── share button ──────────────────────────────────────────────────────── */

.share-cta {
  border: 0;
  border-radius: 12px;
  padding: 13px;
  font-weight: 700;
  font-size: 0.95rem;
  background: var(--accent);
  color: #fff;
  transition: opacity 150ms, filter 150ms;
}

.share-cta:disabled { opacity: 0.32; cursor: not-allowed; }
.share-cta:not(:disabled):hover { filter: brightness(1.08); }

/* ─── share view ────────────────────────────────────────────────────────── */

#share-view {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto auto;
  gap: 10px;
  padding: max(10px, env(safe-area-inset-top)) 12px max(10px, env(safe-area-inset-bottom));
}

#share-view[hidden] { display: none; }

.share-scroll {
  overflow-y: auto;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

/* Auto margins centre a short card without the align-items:center trap, where a card
   taller than the viewport becomes impossible to scroll back to the top of. */
.card { margin-block: auto; }

.card {
  width: 100%;
  max-width: 460px;
  background: linear-gradient(170deg, #161b26, #0e1118);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 18px 16px 14px;
}

.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 13px;
}

.card-head h2 {
  margin: 0;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
}

.card-season {
  font-size: 0.76rem;
  color: var(--muted);
  font-weight: 600;
}

.card .cap {
  background: transparent;
  border: 0;
  padding: 0;
  margin-bottom: 14px;
}

.card-list {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.card-row {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 9px;
  background: rgba(255, 255, 255, 0.035);
  border: 0;
  border-left: 3px solid var(--row-color, var(--line));
  border-radius: 9px;
  text-align: left;
  color: inherit;
  transition: background 140ms, box-shadow 140ms;
}

.card-row:hover { filter: brightness(1.15); }

/* The starred rows are the starting five. Background and ring are set inline in JS with
   real rgba values, because html2canvas has to reproduce them in the downloaded image. */
.card-star {
  flex: 0 0 auto;
  font-size: 0.8rem;
  line-height: 1;
  color: #ffd35c;
}

.starter-hint {
  margin: 0;
  min-height: 1.15em;
  text-align: center;
  font-size: 0.76rem;
  color: var(--muted);
}

.card-row-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-row-team {
  font-size: 0.68rem;
  color: var(--muted);
  font-weight: 700;
  letter-spacing: 0.03em;
}

.card-row-salary {
  font-size: 0.84rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.card-foot {
  margin: 0;
  font-size: 0.7rem;
  color: var(--muted);
  text-align: center;
}

.card-url { color: var(--accent); font-weight: 700; }

.share-actions {
  display: flex;
  gap: 8px;
}

.share-actions button {
  flex: 1;
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 11px;
  padding: 12px 6px;
  font-weight: 650;
  font-size: 0.85rem;
}

.share-actions .primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.share-actions .ghost { color: var(--muted); }
.share-actions button:hover { filter: brightness(1.1); }

.share-hint {
  margin: 0;
  min-height: 1.1em;
  text-align: center;
  font-size: 0.75rem;
  color: var(--muted);
}

/* ─── wider screens ─────────────────────────────────────────────────────── */

@media (min-width: 640px) {
  .team { width: 60px; height: 60px; }
  .carousel { --wheel-spacing: 56px; --wheel-visible: 5; }
  .cap-mark::after { font-size: 0.6rem; }
}

/* Phone landscape: ~390px of height for five stacked rows. Give the list the slack. */
@media (max-height: 470px) {
  #builder { gap: 7px; }
  .cap { padding: 8px 12px 7px; }
  .cap-total { font-size: 1.15rem; }
  .cap-track { height: 20px; }
  .cap-note { display: none; }
  .squad { min-height: 46px; }
  .squad-empty { padding-top: 11px; font-size: 0.76rem; }
  .team { width: 42px; height: 42px; border-radius: 10px; }
  .carousel { height: 58px; --wheel-spacing: 37px; }
  .share-cta { padding: 9px; font-size: 0.88rem; }
}

/* Landscape phones have no vertical room for five stacked bands — the list ends up one
   row tall. There is plenty of width, so use it: cap across the top, list down the left,
   everything else in a right-hand column with the share button pinned to the bottom. */
@media (orientation: landscape) and (max-height: 520px) {
  #builder {
    max-width: 920px;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto 1fr auto;
    grid-template-areas:
      "cap  cap"
      "list squad"
      "list wheel"
      "list ."
      "list cta";
    column-gap: 12px;
    row-gap: 7px;
  }

  #cap       { grid-area: cap; }
  .roster    { grid-area: list; }
  .squad     { grid-area: squad; }
  .carousel  { grid-area: wheel; }
  .share-cta { grid-area: cta; }

  .cap-note { display: block; }      /* the width is there for it again */
  .squad { min-height: 52px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
