/* classic — desktop (>=1281px). Linked via <link media> so this file only loads
   when the media query matches; no @media wrapper inside. The 1281px floor
   is the classic-template's mobile/desktop breakpoint — below it the mobile
   shell (NavMobile drawer + bottom-nav) takes over.
   Layout follows mood555's `.home-container` pattern: the shell is a
   flex row with the sidebar as one flex item and the main column as
   the other. The topbar is `position: fixed` across the whole
   viewport (overlays both columns), so `.shell` reserves the gap
   with `padding-top: var(--topbar-height)`. */
.shell {
  /* `--rail-width` + `--topbar-height` now live on body in
     `classic/layout.astro` so tenant `SIDEBAR_WIDTH` / `TOPBAR_HEIGHT`
     overrides win via attribute-selector specificity (#399 final).
     Previously declared here, which shadowed body-scoped overrides.
     `--topbar-search-inset` only nudges `.topbar-search`'s left
     margin — main content is centered at `max-width: 1200px` via
     `.main` and doesn't share this offset anymore (it used to,
     before main was capped + centered). */
  --topbar-search-inset: 64px;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  min-height: 100vh;
  padding-top: var(--topbar-height);
  box-sizing: border-box;
}
/* Topbar — laos338 chrome restyled to mirror mood555.com's header
   composition: flat dark bg, 64px row, three slots (brand left ·
   centred search · auth pills right). Compact sizing — search and
   auth buttons all ride at 40px so the row reads as one band. The
   bg is distinct from `.sidebar` (which keeps its bg-derived rail
   tone) so the topbar reads as a separate horizontal surface above
   the sidebar. */
.topbar {
  /* Fixed across the viewport top, above both the sticky sidebar and
     the main column. `position: fixed` removes it from the document
     flow — `.shell` reserves the gap with its own `padding-top` so
     the flex items below it don't slide underneath. z-index sits
     above any in-flow content so the topbar reads as the outermost
     layer. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 10px 20px;
  min-height: var(--topbar-height);
  height: var(--topbar-height);
  box-sizing: border-box;
  /* Same diagonal two-tone as `--game-top-bg` in mood555's theme — the
     topbar shares the rail's surface so the header band reads as one
     piece of chrome with the floating sidebar panel below. Shadow
     replaces the prior bottom border to match `--game-top-shadow`. */
  background: linear-gradient(159deg, var(--surface-rail-1) 13.75%, var(--surface-rail-2) 103.1%);
  box-shadow: 0px 2px 5px 0px #131617;
}
/* Brand sits in a sized cell so the search field's left edge
   aligns with the main-content column's start. Width = rail width
   minus the topbar's `padding-left` (20px) minus the gap to the
   next slot (20px) — derived from `--rail-width` so the alignment
   tracks any rail-width change automatically. */
.topbar .brand { display: flex; align-items: center; text-decoration: none; flex: 0 0 calc(var(--rail-width) - 40px); }
.topbar .brand img { height: 40px; width: auto; }
.topbar .brand-text { font-weight: 700; font-size: 18px; color: var(--fg); letter-spacing: 0.5px; }
.topbar .actions { margin-left: 0; flex: 0 0 auto; }

/* Centred search bar. `flex: 1` lets it stretch into the available
   middle space; `max-width` keeps it from sprawling on ultrawide
   viewports. Surface lifts a notch above the topbar bg with an
   8px-radius pill — sized to match the auth buttons so the row
   reads as one consistent control band. */
