/* ==========================================================================
   Layout — containers, grid, responsive utilities
   ========================================================================== */

/* --- Iframe embed: hide header when page is inside the hub iframe ---
   The `.in-iframe` class lands on <html> at parse-time via an inline
   script in BaseLayout (so the embedded page never flashes its header
   before paint) and on <body> via main.js after parse — both selectors
   are honoured so older pages without the inline-script BaseLayout still
   work. */
html.in-iframe .site-header,
body.in-iframe .site-header,
html.in-iframe .menu-overlay,
body.in-iframe .menu-overlay,
html.in-iframe .site-footer,
body.in-iframe .site-footer {
  display: none !important;
}

/* Astro dev toolbar — present in dev only. The hub embeds showcase
   pages in an iframe; each iframe loads its own toolbar, so two pile
   up at the bottom of the viewport (the parent's and the child's).
   Hide the child copy in iframe context — the parent's toolbar is the
   one you actually want to interact with. Production builds never
   inject this element, so the rule is a no-op there. */
html.in-iframe astro-dev-toolbar,
body.in-iframe astro-dev-toolbar {
  display: none !important;
}

/* Showcase pages open both standalone and embedded in the hub iframe.
   In the iframe the available width is already narrower than the parent
   window, so inputs/selects that stretch to 100% end up almost touching
   the iframe edges with just the default 24px gutter. Widen the gutter
   when embedded so controls breathe. Mobile stays at the base 16px. */
html.in-iframe .container,
body.in-iframe .container {
  padding-left: var(--space-40);
  padding-right: var(--space-40);
}

@media (max-width: 780px) {
  html.in-iframe .container,
  body.in-iframe .container {
    padding-left: var(--space-16);
    padding-right: var(--space-16);
  }
}

/* --- Reset & Base --- */

*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-body);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.2;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

/* --- Container --- */

.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--space-24);
}

.container-narrow {
  max-width: 880px;
}

.container-text {
  max-width: 640px;
}

/* --- Sections --- */

.section {
  padding: var(--space-120) 0;
}

/* Section-sm: top padding pinned to 80 on every breakpoint so the iframe's
   first heading shares a horizontal baseline with the hub sidebar's first
   nav item (which also sits at 80 top). Bottom padding scales responsively
   below. */
.section-sm {
  padding: var(--space-80) 0;
}

/* --- Showcase variant-meta ---
   Documentation header that sits ABOVE each variant in section-archetype
   showcase pages (hero, bento, trust-bar, faq, stats, footer). Hairline
   above, 48 top / 48 bottom rhythm — the gap from the description's last
   line down to the demo component is 48 px in every showcase section.
   h2/p typography pinned to 14/1.4. The 5 legacy per-page class names
   (.hero-variant-meta, etc) all alias to the same rule here — page CSS
   files no longer redeclare them. */
.section-variant-meta,
.hero-variant-meta,
.bento-variant-meta,
.trustbar-variant-meta,
.faq-variant-meta,
.stats-variant-meta,
.footer-variant-meta {
  padding: var(--space-48) 0;
  border-top: 1px solid var(--color-white-8);
}
.section-variant-meta:first-of-type,
.hero-variant-meta:first-of-type,
.bento-variant-meta:first-of-type,
.trustbar-variant-meta:first-of-type,
.faq-variant-meta:first-of-type,
.stats-variant-meta:first-of-type,
.footer-variant-meta:first-of-type {
  padding-top: var(--space-96);
  border-top: none;
}
.section-variant-meta h2,  .section-variant-meta p,
.hero-variant-meta h2,     .hero-variant-meta p,
.bento-variant-meta h2,    .bento-variant-meta p,
.trustbar-variant-meta h2, .trustbar-variant-meta p,
.faq-variant-meta h2,      .faq-variant-meta p,
.stats-variant-meta h2,    .stats-variant-meta p,
.footer-variant-meta h2,   .footer-variant-meta p { font-size: 14px; line-height: 1.4; }

@media (max-width: 1200px) {
  .section { padding: var(--space-80) 0; }
  /* Top stays at 80 (pinned above); bottom scales down. */
  .section-sm { padding-bottom: var(--space-64); }
}

@media (max-width: 780px) {
  .container { padding: 0 var(--space-16); }
  .section { padding: var(--space-80) 0 var(--space-64); }
  /* Top stays at 80; bottom tightens further on mobile. */
  .section-sm { padding-bottom: var(--space-40); }
}

/* --- Flex utilities --- */

.flex { display: flex; }
.flex-col { flex-direction: column; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }

