/*
 * Shared responsive shell and layout primitives.
 *
 * Breakpoints only change presentation: route controllers keep the same DOM and
 * workflow state. Page-level overflow is intentionally never clipped or hidden;
 * genuinely two-dimensional content belongs in a named, focusable scroll region.
 */

:root {
  --layout-gutter: clamp(var(--space-4), 4vw, var(--space-6));
  --layout-section-space: clamp(var(--space-6), 7vw, var(--space-8));
  --header-block-size: calc(var(--control-min-block) + var(--space-4));
  --header-clearance: calc(
    var(--header-block-size) + var(--space-4) + env(safe-area-inset-top, 0px)
  );
  --grid-item-min: 20rem;
  --form-field-min: 20rem;
  --dialog-edge-space: var(--space-4);
}

html {
  scroll-padding-block-start: var(--header-clearance);
}

/* Page shell and bounded content measures */
:where(.site-shell, .page-shell) {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-block-size: 100vh;
  min-block-size: 100dvh;
}

:where(.site-shell, .page-shell) > *,
:where(.site-main, main) {
  min-inline-size: 0;
}

:where(.container, .content-container, .l-container) {
  inline-size: min(
    calc(100% - var(--layout-gutter) - var(--layout-gutter)),
    var(--container-max, var(--content-max))
  );
  max-inline-size: 100%;
  margin-inline: auto;
}

:where(.container--reading, .content-container--reading) {
  --container-max: var(--reading-max);
}

:where(.container--fluid, .content-container--fluid) {
  --container-max: 100%;
}

:where(.layout-section, .section-shell) {
  padding-block: var(--layout-section-space);
}

:where(.reading-measure, .measure, .prose) {
  inline-size: 100%;
  max-inline-size: var(--reading-max);
  overflow-wrap: break-word;
}

:where(.reading-measure--center, .measure--center, .prose--center) {
  margin-inline: auto;
}

/* Content-driven grids, stacks, and wrapping clusters */
:where(.grid, .layout-grid, .l-grid, .layout-split) {
  display: grid;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, var(--grid-item-min)), 1fr)
  );
  gap: var(--grid-gap, var(--space-5));
  align-items: stretch;
}

:where(.grid, .layout-grid, .l-grid, .layout-split) > *,
:where(.stack, .layout-stack, .l-stack) > *,
:where(.cluster, .layout-cluster, .l-cluster) > * {
  min-inline-size: 0;
  max-inline-size: 100%;
}

:where(.grid--compact, .layout-grid--compact) {
  --grid-item-min: 14rem;
}

:where(.grid--wide, .layout-grid--wide, .layout-split) {
  --grid-item-min: 24rem;
}

:where(.grid--start, .layout-grid--start) {
  align-items: start;
}

:where(.stack, .layout-stack, .l-stack) {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap, var(--space-5));
}

:where(.stack--compact, .layout-stack--compact) {
  --stack-gap: var(--space-3);
}

:where(.stack--spacious, .layout-stack--spacious) {
  --stack-gap: var(--space-7);
}

:where(.cluster, .layout-cluster, .l-cluster) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster-gap, var(--space-3));
}

:where(.cluster--between, .layout-cluster--between) {
  justify-content: space-between;
}

/* Persistent header and responsive, progressively enhanced navigation */
.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  min-inline-size: 0;
  background: var(--color-surface-inverse);
  color: var(--color-text-inverse);
  border-block-end: var(--border-width) solid var(--color-border-strong);
}

.site-header__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3) var(--space-4);
  inline-size: min(
    calc(100% - var(--layout-gutter) - var(--layout-gutter)),
    var(--content-max)
  );
  /* This is an input floor, not the measured outer header height. Using
     --header-block-size here created a ResizeObserver feedback loop: each
     measurement included this element's padding, then fed the larger result
     back as its next min-size (60px → 76px → 92px → …). */
  min-block-size: var(--control-min-block);
  margin-inline: auto;
  padding-block: var(--space-2);
}

