﻿/* ============================================================
   Ambient background
   ============================================================ */
.bg-field{
  position:fixed; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(ellipse 60% 45% at 50% 8%, rgba(127,162,201,0.10), transparent 60%),
    radial-gradient(ellipse 70% 50% at 50% 100%, rgba(205,166,95,0.05), transparent 60%),
    var(--ink);
}
.bg-grid{
  position:absolute; inset:0;
  background-image:
    linear-gradient(rgba(236,231,220,0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(236,231,220,0.028) 1px, transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(ellipse 80% 70% at 50% 30%, black 20%, transparent 75%);
}
.glyph{
  position:absolute;
  font-family:var(--font-display);
  color:rgba(236,231,220,0.05);
  font-size:11rem;
  font-weight:500;
  user-select:none;
  animation:drift 22s ease-in-out infinite;
}
.glyph--1{ top:8%;  left:6%;  font-size:9rem;  animation-duration:26s; }
.glyph--2{ top:58%; left:4%;  font-size:12rem; animation-duration:30s; animation-delay:-4s; }
.glyph--3{ top:12%; right:6%; font-size:14rem; animation-duration:24s; animation-delay:-9s; }
.glyph--4{ top:62%; right:8%; font-size:10rem; animation-duration:28s; animation-delay:-14s; }
.glyph--5{ bottom:4%; left:44%; font-size:8rem; animation-duration:20s; animation-delay:-6s; }
@keyframes drift{
  0%,100%{ transform:translateY(0) rotate(0deg); }
  50%{ transform:translateY(-22px) rotate(1.5deg); }
}
.bg-vignette{
  position:absolute; inset:0;
  box-shadow:inset 0 0 220px 40px rgba(0,0,0,0.75);
}


/* ============================================================
   View switching (Gacha / Collection)
   ============================================================ */
.view{ display:none; flex:1; }
.view--active{ display:flex; flex-direction:column; }
#collectionView.view--active{ display:block; }

/* ============================================================
   Hero (Gacha view)
   ============================================================ */
.hero{
  flex:1;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center;
  padding:30px 20px 60px;
}
.hero__eyebrow{
  margin:0 0 26px; font-size:0.72rem; letter-spacing:0.22em; text-transform:uppercase; color:var(--paper-dim);
}

.pack-progress{ display:flex; flex-wrap:wrap; justify-content:center; gap:10px; margin-bottom:22px; }
.pack-progress__item{
  display:flex; align-items:baseline; gap:6px;
  padding:8px 16px; border-radius:999px;
  background:rgba(236,231,220,0.04); border:1px solid var(--line);
  font-size:0.76rem; color:var(--paper-dim);
  transition:border-color .25s var(--ease), background .25s var(--ease);
}
.pack-progress__count{ font-family:var(--font-display); font-weight:600; font-size:1rem; color:var(--paper); }
.pack-progress__item.is-ready{ border-color:var(--gold-dim); background:rgba(205,166,95,0.1); }
.pack-progress__item.is-ready .pack-progress__count{ color:var(--gold); }

.pack-stage{ position:relative; width:min(46vw, 320px); display:flex; align-items:center; justify-content:center; }
.pack-stage__glow{
  position:absolute; top:50%; left:50%; width:65%; height:65%;
  transform:translate(-50%,-50%);
  background:radial-gradient(circle, rgba(200,198,190,0.4) 0%, rgba(200,198,190,0.14) 45%, transparent 72%);
  filter:blur(14px); animation:pulse 4.5s ease-in-out infinite; z-index:0;
  transition:background .4s var(--ease);
}
.pack-stage__glow[data-tier="rare"]{
  background:radial-gradient(circle, rgba(127,162,201,0.45) 0%, rgba(127,162,201,0.16) 45%, transparent 72%);
}
.pack-stage__glow[data-tier="legendary"]{
  background:radial-gradient(circle, rgba(205,166,95,0.5) 0%, rgba(205,166,95,0.18) 45%, transparent 72%);
}
@keyframes pulse{
  0%,100%{ opacity:0.65; transform:translate(-50%,-50%) scale(0.96); }
  50%{ opacity:1; transform:translate(-50%,-50%) scale(1.04); }
}
.pack{
  position:relative; z-index:1; border:none; background:transparent; padding:0; width:100%; display:block;
  animation:float 5s ease-in-out infinite;
  filter:drop-shadow(0 30px 45px rgba(0,0,0,0.65)) drop-shadow(0 0 40px rgba(127,162,201,0.18));
  /* filter is here too (not just transform) as a safety net for the
     moment .flash is removed after a pull -- the keyframes' own 100% frame
     already lands back on this exact filter, so this only ever has to
     smooth over a slow server response stretching past the animation's
     planned duration, not fight the keyframes themselves. */
  transition:transform .4s var(--ease), filter .4s var(--ease);
}
.pack:hover{ transform:scale(1.035) rotate(-0.6deg); }
.pack:active{ transform:scale(0.985) rotate(0.2deg); }
.pack.is-locked{ cursor:default; }
@keyframes float{
  0%,100%{ transform:translateY(0); }
  50%{ transform:translateY(-10px); }
}

.pack__inner{ display:block; transform-origin:50% 60%; transition:transform .3s var(--ease); }
.pack__inner.shaking{ animation:pack-shake 650ms cubic-bezier(.36,.07,.19,.97) both; }
@keyframes pack-shake{
  8%  { transform:translateX(-7px) rotate(-3deg); }
  16% { transform:translateX(8px)  rotate(3.4deg); }
  24% { transform:translateX(-10px) rotate(-4deg); }
  32% { transform:translateX(10px) rotate(4deg); }
  40% { transform:translateX(-9px) rotate(-3.6deg); }
  48% { transform:translateX(9px)  rotate(3.6deg); }
  56% { transform:translateX(-7px) rotate(-2.6deg); }
  64% { transform:translateX(7px)  rotate(2.6deg); }
  72% { transform:translateX(-4px) rotate(-1.6deg); }
  80% { transform:translateX(4px)  rotate(1.6deg); }
  88% { transform:translateX(-2px) rotate(-0.6deg); }
  100%{ transform:translateX(0)    rotate(0deg); }
}

.pack.flash{ animation:pack-flash 550ms ease-out both; }
@keyframes pack-flash{
  0%{ filter:drop-shadow(0 30px 45px rgba(0,0,0,0.65)) drop-shadow(0 0 40px rgba(127,162,201,0.18)) brightness(1); }
  35%{ filter:drop-shadow(0 30px 45px rgba(0,0,0,0.65)) drop-shadow(0 0 90px rgba(205,166,95,0.85)) brightness(1.6); transform:scale(1.06); }
  100%{ filter:drop-shadow(0 30px 45px rgba(0,0,0,0.65)) drop-shadow(0 0 40px rgba(127,162,201,0.18)) brightness(1); transform:scale(1); }
}

.pack__img{ width:100%; height:auto; display:block; border-radius:6px; }

.pack-stage__particles{ position:absolute; inset:0; z-index:2; pointer-events:none; }
.spark{
  position:absolute; width:5px; height:5px; border-radius:50%;
  background:var(--gold); box-shadow:0 0 8px 2px rgba(205,166,95,0.7); opacity:0;
}
.spark.play{ animation:spark-fly 900ms ease-out forwards; }
@keyframes spark-fly{
  0%{ opacity:1; transform:translate(0,0) scale(1); }
  100%{ opacity:0; transform:var(--fly) scale(0.3); }
}

.hero__cta-row{ display:flex; justify-content:center; gap:14px; margin-top:38px; }

.wheel-fab{
  position:fixed; left:20px; bottom:20px; z-index:30;
  display:flex; align-items:center; gap:8px;
  padding:11px 18px; border-radius:999px;
  background:var(--ink-3); border:1px solid var(--line); color:var(--paper-dim);
  font-size:0.82rem; font-weight:600; text-decoration:none; cursor:pointer;
  box-shadow:0 14px 30px rgba(0,0,0,0.4);
  transition:color .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
}
.wheel-fab:hover{ color:var(--gold); border-color:var(--gold-dim); transform:translateY(-2px); }
.wheel-fab[hidden]{ display:none; }

/* ============================================================
   Fortune wheel
   ============================================================ */
.wheel-modal__panel{ max-width:600px; }
.wheel{
  position:relative; width:min(480px, 90vw); height:min(480px, 90vw); margin:0 auto 26px;
  filter:drop-shadow(0 24px 50px rgba(0,0,0,0.5));
}
.wheel__pointer{
  position:absolute; top:-10px; left:50%; transform:translateX(-50%); z-index:3;
  width:0; height:0; border-left:15px solid transparent; border-right:15px solid transparent;
  border-top:26px solid var(--gold); filter:drop-shadow(0 3px 5px rgba(0,0,0,0.5));
}
.wheel__disc{
  position:relative; width:100%; height:100%; border-radius:50%;
  border:6px solid var(--gold);
  box-shadow:0 0 0 1px var(--ink-2), inset 0 0 40px rgba(0,0,0,0.35), 0 0 0 10px rgba(205,166,95,0.08);
  transition:transform 4.2s cubic-bezier(0.12, 0.66, 0.1, 1);
}
/* Hub -- purely decorative, sits above every wedge/label at the exact
   center so the 13 rotated labels all converge on a clean point instead of
   a visible seam. */
.wheel__disc::after{
  content:''; position:absolute; top:50%; left:50%; width:15%; height:15%;
  transform:translate(-50%, -50%); border-radius:50%;
  background:radial-gradient(circle at 35% 30%, #f0d9a8, var(--gold) 55%, var(--gold-dim));
  border:2px solid var(--ink-2); box-shadow:0 3px 10px rgba(0,0,0,0.5); z-index:2;
}
.wheel__disc-label{
  position:absolute; top:50%; left:50%; width:0; height:0; z-index:1;
  text-align:center; white-space:nowrap;
}
.wheel__disc-label-inner{ display:flex; flex-direction:column; align-items:center; gap:2px; }
.wheel__disc-coin{ font-size:1.1rem; color:var(--ink); line-height:1; }
.wheel__disc-amount{ font-size:0.92rem; font-weight:800; color:var(--ink); }
.wheel__disc-label--on-dark .wheel__disc-coin,
.wheel__disc-label--on-dark .wheel__disc-amount{ color:var(--paper); }
.wheel__disc-pack-img{ width:38px; height:38px; object-fit:contain; filter:drop-shadow(0 2px 3px rgba(0,0,0,0.4)); }
.wheel__disc-count{
  font-size:0.76rem; font-weight:800; color:var(--ink); background:rgba(255,255,255,0.55);
  border-radius:999px; padding:1px 7px; margin-top:-2px;
}
.wheel__disc-label--on-dark .wheel__disc-count{ color:var(--paper); background:rgba(0,0,0,0.35); }
.wheel__result{
  margin:0 0 18px; font-size:1rem; color:var(--gold); font-weight:600; min-height:1.3em;
}
.wheel__spin-btn{ width:100%; justify-content:center; }
.wheel__spin-btn:disabled{ opacity:0.5; cursor:not-allowed; transform:none; }

.hero__caption{ margin-top:24px; max-width:440px; font-size:0.84rem; line-height:1.6; color:var(--paper-dim); }
.hero__caption em{ font-style:normal; color:var(--accent); }


/* ============================================================
   Daily quests + hourly claim
   ============================================================ */
.dailies{ max-width:640px; margin:36px auto 0; padding:20px clamp(16px,4vw,28px); border-radius:18px;
  background:rgba(236,231,220,0.03); border:1px solid var(--line); }
.dailies__header{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin-bottom:16px; }
.dailies__title{ font-size:1rem; font-weight:700; color:var(--paper); }
.dailies__countdown{ font-size:0.78rem; color:var(--paper-dim); font-variant-numeric:tabular-nums; }
.dailies__quests{ display:flex; flex-direction:column; gap:10px; }
.dailies__quest{ display:flex; align-items:center; gap:12px; padding:10px 14px; border-radius:12px;
  background:var(--ink-3); border:1px solid var(--line); }
.dailies__quest--done{ border-color:var(--accent-dim); }
.dailies__quest-info{ flex:1; min-width:0; }
.dailies__quest-title{ font-size:0.86rem; color:var(--paper); font-weight:600; }
.dailies__quest-bar{ margin-top:6px; height:6px; border-radius:999px; background:rgba(236,231,220,0.08); overflow:hidden; }
.dailies__quest-bar-fill{ height:100%; background:var(--accent); border-radius:999px; transition:width .3s var(--ease); }
.dailies__quest-progress{ margin-top:4px; font-size:0.72rem; color:var(--paper-dim); }
.dailies__quest-reward{ font-size:0.78rem; color:var(--gold); white-space:nowrap; display:flex; align-items:center; gap:4px; }
.dailies__quest-claim{ padding:8px 16px; font-size:0.78rem; }
.dailies__hourly{ display:flex; align-items:center; justify-content:space-between; gap:12px;
  margin-top:16px; padding-top:16px; border-top:1px solid var(--line); }
.dailies__hourly-info{ display:flex; flex-direction:column; gap:2px; }
.dailies__hourly-label{ font-size:0.86rem; font-weight:600; color:var(--paper); }
.dailies__hourly-sub{ font-size:0.76rem; color:var(--paper-dim); font-variant-numeric:tabular-nums; }


/* ============================================================
   Collection view
   ============================================================ */
.collection{ max-width:1080px; margin:0 auto; padding:20px clamp(20px,5vw,64px) 60px; }
.collection__header{ margin-bottom:22px; }
.collection__title{
  font-family:var(--font-display); font-weight:500; font-size:clamp(1.7rem, 3vw, 2.1rem); margin:0 0 6px;
}
.collection__count{ margin:0; font-size:0.85rem; color:var(--paper-dim); }

.collection__wiki-progress{
  display:inline-flex; align-items:baseline; gap:5px;
  margin:12px 0 0; padding:7px 16px; border-radius:999px;
  background:rgba(205,166,95,0.08); border:1px solid var(--gold-dim);
  font-size:0.76rem; color:var(--paper-dim);
}
.collection__wiki-progress strong{ font-family:var(--font-display); font-weight:700; font-size:0.9rem; color:var(--gold); }

.collection__controls{ display:flex; flex-direction:column; gap:12px; margin-bottom:28px; }


/* ============================================================
   Battle view
   ============================================================ */
.battle{ max-width:1080px; margin:0 auto; padding:20px clamp(20px,5vw,64px) 60px; }
.battle__header{ margin-bottom:28px; }
.battle__title{
  font-family:var(--font-display); font-weight:500; font-size:clamp(1.7rem, 3vw, 2.1rem); margin:0 0 8px;
}
.battle__subtitle{ margin:0; font-size:0.85rem; color:var(--paper-dim); max-width:520px; }

/* A plain vertical list, in source order (Casual, Wager, Risk, Competitive).
   Each card is a 2-row grid: the title spans the full width up top, then
   the win/loss record and the fight buttons share one row below it --
   record anchored left, buttons anchored to the right edge of the card
   (grid-column 2, justify-self:end) -- instead of the record sitting on
   its own row above the buttons, which just made every card taller than
   its content needed. Falls back to a stacked single column under 760px
   (see the responsive section) once there's no width left to share. */
.battle-modes{
  display:flex; flex-direction:column; gap:18px; margin-bottom:40px;
}
.battle-mode-card{
  position:relative;
  display:grid; grid-template-columns:auto 1fr; align-items:center;
  column-gap:24px; row-gap:10px;
  border:1px solid var(--line); border-radius:var(--radius-l);
  background:linear-gradient(165deg, var(--ink-2), var(--ink));
  padding:18px clamp(18px,3vw,28px);
}
.battle-mode-card--competitive{ border-color:rgba(205,166,95,0.3); }
.battle-mode-card--risk{ border-color:rgba(224,138,138,0.3); }
.battle-mode-card--wager{ border-color:rgba(127,162,201,0.35); }
.battle-mode-card__title{
  grid-column:1 / -1;
  margin:0; font-family:var(--font-display); font-weight:500; font-size:1.2rem; color:var(--paper);
}
.battle-mode-card--competitive .battle-mode-card__title{ color:var(--gold); }
.battle-mode-card--risk .battle-mode-card__title{ color:#e08a8a; }
.battle-mode-card--wager .battle-mode-card__title{ color:var(--accent); }

.battle-mode-card__record{ display:flex; flex-wrap:wrap; gap:16px 24px; }
.battle-stat{ display:flex; flex-direction:column; gap:2px; }
.battle-stat__value{ font-family:var(--font-display); font-weight:600; font-size:1.6rem; color:var(--paper); }
.battle-stat__label{ font-size:0.72rem; color:var(--paper-dim); letter-spacing:0.04em; text-transform:uppercase; }

.battle-mode-card__actions{ display:flex; flex-wrap:wrap; justify-content:flex-end; gap:12px; }
/* Queue count lives inside the button itself now (see battle.js's
   loadQueueCounts), stacked under the mode/format label rather than off to
   the side, so "who's searching" reads as part of the button you'd press
   to join them. */
.battle-fight-btn{
  padding:9px 22px; font-size:0.85rem; border-radius:var(--radius-l);
  display:flex; flex-direction:column; align-items:center; gap:2px;
}
.battle-fight-btn__label{ line-height:1.3; }
.battle-fight-btn__count{
  display:inline-flex; align-items:center; gap:5px;
  font-size:0.7rem; color:rgba(7,7,10,0.6); white-space:nowrap;
  min-height:1em; /* keeps every button's height equal whether or not it has a count */
}
.battle-fight-btn__dot{
  width:7px; height:7px; border-radius:50%;
  background:#2d5f2d; box-shadow:0 0 6px 1px rgba(45,95,45,0.5);
  animation:battle-dot-pulse 1.8s ease-in-out infinite;
}
@keyframes battle-dot-pulse{
  0%,100%{ opacity:1; } 50%{ opacity:0.45; }
}

/* Corner info-tip on each mode card -- one per card (not per format
   button), top-right so it never collides with the title or actions.
   Compound selector (.info-tip.battle-mode-card__info) so this reliably
   beats the base .info-tip{position:relative} rule regardless of which
   comes later in the stylesheet -- two classes of equal specificity would
   otherwise let source order decide, which put the icon back in normal
   flow (top-left) instead of the corner. */
.info-tip.battle-mode-card__info{ position:absolute; top:14px; right:14px; z-index:2; }
/* Bubble sits to the RIGHT of the "?" icon, vertically centered on it.
   Both the resting and hover rules use the compound .info-tip.battle-
   mode-card__info selector (not just .battle-mode-card__info) for the
   same reason as the positioning rule above: .info-tip:hover .info-tip__
   bubble (below) sets `transform` too, at equal specificity to a single-
   class override -- a tie source order would resolve in the base rule's
   favor, silently reintroducing its translateX(-50%) centering and
   shifting this bubble sideways on hover. */
.info-tip.battle-mode-card__info .info-tip__bubble{
  top:50%; bottom:auto; left:calc(100% + 10px); right:auto; transform:translateY(-50%) translateX(-4px);
}
.info-tip.battle-mode-card__info:hover .info-tip__bubble,
.info-tip.battle-mode-card__info:focus .info-tip__bubble{
  transform:translateY(-50%) translateX(0);
}

.info-tip{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  width:22px; height:22px; border-radius:50%;
  border:1px solid var(--line); color:var(--paper-dim); font-size:0.72rem; font-weight:700;
  cursor:help; transition:color .2s var(--ease), border-color .2s var(--ease);
}
.info-tip:hover, .info-tip:focus{ color:var(--accent); border-color:var(--accent-dim); outline:none; }
.info-tip__bubble{
  position:absolute; bottom:calc(100% + 10px); left:50%; transform:translateX(-50%) translateY(4px);
  width:220px; padding:10px 12px; border-radius:var(--radius-s);
  background:var(--ink-3); border:1px solid var(--line); box-shadow:0 14px 30px rgba(0,0,0,0.5);
  font-size:0.76rem; line-height:1.5; color:var(--paper-dim); text-align:left;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .18s var(--ease), transform .18s var(--ease);
  z-index:5;
}
.info-tip:hover .info-tip__bubble, .info-tip:focus .info-tip__bubble{
  opacity:1; visibility:visible; transform:translateX(-50%) translateY(0);
}


.server-boss{ display:grid; grid-template-columns:1.3fr 1fr; gap:20px; margin-bottom:18px; align-items:start; }

.server-boss__card{
  position:relative; overflow:hidden;
  border:1px solid var(--gold-dim); border-radius:var(--radius-l);
  background:linear-gradient(165deg, var(--ink-2), var(--ink));
  padding:26px clamp(20px,3vw,32px);
  display:flex; flex-direction:column; gap:18px;
}
.server-boss__glow{
  position:absolute; top:-30%; right:-10%; width:60%; height:160%;
  background:radial-gradient(circle, rgba(205,166,95,0.16) 0%, transparent 70%);
  pointer-events:none; animation:server-boss-glow-pulse 5s ease-in-out infinite;
}
@keyframes server-boss-glow-pulse{
  0%,100%{ opacity:0.7; transform:scale(1); }
  50%{ opacity:1; transform:scale(1.08); }
}
.server-boss__card[data-status="defeated"]{ border-color:rgba(111,191,127,0.5); }
.server-boss__card[data-status="defeated"] .server-boss__glow{ background:radial-gradient(circle, rgba(111,191,127,0.2) 0%, transparent 70%); }
.server-boss__card[data-status="expired"] .server-boss__glow{ animation:none; opacity:0.2; }

.server-boss__header{ position:relative; display:flex; align-items:flex-start; justify-content:space-between; gap:14px; flex-wrap:wrap; }
.server-boss__identity{ display:flex; align-items:center; gap:14px; }
.server-boss__emoji{
  font-size:2.6rem; line-height:1; filter:drop-shadow(0 6px 16px rgba(0,0,0,0.5));
  animation:server-boss-emoji-float 4s ease-in-out infinite;
}
@keyframes server-boss-emoji-float{
  0%,100%{ transform:translateY(0) rotate(0deg); }
  50%{ transform:translateY(-4px) rotate(-3deg); }
}
.server-boss__eyebrow{ margin:0 0 4px; font-size:0.7rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--gold); }
.server-boss__name{ margin:0; font-family:var(--font-display); font-weight:500; font-size:1.5rem; color:var(--paper); }
.server-boss__timer{ text-align:right; }
.server-boss__timer-label{ display:block; font-size:0.68rem; letter-spacing:0.06em; text-transform:uppercase; color:var(--paper-dim); }
.server-boss__timer-value{ display:block; font-family:var(--font-display); font-size:1.15rem; color:var(--paper); font-variant-numeric:tabular-nums; }

.server-boss__hp{ position:relative; display:flex; flex-direction:column; gap:6px; }
.server-boss__hp-track{
  position:relative; height:22px; border-radius:999px; background:rgba(0,0,0,0.35);
  border:1px solid var(--line); overflow:hidden;
}
.server-boss__hp-fill{
  height:100%; border-radius:999px;
  background:linear-gradient(90deg, #a3403f, #e0c25f 55%, #f6e3a1);
  transition:width .6s var(--ease);
  box-shadow:0 0 16px rgba(224,194,95,0.45);
}
.server-boss__card[data-status="defeated"] .server-boss__hp-fill{ background:linear-gradient(90deg, #3f8a52, #6fbf7f); box-shadow:0 0 16px rgba(111,191,127,0.4); }
.server-boss__hp-labels{ display:flex; justify-content:space-between; font-size:0.76rem; color:var(--paper-dim); font-variant-numeric:tabular-nums; }

.server-boss__mine{
  display:grid; grid-template-columns:repeat(4, 1fr); gap:14px;
  padding:14px 16px; border-radius:var(--radius-m); background:rgba(236,231,220,0.03); border:1px solid var(--line);
}
.server-boss__mine[hidden]{ display:none; }
.server-boss__mine-stat{ display:flex; flex-direction:column; gap:2px; text-align:center; }
.server-boss__mine-value{ font-family:var(--font-display); font-weight:600; font-size:1.15rem; color:var(--paper); }
.server-boss__mine-label{ font-size:0.66rem; color:var(--paper-dim); letter-spacing:0.03em; text-transform:uppercase; }

.server-boss__attack-btn{ width:100%; padding:13px; font-size:0.95rem; }
.server-boss__note{ margin:0; text-align:center; font-size:0.78rem; color:var(--paper-dim); min-height:1.2em; }

.server-boss__side{ display:flex; flex-direction:column; gap:18px; min-width:0; }
.server-boss__leaderboard, .server-boss__history{
  border:1px solid var(--line); border-radius:var(--radius-l); background:rgba(236,231,220,0.02);
  padding:18px clamp(16px,2vw,22px);
}
.server-boss__panel-title{ margin:0 0 12px; font-family:var(--font-display); font-weight:500; font-size:1rem; color:var(--paper); }
.server-boss__empty-row{ text-align:center; color:var(--paper-dim); padding:16px 0 !important; }

.server-boss__history-list{ display:flex; flex-direction:column; gap:10px; max-height:260px; overflow-y:auto; }
.server-boss__history-empty{ text-align:center; color:var(--paper-dim); font-size:0.85rem; padding:16px 0; margin:0; }
.server-boss__history-row{
  display:flex; align-items:center; gap:12px; padding:10px 12px;
  border-radius:var(--radius-m); background:rgba(236,231,220,0.025); border:1px solid var(--line);
}
.server-boss__history-emoji{ font-size:1.4rem; flex-shrink:0; }
.server-boss__history-body{ min-width:0; }
.server-boss__history-name{ margin:0; font-size:0.86rem; font-weight:600; color:var(--paper); }
.server-boss__history-status{
  margin-left:6px; font-size:0.62rem; font-weight:600; letter-spacing:0.03em; text-transform:uppercase;
  padding:2px 7px; border-radius:999px;
}
.server-boss__history-status--defeated{ color:#7fbf7f; background:rgba(111,191,127,0.14); }
.server-boss__history-status--expired{ color:var(--paper-dim); background:rgba(236,231,220,0.08); }
.server-boss__history-meta{
  margin:2px 0 0; font-size:0.72rem; color:var(--paper-dim);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

@media (max-width:900px){
  .server-boss{ grid-template-columns:1fr; }
}
@media (max-width:600px){
  .server-boss__mine{ grid-template-columns:repeat(2, 1fr); }
}

.reveal-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(110px, 1fr)); gap:14px; margin-bottom:32px; }

.reveal-card{
  position:relative;
  aspect-ratio:5 / 7.4;
  border-radius:var(--radius-m);
  border:1px solid var(--line);
  background:linear-gradient(160deg, var(--ink-2), var(--ink));
  display:flex; flex-direction:column; overflow:hidden;
  opacity:0; transform:translateY(14px) scale(0.9) rotateY(90deg);
  transition:transform .55s var(--ease), opacity .55s var(--ease), box-shadow .3s var(--ease);
}
.reveal-card.in{ opacity:1; transform:translateY(0) scale(1) rotateY(0deg); }
/* Brief brighter flash on arrival, settling into the persistent glow
   defined above (same --r-current the rank text/badges already use). */
.reveal-card.in[data-rarity]{ animation:glow-flash 1.1s var(--ease); }
@keyframes glow-flash{
  0%{ box-shadow:0 0 0 0 transparent; }
  35%{ box-shadow:0 0 34px 4px color-mix(in srgb, var(--r-current) 75%, transparent); }
  100%{ box-shadow:0 0 16px -4px color-mix(in srgb, var(--r-current) 55%, transparent); }
}

.reveal-card__thumb{ width:100%; aspect-ratio:4/3; object-fit:cover; background:var(--ink-3); }
.reveal-card__thumb--placeholder{ display:flex; align-items:center; justify-content:center; font-family:var(--font-display); font-size:1.6rem; color:var(--paper-dim); }
.reveal-card__body{ padding:8px 8px 10px; display:flex; flex-direction:column; gap:6px; flex:1; }
.reveal-card__title{ font-size:0.72rem; font-weight:600; line-height:1.25; color:var(--paper); }
.reveal-card__rarity{ font-size:0.6rem; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; }
.reveal-card__stats{ display:flex; flex-wrap:wrap; gap:5px; margin-top:auto; }
.reveal-card__stats .stat-pill{ font-size:0.62rem; padding:3px 6px; }


.settings-section{ padding:18px 0; border-top:1px solid var(--line); }
.settings-section:first-of-type{ border-top:none; padding-top:0; }
.settings-section__title{
  margin:0 0 14px; font-family:var(--font-body); font-weight:600;
  font-size:0.72rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--paper-dim);
}

.settings-toggle{
  display:flex; align-items:center; justify-content:space-between; gap:24px;
  cursor:pointer;
}
.settings-toggle__text{ display:flex; flex-direction:column; gap:2px; }
.settings-toggle__label{ font-size:0.92rem; font-weight:500; color:var(--paper); }
.settings-toggle__hint{ font-size:0.78rem; color:var(--paper-dim); }

.settings-section--danger .settings-section__title{ color:#e08a8a; }

/* Delete-my-account confirmation modal (#deleteAccountModal) -- reuses
   .modal__panel--detail/.admin-form's text-align:left layout. */
.modal__body-text{ margin:0 0 16px; font-size:0.88rem; color:var(--paper-dim); line-height:1.5; }
.delete-account-list{
  list-style:none; margin:0 0 20px; padding:0; display:flex; flex-direction:column; gap:8px;
  font-size:0.84rem; color:var(--paper);
}
.delete-account-list li{ display:flex; align-items:flex-start; gap:8px; }
.delete-account-list__mark{ flex:0 0 auto; font-weight:700; line-height:1.4; }
.delete-account-list__mark--bad{ color:#e08a8a; }
.delete-account-list__mark--ok{ color:#7fbf7f; }

/* Own vertical-column form, not a reused .admin-form -- that one is a
   flex ROW meant for a horizontal strip of admin-panel fields, and
   stacking a label above a full-width input inside it produced a
   squeezed, wrapping mess instead of a normal single-column form. */
.delete-account-form{ display:flex; flex-direction:column; gap:10px; text-align:left; }
.delete-account-form__label{ font-size:0.84rem; color:var(--paper-dim); }
.delete-account-form__label strong{ color:var(--paper); }
.delete-account-form__input{
  width:100%; padding:12px 16px; border-radius:var(--radius-m);
  border:1px solid var(--line); background:rgba(236,231,220,0.04);
  color:var(--paper); font-family:inherit; font-size:0.92rem;
  transition:border-color .2s var(--ease), background .2s var(--ease);
}
.delete-account-form__input:focus{
  outline:none; border-color:#e08a8a; background:rgba(224,138,138,0.06);
}
.delete-account-form__submit{ width:100%; margin-top:4px; }

/* Sign in / Register modal -- replaces the old Google OAuth redirect.
   Two forms share one modal (login shown by default, register toggled in
   via the switch link at the bottom) rather than two separate modals,
   since a signed-out visitor bounces between them constantly ("oh wait I
   don't have an account yet"). Same input styling as .delete-account-form
   above (own copy, not shared -- the two live in unrelated modals and
   nothing here is danger-red). */
.auth-form{ display:flex; flex-direction:column; gap:10px; text-align:left; }
.auth-form[hidden]{ display:none; }
.auth-form__label{ font-size:0.84rem; color:var(--paper-dim); }
.auth-form__input{
  width:100%; padding:12px 16px; border-radius:var(--radius-m);
  border:1px solid var(--line); background:rgba(236,231,220,0.04);
  color:var(--paper); font-family:inherit; font-size:0.92rem;
  transition:border-color .2s var(--ease), background .2s var(--ease);
}
.auth-form__input:focus{ outline:none; border-color:var(--accent-dim); background:rgba(127,162,201,0.06); }
.auth-form__error{
  margin:0; padding:10px 12px; border-radius:var(--radius-s);
  border:1px solid rgba(216,110,110,0.4); background:rgba(216,110,110,0.08);
  color:#e08a8a; font-size:0.84rem;
}
.auth-form__error[hidden]{ display:none; }
.auth-form__success{
  margin:0; padding:10px 12px; border-radius:var(--radius-s);
  border:1px solid rgba(127,191,127,0.4); background:rgba(127,191,127,0.08);
  color:#7fbf7f; font-size:0.84rem;
}
.auth-form__success[hidden]{ display:none; }
.auth-form__submit{ width:100%; margin-top:4px; }
.auth-form__switch{ margin:16px 0 0; font-size:0.82rem; color:var(--paper-dim); text-align:center; }
.auth-form__switch[hidden]{ display:none; }
.auth-form__switch-btn{
  background:none; border:none; padding:0; margin:0; font:inherit; cursor:pointer;
  color:var(--gold); text-decoration:underline;
}

/* ============================================================
   Battle: locked nav, card picker, matchmaking, arena, history
   ============================================================ */
.nav-pill:disabled, .nav-pill--locked{ opacity:0.4; pointer-events:none; cursor:default; }

/* -- Card picker modal (choose your team before searching) -- reuses
   .card-tile/.card-tile-grid wholesale, same component as the profile
   page's Showcase picker. */
/* .modal__panel--detail (already on this element for its text-align:left)
   sets max-width:520px, which clamps width down and wins regardless of what
   width is set to -- the exact trap documented above for .modal__panel--
   trade -- so max-width has to be overridden here too, not just width.
   min(1100px, max(520px, 64vw), 96vw): targets ~64vw on a normal desktop
   window, floors at the old 520px on a narrow-but-not-mobile window instead
   of shrinking below it, and never exceeds 96% of the viewport so it still
   fits a phone screen. */
.modal__panel--battle-picker{ width:min(1100px, max(520px, 64vw), 96vw); max-width:none; }

.battle-picker__slots{ justify-content:center; margin-bottom:18px; }
.battle-picker__note{ min-height:1.2em; margin:0 0 14px; font-size:0.82rem; color:var(--accent); text-align:center; }
.battle-picker__note--error{ color:#e08a8a; }
.battle-picker__search{ margin-bottom:12px; }
.battle-picker__sort{ margin-bottom:16px; }
.battle-picker__inventory{ max-height:340px; overflow-y:auto; margin-bottom:22px; padding-right:4px; }

/* Slots/inventory tiles need room for stat pills the showcase-picker
   version of .card-tile was never designed to show, so let them grow
   instead of locking to the showcase's portrait aspect-ratio. */
.battle-picker__slots .card-tile, .battle-picker__inventory .card-tile{ aspect-ratio:auto; }
.battle-picker__slots .card-tile__thumb, .battle-picker__inventory .card-tile__thumb{ aspect-ratio:4/3; flex:none; }

/* -- Full-screen overlays (searching / arena) -- block interaction with
   the rest of the page while a battle is being found or fought. -- */
.battle-overlay{
  position:fixed; inset:0; z-index:70;
  display:flex; align-items:center; justify-content:center;
  background:rgba(4,4,6,0.92); backdrop-filter:blur(6px);
  padding:24px;
  animation:backdrop-in .3s var(--ease);
}
.battle-overlay[hidden]{ display:none; }

.battle-search{ max-width:360px; text-align:center; }
.battle-search__spinner{
  width:48px; height:48px; margin:0 auto 22px;
  border-radius:50%; border:3px solid var(--line); border-top-color:var(--accent);
  animation:battle-spin 0.9s linear infinite;
}
@keyframes battle-spin{ to{ transform:rotate(360deg); } }
.battle-search__title{ margin:0 0 8px; font-family:var(--font-display); font-size:1.3rem; color:var(--paper); }
.battle-search__meta{ margin:0 0 4px; font-size:0.86rem; color:var(--paper-dim); }
.battle-search__timer{ margin:10px 0 4px; font-family:var(--font-display); font-weight:600; font-size:1.8rem; color:var(--gold); }
.battle-search__window{ margin:0 0 26px; font-size:0.8rem; color:var(--paper-dim); }
/* .btn is display:flex (block-level), which stretches to the full width of
   this non-flex parent and left-aligns its content -- shrink it back to
   its own content width so margin:auto can actually center it. */
.battle-search .btn{ width:fit-content; margin:0 auto; }

/* -- Arena: two facing rows of battle-cards + a coin flip in the middle -- */
.battle-arena{
  width:100%; max-width:900px;
  display:grid; grid-template-columns:1fr auto 1fr; align-items:start; gap:20px;
}
.battle-arena__side{ display:flex; flex-direction:column; gap:14px; }
.battle-arena__side--opponent{ align-items:flex-end; }
.battle-arena__header{ display:flex; align-items:center; gap:10px; }
.battle-arena__side--opponent .battle-arena__header{ flex-direction:row-reverse; }
.battle-arena__avatar{
  display:inline-flex; align-items:center; justify-content:center;
  width:44px; height:44px; border-radius:50%; font-size:1.6rem;
}
.battle-arena__name{ font-family:var(--font-display); font-weight:600; font-size:1.05rem; color:var(--paper); }
.battle-arena__field{ display:flex; gap:10px; flex-wrap:wrap; }
.battle-arena__side--opponent .battle-arena__field{ justify-content:flex-end; }

.battle-arena__center{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  min-width:100px; padding-top:40px; perspective:600px;
}
.battle-arena__coin-result{ max-width:150px; margin:0; font-family:var(--font-display); font-size:0.95rem; color:var(--gold); text-align:center; }
.battle-arena__coin-result--positive{ color:#7fbf7f; font-size:1.3rem; font-weight:600; }
.battle-arena__coin-result--negative{ color:#e08a8a; font-size:1.3rem; font-weight:600; }
.battle-arena__vs{ font-family:var(--font-display); font-size:1.6rem; color:var(--paper-dim); opacity:0.5; }

.winrate-badge{ padding:2px 8px; border-radius:999px; background:rgba(236,231,220,0.06); font-size:0.72rem; font-weight:700; }
.winrate-badge--good{ color:#7fbf7f; }
.winrate-badge--bad{ color:#e08a8a; }

/* -- Coin flip -- pure CSS 3D, no library -- */
.coin{ position:relative; width:64px; height:64px; margin:0 auto 14px; transform-style:preserve-3d; }
.coin[hidden]{ display:none; }
.coin__face{
  position:absolute; inset:0; border-radius:50%; backface-visibility:hidden;
  display:flex; align-items:center; justify-content:center; font-size:1.6rem;
  background:linear-gradient(180deg, #ddb977, var(--gold) 55%, var(--gold-dim));
  color:#1a1408; border:2px solid rgba(255,255,255,0.35);
  box-shadow:0 8px 20px rgba(0,0,0,0.4);
}
.coin__face--back{ transform:rotateY(180deg); }
.coin.coin--flip{ animation:coin-flip 2.5s cubic-bezier(.3,.6,.2,1) both; }
@keyframes coin-flip{
  0%{ transform:rotateY(0deg) translateY(0); }
  45%{ transform:rotateY(1440deg) translateY(-40px); }
  100%{ transform:rotateY(1800deg) translateY(0); }
}

/* -- Battle card (arena combatant) -- deliberately close to .wiki-card's
   visual language (same rarity color ramp, same stat-pill component) so
   the arena doesn't feel like a different app. -- */
.battle-card{
  position:relative; width:118px;
  display:flex; flex-direction:column; align-items:center; gap:4px;
  padding:8px; border-radius:var(--radius-m); border:1px solid var(--line);
  background:linear-gradient(160deg, var(--ink-2), var(--ink));
  transition:transform 0.18s ease-out, opacity 0.3s ease, filter 0.3s ease;
}
.battle-card__thumb{ width:100%; aspect-ratio:4/3; object-fit:cover; border-radius:7px; background:var(--ink-3); }
.battle-card__thumb--placeholder{ display:flex; align-items:center; justify-content:center; font-family:var(--font-display); font-size:1.3rem; color:var(--paper-dim); }
.battle-card__name{ font-size:0.66rem; font-weight:600; line-height:1.25; text-align:center; color:var(--paper); }
.battle-card__hp-track{ position:relative; width:100%; height:6px; margin:2px 0; border-radius:999px; background:rgba(236,231,220,0.08); overflow:hidden; }
.battle-card__hp-fill{ height:100%; border-radius:999px; background:linear-gradient(90deg, #7fbf7f, #55b9a6); transition:width 0.35s ease; }
.battle-card__stats{ display:flex; flex-wrap:wrap; gap:4px; }
.battle-card__stats .stat-pill{ padding:2px 6px; font-size:0.6rem; }

.battle-card--lunge-right{ transform:translateX(18px) scale(1.05); z-index:2; }
.battle-card--lunge-left{ transform:translateX(-18px) scale(1.05); z-index:2; }
.battle-card--hit{ filter:brightness(1.8) drop-shadow(0 0 14px rgba(224,138,138,0.9)); }
.battle-card--dead{ opacity:0.16; filter:grayscale(1); transform:scale(0.92); }
.battle-card--transferred{ box-shadow:0 0 0 2px var(--gold), 0 0 22px rgba(205,166,95,0.5); }

.battle-card__crit-flash{
  position:absolute; top:-6px; left:50%; z-index:5; pointer-events:none;
  font-family:var(--font-display); font-weight:700; font-size:0.8rem; letter-spacing:0.03em;
  color:#f6c945; text-shadow:0 0 8px rgba(246,201,69,0.85), 0 1px 2px rgba(0,0,0,0.6);
  animation:battle-crit-pop 0.5s ease-out forwards;
}
@keyframes battle-crit-pop{
  0%{ opacity:0; transform:translate(-50%, 6px) scale(0.8); }
  30%{ opacity:1; transform:translate(-50%, -6px) scale(1.15); }
  100%{ opacity:0; transform:translate(-50%, -16px) scale(1); }
}

/* Floating damage number -- normal hits in the same red the --hit filter
   flashes the card in, crits bigger and gold to match the CRIT! callout
   above it, so a critical hit's number reads differently at a glance
   without having to read the digits. */
.battle-card__dmg-flash{
  position:absolute; top:38%; left:50%; z-index:5; pointer-events:none;
  font-family:var(--font-display); font-weight:700; font-size:0.95rem;
  color:#e08a8a; text-shadow:0 1px 3px rgba(0,0,0,0.7);
  animation:battle-dmg-pop 0.6s ease-out forwards;
}
.battle-card__dmg-flash--crit{
  font-size:1.3rem;
  color:#f6c945; text-shadow:0 0 10px rgba(246,201,69,0.9), 0 1px 3px rgba(0,0,0,0.7);
}
@keyframes battle-dmg-pop{
  0%{ opacity:0; transform:translate(-50%, 4px) scale(0.75); }
  25%{ opacity:1; transform:translate(-50%, -8px) scale(1.1); }
  100%{ opacity:0; transform:translate(-50%, -26px) scale(1); }
}

/* -- Victory / defeat -- full-screen, on top of the arena -- */
.battle-result{
  position:absolute; inset:0; z-index:2;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px; text-align:center;
  background:rgba(4,4,6,0.92);
  animation:panel-in .4s var(--ease);
}
.battle-result[hidden]{ display:none; }
.battle-result__title{ margin:0; font-family:var(--font-display); font-weight:600; font-size:clamp(2.4rem,7vw,4rem); letter-spacing:0.02em; animation:battle-result-pop .6s var(--ease); }
.battle-result--victory .battle-result__title{ color:var(--gold); text-shadow:0 0 40px rgba(205,166,95,0.5); }
.battle-result--defeat .battle-result__title{ color:#e08a8a; text-shadow:0 0 40px rgba(224,138,138,0.4); }
@keyframes battle-result-pop{
  0%{ opacity:0; transform:scale(0.6); }
  60%{ opacity:1; transform:scale(1.08); }
  100%{ opacity:1; transform:scale(1); }
}
.battle-result__subtitle{ max-width:420px; margin:0; font-size:0.92rem; line-height:1.6; color:var(--paper-dim); }
.battle-result__report{
  border:none; background:transparent; color:var(--paper-dim); font-size:0.76rem;
  text-decoration:underline; cursor:pointer; opacity:0.7; transition:opacity .2s var(--ease), color .2s var(--ease);
}
.battle-result__report:hover{ opacity:1; color:#e08a8a; }


/* -- Battle history -- */
.battle-history{
  margin-top:26px; padding:24px clamp(18px,3vw,28px);
  border:1px solid var(--line); border-radius:var(--radius-l); background:rgba(236,231,220,0.02);
}
.battle-history__header{ margin-bottom:16px; }
.battle-history__title{ margin:0; font-family:var(--font-display); font-weight:500; font-size:1.2rem; color:var(--paper); }
.battle-history__filters{ display:flex; flex-direction:column; gap:8px; margin-bottom:20px; }
.battle-history__list{ display:flex; flex-direction:column; gap:12px; }
.battle-history__empty{ margin:0; padding:24px 0; text-align:center; font-size:0.88rem; color:var(--paper-dim); }
.battle-history__expand{ width:fit-content; margin:18px auto 0; }
/* .btn sets display:flex, which (same issue as the corner info-tip fix
   above) can outrank the UA [hidden]{display:none} default depending on
   source order -- pin it explicitly so the button actually disappears
   once there's nothing left to expand. */
.battle-history__expand[hidden]{ display:none; }
.battle-history__row{ padding:14px 16px; border:1px solid var(--line); border-radius:var(--radius-m); background:rgba(236,231,220,0.02); }
.battle-history__row--won{ border-left:3px solid #7fbf7f; }
.battle-history__row--lost{ border-left:3px solid #e08a8a; }
.battle-history__top{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom:10px; font-size:0.82rem; }
.battle-history__result{ font-weight:700; }
.battle-history__row--won .battle-history__result{ color:#7fbf7f; }
.battle-history__row--lost .battle-history__result{ color:#e08a8a; }
.battle-history__mode{ color:var(--paper-dim); text-transform:capitalize; }
.battle-history__opponent{ color:var(--paper); }
.battle-history__rating{ color:var(--gold); }
.battle-history__date{ margin-left:auto; font-size:0.76rem; color:var(--paper-dim); }
.battle-history__teams{ display:flex; flex-wrap:wrap; align-items:center; gap:12px; }
.battle-history__team{ display:flex; flex-wrap:wrap; gap:6px; }
.battle-history__vs{ font-size:0.76rem; color:var(--paper-dim); }
.battle-history__card{
  width:92px; display:flex; flex-direction:column; gap:3px;
  padding:6px; border:1px solid currentColor; border-radius:var(--radius-s); background:var(--ink-3);
  cursor:pointer; transition:transform .2s var(--ease);
}
.battle-history__card:hover{ transform:translateY(-2px); }
.battle-history__card-thumb{ width:100%; aspect-ratio:4/3; object-fit:cover; display:block; border-radius:6px; background:var(--ink-2); }
.battle-history__card-thumb--placeholder{ display:flex; align-items:center; justify-content:center; font-family:var(--font-display); font-size:1rem; color:var(--paper-dim); }
.battle-history__card-name{ overflow:hidden; font-size:0.62rem; font-weight:600; line-height:1.25; color:var(--paper); text-overflow:ellipsis; white-space:nowrap; }
.battle-history__card-stats{ display:flex; flex-wrap:wrap; gap:3px; }
.battle-history__card-stats .stat-pill{ padding:1px 5px; font-size:0.56rem; }

@media (max-width:760px){
  .battle-arena{ grid-template-columns:1fr; }
  .battle-arena__side--opponent{ align-items:flex-start; }
  .battle-arena__side--opponent .battle-arena__header{ flex-direction:row; }
  .battle-arena__side--opponent .battle-arena__field{ justify-content:flex-start; }
  .battle-arena__center{ padding-top:10px; }
  /* No room to share a row at this width -- back to record above buttons,
     both spanning full width. */
  .battle-mode-card{ grid-template-columns:1fr; }
  .battle-mode-card__actions{ justify-content:flex-start; }
}


/* ============================================================
   Shop
   ============================================================ */
.shop__header{ margin-bottom:22px; }
.shop__title{
  font-family:var(--font-display); font-weight:500; font-size:clamp(1.7rem, 3vw, 2.1rem); margin:0 0 8px;
}
.shop__subtitle{ margin:0; font-size:0.85rem; color:var(--paper-dim); max-width:520px; }

.shop__mode-tabs{ margin-bottom:14px; }
.shop__tabs{ margin-bottom:20px; }
.shop__empty{ text-align:center; color:var(--paper-dim); font-size:0.9rem; padding:60px 0; }
.shop-tab__count{ margin-left:5px; opacity:0.65; font-variant-numeric:tabular-nums; }

.shop__grid{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(170px, 1fr));
  gap:14px;
}
.shop__grid--compact{
  grid-template-columns:repeat(auto-fill, minmax(96px, 1fr));
  gap:10px;
}
.shop__grid--compact .shop-card{ padding:8px; gap:6px; }
.shop__grid--compact .shop-card__preview-wrap{ height:52px; }

.shop-card{
  position:relative;
  display:flex; flex-direction:column; gap:10px;
  padding:14px; border-radius:var(--radius-m);
  border:1px solid var(--line);
  background:linear-gradient(165deg, var(--ink-2), var(--ink));
  cursor:pointer;
  transition:transform .25s var(--ease), border-color .25s var(--ease);
}
.shop-card:hover{ transform:translateY(-3px); border-color:var(--accent-dim); }
.shop-card--equipped{ border-color:var(--gold-dim); }
.shop-card--donor{ border-color:rgba(205,166,95,0.35); }
.shop-card--donor:hover{ border-color:var(--gold-dim); }
.shop-card--locked{ opacity:0.72; }

.shop-card__preview-wrap{
  display:flex; align-items:center; justify-content:center;
  height:84px; border-radius:var(--radius-s);
  background:rgba(236,231,220,0.03);
}

/* Generic preview swatch -- the actual frame/background/coin/chat-theme
   visual is applied by cosmetics.css via data-cosmetic-* on this element
   (or its children), so a shop card always shows the real preset, never a
   hand-drawn stand-in. */
.shop-swatch{
  width:56px; height:56px; border-radius:var(--radius-s);
  display:flex; align-items:center; justify-content:center;
  font-size:1.4rem; background:var(--ink-3); border:1px solid var(--line);
  overflow:hidden;
}
.shop-swatch--round{ border-radius:50%; }
.shop-swatch--default{ border-style:dashed; opacity:0.7; }
.shop-swatch--emoji{ font-size:1.8rem; background:transparent; border:none; }
.shop-swatch--title{ width:auto; height:auto; padding:6px 10px; background:transparent; border:none; }
.shop-swatch--chat{ flex-direction:column; gap:4px; padding:6px; }
.shop-swatch--chat .thread-bubble{ font-size:0.5rem; padding:3px 7px; max-width:none; }
.shop-swatch--coin{ background:transparent; border:none; }

.shop-card__name{ font-size:0.84rem; font-weight:600; color:var(--paper); text-align:center; }

.shop-card__footer{ display:flex; align-items:center; justify-content:center; gap:6px; font-size:0.78rem; }
.shop-card__price{ display:flex; align-items:center; gap:4px; color:var(--gold); font-weight:600; }
.shop-card__price .btn__coin{ font-size:0.72rem; }
.shop-card__status{
  padding:3px 10px; border-radius:999px; font-size:0.68rem; font-weight:600;
  letter-spacing:0.03em; text-transform:uppercase;
}
.shop-card__status--owned{ background:rgba(236,231,220,0.08); color:var(--paper-dim); }
.shop-card__status--equipped{ background:rgba(205,166,95,0.14); color:var(--gold); border:1px solid var(--gold-dim); }
.shop-card__status--donor{ background:rgba(205,166,95,0.14); color:var(--gold); border:1px solid var(--gold-dim); }
.shop-card__status--level{ background:rgba(127,162,201,0.12); color:var(--accent); border:1px solid var(--accent-dim); }

/* Shop item detail modal -- bigger version of the same preview idiom,
   swapped in per-slot by shop.js's renderItemModal (see PREVIEW_CONTEXTS). */
.shop-detail{ display:flex; flex-direction:column; align-items:center; gap:18px; text-align:center; }
.shop-detail__preview-wrap{
  display:flex; align-items:center; justify-content:center;
  width:100%; min-height:160px; border-radius:var(--radius-l);
  background:rgba(236,231,220,0.03); padding:24px;
}
.shop-detail__name{ font-family:var(--font-display); font-size:1.3rem; font-weight:500; margin:0; }
.shop-detail__desc{ font-size:0.84rem; color:var(--paper-dim); margin:0; max-width:360px; }
.shop-detail__actions{ display:flex; align-items:center; gap:10px; }

/* Try-on mockups inside the detail modal are the SAME markup/classes the
   real site renders (profile aside, chat thread, topbar button, battle
   coin -- see shop.js's buildProfileMock/buildChatMock/etc.), so a preview
   can never drift from production. Every cosmetic visual (frame ring,
   background pattern, chat theme, coin skin, pack animation) already lives
   once in cosmetics.css's shared [data-cosmetic-*] rules and needs no
   repeating here -- everything below is a LAYOUT-only override, needed only
   because these components normally live in a full page section, not a
   small modal panel. */
/* top:auto (not just position:static) is required here: buildProfileMock
   always adds .cf-ring alongside this class, and when the previewed/real
   account has ANY profileFrame equipped, cosmetics.css's
   `.cf-ring[data-cosmetic-frame]:not([data-cosmetic-frame="none"])` rule
   (3 selectors) sets position:relative -- more specific than the
   position:static above (2 classes) -- which silently revives the real
   page's `.profile-layout__aside{ top:24px }` (meant only for its sticky
   sidebar) as a real 24px downward offset, pushing the whole preview block
   toward the bottom of this box instead of centering it. Overriding `top`
   directly here neutralizes the offset regardless of which position value
   ultimately wins. */
.shop-detail__preview-wrap .profile-layout__aside{ position:static; top:auto; width:220px; margin:0 auto; }

.shop-detail__preview-wrap .messages-layout__thread{ width:280px; }
.shop-detail__preview-wrap .thread-active{ flex:none; }
.shop-detail__preview-wrap .thread-active__header{ padding:10px 14px; }
.shop-detail__preview-wrap .thread-active__messages{ flex:none; overflow:visible; padding:14px; }

.shop-detail__preview-wrap .profile-btn{ width:64px; height:64px; cursor:default; }
.shop-detail__preview-wrap .profile-btn__emoji{ font-size:28px; }

.shop-detail__preview-wrap .pack-stage{ width:120px; }
.shop-mock-pack{ display:flex; flex-direction:column; align-items:center; }
.shop-mock-pack .pack{ pointer-events:none; }
.shop-mock-pack .pack__inner{ font-size:3rem; }
.shop-mock-replay{ margin-top:10px; }

.shop-mock-coin-duel{ display:flex; flex-direction:column; align-items:center; gap:14px; }
.shop-mock-coin-duel .coin{ width:88px; height:88px; }
.shop-mock-coin-duel .coin__face{ font-size:2rem; }

/* Try-on carousel -- prev/next arrows flank the preview when a slot offers
   more than one context (see shop.js's PREVIEW_CONTEXTS). */
.shop-detail__carousel{ display:flex; align-items:center; gap:10px; width:100%; }
.shop-detail__arrow{
  flex-shrink:0; width:32px; height:32px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  border:1px solid var(--line); background:var(--ink-3); color:var(--paper);
  font-size:1rem; cursor:pointer; transition:border-color .2s var(--ease), color .2s var(--ease);
}
.shop-detail__arrow:hover{ border-color:var(--accent-dim); color:var(--accent); }
/* display:none (not visibility:hidden) -- for the 9 of 11 slots with only
   one try-on context, there's nothing to navigate to, so the arrows
   shouldn't reserve dead space on either side of the preview either. */
.shop-detail__arrow[hidden]{ display:none; }
.shop-detail__preview-wrap{ flex:1; min-width:0; }
.shop-detail__context-label{ font-size:0.72rem; color:var(--paper-dim); text-align:center; margin:0; }


/* ============================================================
   Support -- was the Store (donation shop, store.js). Replaced by a single
   DonationAlerts link (see donations.py's module docstring on why: no
   payment processor was ever actually wired in here, so a real external
   donation platform is strictly more honest than a fake catalog that never
   charged anyone). Only the redeem-a-promo-code form survives from the old
   layout (unrelated system, see promocodes.py).
   ============================================================ */
.store__header{ margin-bottom:22px; }
.store__title{
  font-family:var(--font-display); font-weight:500; font-size:clamp(1.7rem, 3vw, 2.1rem); margin:0 0 8px;
}
.store__subtitle{ margin:0; font-size:0.85rem; color:var(--paper-dim); max-width:560px; }

.support-card{
  display:flex; flex-direction:column; align-items:center; text-align:center; gap:14px;
  max-width:420px; margin:0 0 32px; padding:36px 28px; border-radius:var(--radius-l);
  border:1px solid var(--gold-dim);
  background:linear-gradient(165deg, rgba(205,166,95,0.1), var(--ink-2));
}
.support-card__icon{ font-size:2.6rem; }
.support-card__lead{ margin:0; font-size:0.92rem; color:var(--paper); line-height:1.5; }
.support-card__btn.btn--lg{ padding:14px 36px; font-size:1rem; }
.support-card__note{ margin:0; font-size:0.74rem; color:var(--paper-dim); line-height:1.5; }

.store__redeem{ display:flex; gap:10px; max-width:420px; margin:16px 0 4px; }
.store__redeem input{
  flex:1 1 auto; min-width:0; padding:12px 16px; border-radius:999px;
  border:1px solid var(--line); background:var(--ink-3); color:var(--paper);
  font-family:var(--font-body); font-size:0.85rem; text-transform:uppercase; letter-spacing:0.02em;
  transition:border-color .2s var(--ease);
}
.store__redeem input:focus{ outline:none; border-color:var(--accent-dim); }
.store__redeem-note{ font-size:0.8rem; min-height:1.2em; margin:0 0 18px; }
.store__redeem-note--error{ color:#e08a8a; }
.store__redeem-note--success{ color:var(--accent); }
.store__redeem-hint{ font-size:0.78rem; color:var(--paper-dim); margin:0 0 20px; }
.store__redeem-hint a{ color:var(--accent); text-decoration:none; }
.store__redeem-hint a:hover{ text-decoration:underline; }

/* Donation thank-you modal (see script.js) */
.donation-thanks{ display:flex; flex-direction:column; align-items:center; gap:16px; text-align:center; }
.donation-thanks__icon{ font-size:2.6rem; }
.donation-thanks__title{ font-family:var(--font-display); font-size:1.3rem; font-weight:500; margin:0; }
.donation-thanks__amount{ font-size:1.4rem; font-weight:600; color:var(--gold); font-variant-numeric:tabular-nums; }
.donation-thanks__msg{ margin:0; font-size:0.88rem; color:var(--paper-dim); line-height:1.6; max-width:360px; }
.donation-thanks__cosmetics{ display:flex; gap:16px; margin-top:6px; }
.donation-thanks__cosmetic{ display:flex; flex-direction:column; align-items:center; gap:6px; }
.donation-thanks__cosmetic-label{ font-size:0.7rem; color:var(--paper-dim); text-transform:uppercase; letter-spacing:0.04em; }

/* ============================================================
   First-login topbar tour (see script.js's startTour)
   ============================================================ */
/* Above .battle-overlay's z-index:70 (components.css) and every .modal
   (z-index:50/60) -- the tour has to dominate everything, and blocks all
   clicks on its own (nothing needs pointer-events:none here) so a stray
   click during the tour can't reach the real page underneath. */
.tour-overlay{ position:fixed; inset:0; z-index:95; }
/* The "spotlight hole" is a giant box-shadow, not clip-path/mask -- a
   transparent .tour-spotlight box whose shadow spreads 9999px darkens the
   ENTIRE viewport except its own rect, which is what makes the real topbar
   element underneath show through untouched. Animates smoothly between
   steps since only top/left/width/height change, not the element itself. */
.tour-spotlight{
  position:fixed; border-radius:999px;
  box-shadow:0 0 0 9999px rgba(4,4,6,0.87);
  border:2px solid var(--gold); pointer-events:none;
  transition:top .35s var(--ease), left .35s var(--ease), width .35s var(--ease), height .35s var(--ease);
}
.tour-caption{
  position:fixed; top:82px; left:50%; transform:translateX(-50%);
  width:min(360px, calc(100vw - 32px));
  background:linear-gradient(165deg, var(--ink-2), var(--ink));
  border:1px solid var(--line); border-radius:var(--radius-l);
  padding:18px 22px; text-align:center;
  box-shadow:0 12px 40px -12px rgba(0,0,0,0.6);
}
.tour-caption__step{
  margin:0 0 8px; font-size:0.68rem; font-weight:700; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--gold);
}
.tour-caption__text{ margin:0 0 16px; font-size:0.88rem; line-height:1.55; color:var(--paper); }
.tour-caption__actions{ display:flex; gap:10px; justify-content:center; }

