/* ─────────────────────────────────────────────────────────────────────────
   Shared page chrome: the top row, the menu overlay and the mechanics rail.

   These rules were inline in BOTH throne.blade.php and play.blade.php, and
   the archive would have been a third copy. Duplicated chrome is why the
   History and Profile links sat pointing at the live site long after those
   pages existed here — a fix only ever landed in one copy.

   /history loads this file. throne + play still carry their own inline
   copies; migrating them is a follow-up, deliberately not done in the same
   pass that ported the archive.
   ───────────────────────────────────────────────────────────────────────── */
.top{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 4px}
.logo{font-family:var(--font-display);font-size:30px;letter-spacing:1px;transform:rotate(-2deg);display:inline-block;color:var(--bam-text);text-decoration:none}
.logo b{color:var(--bam-red);font-weight:inherit}
.top-right{display:flex;align-items:center;gap:8px}
.menu-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:32px;border:1.5px solid var(--bam-border);border-radius:var(--radius-sm);
  color:var(--bam-text-muted);transition:border-color .15s,color .15s,background .15s;
}
.menu-btn:hover{border-color:var(--bam-yellow);color:var(--bam-yellow)}
.menu-btn svg{width:18px;height:18px;display:block}
.menu-overlay{
  position:fixed;inset:0;z-index:80;background:rgba(10,10,20,.97);
  display:none;flex-direction:column;align-items:center;justify-content:center;
  padding:60px 20px;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.menu-overlay.open{display:flex;animation:menuin .25s ease}
.menu-overlay::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(circle at 20% 25%, rgba(226,75,74,.12), transparent 40%),
    radial-gradient(circle at 80% 70%, rgba(255,217,61,.08), transparent 40%);
}
.menu-close{
  position:absolute;top:18px;right:18px;
  width:40px;height:40px;border:1.5px solid var(--bam-border);border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;
  color:var(--bam-text-muted);transition:border-color .15s,color .15s
}
.menu-close:hover{border-color:var(--bam-red);color:var(--bam-red)}
.menu-close svg{width:18px;height:18px}
.menu-brand{
  font-family:var(--font-display);font-size:46px;letter-spacing:1.5px;
  transform:rotate(-2deg);margin-bottom:34px;color:var(--bam-text);text-decoration:none;
  text-shadow:3px 3px 0 rgba(226,75,74,.5);
}
.menu-brand b{color:var(--bam-red);font-weight:inherit}
.menu-mech{display:flex;flex-direction:column;gap:10px;align-items:center;margin-bottom:6px}
.menu-mech a{
  font-family:var(--font-display);font-size:34px;letter-spacing:1.5px;line-height:1;
  color:var(--bam-text);text-decoration:none;text-transform:uppercase;
  padding:6px 14px;position:relative;
  transition:color .12s,transform .12s,text-shadow .12s
}
.menu-mech a:nth-child(odd){transform:rotate(-1deg)}
.menu-mech a:nth-child(even){transform:rotate(1deg)}
.menu-mech a:hover{color:var(--bam-yellow);text-shadow:2px 2px 0 var(--bam-red)}
.menu-mech a:nth-child(odd):hover{transform:rotate(-1deg) scale(1.04)}
.menu-mech a:nth-child(even):hover{transform:rotate(1deg) scale(1.04)}
.menu-mech a.current{color:var(--bam-yellow);border-bottom:3px solid var(--bam-yellow);padding-bottom:3px}
.menu-mech a.current::after{
  content:' · you\2019re here';font-family:var(--font-ui);font-size:12px;letter-spacing:1.4px;
  color:var(--bam-text-dim);text-transform:uppercase;display:inline-block;margin-left:4px;
  vertical-align:middle;text-shadow:none;font-weight:400;
}
.menu-divider{width:32px;height:1px;background:var(--bam-border);margin:14px 0;border:0}
.menu-meta{display:flex;gap:18px;align-items:center;flex-wrap:wrap;justify-content:center}
.menu-meta a{
  font-family:var(--font-display);font-size:22px;letter-spacing:1.2px;
  color:var(--bam-text-muted);text-decoration:none;text-transform:uppercase;
  transition:color .12s
}
.menu-meta a:hover{color:var(--bam-yellow)}
.menu-legal{
  display:flex;gap:10px;align-items:center;justify-content:center;flex-wrap:wrap;
  font-family:var(--font-ui);font-size:12px;letter-spacing:1.4px;text-transform:uppercase;
  color:var(--bam-text-dim);margin-top:6px
}
.menu-legal a{color:var(--bam-text-dim);text-decoration:none;transition:color .12s}
.menu-legal a:hover{color:var(--bam-yellow)}
.menu-legal .dot{opacity:.5}
.menu-foot{position:absolute;bottom:24px;font-family:var(--font-ui);font-size:12px;color:var(--bam-text-dim);letter-spacing:1.4px;text-transform:uppercase;text-align:center}
@keyframes menuin{0%{opacity:0}100%{opacity:1}}

