/* ==========================================================================
   Strata Agronomy — design system
   --------------------------------------------------------------------------
   Concept: "strata" = soil horizons. The page descends tonally from pale
   mineral surface into deep forest bedrock. Colour is taken from the logo and
   nothing outside those values is used.

   Palette source of truth (sampled from logos/Strata+logo.png):
     #11532F  forest   — wordmark
     #6EB944  leaf     — leaf counter-form + AGRONOMY
   Everything else is a neutral derived to sit with those two.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Brand — exact logo values */
  --forest:        #11532F;
  --leaf:          #6EB944;

  /* Derived greens, used for layering without gradients */
  --forest-deep:   #0B3A21;   /* bedrock: the darkest band */
  --moss:          #2F7346;   /* mid horizon, hover states on forest */

  /* Mineral neutrals — cool and grey-green, deliberately NOT warm cream */
  --stone:         #E4E4DE;   /* primary light ground */
  --chalk:         #F5F5F2;   /* lifted surface on stone */
  --ash:           #CBCCC4;   /* hairlines on light */
  --slate:         #5C6259;   /* muted text on light */
  --ink:           #0F1A14;   /* body text — near-black, green undertone */

  /* On-forest text */
  --on-forest:     #EDF0EA;
  --on-forest-mut: #9FB3A4;

  /* ---- Spacing scale (4px base). No arbitrary padding anywhere. ---- */
  --s-1:  0.25rem;  /*  4 */
  --s-2:  0.5rem;   /*  8 */
  --s-3:  0.75rem;  /* 12 */
  --s-4:  1rem;     /* 16 */
  --s-5:  1.5rem;   /* 24 */
  --s-6:  2rem;     /* 32 */
  --s-7:  3rem;     /* 48 */
  --s-8:  4rem;     /* 64 */
  --s-9:  6rem;     /* 96 */
  --s-10: 8rem;     /* 128 */
  --s-11: 10rem;    /* 160 */

  /* ---- Type ---- */
  /* Newsreader: an editorial serif with real personality that has not been
     flattened by ubiquity. Chosen over Fraunces, which the design detector
     correctly flags as a saturated AI-default face. */
  --font-display: "Newsreader", "Iowan Old Style", Georgia, serif;
  --font-body:    "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

  /* Fluid scale, clamped so it never collapses or runs away */
  --t-hero:  clamp(2.75rem, 7vw, 6rem);
  --t-h1:    clamp(2.25rem, 5vw, 4rem);
  --t-h2:    clamp(1.75rem, 3.5vw, 2.75rem);
  --t-h3:    clamp(1.25rem, 2vw, 1.625rem);
  --t-lead:  clamp(1.125rem, 1.6vw, 1.375rem);
  --t-body:  1.0625rem;
  --t-small: 0.9375rem;
  --t-label: 0.75rem;

  /* ---- Layout ---- */
  --wrap:      78rem;
  --wrap-text: 42rem;   /* ~68ch — reading measure */
  --gutter:    var(--s-5);

  /* ---- Motion ---- */
  --ease:      cubic-bezier(0.2, 0.6, 0.2, 1);
  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --dur:       260ms;
  --dur-slow:  700ms;

  /* Scroll-scrub progress, 0–1. Written by JS via el.style.setProperty on the
     scrubbed container; read by descendant transforms below. The value here
     is the default before JS attaches, so nothing looks broken pre-hydration. */
  --scrub: 0;
}

/* --------------------------------------------------------------------------
   2. Reset
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* This design commits to a single light treatment. Declaring it explicitly
     makes native controls (the <select>, scrollbars, form UI) render correctly
     for visitors whose OS is set to dark. */
  color-scheme: light;
}

/* The header is sticky, so anchor targets must clear it or the heading lands
   underneath. Applies to #waitlist and #newsletter. */
:target,
section[id],
.article-body :is(h2, h3) {
  scroll-margin-top: 6rem;
}

body {
  margin: 0;
  background: var(--stone);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }

/* Removes the ~300ms tap delay and the default blue flash on touch devices. */
a, button, label, select, summary, [role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(17, 83, 47, 0.12);
}