.gap-8 { gap: var(--space-8); }
.gap-12 { gap: var(--space-12); }
.gap-16 { gap: var(--space-16); }
.gap-24 { gap: var(--space-24); }
.gap-32 { gap: var(--space-32); }
.gap-40 { gap: var(--space-40); }
.gap-48 { gap: var(--space-48); }
.gap-64 { gap: var(--space-64); }

/* --- Grid --- */

.grid { display: grid; }

.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* Intrinsic grid — cards wrap based on their minimum width, no media queries.
   Override --min to change the per-card minimum. */
.grid-auto {
  grid-template-columns: repeat(auto-fit, minmax(var(--min, 220px), 1fr));
}

@media (max-width: 1200px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 780px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* --- Every-Layout primitives (named patterns, see DESIGN.md §11.6) --- */

/* Stack — vertical rhythm with consistent gap. Override --stack-gap to tighten. */
.stack { display: flex; flex-direction: column; }
.stack > * + * { margin-block-start: var(--stack-gap, var(--space-24)); }

/* Cluster — horizontal group that wraps. Buttons, pills, tags. */
.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-16);
  align-items: center;
}

/* Switcher — one-line flex until any child would fall below --switcher-threshold,
   then stacks. No media queries. */
.switcher {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-24);
}
.switcher > * {
  flex-grow: 1;
  flex-basis: calc((var(--switcher-threshold, 40rem) - 100%) * 999);
}

/* Cover — full-viewport hero with header/main/footer anchored.
   100svh avoids mobile URL-bar jitter. */
.cover {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-block-size: 100svh;
  gap: var(--space-24);
}

/* --- Text alignment --- */

.text-center { text-align: center; }
.text-left { text-align: left; }

/* --- Margin/Spacing helpers ---
   Full scale: 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 120
   ========================================================================== */

.mt-4  { margin-top: var(--space-4); }
.mt-8  { margin-top: var(--space-8); }
.mt-12 { margin-top: var(--space-12); }
.mt-16 { margin-top: var(--space-16); }
.mt-20 { margin-top: var(--space-20); }
.mt-24 { margin-top: var(--space-24); }
.mt-32 { margin-top: var(--space-32); }
.mt-40 { margin-top: var(--space-40); }
.mt-48 { margin-top: var(--space-48); }
.mt-64 { margin-top: var(--space-64); }
.mt-80 { margin-top: var(--space-80); }

.mb-4  { margin-bottom: var(--space-4); }
.mb-8  { margin-bottom: var(--space-8); }
.mb-12 { margin-bottom: var(--space-12); }
.mb-16 { margin-bottom: var(--space-16); }
.mb-20 { margin-bottom: var(--space-20); }
.mb-24 { margin-bottom: var(--space-24); }
.mb-32 { margin-bottom: var(--space-32); }
.mb-40 { margin-bottom: var(--space-40); }
.mb-48 { margin-bottom: var(--space-48); }
.mb-64 { margin-bottom: var(--space-64); }
.mb-80 { margin-bottom: var(--space-80); }

/* Padding helpers */
.p-16  { padding: var(--space-16); }
.p-24  { padding: var(--space-24); }
.p-32  { padding: var(--space-32); }
.px-16 { padding-left: var(--space-16); padding-right: var(--space-16); }
.px-24 { padding-left: var(--space-24); padding-right: var(--space-24); }
.py-16 { padding-top: var(--space-16); padding-bottom: var(--space-16); }
.py-24 { padding-top: var(--space-24); padding-bottom: var(--space-24); }
.py-32 { padding-top: var(--space-32); padding-bottom: var(--space-32); }

/* --- Visibility --- */

.hide-mobile { display: block; }
.show-mobile { display: none; }

@media (max-width: 780px) {
  .hide-mobile { display: none; }
  .show-mobile { display: block; }
}

/* --- Common resets --- */

.reset-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* --- Scroll-snap row · horizontal carousel utility ---
   Drop-in row for horizontal carousels. Children become snap targets at
   the start of the row. Used by .card-feature in the Carousel section,
   game-grid carousels on landings, and any «one-row catalog» pattern.
   Hide the native scrollbar; cursor stays grab-driven via the consumer. */
.scroll-snap-row {
  display: flex;
  gap: var(--space-12);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
  padding-bottom: var(--space-8); /* room for focus ring on tab */
}
.scroll-snap-row::-webkit-scrollbar { display: none; }
.scroll-snap-row > * {
  scroll-snap-align: start;
  flex: 0 0 auto;
}
