/* ============================================================
   Clash of Cards — app-specific rules.
   Tokens only: every colour, space and radius resolves through
   theme.css (Carbon Terminal). Never edit theme.css; it stays swappable.

   Carbon's three rules, obeyed below:
     1. The body font IS mono. Nothing here reintroduces a proportional face.
     2. Radius never exceeds 3px — so nothing sets a radius directly, it all
        comes from --radius-*, which Carbon caps (--radius-full is 3px here).
     3. Green is status, not decoration. --accent stays on progress, markers
        and links; the card-group colours below deliberately avoid it.
   ============================================================ */

/* ---------- type scale ----------
   The one place this app overrides the theme's tokens, and it stays in app.css so
   theme.css remains a pristine, swappable copy.

   Carbon ships the densest scale in the system — 13px base, 10.5px labels — built
   for log viewers on a desktop. This app is read on phones, at arm's length, by
   people checking card names. Every step is Carbon's own, scaled by ~1.15, so the
   proportions between them are unchanged; the base lands on 15px, which is the
   largest base the design system uses anywhere (Ember and Mono), not a number
   invented here. Everything sized with --fs-* follows automatically. */
:root{
  --fs-xs:   12px;
  --fs-sm:   13.5px;
  --fs-base: 15px;
  --fs-md:   16px;
  --fs-lg:   18.5px;
  --fs-xl:   23px;
  --fs-2xl:  30px;
  --fs-3xl:  39px;
}

/* Intro copy inside a panel: capped line length, consistent gap to the content. */
.panel > p.muted{max-width:70ch;margin:0 0 var(--sp-5)}

/* ---------- login gate ---------- */
#gate{position:fixed;inset:0;z-index:100;overflow-y:auto;-webkit-overflow-scrolling:touch;background:var(--bg)}
.gate-scroll{min-height:100%;display:flex;align-items:center;justify-content:center;padding:var(--sp-5)}
#gate .modal{text-align:center}
#gate .logo{margin:0 auto var(--sp-4)}
.gate-users{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-5)}
.gate-users .btn{width:100%}
#gateMsg{display:none;margin-top:var(--sp-4);text-align:left}
#gateMsg.show{display:flex}

/* ---------- header ---------- */
.nav .chip{padding:var(--sp-1) var(--sp-3)}

/* ---------- card group colours ----------
   The only raw colours in this app, and a deliberate exception to the
   tokens-only rule: these are the game's own collection colours, read off the
   in-game Clash of Cards screen, so that a card reads the same here as it does
   there. No theme palette has magenta or violet, so they cannot come from one.

   They are declared as tokens in a single block, which keeps them behaving like
   the rest of the system and swappable in one place. Each is contrast-checked
   against all four Carbon surfaces at the 3:1 floor the design system sets for
   semantic colour (worst case 3.9:1, the violet).

   A side benefit: the collections no longer borrow --danger / --warning / --info,
   so those go back to meaning state and nothing else. */
:root{
  --cat-elixir:  #d24bc8;  --cat-elixir-soft:  rgba(210,75,200,.14);
  --cat-dark:    #9b5ce0;  --cat-dark-soft:    rgba(155,92,224,.14);
  --cat-builder: #4a9be0;  --cat-builder-soft: rgba(74,155,224,.14);
  --cat-super:   #ef7b2b;  --cat-super-soft:   rgba(239,123,43,.14);
}

/* Set on the card frames, the collection progress bars and the collection tag on
   every trade row — one colour per collection, everywhere it appears. */
.c-elixir { --cat:var(--cat-elixir);  --cat-soft:var(--cat-elixir-soft)  }
.c-dark   { --cat:var(--cat-dark);    --cat-soft:var(--cat-dark-soft)    }
.c-builder{ --cat:var(--cat-builder); --cat-soft:var(--cat-builder-soft) }
.c-super  { --cat:var(--cat-super);   --cat-soft:var(--cat-super-soft)   }