/* --------------------------------------------------------------------------
   Grain
   --------------------------------------------------------------------------
   A static (not animated — no motion permission needed, no reduced-motion
   gate required) noise texture over the whole page. This is the difference
   between a flat colour fill and a surface that feels physical, which is
   most of what separates an "expensive" site from a merely tidy one. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 200;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   Custom cursor — a trailing accent ring, not a replacement
   --------------------------------------------------------------------------
   The system cursor stays fully visible and untouched (no `cursor: none`
   anywhere). Hiding the native pointer is the version of this effect that
   breaks screen magnifiers and some assistive/remote-desktop tooling; this
   is the version that adds presence without that risk. Desktop-with-a-mouse
   only — site.js checks `pointer: fine` before it ever attaches. */
.cursor-fx {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 201;
  width: 28px;
  height: 28px;
  margin: -14px 0 0 -14px;
  border: 1px solid var(--forest);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(-100px, -100px, 0) scale(1);
  transition: opacity var(--dur) var(--ease), scale var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
  will-change: transform;
}
.cursor-fx.is-active { opacity: 0.55; }
.cursor-fx.is-hovering { scale: 1.8; border-color: var(--leaf); }
.cursor-fx.is-dark { border-color: var(--on-forest); }
.cursor-fx.is-dark.is-hovering { border-color: var(--leaf); }

/* Cursor ring only: it tracks a moving pointer, so reduced-motion excludes it.
   Grain is a static texture — no motion involved — so it stays regardless. */
@media (pointer: coarse), (prefers-reduced-motion: reduce) {
  .cursor-fx { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Belt-and-braces: the block above neutralises transition/animation duration,
   but a scrub effect driven by a raw `transform: translateY(calc(var(--scrub)…`
   would still jump instantly with no transition to hide it. JS never starts
   its scroll-scrub loops when this preference is set (see site.js), so
   --scrub stays at its 0 default and every rule below resolves to a no-op —
   this is the CSS-side guarantee that backs that contract. */

/* --------------------------------------------------------------------------
   3. Typography
   -------------------------------------------------------------------------- */
.display, h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  /* Newsreader's optical-size axis: larger opsz tightens the fit for display
     sizes, which is exactly where these are used. */
  font-variation-settings: "opsz" 36;
  line-height: 1.06;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 {
  font-size: var(--t-h3);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.5;
  color: var(--slate);
  text-wrap: pretty;
}

/* The utility voice: labels, eyebrows, data. Mono earns its place on this
   site because there are real figures — altitude, load, group size. */
.label {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate);
}

.prose p { margin-bottom: var(--s-5); max-width: var(--wrap-text); text-wrap: pretty; }
.prose p:last-child { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   4. Layout primitives
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  /* max() keeps content clear of notches and rounded corners in landscape
     without adding padding on devices that have no inset. */
  padding-inline: max(var(--gutter), env(safe-area-inset-left))
                  max(var(--gutter), env(safe-area-inset-right));
}

@media (min-width: 60rem) {
  :root { --gutter: var(--s-8); }
}

/* Asymmetric editorial grid. Content sits in ranges, not centred blocks. */
.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--s-5);
}

@media (max-width: 59.99rem) {
  .grid { grid-template-columns: 1fr; }
  .grid > * { grid-column: 1 !important; }
}

.col-1-6  { grid-column: 1 / 7; }
.col-1-7  { grid-column: 1 / 8; }
.col-1-8  { grid-column: 1 / 9; }
.col-1-9  { grid-column: 1 / 10; }
.col-2-8  { grid-column: 2 / 9; }
.col-5-13 { grid-column: 5 / 13; }
.col-7-13 { grid-column: 7 / 13; }
.col-8-13 { grid-column: 8 / 13; }
.col-9-11 { grid-column: 9 / 11; }
.col-9-13 { grid-column: 9 / 13; }
.col-10-13 { grid-column: 10 / 13; }
.col-11-13 { grid-column: 11 / 13; }
.col-1-13 { grid-column: 1 / 13; }

.section { padding-block: var(--s-9); }

@media (min-width: 60rem) {
  .section { padding-block: var(--s-10); }
}

/* --------------------------------------------------------------------------
   5. Horizon bands — the stratigraphic descent
   -------------------------------------------------------------------------- */
.band-surface { background: var(--stone); color: var(--ink); }
.band-lifted  { background: var(--chalk); color: var(--ink); }

.band-forest,
.band-bedrock {
  color: var(--on-forest);
}
.band-forest  { background: var(--forest); }
.band-bedrock { background: var(--forest-deep); }

