/* classic — mobile (<=1280px). Linked via <link media>; no @media wrapper.
   The 1280px ceiling covers phones, tablets, and small laptops — anything
   below the classic-template's permanent-rail desktop layout at 1281+. */
.shell { min-height: 100vh; display: flex; flex-direction: column; }
/* Topbar (#321): hamburger left → left-aligned brand → single auth
   pill right. The brand sits flush after the hamburger so the logo
   reads as part of the left-aligned navigation cluster. The `.ha-*`
   pill rules are re-declared locally further down (the desktop
   sheet doesn't load below 1281px). */
.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  /* `--topbar-height` defaults to 52px on the mobile media-query in
     `classic/layout.astro` (`81px` on desktop); operator override via
     `TOPBAR_HEIGHT` flows through both viewports (#399 final). */
  min-height: var(--topbar-height, 52px);
  background: color-mix(in oklab, var(--bg) 92%, #000 8%);
  border-bottom: 1px solid var(--border);
}
/* `flex: 1` still claims the available space between hamburger and
   auth pills, but `justify-content: flex-start` pins the logo to the
   LEFT edge of that space (right after the hamburger). The auth pills
   stay flush right via the `.actions` cell's own flex behaviour. */
.topbar .brand { flex: 1; display: flex; justify-content: flex-start; text-decoration: none; }
.topbar .brand img { height: 28px; width: auto; }
.topbar .brand-text { font-weight: 700; font-size: 16px; text-align: left; color: var(--fg); }
.topbar .actions { display: flex; align-items: center; }

/* HeaderAuth pill cluster — full primary/ghost theming declared here
   because `classic-desktop.css` (which owns the canonical `.ha-btn`
   rules) doesn't load at viewports ≤1280px. Without these copies the
   topbar buttons render as unstyled defaults inside the mobile shell.
   Keep in sync with `classic-desktop.css:130-172` when either side
   changes — same colour vocabulary, only the sizing varies. */
.ha-actions { display: flex; align-items: center; gap: 6px; }
.ha-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--button-height, 32px);
  padding: 0 12px;
  box-sizing: border-box;
  border-radius: var(--button-radius, 8px);
  font-weight: 600;
  font-size: 13px;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: filter var(--motion-fast, 0.12s), background var(--motion-fast, 0.12s), border-color var(--motion-fast, 0.12s), color var(--motion-fast, 0.12s);
  white-space: nowrap;
}
.ha-btn-primary {
  /* Metallic cream-gold sweep — top stop reuses `--accent` (the
     brand tone) so a tenant `MAIN_COLOR` flip auto-tints the lighter
     half of the gradient; bottom stop is `--accent-strong`. */
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-strong) 100%);
  color: var(--accent-ink);
  border-color: var(--accent);
}
.ha-btn-primary:hover { filter: brightness(1.06); }
.ha-btn-ghost {
  background: transparent;
  color: var(--accent-light);
  border-color: var(--accent);
}
.ha-btn-ghost:hover {
  background: color-mix(in oklab, var(--accent) 12%, transparent);
  color: var(--accent-light-hover);
}
/* BUTTON_VARIANT (#399 final slice) — mirror of the desktop rules
   above so the mobile shell renders the same variant when the
   operator picks one. Keep in sync with `classic-desktop.css` next
   to its `.ha-btn-primary` block. */
body[data-button-variant="outlined"] .ha-btn-primary {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
  font-weight: 700;
}
body[data-button-variant="outlined"] .ha-btn-primary:hover {
  background: color-mix(in oklab, var(--accent) 14%, transparent);
  color: var(--accent-light-hover);
  filter: none;
}
body[data-button-variant="pill"] .ha-btn-primary {
  border-radius: 999px;
}
body[data-button-variant="ghost"] .ha-btn-primary {
  background: transparent;
  color: var(--accent-light);
  border-color: transparent;
  font-weight: 600;
}
body[data-button-variant="ghost"] .ha-btn-primary:hover {
  background: color-mix(in oklab, var(--accent) 10%, transparent);
  color: var(--accent-light-hover);
  filter: none;
}

