/*
 * Reset, document chrome, and the two things WordPress adds that this layout
 * cannot have: a wrapper with layout margins, and core block spacing.
 */

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

* {
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

html,
body {
  max-width: 100vw;
  /* `clip`, not `hidden` — `hidden` makes body a scroll container, which
     silently breaks the sticky footer reveal. */
  overflow-x: clip;
}

body {
  background: var(--green);
  color: var(--white);
  font-family: var(--font-sans), "Inter Fallback", system-ui, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/*
 * Inter, self-hosted: the exact latin-subset variable woff2 next/font emitted,
 * copied out of .next/static/media/ rather than re-downloaded. Never called
 * from Google — a network hop, a GDPR problem in Spain, and slower.
 *
 * Declared here rather than in theme.json. theme.json's fontFace support emits
 * `font-family: var(--font-sans)` into the @font-face rule, and a custom
 * property is not legal in a font descriptor — so the face silently never
 * registers and the whole site falls back to system-ui. theme.json still
 * declares the family, because that is what the editor's font picker reads;
 * it just no longer owns the @font-face.
 */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin-variable.woff2") format("woff2");
}

/*
 * The size-adjusted fallback next/font used to generate.
 *
 * Inter loads with font-display: swap, so the first paint uses this. Without
 * the overrides the swap reflows every line and the layout shifts — which is
 * the CLS risk on this site, not GSAP. The metrics are Inter against Arial;
 * re-derive them if the subset is ever recut.
 */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  ascent-override: 90.2%;
  descent-override: 22.48%;
  line-gap-override: 0%;
  size-adjust: 107.12%;
}

/*
 * WordPress wraps every top-level block in .wp-site-blocks and gives it a
 * flow layout with vertical margins between children. The site's modules own
 * their own spacing, and the footer's sticky reveal depends on <main> and
 * <footer> being adjacent with nothing between them.
 *
 * The wrapper itself is fine — it is a plain div, so it is neither a scroll
 * container nor a containing block, and `position: sticky` still resolves
 * against the viewport. Verified at 390 / 834 / 1440 / 1920.
 */
.wp-site-blocks > * + * {
  margin-block-start: 0;
}

.wp-site-blocks {
  /* Never let this become a containing block or a scroll container: both would
     break the sticky footer, and neither failure is visible in a screenshot
     until you scroll. */
  position: static;
  overflow: visible;
  transform: none;
}

/*
 * Body copy sits back from the headings site-wide. Set on the element rather
 * than per module, so a paragraph reads the same wherever it is placed.
 *
 * Held in a custom property because the reveal's fade has to land back on it
 * and cannot read it off the element: the from-state in motion.css is already
 * in force at first paint, so the computed opacity is 0 by the time GSAP
 * looks. A module that sets copy back further restates the property, not the
 * opacity — see blocks/syllabus/style.css.
 */
p {
  --rest-opacity: 0.8;
  opacity: var(--rest-opacity);
}

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

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

button {
  font: inherit;
  color: inherit;
}

/*
 * One global focus rule.
 *
 * The colour is a variable rather than a literal lime: two home modules run on
 * a lime ground and both hold focusable CTAs, so a lime ring on them had zero
 * contrast — a WCAG 2.2 1.4.11 / 2.4.13 failure. ground.css overrides the
 * token per ground.
 */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: 2px;
}

/*
 * Skip link. There was none on the Next site; with a fixed header and a long
 * scroll-driven page, it is the difference between reaching the content in one
 * keystroke and tabbing through eight nav items on every page.
 */
.btd-skip {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 300;
  padding: 0.75rem 1.25rem;
  background: var(--lime);
  color: var(--ink);
  font-size: 0.875rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  transform: translateY(-120%);
  transition: transform 150ms ease;
}

.btd-skip:focus-visible {
  transform: translateY(0);
}

/* While the entrance overlay is up. `overflow: hidden` on both is what
   actually pins the page — Lenis is also stopped, but it may not have mounted
   on the first tick, so this is the guarantee rather than the belt. */
html[data-intro-active],
html[data-intro-active] body {
  overflow: hidden;
}

/* While the mobile menu sheet is open. */
html[data-menu-open],
html[data-menu-open] body {
  overflow: hidden;
}

/* Set once the curtain has cleared; stays set for the life of the document. */
html[data-intro-done] [data-intro] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