.band-forest h1, .band-forest h2, .band-forest h3,
.band-bedrock h1, .band-bedrock h2, .band-bedrock h3 { color: var(--on-forest); }

.band-forest .lead, .band-bedrock .lead,
.band-forest .label, .band-bedrock .label { color: var(--on-forest-mut); }

/* --------------------------------------------------------------------------
   6. SIGNATURE: the horizon rule
   --------------------------------------------------------------------------
   A hairline interrupted by a label, taken straight from the logo's
   "—— AGRONOMY ——" lockup. This is the one motif that repeats site-wide.
   -------------------------------------------------------------------------- */
.horizon {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-bottom: var(--s-7);
}

.horizon::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--ash);
}

.horizon__label {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--forest);
  white-space: nowrap;
}

.band-forest .horizon::after,
.band-bedrock .horizon::after { background: rgba(237, 240, 234, 0.22); }

.band-forest .horizon__label,
.band-bedrock .horizon__label { color: var(--leaf); }

/* --------------------------------------------------------------------------
   7. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  border: 1px solid transparent;
  border-radius: 2px;              /* near-square: structural, not app-like */
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease), transform 320ms var(--ease-out);
}

/* Magnetic pull toward the cursor (site.js, pointer:fine + primary CTAs
   only — [data-magnetic]). translate3d keeps it on its own compositor layer
   so the drag never touches layout. */
[data-magnetic] { display: inline-flex; transform: translate3d(0, 0, 0); }

.btn--primary {
  background: var(--forest);
  color: var(--on-forest);
}
.btn--primary:hover { background: var(--moss); }

.btn--ghost {
  background: transparent;
  border-color: var(--forest);
  color: var(--forest);
}
.btn--ghost:hover { background: var(--forest); color: var(--on-forest); }

/* On dark bands the primary inverts to the leaf accent. Leaf against forest
   clears 4.5:1 at this weight and size; it is never used for small body copy. */
.band-forest .btn--primary,
.band-bedrock .btn--primary {
  background: var(--leaf);
  color: var(--forest-deep);
}
.band-forest .btn--primary:hover,
.band-bedrock .btn--primary:hover { background: #7FC957; }

.band-forest .btn--ghost,
.band-bedrock .btn--ghost { border-color: rgba(237, 240, 234, 0.4); color: var(--on-forest); }
.band-forest .btn--ghost:hover,
.band-bedrock .btn--ghost:hover { background: rgba(237, 240, 234, 0.1); }

/* Visible keyboard focus everywhere, on both grounds. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--leaf);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   8. Skip link
   -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: var(--s-4);
  top: var(--s-4);
  z-index: 100;
  padding: var(--s-3) var(--s-5);
  background: var(--forest);
  color: var(--on-forest);
  text-decoration: none;
  /* transform rather than `top`: animating a layout property forces reflow. */
  transform: translateY(-200%);
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* --------------------------------------------------------------------------
   9. Header
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--stone);
  border-bottom: 1px solid var(--ash);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: 4.5rem;
}

.site-header__logo img { height: 2rem; width: auto; }

.nav {
  display: flex;
  align-items: center;
  gap: var(--s-6);
}

.nav a {
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  padding-block: var(--s-2);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
}
.nav a:hover { border-bottom-color: var(--leaf); }
.nav a[aria-current="page"] { border-bottom-color: var(--forest); }

.nav__cta { margin-left: var(--s-2); }

.nav-toggle { display: none; }

@media (max-width: 47.99rem) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    background: none;
    border: 1px solid var(--ash);
    border-radius: 2px;
    padding: var(--s-2) var(--s-3);
    font-size: var(--t-small);
    cursor: pointer;
  }
  .nav {
    display: none;
    position: absolute;
    inset-inline: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--stone);
    border-bottom: 1px solid var(--ash);
    padding: var(--s-4) var(--gutter) var(--s-6);
  }
  .nav[data-open="true"] { display: flex; }
  .nav a { padding-block: var(--s-4); border-bottom: 1px solid var(--ash); }
  .nav__cta { margin: var(--s-4) 0 0; justify-content: center; }
}

/* --------------------------------------------------------------------------
   10. Forms
   -------------------------------------------------------------------------- */
.field { margin-bottom: var(--s-5); }

