*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

/* The UA rule for [hidden] is display:none at the lowest specificity, so any class of ours that
   sets display (the search and mobile-nav panels are display:flex) silently overrides it and the
   element stays visible while JS thinks it's hidden. */
[hidden] { display: none !important; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Sticky footer: #site-footer is the last real child of body on every page, so pushing it
   with auto margin keeps it pinned to the bottom on short pages without wrapping every
   page's content in an extra container. */
#site-footer { margin-top: auto; }

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

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

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.12;
  margin: 0 0 14px;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(32px, 4.2vw, 56px); }
h2 { font-size: clamp(26px, 3vw, 38px); }
h3 { font-size: clamp(20px, 2.2vw, 26px); }

p { margin: 0 0 8px; color: var(--ink-dim); }

.eyebrow {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
}

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* padding-block, not the padding shorthand: every page puts these on the SAME element as
   .container (`class="container section-tight"`). A shorthand here resets padding-left/right to
   0 and silently deletes the container gutter, which is invisible on a wide screen but puts the
   heading and body text flush against both edges of a phone. */
.section { padding-block: 56px; }
.section-tight { padding-block: 32px; }

.grid {
  display: grid;
  gap: 20px;
}

@media (min-width: 720px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 980px) {
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

::selection { background: var(--green-surface); color: #fff; }

.skeleton {
  background: linear-gradient(90deg, var(--line) 25%, var(--fill-track) 37%, var(--line) 63%);
  background-size: 400% 100%;
  animation: skeleton-loading 1.4s ease infinite;
  border-radius: var(--r-sm);
}

@keyframes skeleton-loading {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

.empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--ink-dim);
}

/* Sections fade up as they enter the viewport. Content is NEVER hidden by CSS alone: layout.js
   only adds .reveal-armed once an IntersectionObserver is actually attached, and it force-shows
   everything after a timeout. So if JS fails, the observer never fires, or the browser is odd,
   the page still renders fully instead of showing blank sections. */
.reveal-armed { opacity: 0; transform: translateY(18px); }
.reveal-armed.in-view { opacity: 1; transform: none; transition: opacity .6s ease, transform .6s ease; }

@media (prefers-reduced-motion: reduce) {
  .reveal-armed, .reveal-armed.in-view { opacity: 1; transform: none; transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