:where(.site-brand, .site-header__brand) {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-inline-size: 0;
  max-inline-size: 100%;
}

:where(.site-brand__text, .site-header__brand-text) {
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.site-nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--target-size-min);
  min-block-size: var(--target-size-min);
  justify-self: end;
}

/* Static navigation remains visible. The toggle appears only after its controller is ready. */
[data-navigation-ready="true"] .site-nav__toggle {
  display: inline-flex;
}

:where(.site-nav, .site-nav__panel) {
  grid-column: 1 / -1;
  min-inline-size: 0;
  inline-size: 100%;
}

:where(.site-nav__list, .site-footer__nav-list) {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav__list :where(a, button),
.site-header__actions :where(a, button) {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--target-size-min);
  max-inline-size: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}

.site-header__actions {
  display: flex;
  grid-column: 1 / -1;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-inline-size: 0;
}

/* An open enhanced menu scrolls internally instead of extending beyond the viewport. */
[data-navigation-ready="true"] :where(.site-nav, .site-nav__panel):not([hidden]) {
  max-block-size: calc(100vh - var(--header-clearance));
  max-block-size: calc(100dvh - var(--header-clearance));
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}


/* Once the controller is ready, a closed mobile menu must stop participating
   in header layout. Without this shared state rule, utility routes depended on
   route-specific :has() selectors and could leave all links stacked inside the
   sticky bar. Static navigation remains visible when JavaScript is absent. */
@media (max-width: 63.9375rem) {
  [data-navigation-ready="true"]
    :where(.site-nav, .site-nav__panel)[data-nav-state="closed"] {
    display: none;
  }

  [data-navigation-ready="true"]
    :where(.site-nav, .site-nav__panel)[data-nav-state="open"] {
    display: grid;
  }
}

/* Footer shell */
.site-footer {
  margin-block-start: auto;
  min-inline-size: 0;
  background: var(--color-surface-inverse);
  color: var(--color-text-inverse);
}

.site-footer__inner {
  inline-size: min(
    calc(100% - var(--layout-gutter) - var(--layout-gutter)),
    var(--content-max)
  );
  margin-inline: auto;
  padding-block: var(--space-7);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, 14rem), 1fr)
  );
  gap: var(--space-6);
  align-items: start;
}

.site-footer__grid > *,
.site-footer__nav-list > * {
  min-inline-size: 0;
  max-inline-size: 100%;
}

.site-footer :where(a, p, li, address) {
  max-inline-size: 100%;
  overflow-wrap: anywhere;
}

/* Forms reflow from one to multiple columns only when their labels can fit. */
:where(.form-layout, .form-shell) {
  inline-size: 100%;
  max-inline-size: var(--form-max-inline, var(--reading-max));
  margin-inline: auto;
}

:where(.form-grid, .form-row) {
  display: grid;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, var(--form-field-min)), 1fr)
  );
  gap: var(--form-row-gap, var(--space-5));
  align-items: start;
}

:where(.form-grid, .form-row) > *,
:where(.form-field, .field-group, fieldset) {
  min-inline-size: 0;
  max-inline-size: 100%;
}

:where(.form-grid__full, .form-row__full, [data-form-span="full"]) {
  grid-column: 1 / -1;
}

:where(.form-field, .field-group) :where(input, select, textarea) {
  inline-size: 100%;
  max-inline-size: 100%;
}

:where(.form-field, .field-group) :where(label, legend, .field-hint, .field-error) {
  max-inline-size: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}

.form-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  align-items: center;
  min-inline-size: 0;
}

.form-actions > * {
  min-inline-size: 0;
  max-inline-size: 100%;
  white-space: normal;
}

/*
 * Wide tables, code, and comparison content must use one of these wrappers.
 * The wrapper is the only intentional two-dimensional overflow boundary: give
 * it role="region", tabindex="0", and aria-label or aria-labelledby in markup
 * so keyboard and assistive-technology users can reach and identify it.
 */