/* mechanics rail — see partials/mech-nav.blade.php */
.mech-nav    { grid-column:1 / -1; grid-row:2 }
.mech-nav{display:flex;justify-content:center;flex-wrap:wrap;gap:6px;padding:8px;background:#0a0a14;border:1.5px solid var(--bam-border);border-radius:999px;box-shadow:inset 0 1px 0 rgba(255,255,255,.04);margin:6px auto 0;max-width:max-content}
.mech-nav a{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border-radius:999px;font-family:var(--font-display);font-size:14px;letter-spacing:1.3px;color:var(--bam-text-muted);text-decoration:none;text-transform:uppercase;transition:color .15s, background .15s, transform .12s}
.mech-nav a:hover{color:var(--bam-yellow)}
.mech-nav a svg{width:17px;height:17px;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s cubic-bezier(.34,1.56,.64,1)}
.mech-nav a:hover svg{transform:rotate(-8deg) scale(1.1)}
.mech-nav a.current{background:linear-gradient(180deg, #FFD93D 0%, #E5A828 100%);color:#1a0f00;box-shadow:0 0 18px -4px rgba(255,217,61,.55), inset 0 1px 0 rgba(255,255,255,.4)}
.mech-nav a.current:hover{color:#1a0f00}
.mech-nav a.current svg{transform:scale(1.08)}
.mech-nav a{padding:9px 12px;font-size:14px;gap:6px}
.mech-nav a svg{width:15px;height:15px}
.mech-nav{gap:16px}
.mech-nav a{font-size:19px;letter-spacing:1.2px}
@media (max-width:380px){.mech-nav a{padding:9px 12px;font-size:14px;gap:6px}.mech-nav a svg{width:15px;height:15px}}

/* ─────────────────────────────────────────────────────────────────────────
   The page shell — the boxed card every bam.li page sits in.

   play and throne each declare this inline and identically; the archive
   shipped without it and looked like a different site (no card, no border,
   no ring). Same rule, one place. Width is the only thing that varies:
   the game pages are a narrow 420px column, the archive is a 920px table.
   ───────────────────────────────────────────────────────────────────────── */
body{
  /* Nunito is proportional; stat columns and timers need tabular figures. */
  font-variant-numeric:tabular-nums;
  display:flex;flex-direction:column;align-items:center;
  padding:14px 12px 32px;gap:14px;position:relative;min-height:100vh;
}
.frame{
  width:100%;max-width:var(--frame-max, 420px);
  display:flex;flex-direction:column;gap:14px;
  position:relative;z-index:1;
}
@media (min-width: 720px){
  body{padding:40px 20px}
  .frame{
    background:#0d0d16;border:1.5px solid #1f1f28;border-radius:28px;
    padding:22px 22px 26px;
    box-shadow:
      0 0 0 6px #0a0a14,
      0 0 0 7.5px #1f1f28,
      0 30px 80px -10px rgba(0,0,0,.7),
      0 0 60px -20px rgba(226,75,74,.15);
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   THE DESKTOP SHELL — the layout the homepage uses above 1200px.

   The rail stops being a horizontal pill bar and parks as a sticky vertical
   column on the left, with the content beside it. Cookie Clicker's mental
   map: navigation parked, the thing you came for in the centre.

   The archive shipped with the old horizontal bar while the homepage had
   already moved to this, which is exactly what "not consistent with the
   homepage" meant. play declares its own copy inline (it has a third column
   for leaderboards); this generic two-column form is what every other page
   needs, and throne should adopt it next.

   Content children need no rules: the rail is pinned to column 1 and
   everything else auto-places into column 2.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width:1200px){
  body.shell.shell-auto .frame{
    display:grid;
    max-width:min(1280px, 100% - 96px);
    grid-template-columns:206px minmax(0,1fr);
    gap:12px 20px;
    padding:22px 24px 28px;
    align-content:start;
  }
  body.shell .frame > .top{ grid-column:1 / -1; grid-row:1 }
  body.shell .frame .mech-nav{
    grid-column:1; grid-row:2 / span 99;
    flex-direction:column; align-items:stretch; flex-wrap:nowrap;
    max-width:none; width:100%;
    border-radius: 4px; padding:10px; gap:2px;
    position:sticky; top:16px; align-self:start;
    overflow:visible;
  }
  body.shell .frame .mech-nav a{
    justify-content:flex-start; padding:11px 13px; border-radius: 4px;
    font-size:14.5px; letter-spacing:.9px;
  }
  /* Auto-placement, for pages with NO bespoke grid of their own.
     GATED behind .shell-auto deliberately. `:not()` contributes its
     argument's specificity, so this selector lands at (0,5,1) — high enough
     to beat a page's own `body.shell .frame > .lb-stack` at (0,3,1). Left
     ungated it silently dragged the homepage's leaderboard column out of
     column 3 and stacked it under the globe. */
    /* .foot and .rail-col are placed by the shared rules above. `:not()`
     contributes specificity, so this catch-all sits at (0,6,1) and would
     otherwise outrank them and drag both into the content column — which is
     exactly how history ended up with its rail full-width in column 2. */
  body.shell.shell-auto .frame > *:not(.top):not(.rail-col):not(.mech-nav):not(.menu-overlay):not(.foot){
    grid-column:2;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   VERTICAL ALIGNMENT — every page's card starts at the same height.

   The homepage nests its frame in `.bam-stage-wrap` (the burst-animation
   stage), which repeats the body's 40px top padding. Net effect: the
   homepage card sits at 80px and every page WITHOUT that wrapper sat at
   40px — the throne read as "higher than the homepage", because it was, by
   exactly 40px, and every row below inherited the shift.

   The child combinator is doing real work: on the homepage the frame is a
   grandchild of body, so this rule deliberately does not match it and it
   keeps the offset it already gets from the wrapper.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width: 720px){
  body > main.frame{ margin-top:40px }
}

/* ─────────────────────────────────────────────────────────────────────────
   FOOTER — the mechanics footer shared by every game page.
   play and throne each declared these same 16 rules inline.
   ───────────────────────────────────────────────────────────────────────── */
.foot{display:flex;flex-direction:column;align-items:center;gap:14px;padding:14px 8px 4px;text-align:center}
.foot-mech{display:flex;gap:18px;align-items:baseline;flex-wrap:wrap;justify-content:center}
.foot-mech a{font-family:var(--font-display);font-size:22px;letter-spacing:1.2px;color:var(--bam-text-muted);text-decoration:none;text-transform:uppercase;transition:color .12s}
.foot-mech a:hover{color:var(--bam-yellow)}
.foot-mech a.current{color:var(--bam-yellow);border-bottom:2px solid var(--bam-yellow);padding-bottom:2px}
.foot-divider{width:80%;height:1px;background:var(--bam-border);border:0;margin:2px 0}
.foot-meta{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:6px 10px;font-family:var(--font-ui);font-size:13px;letter-spacing:.6px;color:var(--bam-text-muted)}
.foot-meta a{color:var(--bam-text-muted);text-decoration:none;transition:color .12s}
.foot-meta a:hover{color:var(--bam-yellow)}
.foot-meta .from{color:var(--bam-text-dim);font-style:italic;letter-spacing:.4px}
.foot-meta .dot{opacity:.5;color:var(--bam-text-dim)}
.foot-legal{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:6px 10px;font-family:var(--font-ui);font-size:12px;letter-spacing:1px;text-transform:uppercase;color:var(--bam-text-dim)}
.foot-legal a{color:var(--bam-text-dim);text-decoration:none;transition:color .12s}
.foot-legal a:hover{color:var(--bam-yellow)}
.foot-legal .dot{opacity:.5}
.foot-copy{font-family:var(--font-ui);font-size:11px;letter-spacing:1.1px;color:var(--bam-text-dim);text-transform:uppercase;margin-top:2px}
.foot-social{display:flex;justify-content:center}
.foot-fb{display:inline-flex;align-items:center;gap:8px;color:var(--bam-text-muted);text-decoration:none;font-family:var(--font-ui);font-size:13px;letter-spacing:.8px;transition:color .12s}
.foot-fb:hover{color:var(--bam-yellow)}
.foot-fb svg{width:18px;height:18px;fill:currentColor}

/* ─────────────────────────────────────────────────────────────────────────
   RAIL AS A CARD — the reference layout Gray supplied.

   The rail was a bare rounded pill strip; in the shell it now reads as a
   proper panel with room to breathe, matching the cards beside it. Applies
   only in the shell, because below 1200px the rail is a horizontal bar and a
   card border around it would be noise.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width:1200px){
  body.shell .frame .mech-nav{
    background:var(--bam-card);
    border:1.5px solid var(--bam-border);
    border-radius: 4px;
    padding:14px 12px;
    gap:4px;
    box-shadow:0 3px 0 -1px rgba(0,0,0,.4);
  }
  body.shell .frame .mech-nav a{
    padding:12px 14px;
    border-radius: 4px;
    font-size:14px;
    letter-spacing:1.1px;
  }
  body.shell .frame .mech-nav a svg{ width:18px;height:18px }

  /* Promo — under the rail, column 1. */
  body.shell .frame .rail-promo{
    grid-column:1; grid-row:11;
    align-self:start;
    background:var(--bam-card);
    border:1.5px solid var(--bam-border);
    border-radius: 4px;
    padding:16px 14px;
    display:flex; flex-direction:column; gap:12px;
    box-shadow:0 3px 0 -1px rgba(0,0,0,.4);
  }

}

/* The promo is a shell-only element: below 1200px there is no column for it. */
.rail-promo{ display:none }
@media (min-width:1200px){ body.shell .rail-promo{ display:flex } }
.rail-promo-top{ display:flex; gap:11px; align-items:flex-start }
.rail-promo-icon{
  flex:0 0 auto; width:38px; height:38px; border-radius: 4px;
  display:inline-flex; align-items:center; justify-content:center;
  color:var(--bam-yellow);
  background:linear-gradient(180deg, rgba(255,217,61,.16), rgba(255,217,61,.05));
  border:1.5px solid rgba(255,217,61,.35);
}
.rail-promo-icon svg{ width:20px;height:20px }
.rail-promo h3{
  font-family:var(--font-display); font-size:15px; letter-spacing:1.1px;
  text-transform:uppercase; color:var(--bam-text); margin:1px 0 4px;
}
.rail-promo p{
  font-family:var(--font-sans); font-size:13.5px; line-height:1.45;
  color:var(--bam-text-muted); margin:0;
}
.rail-promo-btn{
  display:block; text-align:center; text-decoration:none;
  font-family:var(--font-display); font-size:14.5px; letter-spacing:1.3px;
  text-transform:uppercase; color:var(--bam-purple);
  border:1.5px solid var(--bam-purple); border-radius: 4px; padding:10px 12px;
  transition:background .15s, color .15s;
}
.rail-promo-btn:hover{ background:rgba(127,119,221,.14); color:var(--bam-text) }

/* ─────────────────────────────────────────────────────────────────────────
   LEFT COLUMN — rail + promo as one sticky cell, footer beneath it.

   Grid rows are sized by the tall centre column, so anything given its own
   row in column 1 lands level with whatever huge thing is beside it — a
   promo placed that way sat ~1,300px below the rail. One cell, flex column.
   ───────────────────────────────────────────────────────────────────────── */
@media (min-width:1200px){
  /* The rail is an ABSOLUTE full-height track, not a grid citizen.
     Grid-row spans were tried twice and both fail structurally: a small
     span starves the sticky of travel (the rail scrolled away with the
     page), a large one reserves phantom rows that each pay the 12px
     row-gap (a ~260px void before the footer). Column 1 of the grid is
     just the 206px spacer this track sits over. Top = frame padding +
     header row + gap; the shared header is identical on every page, so
     the offset is a constant, and the sticky inside gets the whole frame
     height to travel. */
  body.shell .frame{
    position:relative;
    /* Tall enough that the rail track (79 top + ~490 of nav+promo + 30
       bottom) never pokes out of the card on a near-empty page. */
    min-height:600px;
  }
  body.shell .frame > .rail-col{
    position:absolute; left:24px; top:79px; bottom:30px; width:206px;
    /* NO grid placement up here. The pages place .rail-col on row 2 for
       their narrower layouts, and those rules also match at this width. An
       absolutely positioned grid child WITH a placement is positioned from
       its grid area, not the frame's padding edge — so left:24 was counted
       from the content edge, the rail landed 24px right, ran 5px into the
       centre column and closed the gap entirely. */
    grid-column:auto; grid-row:auto;
  }
  body.shell .frame > .rail-col .rail-stick{
    position:sticky; top:16px;
    display:flex; flex-direction:column; gap:14px;
  }
  body.shell .frame .rail-col .mech-nav{
    flex-direction:column; align-items:stretch; flex-wrap:nowrap;
    max-width:none; width:100%;
    position:static;
    mask-image:none; -webkit-mask-image:none;
  }
  /* Arena: square rail, the current page is a slanted yellow block. */
  body.shell .frame .rail-col .mech-nav{ border-radius:4px }
  body.shell .frame .rail-col .mech-nav a{ border-radius:2px }
  body.shell .frame .rail-col .mech-nav a.current{
    border-radius:0; box-shadow:none;
    clip-path:polygon(0 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
  }
  body.shell .frame .rail-col .rail-promo{ border-radius:4px }
  body.shell .frame .rail-col .rail-promo-btn{ border-radius:2px }
  /* Footer: full-width band on an AUTO row, so it lands directly after the
     last content row on every page. Parking it at a fixed far row (33) left
     a void of empty gap-rows above it, and pinning it into column 1 left it
     orphaned bottom-left beside nothing. */
  body.shell .frame > .foot{
    /* Columns 2/-1, NOT 1/-1. The rail is an absolute overlay on column 1,
       so a full-width footer renders UNDERNEATH it — "BAM Brawl" and half
       of "Steal the Throne" were hidden behind the rail card on any page
       whose footer nav was wide enough to reach back that far. */
    grid-column:2 / -1; grid-row:auto;
    margin-top:6px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   THE RAIL BELOW THE SHELL — an even GRID, not a ragged flex line.

   Seven destinations wrapped as flex gave 3 / 3 / 1: uneven rows with ARMY
   orphaned on its own line, which reads as a layout that has come apart.

   NOT a scrolling tab bar, though it was asked for: this is navigation, and
   the house rule is that navigation wraps rather than hiding destinations
   behind a sideways gesture nobody knows is available. An even grid gets the
   tidiness a tab strip was wanted for, while every destination stays visible.
   The odd last item spans the full width so it is never an orphan.
   ───────────────────────────────────────────────────────────────────────── */
/* Below 1200 the rail is the tab grid across the top, so on any page that
   lays itself out as a grid its wrapper must span the full width. Pages
   used to place `.frame > .mech-nav` themselves; once the nav moved inside
   .rail-col those rules stopped matching and the wrapper auto-placed into a
   single cell — half-width on throne, crushed into 60px on the homepage.
   Column set HERE, once; each page still picks its own row. */
@media (max-width:1199px){
  body.shell .frame > .rail-col{ grid-column:1 / -1 }
}

@media (max-width:1199px){
  /* TAB LOOK, per Gray. The container pill read as an empty blob around a
     ragged menu; as tabs the strip is flat with an underline on the current
     page — same language as the archive's filter tabs. Still a GRID and
     still every destination visible: the tab LOOK, not a scroll rail. */
  .mech-nav{
    display:grid; grid-template-columns:repeat(3, 1fr);
    gap:2px 6px; padding:2px 4px 0;
    /* The base rule caps this at `max-content`, which kept the grid narrow
       and wrapped "BAM BRAWL" inside its own cell. Fill the frame so each
       cell has room for its label on one line. */
    width:100%; max-width:none; margin:6px 0 0;
    background:transparent; border:0; border-radius:0; box-shadow:none;
    border-bottom:1.5px solid var(--bam-border);
  }
  .mech-nav a{
    justify-content:center; padding:12px 8px 14px; border-radius:0;
    white-space:nowrap; min-width:0; position:relative;
  }
  /* current = yellow text + underline, not the filled pill (that stays for
     the desktop rail card, which matches the reference mockup). */
  .mech-nav a.current{ background:none; color:var(--bam-yellow); box-shadow:none }
  .mech-nav a.current:hover{ color:var(--bam-yellow) }
  .mech-nav a.current::after{
    content:''; position:absolute; left:16%; right:16%; bottom:0; height:3px;
    background:var(--bam-yellow); border-radius:2px 2px 0 0;
    box-shadow:0 0 10px rgba(255,217,61,.5);
  }
  /* 7 items over 3 columns leaves one on the last row — span it. */
  .mech-nav a:last-child{ grid-column:1 / -1 }
}
@media (max-width:560px){
  .mech-nav{ grid-template-columns:repeat(2, 1fr) }
  /* 7 over 2 columns leaves one over — same treatment. */
  .mech-nav a:last-child{ grid-column:1 / -1 }
  .mech-nav a{ font-size:14.5px; letter-spacing:1px; gap:6px }
  .mech-nav a svg{ width:15px;height:15px }
}

/* ─────────────────────────────────────────────────────────────────────────
   SEO PROSE SECTIONS — the "what is this game" block at the foot of the
   game pages. Was a bare wall of six paragraphs in a 680px column floating
   in the frame; now the house pattern: eyebrow + display title, a lead
   line, and the body split across cards. Every sentence kept — this text
   ranks, so it gets structure, not scissors.
   ───────────────────────────────────────────────────────────────────────── */
.sp-head{ text-align:center; margin-bottom:4px }
.sp-eyebrow{
  display:block; font-family:var(--font-ui); font-size:13px;
  letter-spacing:1.8px; text-transform:uppercase; color:var(--bam-text-dim);
  margin-bottom:6px;
}
.seo-prose .sp-lead{ max-width:72ch; margin:0 auto; text-align:center }
.sp-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:14px;
  margin:10px 0 2px; text-align:left;
}
@media (max-width:900px){ .sp-grid{ grid-template-columns:1fr } }
.sp-card{
  background:var(--bam-card); border:1.5px solid var(--bam-border);
  border-radius: 4px; padding:18px 20px;
}
.sp-card h3{
  font-family:var(--font-ui); font-size:13px; font-weight:700;
  letter-spacing:1.8px; text-transform:uppercase; color:var(--bam-yellow);
  margin:0 0 10px;
}
.sp-card p{ margin:0 }
.sp-card p + p{ margin-top:10px }
.seo-prose .sp-cross{
  margin:0; text-align:center;
  background:var(--bam-card); border:1.5px solid var(--bam-border);
  border-radius: 4px; padding:14px 20px;
}

/* ─────────────────────────────────────────────────────────────────────────
   BUTTON HYGIENE, SITE-WIDE — from a full-page audit (2026-08-16).

   Three faults, found by checking every button-shaped element on every
   page against the stylesheet's own :hover/:active rules:
   · <a class="btn"> carried the browser's default underline ("Plan an
     attack" and every other link-as-button on the army pages).
   · .menu-btn is a <button>, and buttons get cursor:default from the UA.
   · Several families had no press feedback at all (no :active rule and
     zero transition): the army .btn set, dashboard's .btn-secondary,
     the shop's .shop-btn, activity's pager, sign-out, play's feed chips.
   Page styles load after this sheet, so anything a page sets deliberately
   still wins. */
a.btn { text-decoration: none }
button:not(:disabled) { cursor: pointer }

.btn, .btn-primary, .btn-secondary, .shop-btn, .buy-btn,
.pager button, .pager-btn, .t-row, .whoami .logout, .menu-btn, .rail-promo-btn,
.feed-card .filter button {
  transition: filter .15s, background .15s, color .15s, border-color .15s, transform .08s;
}
.btn:active:not(:disabled), .btn-primary:active, .btn-secondary:active,
.shop-btn:active, .buy-btn:active, .pager button:active:not(:disabled),
.pager-btn:active:not(:disabled), .t-row:active:not(:disabled),
.whoami .logout:active, .menu-btn:active, .rail-promo-btn:active,
.feed-card .filter button:active {
  transform: translateY(1px);
}
/* the two families the audit found with NO hover state at all */
.btn-secondary:hover, .shop-btn:hover,
.feed-card .filter button:hover { filter: brightness(1.18) }

/* ─────────────────────────────────────────────────────────────────────────
   (?) HELPERS — see public/bam-help.js. A marker becomes a small button;
   the explainer is a fixed card (a bottom sheet under 560px) linking into
   /how-to-play. Kept deliberately quiet: it must sit beside a label without
   competing with it.
   ───────────────────────────────────────────────────────────────────────── */
.help-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;margin-left:6px;vertical-align:middle;flex:0 0 auto;
  border-radius:50%;border:1.5px solid var(--bam-text-dim,#555);background:transparent;
  color:var(--bam-text-muted,#888);font-family:var(--font-ui);font-size:10.5px;font-weight:700;
  line-height:1;cursor:pointer;padding:0;transition:color .15s,border-color .15s,background .15s,transform .08s;
}
.help-btn:hover,.help-btn:focus-visible,.help-btn[aria-expanded="true"]{
  color:#1a0f00;background:var(--bam-yellow);border-color:var(--bam-yellow);outline:none;
}
.help-btn:active{transform:translateY(1px)}
.help-pop{
  position:fixed;z-index:120;width:320px;max-width:calc(100vw - 24px);
  background:#15151c;border:1.5px solid rgba(255,217,61,.45);border-radius: 4px;
  padding:14px 16px 14px;box-shadow:0 18px 50px rgba(0,0,0,.6),0 0 0 4px rgba(10,10,20,.9);
  font-family:var(--font-sans);color:var(--bam-text-muted,#aaa);font-size:15px;line-height:1.55;
  animation:helpin .14s ease;
}
@keyframes helpin{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.help-pop.sheet{left:12px;right:12px;bottom:12px;top:auto;width:auto;max-width:none}
.help-pop-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:6px}
.help-pop h4{margin:0;font-family:var(--font-display);font-size:17px;letter-spacing:.6px;color:var(--bam-text,#fff)}
.help-pop-x{background:none;border:0;color:var(--bam-text-dim,#666);font-size:20px;line-height:1;cursor:pointer;padding:0 2px;margin:-4px -4px 0 0}
.help-pop-x:hover{color:var(--bam-text,#fff)}
.help-pop p{margin:0 0 10px}
.help-pop-more{display:inline-block;font-family:var(--font-ui);font-size:13px;letter-spacing:1.2px;text-transform:uppercase;color:var(--bam-yellow);text-decoration:none;border-bottom:1px dashed var(--bam-yellow)}
.help-pop-more:hover{color:#fff;border-color:#fff}
@media (prefers-reduced-motion:reduce){.help-pop{animation:none}}


/* ─────────────────────────────────────────────────────────────────────────
   GAME CARDS — the shared look for anything you buy, train or unlock.
   Built for the Shop (a game store: icon, big number, price on the button,
   owned / next / locked readable at a glance) and reused by the Army.
   One copy: pages must not restyle these, they add modifiers.
   ───────────────────────────────────────────────────────────────────────── */
.shop-top .section-title { margin: 0; }
.shop-stats { display: flex; gap: 10px; flex-wrap: wrap; }
.stat-chip {
    display: flex; align-items: center; gap: 7px; padding: 8px 14px;
    position: relative; isolation: isolate; background: none; border: 0;
    font-family: var(--font-ui); font-size: 13px; letter-spacing: .8px; text-transform: uppercase; color: var(--bam-text-muted);
}
.stat-chip::before { content: ''; position: absolute; inset: 0; z-index: -1; background: #0d0d13; border-left: 3px solid var(--bam-yellow); transform: skewX(-10deg); }
.stat-chip b { font-family: var(--font-display); font-size: 22px; color: var(--bam-yellow); letter-spacing: .5px; text-transform: none; }
.chip-ico { font-size: 17px; }

.shop-section { margin-bottom: 28px; }
.shop-h { font-family: var(--font-display); font-size: 26px; letter-spacing: 1px; text-transform: uppercase; margin: 0 0 12px; display: flex; align-items: center; gap: 10px; }
.count-chip { font-family: var(--font-ui); font-size: 12.5px; letter-spacing: 1px; color: var(--bam-text-muted); background: #12121a; border: 1px solid var(--bam-line); border-radius: 999px; padding: 3px 10px; }

.ucard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 12px; }
.ucard {
    position: relative; display: flex; flex-direction: column; gap: 10px;
    background: linear-gradient(180deg, #17171f, #121219);
    border: 1px solid var(--bam-line); border-top: 2px solid var(--bam-red); border-radius: 4px; padding: 16px;
    transition: transform .12s, border-color .12s, box-shadow .12s;
}
.ucard-ico {
    width: 52px; height: 52px; border-radius: 4px; display: grid; place-items: center;
    font-size: 28px; background: #1d1d27; border: 1px solid var(--bam-line);
}
.ucard-body { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.ucard-name { font-family: var(--font-display); font-size: 22px; letter-spacing: 1px; line-height: 1; text-transform: uppercase; }
.ucard-flavor { font-family: var(--font-ui); font-size: 13.5px; color: var(--bam-text-muted); line-height: 1.4; }
.ucard-gain { font-family: var(--font-display); font-size: 30px; color: var(--bam-yellow); line-height: 1; margin-top: 8px; }
.ucard-gain small { font-family: var(--font-ui); font-size: 13px; letter-spacing: .6px; color: var(--bam-text-muted); text-transform: uppercase; }

/* next up — the one to buy */
.ucard.is-next { border-color: rgba(255,217,61,.6); box-shadow: 0 0 0 1px rgba(255,217,61,.18) inset, 0 8px 26px -14px rgba(255,217,61,.55); }
.ucard.is-next .ucard-ico { background: rgba(255,217,61,.12); border-color: rgba(255,217,61,.45); }
.ucard.can-buy { animation: ucard-pulse 1.8s ease-in-out infinite; }
@keyframes ucard-pulse { 50% { box-shadow: 0 0 0 1px rgba(255,217,61,.35) inset, 0 8px 34px -10px rgba(255,217,61,.8); } }
@media (prefers-reduced-motion: reduce) { .ucard.can-buy { animation: none; } }
/* owned — steps back */
.ucard.is-owned { opacity: .55; }
.ucard.is-owned .ucard-gain { color: var(--bam-green); }
/* locked — visible so you know what's coming, clearly not yours yet */
.ucard.is-locked { opacity: .5; }
.ucard.is-locked .ucard-ico { filter: grayscale(1); }
.ucard.is-locked .ucard-gain { color: var(--bam-text-muted); }

.ucard-gain.price { font-size: 24px; }
.ucard-owned { font-family: var(--font-ui); font-size: 13px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--bam-green); font-weight: 700; padding: 10px 0 2px; }
.ucard-locked { font-family: var(--font-ui); font-size: 12.5px; letter-spacing: .6px; color: var(--bam-text-dim); padding: 10px 0 2px; }
.ucard-bar { height: 8px; border-radius: 99px; background: rgba(255,255,255,.07); overflow: hidden; }
.ucard-bar span { display: block; height: 100%; background: linear-gradient(90deg, #FFD93D, #EF9F27); border-radius: 99px; }

.ucard.ascend { flex-direction: row; align-items: center; border-color: rgba(127,119,221,.55); margin-bottom: 12px; }
.ucard.ascend .game-btn { width: auto; padding: 12px 22px; }


/* ── BATTLE ROWS (army page + battle reports) ── */
.battle-row { display: grid; grid-template-columns: 76px 1fr auto 18px; gap: 10px; align-items: center; padding: 12px 18px; text-decoration: none; color: var(--bam-text); border-top: 1px solid var(--bam-line); font-family: var(--font-ui); font-size: 14px; }
.battle-row:first-child { border-top: 0; }
.battle-row:hover { background: #17171f; }
.battle-row:active { background: #1c1c25; }
.battle-row .result { font-family: var(--font-display); letter-spacing: 1px; font-size: 14px; }
.battle-row .result.won { color: #7fd79a; }
.battle-row .result.lost { color: var(--bam-red); }
.battle-row .when { display: block; font-size: 12px; color: var(--bam-text-muted); margin-top: 2px; }
.battle-row .loot { font-family: var(--font-display); color: var(--bam-yellow); white-space: nowrap; }
.battle-row .lost-n { color: #ef8a89; }
.battle-row .chev { color: var(--bam-text-dim); }
