/* Bot Manners — shared page shell (R2, bot-manners-school-overhaul-2026-11-02).
 *
 * ONE shell for every manners surface. This file layers ON TOP of the
 * vendored tokens.css + components.css folds; it never replaces them
 * and it carries only what the canon .ds- classes do not: the page
 * chrome (header / footer), the full-height shell, and the house
 * floors (focus, input size, safe areas, motion). Every value resolves
 * to a --29d-* token defined in tokens.css — no local values, so the
 * deploy token lint governs this file exactly like the canon folds.
 *
 * How a surface wears it (see the campaign SHELL.md for the per-surface
 * table): link it after components.css with the same relative path the
 * surface already uses for tokens.css, and build.py / deploy.py fold
 * the link into an inline <style> in the same pass. Markup pattern:
 *
 *   <body>
 *     <div class="ds-root school-shell">
 *       <header class="school-header">
 *         <a class="school-brand" href="https://29court.com/grok">Bot Manners</a>
 *         <nav class="school-actions">
 *           <a class="ds-btn ds-btn-outline ds-btn-sm" href="/enroll/">Member sign in</a>
 *         </nav>
 *       </header>
 *       <main class="school-main"> …page… </main>
 *       <footer class="school-footer">
 *         <a href="/privacy">Privacy</a> · <a href="/console">Your console</a>
 *       </footer>
 *     </div>
 *   </body>
 *
 * Light is the token default; dark is the tokens.css
 * [data-theme="dark"] remap ("Melee Night" live values) — this file
 * names no scheme of its own. Theme seeding is one script + one
 * storage key (sh29core_theme) in each page's <head>, per DESIGN-SPEC
 * §4.2(4); this stylesheet only consumes the result.
 */

/* ---- Shell: full-height column, safe-area padded ------------------ */
.school-shell {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--29d-bg);
  color: var(--29d-text-1);
  font-family: var(--29d-font-ui);
  font-size: var(--29d-body-size);
  line-height: var(--29d-body-lh);
  padding:
    env(safe-area-inset-top, 0px)
    env(safe-area-inset-right, 0px)
    env(safe-area-inset-bottom, 0px)
    env(safe-area-inset-left, 0px);
  box-sizing: border-box;
}
.school-main {
  flex: 1 1 auto;
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: var(--29d-page-pad);
  box-sizing: border-box;
  min-width: 0;
}

/* ---- The hidden floor --------------------------------------------------
 * An author display on a component class (.ds-btn sets flex) beats the
 * UA's [hidden] rule, so a "hidden" control RENDERS — the F13 defect.
 * It was patched instance by instance (three backdrop classes in
 * components.css, the node rows in onboarding) and stayed loose
 * everywhere else: the enroll header showed signed-out strangers a
 * live "Sign out" button next to "Sign in", and "Keep my plan" showed
 * before any plan existed (rig-proven, 2026-11-03). The console sheet
 * already carries this floor in this exact shape; it belongs in the
 * shared shell sheet too, so the attribute means it on every surface
 * that wears the shell. */
.ds-root [hidden] { display: none !important; }

/* ---- Header: one floating bar, product name in plain words -------- */
.school-header {
  position: sticky;
  top: var(--29d-s-2);
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--29d-s-3);
  max-width: 960px;
  width: calc(100% - var(--29d-s-4));
  margin: var(--29d-s-2) auto 0;
  padding: var(--29d-s-1) var(--29d-s-2) var(--29d-s-1) var(--29d-s-4);
  background: color-mix(in srgb, var(--29d-raised) 97%, transparent);
  border: 1px solid var(--29d-border);
  border-radius: var(--29d-pill);
  box-shadow: var(--29d-shadow-pop);
  box-sizing: border-box;
}
.school-brand {
  font-family: var(--29d-font-display);
  font-weight: var(--29d-weight-xbold);
  font-size: var(--29d-text-xl);
  line-height: var(--29d-lh-xl);
  letter-spacing: -0.01em;
  color: var(--29d-text-1);
  text-decoration: none;
  white-space: nowrap;
}
.school-brand small {
  display: block;
  font-family: var(--29d-font-ui);
  font-weight: var(--29d-weight-medium);
  font-size: var(--29d-text-xs);
  line-height: var(--29d-lh-xs);
  color: var(--29d-text-3);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.school-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--29d-s-2);
  flex: 0 1 auto;
  min-width: 0;
}
/* Phone width: the bar wraps instead of pushing a button off the
 * pill. The brand (the prose) keeps its line and its size; the
 * actions (the furniture) wrap below it, right-aligned — the Squish
 * Law: furniture wraps, prose is defended, nothing is crushed and
 * nothing escapes the container. Before this, brand + two buttons
 * simply did not fit at 390px and "Your account" slid 8px past the
 * pill's border, clipped by the screen edge (the Principal's
 * screenshot, 2026-11-03). The privacy page carried a local copy of
 * this wrap for its own header; it lives here now, in the shared
 * sheet, so every surface wearing the shell inherits it. */
