/* ==========================================================================
   Stelar Reality — layout
   Containers, the responsive gutter, and the handful of grid primitives every
   page composes from. Layout primitives never carry colour, border or type.
   Breakpoints: 30rem / 48rem / 64rem / 75rem only (see tokens.css).
   ========================================================================== */

/* --- 1. Gutter steps -------------------------------------------------------
   One token, three values. Everything that reads --gutter (containers, page
   padding, off-canvas drawers) steps together, so there is exactly one place
   to change horizontal rhythm. */

@media (min-width: 48rem) {
  :root { --gutter: 32px; }
}

@media (min-width: 75rem) {
  :root { --gutter: 64px; }
}

/* --- 2. Containers ---------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Self-nesting guard. Nine templates place their own .container inside the
   one in base.html; with a 64px desktop gutter that stacks to 128px of dead
   inset and those pages stop lining up with the rest of the app. The gutter
   belongs to the outermost container only. */
.container .container,
.container .container-narrow { padding-inline: 0; }

/* Long-form reading measure: 55–75 characters. */
.container-narrow {
  width: 100%;
  max-width: var(--text-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* --- 3. Page shell ----------------------------------------------------------- */

.page { padding-block: var(--space-6); }

.page-wide { max-width: none; }

/* --- 4. Grid primitives ------------------------------------------------------
   All auto-placing. None of them declare a fixed column count, so they never
   need a breakpoint of their own. */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-5);
}

.card-grid-sm {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-5);
}

.stat-grid {
  display: grid;
  /* auto-fit, not auto-fill: three stat cards should fill the row rather
     than leave a phantom fourth column. */
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-5);
}

/* Generic escape hatch — set --grid-min per instance. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min, 240px), 1fr));
  gap: var(--space-5);
}

/* Form fields that share a row and collapse together. */
.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
}

/* --- 5. Splits ---------------------------------------------------------------
   Explicit two-part layouts, single column until there is room. */

.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

.split-main {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

.split-aside {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

/* Same trap .admin-main documents, one level down. A grid item's default
   `min-width: auto` sizes it to its widest content, so a wide table inside a
   card in one of these columns pushes the column past the viewport instead of
   scrolling inside its own .table-wrap. The columns belong to these primitives,
   so the floor belongs here too. */
.split > *,
.split-main > *,
.split-aside > * { min-width: 0; }

@media (min-width: 48rem) {
  .split { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 64rem) {
  .split-main { grid-template-columns: 2fr 1fr; }
  .split-aside { grid-template-columns: 1fr 2fr; }
}

/* --- 6. Stack ------------------------------------------------------------------
   Vertical rhythm without margins. Override --stack-gap per instance. */

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap, var(--space-4));
}

/* --- 7. Admin shell ------------------------------------------------------------ */

.admin-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100dvh;
}

/* REQUIRED. A grid item's default `min-width: auto` sizes it to its content,
   so a wide admin table (or any long unbroken cell) pushes the 1fr column
   past the viewport and blows the whole shell out horizontally — the sidebar
   scrolls off-screen and the page gains a body scrollbar. `min-width: 0`
   lets the column shrink so .table-wrap can do its job and scroll internally.
   Do not remove this. */
.admin-main { min-width: 0; }

.admin-content { padding: var(--space-6) var(--gutter); }

@media (max-width: 63.98rem) {
  .admin-shell { grid-template-columns: 1fr; }
}

/* Sticky summary rail inside .split-main / .split-aside. align-self is
   load-bearing: a stretched grid item leaves sticky nothing to travel in.
   The offset is the topbar plus a breathing gap, read from --topbar-h so the
   rail follows the header when it grows a second row below 64rem. */
.sticky-aside {
  position: sticky;
  inset-block-start: calc(var(--topbar-h) + 16px);
  align-self: start;
}