:where(
    .scroll-region,
    .table-scroll,
    .two-dimensional-scroll,
    .comparison-scroll,
    [data-scroll-region="two-dimensional"]
  ) {
  inline-size: 100%;
  min-inline-size: 0;
  max-inline-size: 100%;
  max-block-size: min(75vh, var(--content-max));
  max-block-size: min(75dvh, var(--content-max));
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable both-edges;
  scrollbar-color: var(--color-border-strong) var(--color-surface-canvas);
  touch-action: pan-x pan-y pinch-zoom;
  contain: inline-size;
  scroll-padding: var(--space-3);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-control);
  background: var(--color-surface-raised);
  box-shadow: var(--shadow-inset);
}

:where(
    .scroll-region,
    .table-scroll,
    .two-dimensional-scroll,
    .comparison-scroll,
    [data-scroll-region="two-dimensional"]
  ):focus-visible {
  outline: var(--focus-width) solid var(--color-focus-ring);
  outline-offset: var(--focus-offset);
}

:where(
    .scroll-region,
    .table-scroll,
    .two-dimensional-scroll,
    .comparison-scroll,
    [data-scroll-region="two-dimensional"]
  )
  > :where(table, pre, [data-wide-content]) {
  inline-size: max-content;
  min-inline-size: 100%;
  max-inline-size: none;
}

:where(
    .scroll-region,
    .table-scroll,
    .two-dimensional-scroll,
    .comparison-scroll,
    [data-scroll-region="two-dimensional"]
  )
  :where(th, td) {
  white-space: normal;
  overflow-wrap: break-word;
}

/* Dialogs use dynamic viewport bounds and scroll only their content region. */
:where(.dialog-layer, .dialog-overlay, [data-dialog-overlay]) {
  position: fixed;
  inset: 0;
  z-index: var(--z-dialog);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  min-inline-size: 0;
  max-inline-size: 100%;
  max-block-size: 100vh;
  max-block-size: 100dvh;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  padding-block: max(var(--dialog-edge-space), env(safe-area-inset-top, 0px))
    max(var(--dialog-edge-space), env(safe-area-inset-bottom, 0px));
  padding-inline: max(var(--dialog-edge-space), env(safe-area-inset-left, 0px))
    max(var(--dialog-edge-space), env(safe-area-inset-right, 0px));
}

:where(.dialog-layer, .dialog-overlay, [data-dialog-overlay])[hidden] {
  display: none;
}

:where(.dialog__surface, [data-dialog-surface], dialog.dialog) {
  display: flex;
  flex-direction: column;
  inline-size: min(100%, var(--dialog-max-inline, var(--reading-max)));
  max-inline-size: 100%;
  max-block-size: calc(
    100vh - max(var(--dialog-edge-space), env(safe-area-inset-top, 0px)) -
      max(var(--dialog-edge-space), env(safe-area-inset-bottom, 0px))
  );
  max-block-size: calc(
    100dvh - max(var(--dialog-edge-space), env(safe-area-inset-top, 0px)) -
      max(var(--dialog-edge-space), env(safe-area-inset-bottom, 0px))
  );
  min-inline-size: 0;
  min-block-size: 0;
  margin: auto;
}

:where(.dialog__surface--wide, [data-dialog-size="wide"]) {
  --dialog-max-inline: var(--content-max);
}

:where(.dialog__header, .dialog__footer) {
  flex: 0 0 auto;
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow-wrap: anywhere;
}

:where(.dialog__body, [data-dialog-scroll]) {
  flex: 1 1 auto;
  min-inline-size: 0;
  min-block-size: 0;
  max-inline-size: 100%;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  scroll-padding-block: var(--space-4);
}

/* Persistent-header clearance for anchors, focus targets, and validation output. */
:where([id], [data-scroll-target], [data-focus-target], [role="tabpanel"]) {
  scroll-margin-block-start: var(--header-clearance);
}