.field label {
  display: block;
  margin-bottom: var(--s-2);
  font-size: var(--t-small);
  font-weight: 600;
}

.field .hint {
  display: block;
  margin-top: var(--s-2);
  font-size: var(--t-small);
  color: var(--slate);
}

.input {
  width: 100%;
  padding: var(--s-4);
  background: var(--chalk);
  border: 1px solid var(--ash);
  border-radius: 2px;
  transition: border-color var(--dur) var(--ease);
}
.input:hover  { border-color: var(--slate); }
.input:focus  { border-color: var(--forest); outline-offset: 1px; }
.input::placeholder { color: var(--slate); opacity: 0.7; }

/* Marked by site.js on the field the server rejected. Doubled with the message
   text, so the state is never communicated by colour alone. */
.input[aria-invalid="true"] { border-color: #A8321F; border-width: 2px; }
.band-forest .input[aria-invalid="true"],
.band-bedrock .input[aria-invalid="true"] { border-color: #D9705E; }

select.input {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%235C6259' stroke-width='1.5' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s-4) center;
  padding-right: var(--s-8);
}

.band-forest .input,
.band-bedrock .input {
  background: rgba(237, 240, 234, 0.06);
  border-color: rgba(237, 240, 234, 0.28);
  color: var(--on-forest);
}
.band-forest .input::placeholder,
.band-bedrock .input::placeholder { color: var(--on-forest-mut); }
.band-forest .input:focus,
.band-bedrock .input:focus { border-color: var(--leaf); }
.band-forest .field label,
.band-bedrock .field label { color: var(--on-forest); }
.band-forest .field .hint,
.band-bedrock .field .hint { color: var(--on-forest-mut); }

/* Honeypot — off-screen rather than display:none, which some bots detect. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Form feedback.
   A full hairline box rather than a thick left accent bar — the latter is a
   well-worn generic-UI tell, and the rule system is already this site's
   structural language. State is never carried by colour alone: the message
   text itself is prefixed ("Not sent — ") by site.js. */
.form-msg {
  margin-top: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border: 1px solid;
  border-radius: 2px;
  font-size: var(--t-small);
}
.form-msg--ok    { border-color: var(--forest); background: rgba(17, 83, 47, 0.07); color: var(--forest); }
.form-msg--error { border-color: #A8321F; background: rgba(168, 50, 31, 0.07); color: #7E2517; }

.band-forest .form-msg--ok,
.band-bedrock .form-msg--ok { border-color: var(--leaf); background: rgba(110, 185, 68, 0.14); color: var(--on-forest); }
.band-forest .form-msg--error,
.band-bedrock .form-msg--error { border-color: #D9705E; background: rgba(168, 50, 31, 0.24); color: #F2B5AB; }

/* --------------------------------------------------------------------------
   11. Footer
   -------------------------------------------------------------------------- */
.site-footer { background: var(--forest-deep); color: var(--on-forest); padding-block: var(--s-9) var(--s-6); }
.site-footer a { color: var(--on-forest); text-decoration: none; border-bottom: 1px solid transparent; }
.site-footer a:hover { border-bottom-color: var(--leaf); }
.site-footer__logo img { height: 2.25rem; width: auto; margin-bottom: var(--s-5); }

.footer-heading {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--leaf);
  margin-bottom: var(--s-4);
}

.footer-links li { margin-bottom: var(--s-3); }

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-4);
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 1px solid rgba(237, 240, 234, 0.16);
  font-size: var(--t-small);
  color: var(--on-forest-mut);
}

/* --------------------------------------------------------------------------
   12. Utilities
   -------------------------------------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.stack > * + * { margin-top: var(--s-4); }
.stack-lg > * + * { margin-top: var(--s-6); }

/* ==========================================================================
   12b. Scroll reveal
   --------------------------------------------------------------------------
   Only active when `.js` is present (site.js added it pre-paint) AND the
   visitor has not asked for reduced motion. Absent either condition, content
   is simply visible — never a permanently-hidden state. site.js also short-
   circuits its own IntersectionObserver under reduced motion, so --scrub-type
   effects elsewhere in this file share the same fallback contract.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .js [data-reveal] {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
    transition-delay: calc(var(--reveal-i, 0) * 70ms);
  }
  .js [data-reveal].is-revealed {
    opacity: 1;
    transform: translateY(0);
  }

  /* The horizon rule draws in left-to-right rather than fading — it is a
     line, so it should be drawn, not dissolved. */
  .js [data-reveal="horizon"]::after { transform: scaleX(0); transform-origin: left; }
  .js [data-reveal="horizon"].is-revealed::after {
    transform: scaleX(1);
    transition: transform 900ms var(--ease-out) 120ms;
  }
}