/* Authed-state balance pill (#629). Same shape as the desktop chip
   (wallet icon · currency badge · amount), scaled to match the mobile
   `.ha-btn` row at 32px so the topbar's control band stays consistent.
   Without this block the mobile chip rendered unstyled — `classic-mobile.css`
   doesn't load below 1281px, so any styling has to be declared here too. */
.ha-balance {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: var(--button-height, 32px);
  padding: 0 10px;
  border: 1px solid var(--accent);
  border-radius: var(--button-radius, 8px);
  background: color-mix(in oklab, var(--accent) 8%, transparent);
  line-height: 1;
}
.ha-balance > svg {
  flex: 0 0 auto;
  color: var(--accent);
}
.ha-balance-currency {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--accent-light);
  opacity: 0.85;
}
.ha-balance-value {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.cta { background: var(--accent); color: var(--accent-fg); padding: 6px 12px;
  border-radius: var(--button-radius, 6px); font-weight: 600; text-decoration: none; font-size: 14px; }
/* `padding-bottom` reserves clearance for the fixed `.bottom-nav`
   (56px tab min-height + 6px×2 strip padding = 68px nominal, plus
   the iOS home-bar safe-area inset that the nav itself extends
   through). 80px gives ~12px breathing room above the nav. */
main { flex: 1; padding: 14px; padding-bottom: calc(80px + env(safe-area-inset-bottom)); }
.game-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  list-style: none; margin: 0; padding: 0; }
/* Mobile / tablet variant of the single-column banner stack (#804).
   Card chrome (background, radius, padding) lives in
   `PromoCard.astro`'s scoped <style>. No max-width here; the mobile
   shell's `main` already confines the column. */
.promo-list { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: 1fr; gap: 12px; }
/* Mobile bottom-nav (#813) — mirrors the desktop sidebar's group-card
   treatment: same `--surface-card-1` → `--surface-card-2` two-tone
   sweep, cream-gold `--accent` top border, accent-light active state.
   Fixed strip uses top-border + matching radius on its upper corners
   so the rounded chrome reads as a card edge rather than a flush bar.
   Each tab stacks an icon over its label (SidebarIcon at 22px). */
.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  padding: 6px 6px max(6px, env(safe-area-inset-bottom));
  background: linear-gradient(93deg, var(--surface-card-1) 35%, var(--surface-card-2) 100%);
  border-top: 1px solid var(--accent);
  border-top-left-radius: 14px;
  border-top-right-radius: 14px;
}
.bottom-nav a {
  /* `position: relative` so the active-tab top-stripe pseudo-element
     can anchor against the tab's box. */
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  /* 56px clears the iOS 44px tap-target floor with comfortable
     padding; combined with `padding: 6px` on the nav and the safe-area
     inset, the touch ring still extends to the home-bar edge on
     iPhone X+ devices. */
  min-height: 56px;
  padding: 4px 0;
  border-radius: var(--card-radius, 10px);
  color: var(--fg);
  text-decoration: none;
  /* 12px so labels stay legible at arm's-length glance on a 390px
     phone — 11px was below the standard mobile-label floor (#630).
     Combined with the active top-stripe + accent-light tint this
     gives three independent active-state signals (color, bg, stripe). */
  font-size: 12px;
  font-weight: 500;
  opacity: 0.8;
  transition: background var(--motion-fast, 0.12s), color var(--motion-fast, 0.12s), opacity var(--motion-fast, 0.12s), transform var(--motion-fast, 0.12s);
  /* `-webkit-tap-highlight-color: transparent` so iOS's default grey
     overlay doesn't fight the press-feedback transform below. The
     `:active` rule provides our own deliberate press indicator. */
  -webkit-tap-highlight-color: transparent;
}
.bottom-nav a > svg {
  /* Icon tint follows the row colour (`currentColor` stroke in
     SidebarIcon), so the active-row recolour below carries through
     without a separate fill rule. Slightly muted vs label until
     active so the icon doesn't dominate the dense strip. */
  color: var(--accent);
  opacity: 0.85;
}
/* Hover restricted to fine-pointer devices (#630). On touch screens
   `:hover` sticks after a tap until the next tap elsewhere, leaving
   the previously-tapped tab visually highlighted — confusing alongside
   the real active-tab signal. `(hover: hover)` matches mice /
   trackpads only; touch input falls through to the press / active
   rules. */