/* ---------- collection progress (the in-game tab strip) ---------- */

.cats{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);margin-top:var(--sp-5)}
.cat{background:var(--surface-1);border:var(--bw) solid var(--line);
     border-radius:var(--radius-md);padding:var(--sp-3) var(--sp-4)}
.cat-head{display:flex;align-items:baseline;gap:var(--sp-2);margin-bottom:var(--sp-3)}
.cat-name{font-weight:var(--fw-label);font-size:var(--fs-sm)}
.cat-head .num,.cat-head .badge{margin-left:auto}
.cat .hint{margin-top:var(--sp-2)}
.cat .progress > span{background:var(--cat)}
@media(max-width:760px){.cats{grid-template-columns:repeat(2,1fr)}}

.progress{flex:1;min-width:96px;max-width:280px;height:10px;overflow:hidden;
          background:var(--surface-3);border-radius:var(--radius-full)}
.progress > span{display:block;height:100%;background:var(--accent);
                 border-radius:var(--radius-full);
                 transition:width var(--dur-base) var(--ease)}
.cat .progress,.collected .progress{max-width:none}

/* ---------- the card stream ----------
   One continuous run of all sixty cards in roster order — a collection begins
   wherever the previous one ended instead of on a fresh row, which is what puts
   the last Builder Base card and Super Wall Breaker on the same line. Six across
   at every width, as in game; the tiles shrink rather than the row count
   changing, because a responsive column count would move those breaks. */
.stream{display:grid;grid-template-columns:repeat(6,1fr);gap:var(--sp-3);margin-top:var(--sp-4)}
@media(max-width:560px){.stream{gap:var(--sp-2)}}

/* The artwork is a full-bleed in-game icon that already carries its own
   background, so it sits inside a thin frame in the collection's colour. */
.tile{position:relative;cursor:pointer;user-select:none;padding:var(--sp-1);
      background:var(--cat-soft);border:var(--bw) solid var(--cat);
      border-radius:var(--radius-md);
      transition:opacity var(--dur-fast) var(--ease),
                 border-color var(--dur-fast) var(--ease)}
.tile:hover{border-color:var(--accent)}
.tile .art{position:relative;aspect-ratio:1;display:grid;place-items:center;overflow:hidden;
           background:var(--surface-1);border-radius:var(--radius-sm)}
.tile .art img{width:100%;height:100%;object-fit:cover;display:block;
               transition:filter var(--dur-base) var(--ease)}
.tile .art .glyph{font-size:var(--fs-xl)}
/* Six of the sixty cards ship no artwork; an emoji alone doesn't identify them.
   The strip rides the top edge because the bottom belongs to the spare badge. */