/* ==========================================================================
   13. Hero
   ========================================================================== */
.hero {
  padding-block: var(--s-9) var(--s-10);
  border-bottom: 1px solid var(--ash);
}

@media (min-width: 60rem) {
  .hero { padding-block: var(--s-10) var(--s-11); }
  .hero .grid { align-items: center; }
}

/* ---- Pin & scrub -----------------------------------------------------
   `.hero-pin` is the tall runway; `.hero-pin__sticky` is what actually
   pins. Both stay inert (normal document flow, no sticky) until:
     (a) site.js confirms rich effects are wanted → adds `.js-scroll-fx`
         to <html>, and
     (b) the visitor has not requested reduced motion.
   A visitor with JS disabled, or a slow/failed script load, gets an
   ordinary single-viewport hero — never a stretched empty gap. */
@media (prefers-reduced-motion: no-preference) {
  .js-scroll-fx .hero-pin { height: 190vh; }

  .js-scroll-fx .hero-pin__sticky {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    overflow: hidden;
  }

  /* Scrub-driven motion. --scrub (0→1) is written by site.js as the runway
     scrolls past; every value below is transform/opacity only. */
  .js-scroll-fx [data-hero-copy] {
    transform: translateY(calc(var(--scrub) * -3rem));
    opacity: clamp(0, calc(1 - var(--scrub) * 1.15), 1);
  }
  .js-scroll-fx [data-hero-profile] {
    transform: translateY(calc(var(--scrub) * -1.75rem));
  }
}

.hero__eyebrow { margin-bottom: var(--s-5); }

.hero__title {
  font-size: var(--t-hero);
  /* Slightly tighter than the global heading setting: at hero size the default
     leading opens up too much and the block stops reading as one mass. */
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin-bottom: var(--s-5);
}

.hero__lead { max-width: 34rem; margin-bottom: var(--s-7); }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-6);
}

/* ---- Signature: the soil profile ---------------------------------------- */
.profile { margin: 0; }

@media (max-width: 59.99rem) {
  .profile { margin-top: var(--s-8); }
}

.profile__stack {
  border: 1px solid var(--ash);
  border-radius: 2px;
  overflow: hidden;
}

.profile__layer {
  /* Each horizon is a real depth band, so they are not equal heights —
     the O horizon is thin, B is thick. The proportions carry information. */
  border-top: 1px solid rgba(237, 240, 234, 0.14);
}
.profile__layer:first-child { border-top: 0; }

.profile__toggle {
  display: flex;
  align-items: center;
  width: 100%;
  gap: var(--s-4);
  padding: var(--s-5);
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--t-small);
  text-align: left;
}

.profile__layer--o .profile__toggle { background: var(--chalk);       color: var(--ink);       min-height: 3.5rem; }
.profile__layer--a .profile__toggle { background: var(--moss);        color: var(--on-forest); min-height: 6rem; }
.profile__layer--b .profile__toggle { background: var(--forest);      color: var(--on-forest); min-height: 8rem; }
.profile__layer--c .profile__toggle { background: var(--forest-deep); color: var(--on-forest-mut); min-height: 5rem; }

.profile__toggle:hover { filter: brightness(1.08); }
.profile__toggle:focus-visible { outline-offset: -3px; }

.profile__code {
  flex: 0 0 1.5rem;
  font-size: 1.125rem;
  font-weight: 500;
}

.profile__name { letter-spacing: 0.08em; text-transform: uppercase; font-size: var(--t-label); }
.profile__depth { margin-left: auto; opacity: 0.75; font-size: var(--t-label); white-space: nowrap; }

.profile__chevron {
  flex: 0 0 auto;
  width: 0.6rem;
  height: 0.6rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
  opacity: 0.7;
}
.profile__toggle[aria-expanded="true"] .profile__chevron { transform: rotate(-135deg); }