:where(
    a[href],
    button,
    input,
    select,
    textarea,
    summary,
    output,
    [contenteditable="true"],
    [tabindex]:not([tabindex="-1"]),
    [role="alert"],
    [role="status"],
    [aria-live],
    [aria-invalid="true"],
    .validation-summary,
    .field-error,
    [data-validation-message]
  ) {
  /* Extra context keeps a preceding label or instruction below the header. */
  scroll-margin-block-start: calc(var(--header-clearance) + var(--space-5));
  scroll-margin-block-end: calc(var(--space-6) + var(--control-min-block));
}

:where(.dialog__body, [data-dialog-scroll])
  :where(
    [id],
    a[href],
    button,
    input,
    select,
    textarea,
    summary,
    output,
    [contenteditable="true"],
    [tabindex]:not([tabindex="-1"]),
    [role="alert"],
    [role="status"],
    [aria-live],
    [aria-invalid="true"],
    .validation-summary,
    .field-error,
    [data-validation-message]
  ) {
  scroll-margin-block-start: calc(var(--space-4) + var(--space-5));
  scroll-margin-block-end: calc(var(--space-4) + var(--control-min-block));
}

@media (min-width: 40rem) {
  .form-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
  }
}

@media (min-width: 64rem) {
  .site-header__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) auto;
  }

  .site-nav__toggle {
    display: none !important;
  }

  :where(.site-nav, .site-nav__panel) {
    grid-column: auto;
    align-self: stretch;
    inline-size: auto;
    max-block-size: none;
    overflow: visible;
    justify-self: stretch;
  }

  /* A collapsed mobile menu must become visible without mutating its stored state. */
  :where(.site-nav, .site-nav__panel)[hidden] {
    display: block !important;
  }

  .site-nav__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    min-block-size: 100%;
    gap: var(--space-2) var(--space-4);
  }

  .site-header__actions {
    grid-column: auto;
    justify-content: flex-end;
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
   SHARED HEADER BRAND AND NAVIGATION
   These belong to the shell, not to any single route. Previously only the
   materials route defined them, which left the auth, legal and 404 headers
   with an unstyled brand badge. Routes may still override.
   ═══════════════════════════════════════════════════════════════════════════ */
.nav-logo-icon {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  inline-size: var(--control-min-block);
  block-size: var(--control-min-block);
  border: var(--border-width) solid var(--color-brand-gold-300);
  border-radius: var(--radius-control);
  color: var(--color-brand-ink-950);
  background: var(--color-brand-gold-300);
  box-shadow: var(--shadow-inset);
}

.nav-logo-text {
  max-inline-size: 18rem;
  font-size: var(--text-step--1);
}

.nav-logo-text span {
  display: block;
  color: var(--color-brand-gold-300);
  font-size: 0.8em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav-links {
  min-inline-size: 0;
}

.nav-cta {
  justify-self: start;
}

.hamburger {
  grid-column: 2;
  grid-row: 1;
  display: none;
  flex-direction: column;
  gap: var(--space-1);
  padding-inline: var(--space-3);
}

/* The button ships with aria-expanded="false", so this selector always matches.
   Confine it to narrow viewports, otherwise the toggle appears on desktop
   alongside the full navigation. */
@media (max-width: 63.9375rem) {
  .hamburger[aria-expanded] {
    display: inline-flex;
  }
}

.hamburger span {
  display: block;
  inline-size: var(--space-5);
  block-size: calc(var(--border-width) + var(--border-width));
  border-radius: var(--radius-pill);
  background: currentColor;
}

.hamburger.open span:nth-child(2),
.hamburger.is-open span:nth-child(2) {
  opacity: 0;
}

/* Cross-pillar link to the practice application. */
.nav-grammar-link {
  white-space: nowrap;
}

/* Legacy footer row retained by the utility routes. */
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  justify-content: center;
  inline-size: 100%;
  color: var(--color-text-inverse);
  font-size: var(--text-step--1);
}