.topbar-search {
  flex: 1 1 auto;
  max-width: 1100px;
  position: relative;
  display: flex;
  align-items: center;
  /* Height-matches the auth pills so the topbar reads as one band —
     `--button-height` is the operator-overridable knob (#399 final). */
  height: var(--button-height, 40px);
  /* Extra breathing room from the brand cell — the topbar's default
     20px flex `gap` already sits between brand and search; the
     `--topbar-search-inset` margin pulls the field further into the
     main column for the search to read as part of the content area
     rather than pinned to the rail's right edge. */
  margin-left: var(--topbar-search-inset);
  /* mood555 `--gameTop-search-bg` is borderless against the topbar
     gradient — the contrast comes from the surface tone alone
     (`#2e2d2c` vs the gradient stops `#252525`/`#181818`). The
     focus ring is a soft outline so the search remains a flat
     control band on idle. */
  /* #476 — input chrome token; falls back to mood555's #2e2d2c. */
  background: var(--input-bg, #2e2d2c);
  border: 0;
  /* #399 — chrome shape token; falls back to today's 8px on tenants
     that haven't overridden `BUTTON_RADIUS` in tenant_settings. */
  border-radius: var(--button-radius, 8px);
}
.topbar-search:focus-within {
  outline: 1px solid var(--accent);
  outline-offset: 0;
}
.topbar-search-icon {
  position: absolute;
  left: 14px;
  /* #476 — same placeholder tone as the input copy below so the
     icon glyph and the placeholder text share a single muted family. */
  color: var(--input-placeholder, #686868);
  pointer-events: none;
}
.topbar-search input {
  flex: 1 1 auto;
  height: 100%;
  padding: 0 14px 0 40px;
  background: transparent;
  border: 0;
  outline: 0;
  /* Pure `#fff` (not `--fg`'s slightly-off-white `#f4f4f5`) — matches
     mood555's `--gameTop-search-txt: #fff`. The search field is the
     one place in the classic chrome where the input contrast against
     the `#2e2d2c` surface wants the brightest possible foreground;
     `--fg` would read as a noticeably greyer cast next to the topbar's
     metallic gradient. */
  color: #fff;
  font: inherit;
  font-size: 14px;
}
.topbar-search input::placeholder { color: var(--input-placeholder, #686868); }

/* HeaderAuth pill cluster — mood555 colour-treatment: filled gold-
   gradient `Sign up`, outlined cream-gold `Log in`. Both ride at
   the same 40px height as the search field so the topbar reads as
   one consistent row. Gradient stops mirror the metallic-gold
   treatment from the live screenshot reference. */
.ha-actions { display: flex; align-items: center; gap: 8px; }
.ha-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--button-height, 40px);
  /* Equal-width Sign-up / Log-in pills regardless of label length —
     `min-width: 130px` accommodates Thai ("สมัครสมาชิก") and Lao
     ("ສະໝັກສະມາຊິກ") at 14px font without crowding, and stretches
     the shorter English labels to match. `box-sizing: border-box`
     keeps the border in the size calculation so paired buttons end
     up pixel-identical. */
  min-width: 130px;
  padding: 0 22px;
  box-sizing: border-box;
  border-radius: var(--button-radius, 8px);
  font-weight: 600;
  font-size: 14px;
  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's `MAIN_COLOR` automatically tints the lighter
     half of the gradient; bottom stop is `--accent-strong`. Ink stays
     dark for legibility on the cream-gold field. */
  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) — re-skins `.ha-btn-primary`
   (the Sign-up CTA + every other filled gold gradient button in the
   chrome) when the operator picks a non-default flavor. Body carries
   `data-button-variant="outlined" | "pill" | "ghost"`; no attribute
   = the existing filled gradient. Specificity (0,1,1) wins over
   `.ha-btn-primary` (0,1,0) and is bounded enough that future tenant-
   scope rules at (0,2,1) can still override. The `:hover` flavors
   keep the per-variant character (outlined fills on hover, pill
   brightens like filled, ghost tints in). */
body[data-button-variant="outlined"] .ha-btn-primary {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
  /* Operator-overridable accent doesn't have a matching dark-ink
     contrast partner when used as a foreground, so a bolder weight
     pulls the label's visual weight back up to filled-CTA levels. */
  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 {
  /* Same fill as default `filled`; only the radius changes. Wrapped
     here so a tenant `BUTTON_RADIUS` override doesn't accidentally
     un-pill the CTA when both are set — `pill` is a deliberate shape
     choice and stays at 999px. */
  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). Compact horizontal chip — wallet
   icon · currency badge · amount — height-matched to the `.ha-btn` row so
   the topbar reads as one consistent control band. The gold-tinted bg +
   accent border picks up the brand-accent vocabulary the CTAs already use. */
.ha-balance {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: var(--button-height, 40px);
  padding: 0 14px;
  margin-right: 8px;
  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: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--accent-light);
  opacity: 0.85;
}
/* Amount uses tabular numerals so the digit columns line up when the
   balance updates — keeps the chip from jittering visually. */
.ha-balance-value {
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.cta { background: var(--accent); color: var(--accent-fg); padding: 8px 16px;
  border-radius: var(--button-radius, 6px); font-weight: 600; text-decoration: none; }
.sidebar {
  /* Sidebar is a flex item in the `.shell` row — sits next to
     `.main-col` in document flow, not fixed-positioned. `position:
     sticky` + `align-self: flex-start` keeps the rail pinned in the
     viewport at `top: --topbar-height` while main content scrolls
     under it; `max-height` + `overflow-y: auto` opens a scroll
     context inside the rail when the nav itself is too tall for the
     viewport. Margins mirror mood555's `.side-menu-main-container`
     `padding: 11px 8px 8px` for the floating-island inset.
     Rail bg uses mood555 default theme's `--game-top-bg` — a
     diagonal two-tone that gives the rail a subtle metallic sweep
     against the group cards' nearly-horizontal gradient. */
  flex: 0 0 var(--rail-width);
  align-self: flex-start;
  position: sticky;
  top: var(--topbar-height);
  max-height: calc(100vh - var(--topbar-height) - 19px);
  padding: 16px 0;
  margin: 11px 8px 8px;
  overflow-y: auto;
  box-sizing: border-box;
  background: linear-gradient(159deg, var(--surface-rail-1) 13.75%, var(--surface-rail-2) 103.1%);
  /* Sidebar rail = card-class surface; tracks --card-radius so an
     operator who rounds-up the chrome (e.g. CARD_RADIUS=16px) doesn't
     leave the rail flat against rounder cards. */
  border-radius: var(--card-radius, 10px);
  display: flex;
  flex-direction: column;
}
.main-col {
  /* Main column is the second flex item; `flex: 1 1 0` claims the
     remaining horizontal space after the rail. `min-width: 0`
     prevents wide children (announcement marquee, banner) from
     blowing the column past the viewport. Internal flex-column
     stacks `<main>` above the footer with `flex: 1 0 auto` on main
     pushing the footer to the foot of the viewport on short pages. */
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
/* All `.sidebar` row styling lives in `Sidebar.astro`'s scoped <style>
   block now (`.sidebar-row` cards). Keep this file to the shell-level
   layout only — anything more specific would override the card pill
   aesthetic via the global cascade.
   `min-width: 0` on `.main-col` + `main` lets wide intrinsic content
   (announcement marquee, banner carousel) shrink to the flex parent
   instead of blowing the column past the viewport. */
/* `flex: 1 0 auto` inside the `.main-col` flex column so the
   footer is pushed flush to the bottom of the viewport on short
   pages. `align-self: center` + `width: 100%` + `max-width: 1200px`
   caps the main content area at the same 1200px ceiling the
   banner-carousel uses, so the announcement marquee, banner, and
   game grid all share one outer width on wide viewports.
   `box-sizing: border-box` keeps padding inside the 1200px box so
   the cap is honoured at the outer edge. `min-width: 0` keeps wide
   children from blowing the column past the cap. */
main {
  flex: 1 0 auto;
  align-self: center;
  width: 100%;
  max-width: 1200px;
  min-width: 0;
  /* 24px top/bottom + 96px left/right — wider horizontal inset
     pulls the home content (banner, stats bar, type menu, provider
     grid) off the rail's right edge and the viewport's left edge,
     giving the column breathing room on wide displays. Tune in one
     place since every section inside `<main>` inherits it via
     box-model. */
  padding: 24px 96px;
  box-sizing: border-box;
}
.game-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px;
  list-style: none; margin: 0; padding: 0; }
/* Single-column wide banner stack (#804) — mirrors the laos338.org
   reference where each promo is a full-bleed banner with art on top
   and the description / CTA row below. Caps at 760px so banners stay
   readable on ultrawide displays without ballooning to the full
   1200px content cap. Card chrome (background, radius, padding) lives
   in `PromoCard.astro`'s scoped <style>. */
.promo-list { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: 1fr; gap: 16px; max-width: 760px; }
/* Footer is nested inside `.main-col` now — sits below `main` in
   the flex column so it spans only the main content's width, not
   the full viewport. The rail to its left stops above the
   viewport foot (its own scroll context), leaving the footer
   visually scoped to the main column. */
footer { padding: 18px 24px; border-top: 1px solid var(--border); opacity: .7; }