/* Height-animates via the `fr` grid track rather than max-height or JS
   measuring scrollHeight — no layout read, transform/opacity-adjacent, and
   it degrades gracefully to an instant snap in browsers that don't
   interpolate grid-template-rows. */
.profile__detail {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-out);
  font-size: var(--t-small);
}
.profile__toggle[aria-expanded="true"] + .profile__detail { grid-template-rows: 1fr; }

.profile__detail__inner { overflow: hidden; min-height: 0; }
.profile__detail p {
  margin: 0;
  padding: 0 var(--s-5) var(--s-5) calc(1.5rem + var(--s-4));
  max-width: 30rem;
}

.profile__layer--o .profile__detail { background: var(--chalk); color: var(--ink); }
.profile__layer--o .profile__detail p { color: var(--slate); }
.profile__layer--a .profile__detail { background: var(--moss); color: var(--on-forest); }
.profile__layer--b .profile__detail { background: var(--forest); color: var(--on-forest); }
.profile__layer--c .profile__detail { background: var(--forest-deep); color: var(--on-forest-mut); }
.profile__layer--a .profile__detail p,
.profile__layer--b .profile__detail p { color: var(--on-forest-mut); }

.profile__caption {
  margin-top: var(--s-4);
  font-size: var(--t-small);
  color: var(--slate);
  max-width: 22rem;
}

.profile__hint {
  display: block;
  margin-top: var(--s-2);
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--forest);
  opacity: 0.7;
}

/* ==========================================================================
   14. Principles
   ========================================================================== */
/* Columns divided by hairlines rather than cards with shadows — the rule
   system is already the site's structural language. */
.principles {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: 1fr;
}

@media (min-width: 48rem) {
  .principles { grid-template-columns: repeat(3, 1fr); gap: var(--s-7); }
}

.principle { border-top: 2px solid var(--forest); padding-top: var(--s-5); }
.principle__label { margin-bottom: var(--s-4); }
.principle__title { margin-bottom: var(--s-4); }
.principle__body { color: var(--slate); }

/* ==========================================================================
   15. Stages (Cultivating Success / curriculum)
   ========================================================================== */
.stages-wrap { position: relative; }

/* The scrubbed rail: a track the full height of the stage list, with a fill
   that grows as the visitor scrolls through it. Encodes real information —
   how far through the sequence you are — rather than decorating a scroll. */
.stages-rail {
  position: absolute;
  left: -1px;
  top: var(--s-8);
  bottom: 0;
  width: 2px;
  background: rgba(237, 240, 234, 0.16);
  display: none;
}
.stages-rail__fill {
  width: 100%;
  height: 100%;
  background: var(--leaf);
  transform: scaleY(var(--scrub));
  transform-origin: top;
}

@media (min-width: 48rem) and (prefers-reduced-motion: no-preference) {
  .js-scroll-fx .stages-rail { display: block; }
  .js-scroll-fx .stage { padding-left: var(--s-6); }
}

.stages { margin-top: var(--s-8); }

.stage {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-4);
  padding-block: var(--s-6);
  border-top: 1px solid rgba(237, 240, 234, 0.18);
  transition: opacity var(--dur-slow) var(--ease-out);
}
.stage:last-child { border-bottom: 1px solid rgba(237, 240, 234, 0.18); }

@media (min-width: 48rem) {
  .stage {
    grid-template-columns: 6rem minmax(0, 22rem) minmax(0, 1fr);
    gap: var(--s-6);
    align-items: baseline;
  }
}

/* Dims until the rail reaches it, then comes to full strength — reads as the
   sequence "arriving" as you scroll, echoing sediment settling in order.
   Scoped to .stages-wrap specifically: only Home's "Cultivating Success" has
   the rail (and therefore anything that ever adds .is-active). The plain
   .stages list on Workshops has no wrapper and is unaffected — it gets the
   ordinary [data-reveal] treatment instead. */
@media (prefers-reduced-motion: no-preference) {
  .js-scroll-fx .stages-wrap .stage { opacity: 0.4; }
  .js-scroll-fx .stages-wrap .stage.is-active { opacity: 1; }
}

.stage__ordinal {
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-variation-settings: "opsz" 36;
  line-height: 1;
  color: var(--leaf);
  font-variant-numeric: tabular-nums;
  transition: transform var(--dur) var(--ease);
}
.stage.is-active .stage__ordinal { transform: scale(1.12); transform-origin: left center; }

