/* GateIron — base.css: what every page here shares beyond the house chrome. The bar, the footer,
   the account chip, the tokens and .btn are gateiron-shared's /brand/chrome.css, linked from the
   head (src/pageChrome.js); this file only adds to them. */

/* The typewriter face, served rather than hoped for: most Linux boxes, Android and ChromeOS have no
   Courier, and the nearest installed stand-in (Liberation Mono) is not a typewriter face. */
@font-face { font-family: 'Courier Prime'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('/fonts/courier-prime-latin-400.woff2') format('woff2'); }
@font-face { font-family: 'Courier Prime'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('/fonts/courier-prime-latin-700.woff2') format('woff2'); }
:root { --mono: 'Courier Prime', 'Courier New', Courier, monospace; }

.wrap {
  max-width: 1140px;
  margin: 0 auto;
  padding: 0 28px;
}

.btn .arrow { transition: transform 0.18s ease; }
.btn:hover .arrow { transform: translateX(4px); }

/* The bar keeps one row on a phone: the name goes before anything wraps. */
@media (max-width: 660px) {
  .topbar .brand .wordmark { display: none; }
}
@media (max-width: 520px) {
  .topbar .btn { padding: 0.34em 0.7em; font-size: 0.88rem; }
}

/* THE FOOTER RESTS AT THE BOTTOM OF A SHORT PAGE (2026-09-21). Sticky at top:100vh rather than a
   flex-column body: the game floats its canvas, and float does not apply inside a flex container. */
/* The body's top margin sits outside min-height, so it is taken off or the page scrolls by exactly
   that much; the bottom one the compact footer cancels with its own negative margin. A page with a
   margin says --page-margin on body (the game does); the rest have none. */
html { min-height: 100%; }
body { margin: 0; min-height: calc(100vh - var(--page-margin, 0px)); min-height: calc(100svh - var(--page-margin, 0px)); }
.site-footer { position: sticky; top: 100vh; }

/* ---------------- accessibility helpers ---------------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

:focus-visible {
  outline: 3px solid var(--clay);
  outline-offset: 2px;
}

main:focus { outline: none; }

/* ---------------- the account chip's additions ---------------- */
.topbar .account-menu a[hidden] { display: none; }
.account-menu-user { display: block; font-family: var(--mono); font-weight: 700; color: var(--ink); }
/* Review reports, revealed by /js/teacherNotify.js with the number waiting (NH00651), in the
   badge's colour so the two read as one fact. */
.account-menu-flag { color: #A82E5D; font-weight: 700; }

/* The count of reports waiting, beside the chip (/js/adminNotify.js, /js/teacherNotify.js). It is
   its own link, so it sits in the slot rather than inside the <details>. */
.topbar .account-slot { position: relative; }
.admin-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--clay);
  color: #fff;
  font-family: 'Hanken Grotesk', Arial, Helvetica, sans-serif;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  text-decoration: none;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9);
}
.admin-badge:hover { background: var(--clay-dark); }

/* ============================================================
   THE COMPACT DENSITY - game pages (<body class="gi-compact">), on top of chrome.css's own. A
   translucent bar (Jeff, 2026-08-18: the page's background shows through a ~30% paper wash) and
   small buttons, because every pixel of the bar is a pixel the board does not get.

   The bar and the footer claim the page's body margin back with negative margins of exactly the
   page's own value (--page-margin on body), so the game below keeps its spacing.
   ============================================================ */
body.gi-compact { --bar-bg: rgba(245, 239, 227, 0.30); }
body.gi-compact > .topbar {
  margin: calc(-1 * var(--page-margin, 0px)) calc(-1 * var(--page-margin, 0px)) 8px;
  z-index: 1000;
}
body.gi-compact .topbar-inner { gap: 10px; row-gap: 6px; }
body.gi-compact .topbar .btn { padding: 0.38em 0.85em; font-size: 0.8rem; }
body.gi-compact .topbar .btn:hover { transform: none; }
body.gi-compact .topbar .account-menu { z-index: 1100; }

