    :root {
      color-scheme: dark;
      --so-void: #070b1f;
      --so-surface: #0b1230;
      --so-surface-raised: #101838;
      --so-edge: #22306b;
      --so-volt: #2de2ff;
      --so-flux: #b026ff;
      --so-paper: #eaf0ff;
      --so-muted: #9aa8d5;
      --so-line: rgba(143, 246, 255, 0.16);
      --so-ease: cubic-bezier(0.22, 1, 0.36, 1);
    }

    /* ── Floodlights boot screen ─────────────────────────────────────────
       Plain CSS on purpose. tailwind.css is a committed build artifact, so a
       class missing from that build renders as nothing, silently -- and this
       layer has to be correct before anyone can see that it is not. Every rule
       here is self-contained under the boot- prefix.                        */
    #boot-splash {
      position: fixed;
      inset: 0;
      z-index: 9999;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 26px;
      padding: 24px;
      background: #070B1F;
      font-family: Inter, ui-sans-serif, system-ui, sans-serif;
      -webkit-font-smoothing: antialiased;
    }
    #boot-splash[hidden] { display: none; }

    .boot-scene {
      width: min(92vw, 440px);
      height: auto;
      display: block;
    }

    /* Lamp banks. `color` drives currentColor inside the shadow tree of a
       use element, the only styling hook that reaches symbol internals.      */
    .boot-lamp {
      color: #131A38;
      transition: color 0.45s ease-out;
    }
    .boot-scene[data-lit="1"] .boot-lamp[data-light="1"],
    .boot-scene[data-lit="2"] .boot-lamp[data-light="1"],
    .boot-scene[data-lit="2"] .boot-lamp[data-light="2"],
    .boot-scene[data-lit="3"] .boot-lamp[data-light="1"],
    .boot-scene[data-lit="3"] .boot-lamp[data-light="2"],
    .boot-scene[data-lit="3"] .boot-lamp[data-light="3"],
    .boot-scene[data-lit="4"] .boot-lamp,
    .boot-scene[data-lit="blast"] .boot-lamp {
      color: #2DE2FF;
      animation: boot-strike 0.42s steps(1, end) 1, boot-hum 2.6s ease-in-out 0.42s infinite;
      filter: drop-shadow(0 0 5px rgba(45,226,255,0.85)) drop-shadow(0 0 14px rgba(45,226,255,0.45));
    }
    .boot-scene[data-lit="blast"] .boot-lamp {
      animation: none;
      filter: drop-shadow(0 0 9px rgba(45,226,255,1)) drop-shadow(0 0 30px rgba(45,226,255,0.7));
    }

    /* A floodlight does not fade up, it strikes: on, off, on, on. This is the
       difference between reading as a stadium and reading as a checkbox.     */
    @keyframes boot-strike {
      0%   { opacity: 0.15; }
      18%  { opacity: 1; }
      30%  { opacity: 0.2; }
      44%  { opacity: 1; }
      56%  { opacity: 0.45; }
      70%  { opacity: 1; }
      100% { opacity: 1; }
    }
    @keyframes boot-hum {
      0%, 100% { opacity: 1; }
      50%      { opacity: 0.86; }
    }

    .boot-beam, .boot-pool {
      opacity: 0;
      transition: opacity 0.7s ease-out 0.2s;
    }
    .boot-scene[data-lit="1"] [data-light="1"].boot-beam,
    .boot-scene[data-lit="1"] [data-light="1"].boot-pool,
    .boot-scene[data-lit="2"] [data-light="1"].boot-beam,
    .boot-scene[data-lit="2"] [data-light="1"].boot-pool,
    .boot-scene[data-lit="2"] [data-light="2"].boot-beam,
    .boot-scene[data-lit="2"] [data-light="2"].boot-pool,
    .boot-scene[data-lit="3"] [data-light="1"].boot-beam,
    .boot-scene[data-lit="3"] [data-light="1"].boot-pool,
    .boot-scene[data-lit="3"] [data-light="2"].boot-beam,
    .boot-scene[data-lit="3"] [data-light="2"].boot-pool,
    .boot-scene[data-lit="3"] [data-light="3"].boot-beam,
    .boot-scene[data-lit="3"] [data-light="3"].boot-pool,
    .boot-scene[data-lit="4"] .boot-beam,
    .boot-scene[data-lit="4"] .boot-pool,
    .boot-scene[data-lit="blast"] .boot-beam,
    .boot-scene[data-lit="blast"] .boot-pool {
      opacity: 1;
    }

    /* The grass genuinely brightens four times -- one step per real event. */
    .boot-grass {
      fill: #2DE2FF;
      opacity: 0.018;
      transition: opacity 0.6s ease-out;
    }
    .boot-scene[data-lit="1"] .boot-grass { opacity: 0.032; }
    .boot-scene[data-lit="2"] .boot-grass { opacity: 0.05; }
    .boot-scene[data-lit="3"] .boot-grass { opacity: 0.075; }
    .boot-scene[data-lit="4"] .boot-grass { opacity: 0.1; }
    .boot-scene[data-lit="blast"] .boot-grass { opacity: 0.2; }

    .boot-line {
      fill: none;
      stroke: #2DE2FF;
      stroke-width: 1.1;
      opacity: 0.1;
      transition: opacity 0.6s ease-out;
    }
    .boot-scene[data-lit="1"] .boot-line { opacity: 0.16; }
    .boot-scene[data-lit="2"] .boot-line { opacity: 0.23; }
    .boot-scene[data-lit="3"] .boot-line { opacity: 0.3; }
    .boot-scene[data-lit="4"] .boot-line { opacity: 0.4; }
    .boot-scene[data-lit="blast"] .boot-line { opacity: 0.75; }

    .boot-mast { fill: #0E1533; stroke: rgba(255,255,255,0.10); stroke-width: 0.7; }

    .boot-wordmark {
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-weight: 800;
      font-size: 25px;
      letter-spacing: 6px;
      text-anchor: middle;
      fill: rgba(255,255,255,0.22);
      transition: fill 0.6s ease-out;
    }
    .boot-scene[data-lit="2"] .boot-wordmark { fill: rgba(255,255,255,0.4); }
    .boot-scene[data-lit="3"] .boot-wordmark { fill: rgba(255,255,255,0.68); }
    .boot-scene[data-lit="4"] .boot-wordmark,
    .boot-scene[data-lit="blast"] .boot-wordmark { fill: #ffffff; }

    .boot-copy {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 9px;
      text-align: center;
      max-width: 300px;
    }
    .boot-status {
      color: rgba(255,255,255,0.82);
      font-size: 13px;
      font-weight: 600;
      letter-spacing: 0.4px;
      margin: 0;
      min-height: 17px;
    }
    .boot-sub {
      color: rgba(255,255,255,0.34);
      font-size: 11.5px;
      font-weight: 400;
      line-height: 1.5;
      margin: 0;
      min-height: 17px;
    }
    .boot-bar {
      width: 200px;
      height: 3px;
      border-radius: 999px;
      background: rgba(255,255,255,0.08);
      overflow: hidden;
      opacity: 0;
      transition: opacity 0.45s ease-out;
    }
    .boot-bar[data-show="1"] { opacity: 1; }
    .boot-bar-fill {
      display: block;
      position: relative;
      width: 4%;
      height: 100%;
      border-radius: 999px;
      background: #2DE2FF;
      box-shadow: 0 0 8px 1px rgba(45,226,255,0.7);
      overflow: hidden;
      /* Linear, not eased: the bar is driven by its own creep loop, and an
         ease on top of that reads as the bar hesitating.                    */
      transition: width 0.4s linear;
    }
    /* Deep into a cold start the honest value barely moves -- a couple of
       pixels a minute. A bar that holds still reads as broken, so the light
       keeps travelling along it while the number tells the truth.           */
    .boot-bar-fill::after {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(90deg,
        rgba(255,255,255,0) 0%,
        rgba(255,255,255,0.75) 50%,
        rgba(255,255,255,0) 100%);
      animation: boot-sweep 1.6s linear infinite;
    }
    @keyframes boot-sweep {
      from { transform: translateX(-100%); }
      to   { transform: translateX(100%); }
    }

    .boot-action {
      appearance: none;
      -webkit-appearance: none;
      background: transparent;
      border: 1px solid rgba(255,255,255,0.16);
      border-radius: 999px;
      color: rgba(255,255,255,0.55);
      font-family: inherit;
      font-size: 12px;
      font-weight: 600;
      padding: 9px 20px;
      cursor: pointer;
      display: none;
      transition: border-color 0.15s, color 0.15s;
    }
    .boot-action[data-show="1"] { display: inline-block; }
    .boot-action:hover { border-color: rgba(45,226,255,0.5); color: #2DE2FF; }
    .boot-action:active { transform: scale(0.97); }

    #boot-splash[data-state="leaving"] {
      animation: boot-leave 0.44s cubic-bezier(0.4, 0, 0.2, 1) forwards;
      pointer-events: none;
    }
    @keyframes boot-leave {
      0%   { opacity: 1; transform: scale(1); }
      18%  { opacity: 1; transform: scale(1); background: #0b1f06; }
      100% { opacity: 0; transform: scale(1.045); }
    }

    @media (prefers-reduced-motion: reduce) {
      .boot-scene .boot-lamp { animation: none !important; }
      .boot-bar-fill::after { animation: none; opacity: 0; }
      #boot-splash[data-state="leaving"] {
        animation: boot-leave-plain 0.3s ease-out forwards;
      }
      @keyframes boot-leave-plain {
        from { opacity: 1; }
        to   { opacity: 0; }
      }
    }

    :focus-visible { outline: 2px solid #2DE2FF; outline-offset: 3px; }
    .no-scrollbar::-webkit-scrollbar { display: none; }
    .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

    @keyframes pulse-teal {
      0%, 100% { box-shadow: 0 0 6px 1px rgba(45,226,255,0.6); }
      50%       { box-shadow: 0 0 14px 4px rgba(45,226,255,0.9); }
    }
    .live-dot { animation: pulse-teal 1.8s ease-in-out infinite; }

    /* The tab you are on used to pulse a ring at you, forever, for no reason --
       the loudest thing on a screen you are not looking at. It is a still holo
       pill now: the tab is marked, it does not ask for attention. */
    .nav-on {
      background: linear-gradient(150deg, rgba(45,226,255,0.20), rgba(176,38,255,0.16));
      box-shadow: inset 0 0 0 1px rgba(45,226,255,0.4), 0 0 14px -5px rgba(45,226,255,0.9);
    }

    @keyframes court-ping {
      0%   { transform: scale(1);   opacity: 0.8; }
      70%  { transform: scale(2.2); opacity: 0;   }
      100% { transform: scale(1);   opacity: 0;   }
    }
    .court-ping::before {
      content: '';
      position: absolute;
      inset: 0;
      border-radius: 9999px;
      background: #2DE2FF;
      animation: court-ping 1.8s cubic-bezier(0,0,0.2,1) infinite;
    }

    @keyframes toast-in {
      from { opacity: 0; transform: translateX(-50%) translateY(10px); }
      to   { opacity: 1; transform: translateX(-50%) translateY(0);    }
    }
    @keyframes toast-out {
      from { opacity: 1; transform: translateX(-50%) translateY(0);    }
      to   { opacity: 0; transform: translateX(-50%) translateY(10px); }
    }
    .toast-enter { animation: toast-in  0.28s cubic-bezier(0.34,1.56,0.64,1) forwards; }
    .toast-exit  { animation: toast-out 0.22s ease-in forwards; }

    @keyframes section-in {
      from { opacity: 0; transform: translateY(6px); }
      to   { opacity: 1; transform: translateY(0);   }
    }
    .section-enter { animation: section-in 0.2s ease-out forwards; }

    body {
      background-color: #070B1F;
      -webkit-font-smoothing: antialiased;
    }

    button,
    [role="button"],
    a,
    input,
    select,
    textarea {
      touch-action: manipulation;
    }
    button:not(:disabled),
    [role="button"]:not([aria-disabled="true"]),
    a[href] { cursor: pointer; }
    button:disabled,
    [aria-disabled="true"] {
      cursor: not-allowed;
      opacity: 0.48;
    }
    [data-auth-nav][hidden] { display: none !important; }
    body:not(.is-authenticated) #main-content { margin-left: 0 !important; }
    body:not(.is-authenticated) .app-topbar { display: none; }

    /* Logged-out Game Night entrance. The playbook is a tactics board, not a
       generic marketing card: the three rows mirror the real weekly flow. */
    .landing-stage {
      position: relative;
      display: grid;
      min-height: 100dvh;
      width: min(100%, 88rem);
      margin-inline: auto;
      padding: max(1rem, env(safe-area-inset-top)) clamp(1rem, 4vw, 3rem)
        max(1.25rem, env(safe-area-inset-bottom));
      place-items: center;
      isolation: isolate;
    }
    .landing-stage::before {
      content: '';
      position: fixed;
      inset: 0;
      z-index: -2;
      pointer-events: none;
      background:
        radial-gradient(circle at 18% 18%, rgba(45, 226, 255, 0.11), transparent 28rem),
        radial-gradient(circle at 86% 78%, rgba(176, 38, 255, 0.10), transparent 30rem),
        var(--so-void);
    }
    .landing-stage::after {
      content: '';
      position: fixed;
      inset: 0;
      z-index: -1;
      pointer-events: none;
      opacity: 0.32;
      background-image:
        linear-gradient(rgba(143, 246, 255, 0.035) 1px, transparent 1px),
        linear-gradient(90deg, rgba(143, 246, 255, 0.035) 1px, transparent 1px);
      background-size: 40px 40px;
      mask-image: linear-gradient(to bottom, black, transparent 88%);
      -webkit-mask-image: linear-gradient(to bottom, black, transparent 88%);
    }
    .landing-board {
      position: relative;
      display: grid;
      width: 100%;
      overflow: hidden;
      border: 1px solid var(--so-line);
      border-radius: clamp(1.25rem, 3vw, 2rem);
      background:
        linear-gradient(145deg, rgba(16, 24, 56, 0.96), rgba(7, 11, 31, 0.98) 58%),
        var(--so-surface);
      box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.5),
        inset 0 1px rgba(255, 255, 255, 0.04);
    }
    .landing-board::before {
      content: '';
      position: absolute;
      inset: 0;
      pointer-events: none;
      background: linear-gradient(105deg, transparent 38%, rgba(45, 226, 255, 0.06), transparent 62%);
    }
    .landing-copy {
      position: relative;
      z-index: 1;
      display: flex;
      flex-direction: column;
      justify-content: center;
      padding: clamp(1.5rem, 5vw, 4.75rem);
    }
    .landing-brand {
      display: inline-flex;
      align-items: center;
      gap: 0.75rem;
      width: fit-content;
      margin-bottom: clamp(2rem, 5vw, 4.5rem);
      color: var(--so-paper);
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-size: 1.35rem;
      font-weight: 800;
      letter-spacing: 0.055em;
      text-transform: uppercase;
    }
    .landing-brand img {
      width: 2.375rem;
      height: 2.375rem;
    }
    .landing-eyebrow {
      display: inline-flex;
      align-items: center;
      gap: 0.65rem;
      width: fit-content;
      margin: 0 0 1.15rem;
      color: #b6c4ee;
      font-size: 0.75rem;
      font-weight: 800;
      letter-spacing: 0.14em;
      text-transform: uppercase;
    }
    .landing-eyebrow > span {
      width: 1.75rem;
      height: 2px;
      background: var(--so-volt);
      box-shadow: 0 0 12px rgba(45, 226, 255, 0.75);
    }
    .landing-title {
      max-width: 10ch;
      margin: 0;
      color: var(--so-paper);
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-size: clamp(3.25rem, 7vw, 6.8rem);
      font-weight: 800;
      letter-spacing: -0.045em;
      line-height: 0.84;
      text-transform: uppercase;
      text-wrap: balance;
    }
    .landing-title span {
      display: block;
      color: transparent;
      background: linear-gradient(100deg, #8ff6ff 0%, var(--so-volt) 35%, #ffffff 53%, #c77bff 72%, var(--so-flux) 100%);
      background-clip: text;
      -webkit-background-clip: text;
    }
    .landing-subtitle {
      max-width: 38rem;
      margin: 1.5rem 0 0;
      color: var(--so-muted);
      font-size: clamp(1rem, 1.8vw, 1.15rem);
      line-height: 1.65;
    }
    .landing-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 0.75rem;
      margin-top: 2rem;
    }
    .landing-action {
      min-height: 3rem;
      padding: 0.75rem 1.25rem;
      border: 1px solid transparent;
      border-radius: 0.9rem;
      font-size: 0.95rem;
      font-weight: 800;
      transition: border-color 180ms ease, background-color 180ms ease, box-shadow 180ms ease, opacity 180ms ease;
    }
    .landing-action-primary {
      min-width: 13rem;
      color: #ffffff;
      background: linear-gradient(100deg, #14748f, #4f3bc7 52%, #7f1cd1);
      box-shadow: 0 12px 32px -15px rgba(45, 226, 255, 0.9);
    }
    .landing-action-primary:hover {
      box-shadow: 0 15px 38px -14px rgba(45, 226, 255, 0.95);
      opacity: 0.94;
    }
    .landing-action-secondary {
      min-width: 7.5rem;
      color: var(--so-paper);
      border-color: rgba(234, 240, 255, 0.18);
      background: rgba(234, 240, 255, 0.055);
    }
    .landing-action-secondary:hover {
      border-color: rgba(143, 246, 255, 0.38);
      background: rgba(143, 246, 255, 0.09);
    }
    .landing-action:active { opacity: 0.78; }
    .landing-proof {
      margin: 1rem 0 0;
      color: #8997c6;
      font-size: 0.8rem;
      line-height: 1.5;
    }
    .landing-proof strong {
      color: var(--so-volt);
      font-variant-numeric: tabular-nums;
    }
    .landing-playbook {
      position: relative;
      z-index: 1;
      align-self: stretch;
      display: flex;
      flex-direction: column;
      justify-content: center;
      min-width: 0;
      padding: clamp(1.5rem, 4vw, 3.5rem);
      border-left: 1px solid var(--so-line);
      background:
        radial-gradient(circle at 50% 50%, transparent 0 4.9rem, rgba(143, 246, 255, 0.10) 5rem 5.05rem, transparent 5.15rem),
        linear-gradient(90deg, transparent calc(50% - 0.5px), rgba(143, 246, 255, 0.09) 50%, transparent calc(50% + 0.5px)),
        linear-gradient(rgba(45, 226, 255, 0.035), rgba(176, 38, 255, 0.035)),
        rgba(7, 11, 31, 0.58);
    }
    .landing-playbook-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      color: #b6c4ee;
      font-size: 0.7rem;
      font-weight: 800;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }
    .landing-live {
      display: inline-flex;
      align-items: center;
      gap: 0.45rem;
      color: var(--so-volt);
      letter-spacing: 0.08em;
    }
    .landing-live i {
      width: 0.45rem;
      height: 0.45rem;
      border-radius: 999px;
      background: var(--so-volt);
      box-shadow: 0 0 10px rgba(45, 226, 255, 0.9);
    }
    .landing-playbook h2 {
      max-width: 13ch;
      margin: 1.4rem 0 1.75rem;
      color: var(--so-paper);
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-size: clamp(1.8rem, 3vw, 2.6rem);
      font-weight: 700;
      letter-spacing: -0.02em;
      line-height: 1;
      text-transform: uppercase;
    }
    .landing-steps {
      display: grid;
      gap: 0;
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .landing-steps li {
      display: grid;
      grid-template-columns: 2.5rem minmax(0, 1fr);
      gap: 0.85rem;
      align-items: center;
      min-height: 4.75rem;
      padding-block: 0.8rem;
      border-top: 1px solid rgba(143, 246, 255, 0.12);
    }
    .landing-step-number {
      color: var(--so-volt);
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-size: 1.15rem;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
    }
    .landing-steps strong,
    .landing-steps div > span {
      display: block;
    }
    .landing-steps strong {
      color: var(--so-paper);
      font-size: 0.95rem;
    }
    .landing-steps div > span {
      margin-top: 0.2rem;
      color: var(--so-muted);
      font-size: 0.78rem;
      line-height: 1.45;
    }
    .landing-playbook-note {
      margin: 1.2rem 0 0;
      color: #8997c6;
      font-size: 0.75rem;
      line-height: 1.5;
    }
    .landing-secondary-actions {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: center;
      gap: 0.65rem;
      margin-top: 1rem;
      color: #8997c6;
      font-size: 0.78rem;
    }
    .landing-secondary-actions button {
      min-height: 2.75rem;
      padding-inline: 0.35rem;
      color: #aebce5;
      text-underline-offset: 0.25rem;
    }
    .landing-secondary-actions button:hover {
      color: var(--so-volt);
      text-decoration: underline;
    }

    @media (min-width: 840px) {
      .landing-board { grid-template-columns: minmax(0, 1.2fr) minmax(19rem, 0.8fr); }
    }
    @media (max-width: 839px) {
      .landing-stage { place-items: start center; }
      .landing-board { grid-template-columns: minmax(0, 1fr); }
      .landing-brand { margin-bottom: 2.25rem; }
      .landing-playbook {
        border-top: 1px solid var(--so-line);
        border-left: 0;
      }
    }
    @media (max-width: 479px) {
      .landing-copy,
      .landing-playbook { padding: 1.35rem; }
      .landing-title { font-size: clamp(3rem, 16vw, 4.5rem); }
      .landing-subtitle { font-size: 1rem; }
      .landing-actions { display: grid; grid-template-columns: 1fr; }
      .landing-action { width: 100%; min-height: 3.25rem; }
      .landing-secondary-actions { gap: 0.25rem 0.55rem; }
    }

    #feed-map, #courts-mini-map { position: absolute; inset: 0; z-index: 0; }

    .leaflet-tooltip-sportout {
      background: rgba(11,18,48,0.94);
      border: 1px solid rgba(45,226,255,0.35);
      color: #2DE2FF;
      font-family: 'Inter', sans-serif;
      font-size: 11px;
      font-weight: 600;
      border-radius: 8px;
      padding: 4px 8px;
      box-shadow: 0 0 8px 1px rgba(45,226,255,0.25);
      white-space: nowrap;
    }
    .leaflet-tooltip-sportout::before { border: none; }

    #app-toast { bottom: 88px; }
    @media (min-width: 1024px) { #app-toast { bottom: 24px; } }

    /* iOS safe-area utilities */
    .safe-pt     { padding-top: max(1.5rem, env(safe-area-inset-top)); }
    .safe-pb-nav { padding-bottom: max(1rem, env(safe-area-inset-bottom)); }
    .safe-pb-main { padding-bottom: calc(5.5rem + env(safe-area-inset-bottom)); }
    .safe-pb { padding-bottom: max(1.5rem, env(safe-area-inset-bottom)); }
    body:not(.is-authenticated) .safe-pb-main { padding-bottom: 0; }

    .profile-section-gutter {
      width: 100%;
      max-width: 48rem;
      margin-inline: auto;
      padding-inline: 1rem;
    }
    .profile-header-shell {
      width: 100%;
      max-width: 48rem;
      margin-inline: auto;
    }
    .profile-avatar,
    .profile-ovr-badge {
      width: clamp(80px, 5rem, 112px);
      height: clamp(80px, 5rem, 112px);
    }
    .profile-card-head { flex-wrap: wrap; }
    .profile-touch-target {
      min-width: 44px;
      min-height: 44px;
      touch-action: manipulation;
    }
    .profile-touch-target:disabled {
      cursor: not-allowed;
      opacity: 0.5;
    }
    .profile-card-carousel {
      scroll-padding-inline: 0.5rem;
      scroll-snap-type: x proximity;
      padding-right: 0.5rem;
      overscroll-behavior-inline: contain;
    }
    .profile-card-carousel > * { scroll-snap-align: start; }
    .profile-skeleton {
      background: linear-gradient(100deg, rgba(255,255,255,.04) 20%, rgba(255,255,255,.1) 40%, rgba(255,255,255,.04) 60%);
      background-size: 200% 100%;
      animation: profile-skeleton-shift 1.2s ease-in-out infinite;
    }
    @keyframes profile-skeleton-shift {
      from { background-position: 100% 0; }
      to { background-position: -100% 0; }
    }
    body.profile-overlay-open,
    body.app-dialog-open { overflow: hidden; }

    /* Player detail slide-in overlay */
    #player-detail-overlay {
      height: 100dvh;
      overscroll-behavior: contain;
      transform: translateX(100%);
      transition: transform 0.3s ease-out;
      will-change: transform;
    }
    #player-detail-overlay.pd-open {
      transform: translateX(0);
    }

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

    /* Memory sheet slide-in overlay — sits above the player detail */
    #memory-sheet-overlay {
      transform: translateX(100%);
      transition: transform 0.3s ease-out;
      will-change: transform;
    }
    #memory-sheet-overlay.ms-open {
      transform: translateX(0);
    }

    /* One night's temporary team card — above the recap, below player detail. */
    #memory-team-overlay {
      transform: translateX(100%);
      transition: transform 0.3s ease-out;
      will-change: transform;
    }
    #memory-team-overlay.mt-open {
      transform: translateX(0);
    }

    /* Court detail slide-in overlay */
    #court-detail-overlay {
      transform: translateX(100%);
      transition: transform 0.3s ease-out;
      will-change: transform;
    }
    #court-detail-overlay.cd-open {
      transform: translateX(0);
    }

    /* Match detail slide-in overlay */
    #match-detail-overlay {
      transform: translateX(100%);
      transition: transform 0.3s ease-out;
      will-change: transform;
    }
    #match-detail-overlay.md-open {
      transform: translateX(0);
    }

    /* Create match slide-in overlay */
    #create-match-overlay {
      transform: translateX(100%);
      transition: transform 0.3s ease-out;
      will-change: transform;
    }
    #create-match-overlay.cm-open {
      transform: translateX(0);
    }

    /* Form inputs in create-match overlay */
    .cm-input {
      width: 100%;
      background: #182248;
      border: 1px solid rgba(255,255,255,0.08);
      border-radius: 16px;
      padding: 12px 16px;
      color: white;
      font-size: 14px;
      outline: none;
      transition: border-color 0.15s;
      appearance: none;
      -webkit-appearance: none;
    }
    .cm-input:focus { border-color: rgba(45,226,255,0.4); }
    .cm-sport-btn {
      flex: 1;
      min-width: 0;
      padding: 8px 4px;
      border-radius: 12px;
      font-size: 11px;
      font-weight: 600;
      border: 1px solid rgba(255,255,255,0.08);
      background: #182248;
      color: rgba(255,255,255,0.4);
      cursor: pointer;
      transition: all 0.15s;
      text-align: center;
    }
    .cm-sport-btn.active {
      background: rgba(45,226,255,0.15);
      border-color: rgba(45,226,255,0.4);
      color: #2DE2FF;
    }
    .cm-chip {
      flex: 1;
      padding: 10px 4px;
      border-radius: 12px;
      font-size: 13px;
      font-weight: 700;
      border: 1px solid rgba(255,255,255,0.08);
      background: #182248;
      color: rgba(255,255,255,0.4);
      cursor: pointer;
      transition: all 0.15s;
      text-align: center;
    }
    .cm-chip.active {
      background: rgba(45,226,255,0.15);
      border-color: rgba(45,226,255,0.4);
      color: #2DE2FF;
    }

    /* Fullscreen map modal */
    #map-modal {
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transition: opacity 0.25s ease, visibility 0s linear 0.25s;
    }
    #map-modal.map-open {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transition-delay: 0s;
    }
    #fullscreen-map {
      flex: 1;
      min-height: 0;
      position: relative;
    }

    /* Sport filter chip states */
    .sport-chip {
      flex-shrink: 0;
      padding: 6px 16px;
      border-radius: 9999px;
      font-size: 12px;
      font-weight: 500;
      border: 1px solid rgba(255,255,255,0.08);
      background: #101838;
      color: rgba(255,255,255,0.4);
      cursor: pointer;
      transition: all 0.15s;
      white-space: nowrap;
    }
    .sport-chip.active {
      background: rgba(45,226,255,0.15);
      border-color: rgba(45,226,255,0.4);
      color: #2DE2FF;
      font-weight: 600;
    }
    .region-chip {
      flex-shrink: 0;
      padding: 5px 14px;
      border-radius: 9999px;
      font-size: 11px;
      font-weight: 500;
      border: 1px solid rgba(255,255,255,0.06);
      background: #0B1230;
      color: rgba(255,255,255,0.35);
      cursor: pointer;
      transition: all 0.15s;
      white-space: nowrap;
    }
    .region-chip.active {
      background: rgba(45,226,255,0.10);
      border-color: rgba(45,226,255,0.35);
      color: #2DE2FF;
      font-weight: 600;
    }
    .region-chip.following-active {
      background: rgba(45,226,255,0.10);
      border-color: rgba(45,226,255,0.35);
      color: #2DE2FF;
      font-weight: 600;
    }

    /* Highlight grid squares */
    .highlight-sq {
      aspect-ratio: 1;
      border-radius: 6px;
      background: #101838;
      border: 1px solid rgba(255,255,255,0.05);
      cursor: pointer;
      overflow: hidden;
      position: relative;
      transition: border-color 0.15s;
    }
    .highlight-sq:hover { border-color: rgba(45,226,255,0.3); }
    .highlight-sq:active { transform: scale(0.96); }

    /* ═══════════════════════════════════════════════════════════════
       HOLO CARD  (.hc-*)
       The player's identity as a collectible, not as a stats panel.
       Plain CSS on purpose: clip-path polygons, conic gradients and
       background-clip:text do not survive the prebuilt-Tailwind step
       cleanly, and this is the one component the whole product is for.
       ═══════════════════════════════════════════════════════════════ */

    /* The silhouette: cut shoulders and a point at the bottom. This alone is
       what stops the card reading as another rounded rectangle. The border is
       a 2px gradient frame painted by the wrapper showing through the inset. */
    .hc-wrap {
      position: relative;
      display: block;
      padding: 2px;
      --hc-sil: polygon(6% 0, 94% 0, 100% 5%, 100% 92%, 50% 100%, 0 92%, 0 5%);
      clip-path: var(--hc-sil);
      background: linear-gradient(160deg, #2DE2FF, #6C4BFF 42%, #B026FF 70%, #28E7FF);
      filter: drop-shadow(0 0 22px rgba(45,226,255,0.30))
              drop-shadow(0 0 44px rgba(176,38,255,0.34));
    }
    .hc {
      position: relative;
      overflow: hidden;
      clip-path: var(--hc-sil);
      background: linear-gradient(168deg, #1B2A6B 0%, #141C48 34%, #0C1230 72%, #161A44 100%);
      padding: 20px 20px 32px;
    }
    /* Foil: two crossing weaves in cyan and violet — the diamond of a goal net —
       plus one soft gloss band. Screen blend so it lifts the ground instead of
       greying it. */
    .hc::after {
      content: "";
      position: absolute; inset: 0;
      pointer-events: none;
      mix-blend-mode: screen;
      opacity: 0.62;
      background:
        repeating-linear-gradient(45deg,  rgba(45,226,255,0.11) 0 1px, transparent 1px 13px),
        repeating-linear-gradient(-45deg, rgba(176,38,255,0.11) 0 1px, transparent 1px 13px),
        linear-gradient(112deg, transparent 26%, rgba(255,255,255,0.16) 41%,
                                rgba(255,255,255,0.03) 49%, transparent 64%);
    }
    /* The sweep: one highlight crosses the foil, then a long pause. One moment,
       not constant motion — constant motion is what makes a page look generated. */
    .hc::before {
      content: "";
      position: absolute;
      top: -60%; bottom: -60%; left: -60%;
      width: 52%;
      z-index: 4;
      pointer-events: none;
      transform: rotate(16deg);
      background: linear-gradient(90deg, transparent, rgba(255,255,255,0.015) 30%,
                  rgba(255,255,255,0.22) 50%, rgba(255,255,255,0.015) 70%, transparent);
      animation: hc-sweep 5.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;
    }
    @keyframes hc-sweep { 0%, 62% { left: -60%; } 100% { left: 120%; } }

    .hc-body { position: relative; z-index: 5; }

    /* The app's mark: the same cut silhouette at 34px. A highlight sweeping
       across something this small is noise, so the mark does not sweep. */
    .hc-mark {
      display: inline-block;
      padding: 1.5px;
      filter: drop-shadow(0 0 10px rgba(45,226,255,0.35))
              drop-shadow(0 0 18px rgba(176,38,255,0.30));
    }
    .hc-mark .hc         { padding: 0; width: 100%; height: 100%; display: grid; place-items: center; }
    .hc-mark .hc::before { display: none; }

    /* Foil fills. Numerals and the name read as metal, not as coloured text. */
    .hc-holo {
      background: linear-gradient(103deg, #8FF6FF 0%, #2DE2FF 26%, #FFFFFF 43%,
                                  #C77BFF 62%, #B026FF 82%, #7FEFFF 100%);
      -webkit-background-clip: text; background-clip: text; color: transparent;
    }
    .hc-gold {
      background: linear-gradient(175deg, #FFF0B8, #FFC93C 48%, #C98A10 82%, #FFE58A);
      -webkit-background-clip: text; background-clip: text; color: transparent;
    }
    .hc-disp {
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-weight: 800;
    }
    /* line-height under 1 clips a Saira numeral at the baseline; the padding is
       what stops the descender of the gradient fill being cut by the clip-path. */
    .hc-ovr { display: inline-block; font-size: 76px; line-height: 1.04; letter-spacing: -0.02em; padding-bottom: 2px; }
    .hc-name { display: inline-block; font-size: 25px; line-height: 1.05; letter-spacing: 0.01em; }
    .hc-label {
      font-size: 9px; font-weight: 700; letter-spacing: 0.18em;
      text-transform: uppercase; color: #8290C4;
    }
    .hc-stat { font-size: 22px; line-height: 1; font-variant-numeric: tabular-nums; color: #EAF0FF; }
    .hc-rule { height: 1px; background: linear-gradient(90deg, transparent, rgba(45,226,255,0.35), transparent); }

    /* ── The aura ────────────────────────────────────────────────────
       The ONLY thing rep pays out. Light around the player, wherever the
       player appears. It never grants an ability — every player can do
       everything. Rookie is deliberately bare so the first ring is felt. */
    .au { position: relative; display: grid; place-items: center; flex: none; }
    .au-in {
      position: relative; z-index: 2;
      border-radius: 9px;
      display: grid; place-items: center;
      font-family: "Saira Condensed", Oswald, Impact, sans-serif;
      font-weight: 800;
      background: #0E1533;
      border: 1px solid #22306B;
      color: #8290C4;
    }
    .au-rookie  .au-in { border-color: #182248; }
    .au-baller  .au-in {
      border-color: rgba(176,38,255,0.8); color: #C08BFF;
      box-shadow: 0 0 0 1px rgba(176,38,255,0.3), 0 0 10px -3px rgba(176,38,255,0.9);
    }
    .au-allstar .au-in {
      border-color: #2DE2FF; color: #2DE2FF;
      animation: au-breathe 2.6s ease-in-out infinite;
    }
    @keyframes au-breathe {
      0%, 100% { box-shadow: 0 0 0 1px rgba(45,226,255,0.45), 0 0 11px -3px rgba(45,226,255,0.85); }
      50%      { box-shadow: 0 0 0 2px rgba(45,226,255,0.85), 0 0 22px 0    rgba(45,226,255,1); }
    }
    .au-legend::before {
      content: ""; position: absolute; inset: -3px; border-radius: 12px; z-index: 1;
      background: conic-gradient(from 0deg, #FFC93C, #FFF6D0 12%, #2DE2FF 38%,
                                 #B026FF 62%, #FFE9A8 84%, #FFC93C);
      animation: au-spin 3.4s linear infinite;
    }
    .au-legend::after {
      content: ""; position: absolute; inset: -10px; border-radius: 20px; z-index: 0;
      background: radial-gradient(circle, rgba(255,201,60,0.5), rgba(176,38,255,0.18) 45%, transparent 70%);
      animation: au-pulse 2.4s ease-in-out infinite;
    }
    @keyframes au-spin  { to { transform: rotate(360deg); } }
    @keyframes au-pulse { 0%, 100% { opacity: 0.5; transform: scale(0.94); }
                          50%      { opacity: 1;   transform: scale(1.06); } }
    .au-legend .au-in { border-color: transparent; background: #141031; color: #FFD764; }

    /* The aura also has to work as a round avatar, which is how a player is
       drawn everywhere outside their own card. */
    .au-round .au-in     { border-radius: 9999px; }
    .au-round::before    { border-radius: 9999px; }
    .au-round::after     { border-radius: 9999px; }
    .au-av { font-size: 13px; width: 34px; height: 34px; }

    /* One card holds one aura and it can breathe. A list holds twenty, and in a
       group that has played a season most of them are All-Star -- twenty
       breathing rings at once is a flicker wall, not status. On a list the
       All-Star ring holds still and only Legend turns, so the rarest tier is
       the only thing moving. Verified against a full 20-player Board. */
    .au-still.au-allstar .au-in {
      animation: none;
      box-shadow: 0 0 0 1px rgba(45,226,255,0.5), 0 0 13px -3px rgba(45,226,255,0.9);
    }
    .au-still.au-legend::before { animation-duration: 7s; }
    .au-still.au-legend::after  { animation: none; opacity: 0.62; transform: scale(1); }

    /* ── Badges ──────────────────────────────────────────────────────
       The aura says how much you have PLAYED. A badge says what you have
       DONE. Earned once, kept for good, and — like the aura — it grants no
       ability whatsoever. Gold is deliberately absent from this palette:
       it is Legend's alone, and a gold badge would quietly spend it.
       A slot is always drawn, earned or not, so a player with none still
       sees what there is to chase instead of an empty gap. */
    /* The row is the last thing in the card, and the card ends in a point. At
       the default bottom padding the count text lands 0.6% below where the
       silhouette starts tapering — measured, not guessed — which survives ×7
       and would not survive a wider count. The padding lifts the whole row
       clear of the taper instead of relying on the text staying short. */
    .bd-row { display: flex; align-items: flex-start; gap: 9px; padding-bottom: 14px; }
    .bd     { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: none; }
    /* 40px, not the 34px this started at. A mark with two parts — a hat sitting
       on a ball carrying a number — turns to mush at 34/15px; at 40/23px every
       part reads. Checked against the widest case: five medallions come to
       266px inside a card that has 310px on a 390px phone. 46px reads better
       still and was rejected — with most of the catalogue unearned it turns the
       empty slots into five loud holes. */
    .bd-hex {
      display: block; width: 40px; height: 45px; padding: 1.5px;
      --bd-sil: polygon(50% 0, 100% 26%, 100% 74%, 50% 100%, 0 74%, 0 26%);
      clip-path: var(--bd-sil);
      background: #1A2350;
    }
    /* Marks knock detail out of themselves with --bd-bg rather than a baked-in
       hex, so the number on the ball stays the ground behind it in both the
       earned and the unearned state. */
    .bd-in {
      display: grid; place-items: center; width: 100%; height: 100%;
      clip-path: var(--bd-sil);
      --bd-bg: #0B1130;
      background: var(--bd-bg); color: #35427F;
    }
    /* Badge levels, the 2K idea: a badge is easy to GET and hard to MAX, so the
       first one lands early and the top frame takes years. The ladder is the
       app's own — steel, volt, flux, then the full card gradient. Gold is
       deliberately not on it: that colour is the Legend rep tier's alone and a
       top-level badge would spend it. Nothing here animates — the card already
       has one breathing aura, and five moving badges beside it is a flicker
       wall (the same lesson the Board taught). */
    /* Both sizes of the same medallion: .bd-hex on a card, .bs-hex blown up in
       the sheet. The level frame has to reach both — listed once so the sheet
       cannot quietly show a level-4 badge wearing a level-0 frame. */
    .bd-on .bd-in,
    .bd-on .bs-in    { --bd-bg: #101838; color: #EAF0FF; }
    .bd-t1 .bd-hex,
    .bd-t1 .bs-hex   { background: #47548F; }
    .bd-t2 .bd-hex,
    .bd-t2 .bs-hex   {
      background: linear-gradient(158deg, #6FEDFF, #1E9FD8);
      filter: drop-shadow(0 0 6px rgba(45,226,255,0.30));
    }
    .bd-t3 .bd-hex,
    .bd-t3 .bs-hex   {
      background: linear-gradient(158deg, #C77BFF, #7B1FCC);
      filter: drop-shadow(0 0 6px rgba(176,38,255,0.36));
    }
    .bd-t4 .bd-hex,
    .bd-t4 .bs-hex   {
      background: linear-gradient(158deg, #2DE2FF, #6C4BFF 46%, #B026FF);
      filter: drop-shadow(0 0 9px rgba(45,226,255,0.42))
              drop-shadow(0 0 17px rgba(176,38,255,0.38));
    }
    .bd-n {
      font-size: 9px; font-weight: 700; letter-spacing: 0.04em;
      font-variant-numeric: tabular-nums; color: #8290C4; min-height: 11px;
    }
    /* Every slot opens its badge, earned or not — what is still out there is
       half of why anyone chases it. */
    .bd-tap { cursor: pointer; }
    .bd-tap:active .bd-hex { transform: scale(0.94); }
    .bd-hex { transition: transform .12s ease; }
    .bd-tap:focus-visible { outline: 2px solid #2DE2FF; outline-offset: 3px; border-radius: 4px; }

    /* The badge sheet. One badge, big enough to actually look at, with the rule
       in the player's own words underneath. */
    .bs-hex {
      display: block; width: 96px; height: 108px; padding: 2.5px; margin: 0 auto;
      --bd-sil: polygon(50% 0, 100% 26%, 100% 74%, 50% 100%, 0 74%, 0 26%);
      clip-path: var(--bd-sil); background: #1A2350;
    }
    .bs-in {
      display: grid; place-items: center; width: 100%; height: 100%;
      clip-path: var(--bd-sil); --bd-bg: #0B1130; background: var(--bd-bg); color: #35427F;
    }

    /* ── The Board ───────────────────────────────────────────────────
       A league table is a list, not a column of boxes. Bare ground and a
       hairline between entries; the aura does the work the card background
       used to pretend to do. */
    .bo-title {
      font-size: 34px; line-height: 1; letter-spacing: 0.04em;
      text-transform: uppercase; font-weight: 900;
      display: inline-block;
    }
    .bo-row {
      display: flex; align-items: center; gap: 12px;
      padding: 12px 4px;
      cursor: pointer;
      transition: background-color 0.15s;
    }
    .bo-row:active { background: rgba(45,226,255,0.05); }
    .bo-row.is-me  { background: rgba(45,226,255,0.06); border-radius: 12px; }
    .bo-hr { height: 1px; background: rgba(255,255,255,0.06); }
    .bo-rank {
      width: 26px; flex: none; text-align: center;
      font-size: 17px; line-height: 1; color: #5C6AA0;
      font-variant-numeric: tabular-nums;
    }
    .bo-name { font-size: 14px; font-weight: 600; color: #EAF0FF; }
    .bo-sub  { font-size: 11px; color: #6C7AB0; margin-top: 2px; }
    .bo-score { font-size: 22px; line-height: 1; flex: none; font-variant-numeric: tabular-nums; }
    .bo-tag {
      display: inline-block; margin-left: 7px; vertical-align: 1px;
      font-size: 9px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
      padding: 2px 6px; border-radius: 5px;
      border: 1px solid currentColor;
    }
    .t-rookie  { color: #6C7AB0; }
    .t-baller  { color: #C08BFF; }
    .t-allstar { color: #2DE2FF; }
    .t-legend  { color: #FFC93C; }

    @media (prefers-reduced-motion: reduce) {
      .hc::before { animation: none; left: -60%; }
      .au-legend::before, .au-legend::after, .au-allstar .au-in { animation: none; }
      .au-allstar .au-in { box-shadow: 0 0 0 1px rgba(45,226,255,0.6), 0 0 14px -3px rgba(45,226,255,0.9); }
    }