.stage__title { margin-bottom: var(--s-3); }

@media (min-width: 48rem) {
  .stage__title { margin-bottom: 0; }
  .stage__body { display: contents; }
}

.stage__body p { color: var(--on-forest-mut); max-width: 36rem; }

/* Light-band variant, used by the workshop curriculum. */
.band-surface .stage,
.band-lifted .stage { border-top-color: var(--ash); }
.band-surface .stage:last-child,
.band-lifted .stage:last-child { border-bottom-color: var(--ash); }
.band-surface .stage__ordinal,
.band-lifted .stage__ordinal { color: var(--forest); }
.band-surface .stage__body p,
.band-lifted .stage__body p { color: var(--slate); }

/* ==========================================================================
   16. Post list
   ========================================================================== */
.post-list {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--ash);
}

.post-item { border-bottom: 1px solid var(--ash); }

.post-item__link {
  display: grid;
  gap: var(--s-3);
  padding-block: var(--s-6);
  text-decoration: none;
  color: inherit;
  /* transform, not padding: animating a layout property would reflow the whole
     list on every hover. */
  transition: transform var(--dur) var(--ease);
}

@media (min-width: 48rem) {
  .post-item__link {
    grid-template-columns: 12rem minmax(0, 1fr);
    gap: var(--s-6);
    align-items: baseline;
  }
  /* A restrained hover: the row inches right, echoing a page turn. */
  .post-item__link:hover { transform: translateX(var(--s-3)); }
}

.post-item__meta { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }

.post-item__title {
  margin-bottom: var(--s-2);
  transition: color var(--dur) var(--ease);
}
.post-item__link:hover .post-item__title { color: var(--forest); }

.post-item__excerpt { color: var(--slate); max-width: 44rem; }

.tag {
  display: inline-block;
  padding: 2px var(--s-2);
  border: 1px solid var(--forest);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--forest);
}

/* ==========================================================================
   17. Empty state
   ========================================================================== */
.empty {
  border-left: 2px solid var(--leaf);
  padding: var(--s-5) 0 var(--s-5) var(--s-5);
  max-width: 40rem;
}
.empty__title { font-family: var(--font-display); font-size: var(--t-h3); margin-bottom: var(--s-3); }
.empty p:last-child { color: var(--slate); }

/* ==========================================================================
   18. CTA band
   ========================================================================== */
.cta h2 { max-width: 20ch; }

/* ==========================================================================
   19. Page heads
   ========================================================================== */
.page-head { border-bottom: 1px solid var(--ash); }
.page-head h1 { max-width: 18ch; }

@media (min-width: 60rem) {
  .page-head .grid { align-items: end; }
}

/* ==========================================================================
   20. People (About)
   ========================================================================== */
.person {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-6);
  padding-block: var(--s-8);
  border-top: 1px solid var(--ash);
}
.person:last-of-type { border-bottom: 1px solid var(--ash); }

@media (min-width: 48rem) {
  .person { grid-template-columns: 16rem minmax(0, 1fr); gap: var(--s-8); }
}

.person__plate {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--forest);
  border-radius: 2px;
  overflow: hidden;
  display: grid;
  place-items: center;
  /* rotateX/Y set by site.js on pointermove, desktop pointer:fine only.
     transform-style + perspective make the tilt read as depth rather than a
     flat skew. */
  transform-style: preserve-3d;
  transition: transform 420ms var(--ease-out);
  will-change: transform;
}
.person__plate img { width: 100%; height: 100%; object-fit: cover; }

@media (pointer: coarse), (prefers-reduced-motion: reduce) {
  .person__plate { transition: none; }
}

/* Stands in for photography that does not exist yet, without pretending. */
.person__initial {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 72;
  font-size: 6rem;
  line-height: 1;
  color: var(--leaf);
}

.person__name { margin: var(--s-2) 0 var(--s-5); }
.person__bio { margin-bottom: var(--s-6); }

.creds { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); }

.creds__item {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--forest);
  border: 1px solid var(--ash);
  border-radius: 2px;
  padding: var(--s-2) var(--s-3);
}

/* ==========================================================================
   21. Methodology (About)
   ========================================================================== */
.method {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-5);
  padding-block: var(--s-8);
  border-top: 1px solid rgba(237, 240, 234, 0.18);
}
.method:last-of-type { border-bottom: 1px solid rgba(237, 240, 234, 0.18); }