@media (hover: hover) {
  .bottom-nav a:hover {
    background: color-mix(in oklab, #fff 4%, transparent);
    opacity: 1;
  }
}
/* Keyboard-focus ring (#630). Previously `outline: none`, which
   breaks keyboard a11y. `:focus-visible` shows the ring for keyboard
   / AT focus and suppresses it on mouse / touch press. Inset offset
   keeps the ring inside the tab box so it doesn't overlap neighbours. */
.bottom-nav a:focus-visible {
  background: color-mix(in oklab, #fff 4%, transparent);
  opacity: 1;
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* Tap-press feedback (#630). A momentary downward nudge gives the
   user immediate "I registered your tap" feedback before the route
   change, replacing iOS's default grey overlay we suppressed above. */
.bottom-nav a:active {
  transform: translateY(1px);
  opacity: 1;
}
.bottom-nav a[aria-current="page"] {
  color: var(--accent-light);
  background: color-mix(in oklab, var(--accent) 10%, transparent);
  opacity: 1;
}
.bottom-nav a[aria-current="page"] > svg {
  opacity: 1;
}
/* Active-tab top-stripe (#630). 2px accent line anchored at the top
   edge of the active tab — a third independent legibility signal
   alongside text color + background tint, so the active state reads
   clearly even when the player's eyes catch only the row's silhouette
   in peripheral vision. Inset 10% / 90% so the stripe doesn't kiss
   the tab's rounded outer corners. */
.bottom-nav a[aria-current="page"]::before {
  content: "";
  position: absolute;
  top: 0;
  left: 10%;
  right: 10%;
  height: 2px;
  background: var(--accent);
  border-radius: 0 0 2px 2px;
}

/* ── Tablet / small-desktop layer (768-1280px) ──────────────────────
   The mobile shell now covers a 3.5× viewport span (360-1280). All
   the rules above are phone-tuned and feel cramped / undersized at
   1024-1280 widths. This block scales the chrome up + adds a content
   cap to make the row read as "tablet" rather than "stretched
   phone": bigger topbar (52→64px), larger brand image, full-sized
   auth pills matching the desktop shell, capped + centred main with
   24px padding instead of 14px, and the bottom-nav drawer-button
   hidden (the topbar's hamburger drawer covers all the nav already
   at this width). */
@media (min-width: 768px) {
  .topbar {
    padding: 12px 24px;
    min-height: 64px;
    gap: 16px;
  }
  .topbar .brand img { height: 36px; }
  .topbar .brand-text { font-size: 18px; }
  .ha-actions { gap: 8px; }
  .ha-btn {
    height: 40px;
    padding: 0 18px;
    font-size: 14px;
  }
  main {
    align-self: center;
    width: 100%;
    max-width: 1100px;
    box-sizing: border-box;
    padding: 24px;
    /* bottom-nav is hidden at this breakpoint (see below), so we
       drop the phone-width bottom clearance reserved for it. */
    padding-bottom: 24px;
  }
  /* The hamburger drawer is the canonical navigation surface at
     tablet+; the bottom-nav adds nothing the drawer doesn't already
     cover at this width and just eats vertical space. */
  .bottom-nav { display: none; }
}