/* The footer under a game clears the floated canvas, and the gap above it is PADDING, because a
   cleared block's top margin is swallowed into the clearance. */
body.gi-compact > .site-footer {
  clear: both;
  margin: 0 calc(-1 * var(--page-margin, 0px)) calc(-1 * var(--page-margin, 0px));
  padding: 28px 0 24px;
  font-size: 0.85rem;
}
body.gi-compact > .site-footer::before { content: ''; display: block; height: 4vh; min-height: 18px; margin-top: -28px; }
body.gi-compact .site-footer .brand img { height: 32px; }
body.gi-compact .site-footer .fine-print { margin-top: 16px; padding-top: 12px; font-size: 0.74rem; }

/* A narrow game page: the footer becomes the classroom's thin band (no logo - the bar has it -,
   the links in a row, the copyright line alone), so a board that fits does not scroll just to show
   a footer stacked four rows deep (Jeff, 2026-09-26). */
@media (max-width: 600px) {
  body.gi-compact > .site-footer { padding: 8px 0; }
  body.gi-compact > .site-footer::before { display: none; }
  body.gi-compact .site-footer .inner { display: flex; align-items: center; justify-content: space-between; gap: 6px 14px; flex-wrap: wrap; }
  body.gi-compact .site-footer .grid { display: contents; }
  body.gi-compact .site-footer .brand { display: none; }
  body.gi-compact .site-footer .footer-links { gap: 4px 14px; }
  body.gi-compact .site-footer .fine-print { order: -1; margin: 0; padding: 0; border-top: 0; }
  body.gi-compact .site-footer .fine-print span + span { display: none; }
}
/* Buttons give up whitespace, both ways, before anything disappears (Jeff, 2026-08-24). */
@media (max-width: 480px) {
  body.gi-compact .topbar .btn { padding: 0.28em 0.55em; }
  body.gi-compact .topbar-inner { gap: 6px; }
}
/* A phone on its side: the bar gives the board its height back. */
@media (max-height: 500px) {
  body.gi-compact .topbar-inner { min-height: 0; padding-top: 3px; padding-bottom: 3px; }
  body.gi-compact .topbar .brand img { height: 24px; }
  body.gi-compact .topbar .btn { padding-top: 0.25em; padding-bottom: 0.25em; }
  body.gi-compact .topbar .account-slot { min-height: 28px; }
  body.gi-compact .topbar .avatar { width: 28px; height: 28px; }
}

/* THE BOOLEAN SWITCH, site-wide (2026-09-11). Jeff: "All checkboxes on the site (unless there is
   a reason not to) should use a boolean mini slider control." A label with a hidden checkbox and
   a track: <label class="class-switch"><input type="checkbox"><span class="class-switchTrack"
   aria-hidden="true"></span> Words</label>. Born on Manage Class as the Advanced toggle (2026-09-09)
   and moved here from profile.css so every page has it - the game's dialogs included. */
.class-switch { display: inline-flex; align-items: center; gap: 0.4em; cursor: pointer; user-select: none; white-space: nowrap; }
.class-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.class-switchTrack {
    position: relative; display: inline-block; flex: none; width: 2.1em; height: 1.15em; border-radius: 1em;
    background: #cfc9bd; transition: background 0.15s;
}
.class-switchTrack::after {
    content: ""; position: absolute; top: 0.12em; left: 0.12em; width: 0.9em; height: 0.9em;
    border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); transition: left 0.15s;
}
.class-switch input:checked + .class-switchTrack { background: #4A6B3D; }
.class-switch input:checked + .class-switchTrack::after { left: 1.07em; }
.class-switch input:focus-visible + .class-switchTrack { outline: 2px solid #9a7d00; outline-offset: 2px; }
.class-switch input:disabled + .class-switchTrack { opacity: 0.45; }
.class-switch-off { opacity: 0.45; cursor: default; }