@media (min-width: 60rem) {
  .method { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: var(--s-8); }
}

.method__name { margin-bottom: var(--s-4); }

.method__thesis {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-variation-settings: "opsz" 36;
  line-height: 1.25;
  color: var(--leaf);
  text-wrap: pretty;
}

.method__prose { color: var(--on-forest-mut); margin-bottom: var(--s-6); max-width: 42rem; }

.method__point {
  position: relative;
  padding-left: var(--s-5);
  margin-bottom: var(--s-3);
  color: var(--on-forest);
}
/* A rule rather than a bullet, matching the horizon motif. */
.method__point::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.75em;
  width: var(--s-3);
  height: 1px;
  background: var(--leaf);
}

/* ==========================================================================
   22. Facts (Workshops)
   ========================================================================== */
.facts {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  margin: 0;
}

@media (max-width: 59.99rem) {
  .facts { flex-direction: row; flex-wrap: wrap; gap: var(--s-6); margin-top: var(--s-7); }
}

.fact { border-top: 2px solid var(--forest); padding-top: var(--s-3); }
.fact dd { margin: var(--s-2) 0 0; }

.fact__value {
  font-family: var(--font-display);
  font-variation-settings: "opsz" 36;
  font-size: 2rem;
  line-height: 1;
  /* Digits animate in via count-up (site.js); tabular figures stop the value
     jittering in width as it counts, e.g. "5" widening into "50". */
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   23. Waitlist form
   ========================================================================== */
.waitlist-form {
  background: rgba(237, 240, 234, 0.04);
  border: 1px solid rgba(237, 240, 234, 0.16);
  border-radius: 2px;
  padding: var(--s-6);
}

@media (min-width: 48rem) {
  .waitlist-form { padding: var(--s-7); }
}

.waitlist__note {
  margin-top: var(--s-6);
  font-size: var(--t-small);
  color: var(--on-forest-mut);
}

.optional { font-weight: 400; color: var(--on-forest-mut); }

@media (max-width: 59.99rem) {
  .waitlist-form { margin-top: var(--s-7); }
}

/* ==========================================================================
   24. Article
   ========================================================================== */
.horizon__back { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
.horizon__back:hover { border-bottom-color: currentColor; }

.article-head h1 { max-width: 20ch; }

/* Fixed aspect ratio reserves the space before the iframe loads, so the page
   does not shift — CLS is a Core Web Vitals metric. */
.video {
  position: relative;
  aspect-ratio: 16 / 9;
  margin-bottom: var(--s-8);
  background: var(--forest-deep);
  border-radius: 2px;
  overflow: hidden;
}
.video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.article-cover { margin: 0 0 var(--s-8); }
/* Cover images come from arbitrary URLs, so their intrinsic dimensions are
   unknown at render time. A fixed aspect ratio reserves the space instead,
   which is what the explicit width/height attributes would otherwise buy. */
.article-cover img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--stone);
  border-radius: 2px;
}

/* Reading measure. Long-form body copy is capped independently of the grid. */
.article-body { max-width: var(--wrap-text); font-size: 1.125rem; line-height: 1.7; }
.article-body > * + * { margin-top: var(--s-5); }

.article-body h2,
.article-body h3 { margin-top: var(--s-8); }

.article-body a { color: var(--forest); text-decoration: underline; text-underline-offset: 3px; }
.article-body a:hover { color: var(--moss); }

.article-body ul,
.article-body ol { padding-left: var(--s-5); }
.article-body ul li { list-style: disc; margin-bottom: var(--s-3); }
.article-body ol li { list-style: decimal; margin-bottom: var(--s-3); }

.article-body blockquote {
  border-left: 2px solid var(--leaf);
  padding-left: var(--s-5);
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-variation-settings: "opsz" 36;
  line-height: 1.3;
}

.article-body img { border-radius: 2px; }

.article-body code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--stone);
  padding: 2px 6px;
  border-radius: 2px;
}
.article-body pre {
  background: var(--forest-deep);
  color: var(--on-forest);
  padding: var(--s-5);
  border-radius: 2px;
  overflow-x: auto;
}
.article-body pre code { background: none; padding: 0; color: inherit; }

.article-body hr { border: 0; border-top: 1px solid var(--ash); margin-block: var(--s-8); }