@media (max-width: 640px) {
  .school-header {
    flex-wrap: wrap;
    border-radius: var(--29d-r-4);
    row-gap: var(--29d-s-1);
  }
  .school-actions {
    justify-content: flex-end;
    margin-left: auto;
  }
}

/* ---- Footer -------------------------------------------------------- */
.school-footer {
  max-width: 960px;
  width: 100%;
  margin: 0 auto;
  padding: var(--29d-s-6) var(--29d-page-pad) var(--29d-s-8);
  color: var(--29d-text-3);
  font-size: var(--29d-text-sm);
  line-height: var(--29d-lh-sm);
  box-sizing: border-box;
}
.school-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--29d-s-1) var(--29d-s-4);
}
.school-footer a {
  color: var(--29d-text-2);
  display: inline-flex;
  align-items: center;
  min-height: var(--29d-control-h);
}

/* ---- Cards / panels the canon does not lay out for us -------------- */
.school-panel {
  background: var(--29d-surface);
  border: 1px solid var(--29d-border);
  border-radius: var(--29d-r-3);
  padding: var(--29d-card-pad);
  margin-top: var(--29d-s-4);
  min-width: 0;
}
.school-panel > :first-child { margin-top: 0; }
.school-lede {
  font-size: var(--29d-text-lg);
  line-height: var(--29d-lh-lg);
  color: var(--29d-text-2);
  max-width: 62ch;
  overflow-wrap: anywhere;
}
.school-note {
  font-size: var(--29d-text-sm);
  line-height: var(--29d-lh-sm);
  color: var(--29d-text-3);
}
.school-actions-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--29d-s-2);
  align-items: center;
  margin-top: var(--29d-s-4);
}

/* ---- Floors every surface inherits --------------------------------- */
/* Inputs never compute below 16px (the iOS zoom floor). */
.school-shell input,
.school-shell select,
.school-shell textarea {
  font-size: 16px;
  min-height: var(--29d-control-h);
}
/* One visible focus for everything interactive. */
.school-shell a:focus-visible,
.school-shell button:focus-visible,
.school-shell input:focus-visible,
.school-shell select:focus-visible,
.school-shell textarea:focus-visible,
.school-shell [tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--29d-focus-ring), var(--29d-focus-halo);
}
/* Press feedback inside the house motion band. */
.school-shell .ds-btn {
  transition: transform var(--29d-t-instant) var(--29d-ease),
    background-color var(--29d-t-fast) var(--29d-ease),
    box-shadow var(--29d-t-fast) var(--29d-ease);
}
.school-shell .ds-btn:active { transform: scale(0.975); }
@media (hover: hover) {
  .school-brand:hover { color: var(--29d-coral-700); }
  .school-footer a:hover { color: var(--29d-coral-700); }
}

/* Sheets drawn on this shell carry both backdrop-filter spellings
   (the iPhone pair rule) and the capped radius. */
.school-sheet-scrim {
  background: color-mix(in srgb, var(--29d-sunken) 48%, transparent);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.school-sheet {
  background: var(--29d-overlay);
  border-radius: var(--29d-r-4) var(--29d-r-4) 0 0;
  max-height: min(86dvh, 750px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* ---- Motion: the still state is complete --------------------------- */
@media (prefers-reduced-motion: reduce) {
  .school-shell *,
  .school-shell *::before,
  .school-shell *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