.tile .noart{position:absolute;left:0;right:0;top:0;padding:var(--sp-1);
             font-size:var(--fs-xs);line-height:var(--lh-tight);text-align:center;
             background:var(--surface-2);color:var(--text-muted);
             overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* State reads the way it does in game: missing is drained of colour, owned is
   simply full colour, and only a spare carries a badge. */
.tile.s0{opacity:.5}
.tile.s0 .art img{filter:grayscale(1) brightness(.6)}
.tile.s0:hover{opacity:1}
.tile.s0:hover .art img{filter:grayscale(.35) brightness(.9)}

/* Spare marker: sits along the bottom edge of the card, centred, and big enough
   to spot while scanning the grid. Sized by its own padding and type so it stays
   in proportion, and stepped down once the tiles get small at six-across on a
   phone. */
.mark{position:absolute;left:50%;bottom:var(--sp-1);transform:translateX(-50%);
      padding:var(--sp-1) var(--sp-3);display:grid;place-items:center;
      font-size:var(--fs-lg);font-weight:var(--fw-head);line-height:1;
      border-radius:var(--radius-full);box-shadow:var(--shadow-2)}
.mark.dupe{background:var(--warning);color:var(--accent-fg)}
@media(max-width:560px){
  .mark{font-size:var(--fs-md);padding:var(--sp-1) var(--sp-2)}
}

/* ---------- overall collected track ---------- */
.collected{margin-top:var(--sp-5);background:var(--surface-1);
           border:var(--bw) solid var(--line);border-radius:var(--radius-md);
           padding:var(--sp-4)}
.collected-head{display:flex;align-items:baseline;gap:var(--sp-3);margin-bottom:var(--sp-3)}
.collected-head .num{margin-left:auto}

/* ---------- trades ---------- */
/* Filter row: each switch is labelled with the very badge it controls, so the
   colour in the list and the colour in the control are the same thing. */
.trade-filter{display:flex;align-items:center;gap:var(--sp-5);flex-wrap:wrap;
              margin-bottom:var(--sp-5);padding-bottom:var(--sp-4);
              border-bottom:var(--bw) solid var(--line)}
.trade-filter .switch{gap:var(--sp-2)}
@media(max-width:560px){.trade-filter{gap:var(--sp-3)}}

.trade{margin-bottom:var(--sp-4)}
.trade-head{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin-bottom:var(--sp-3)}
.trade-head .name{font-family:var(--font-display);font-size:var(--fs-md);font-weight:var(--fw-head)}
.swap{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;
      padding:var(--sp-3) 0;border-top:var(--bw) solid var(--line)}
.swap:first-of-type{border-top:0}
.chip .ico{width:26px;height:26px;flex:none;object-fit:cover;border-radius:var(--radius-full)}
.chip .glyph{font-size:var(--fs-md)}
/* Collection tag on a trade row: carries that collection's colour, the same one
   the card wears in My Cards. Falls back to neutral if a row ever lacks the class. */
.tag{flex:none;font-size:var(--fs-xs);font-weight:var(--fw-label);letter-spacing:.06em;
     text-transform:uppercase;color:var(--cat,var(--text-muted));
     background:var(--cat-soft,var(--surface-3));
     border-radius:var(--radius-full);padding:3px var(--sp-3)}
.arrow{color:var(--accent);font-weight:var(--fw-head)}
/* Who-gains badge sits at the far end of its row; on a narrow screen it wraps
   below the chips and stays right-aligned rather than jumping to the margin. */
.swap .badge{margin-left:auto}

/* ---------- card packs ---------- */
.pack-form{display:grid;grid-template-columns:1.1fr 116px 2fr auto;gap:var(--sp-3);align-items:start}
.pack-form .input{min-width:0}
#packErr{display:none;margin-top:var(--sp-4)}
#packErr.show{display:flex}
.pack-actions{display:flex;gap:var(--sp-2);justify-content:flex-end}
.table td .input{padding:8px var(--sp-3)}
@media(max-width:640px){
  .pack-form{grid-template-columns:1fr 1fr}
  .pack-form #packDesc,.pack-form .btn{grid-column:1/-1}
}

/* ---------- changelog ---------- */
.log{margin-bottom:var(--sp-4)}
.log:last-child{margin-bottom:0}
.log-head{display:flex;align-items:baseline;gap:var(--sp-3);flex-wrap:wrap;
          margin-bottom:var(--sp-3);padding-bottom:var(--sp-3);
          border-bottom:var(--bw) solid var(--line)}
.log-head .hint{margin-left:auto}
.log-list{margin:0;padding-left:var(--sp-5)}
.log-list li{margin-bottom:var(--sp-2);line-height:var(--lh-normal)}
.log-list li:last-child{margin-bottom:0}
.log-list li::marker{color:var(--accent)}

/* ---------- toast ---------- */
#toast{position:fixed;left:50%;bottom:var(--sp-5);transform:translateX(-50%);z-index:80;
       opacity:0;pointer-events:none;transition:opacity var(--dur-base) var(--ease)}
#toast.show{opacity:1}
