/* Operating Bureau, base tokens, type scale, grounds, utilities */
/* Self-hosted, latin subset, variable files. Nothing loads from a CDN at runtime. */
@font-face{font-family:"Archivo";src:url("../fonts/Archivo.woff2") format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Jost";src:url("../fonts/Jost.woff2") format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Inter";src:url("../fonts/Inter.woff2") format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Oswald";src:url("../fonts/Oswald.woff2") format("woff2");font-weight:200 700;font-display:swap}
@font-face{font-family:"Cinzel";src:url("../fonts/Cinzel.woff2") format("woff2");font-weight:400 900;font-display:swap}


:root{
  --ob-accent:#EAE210;
  --ob-accent-soft:#FFFCA3;
  --ob-ink:#2E2E2E;
  --ob-black:#000000;
  --ob-mist:#EFEAE0;
  --ob-paper:#FFFFFF;
  --ob-cream:#F7F3EC;          /* the ground. warm, not clinical. */
  --ob-cream-deep:#F1EBE0;     /* section alternation, barely there */
  --ob-line:rgba(24,20,14,.13);

  --font-display:"Methane","Archivo","Helvetica Neue",Helvetica,Arial,sans-serif;
  --font-label:"Minimalist","Jost","Futura",system-ui,sans-serif;
  --font-body:"Inter",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;

  --ease:cubic-bezier(.22,.61,.36,1);
  --dur-fast:180ms; --dur:420ms; --dur-slow:700ms;

  --max:1200px;
  --gutter:24px;
  --sec-pad:clamp(64px,9vw,140px);
  --r-sm:10px; --r:16px; --r-lg:24px; --r-pill:999px;
}

*,*::before,*::after{box-sizing:border-box}
/* <figure> carries a UA default of `margin: 1em 40px`. Left in, it shifts every
   scattered photograph on the hero 40px toward the centre of the stage, which
   is enough to slide the outer ones underneath the video, and it silently
   inflates the gaps in every proof and case-study grid. Reset it once here
   rather than per component. */
figure,blockquote{margin:0}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--ob-cream);
  color:var(--ob-ink);
  font-family:var(--font-body);
  font-size:1.0625rem;
  line-height:1.6;
  font-feature-settings:"kern" 1,"liga" 1;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block;height:auto}
a{color:inherit}
button,input,select,textarea{font:inherit;color:inherit}

/* ---- layout ---- */
.wrap{width:100%;max-width:var(--max);margin-inline:auto;padding-inline:max(16px,var(--gutter));
  text-align:center}
/* centred by default; opt out per element with .left, never per section */
.wrap > *{margin-inline:auto}
.left{text-align:left}
.measure{max-width:58ch;margin-inline:auto}
.measure-tight{max-width:46ch;margin-inline:auto}
.section{padding-block:var(--sec-pad)}
.section--mist{background:var(--ob-cream-deep)}
.section--paper{background:var(--ob-paper)}

/* No patterned grounds. A flat warm cream reads more expensive than any
   texture, and the checker was doing the opposite of what it was there for. */

/* ---- type ---- */
/* margin-block:0 + margin-inline:auto, never the margin:0 shorthand: a bare
   heading is a direct child of .wrap almost everywhere it appears, and
   shorthand margin:0 has the same specificity as .wrap > *{margin-inline:auto}
   above, so whichever rule is lower in the file wins and silently cancels
   centering on any heading that doesn't happen to carry a second, more
   specific class re-declaring margin:0 auto (the pitch-site hero title only
   stayed centered by accident, via .hero__head in pitch.css; systems/index.html's
   bare <h1 class="d-xl"> had no such second class and rendered flush-left). */
.d-xl{
  font-family:var(--font-display);
  font-size:clamp(1.875rem,3.6vw,3.25rem);
  line-height:1.06;letter-spacing:-.018em;
  color:var(--ob-black);margin-block:0;margin-inline:auto;
  text-wrap:balance;
}
.d-l{
  font-family:var(--font-display);
  font-size:clamp(1.5rem,2.6vw,2.25rem);
  line-height:1.12;letter-spacing:-.012em;
  color:var(--ob-black);margin-block:0;margin-inline:auto;
  text-wrap:balance;
}
h2.d-l,h3{text-wrap:balance}
h3{font-family:var(--font-display);font-size:1.25rem;line-height:1.25;margin:0 0 .4em;color:var(--ob-black)}
p{margin:0 0 1em;max-width:58ch;margin-inline:auto}
.lead{font-size:1.1875rem;line-height:1.55}
.eyebrow{
  font-family:var(--font-label);
  font-size:.6875rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ob-ink);opacity:.72;margin:0 0 1rem;display:block;
}
.num{font-variant-numeric:tabular-nums}

/* ---- marks ---- */
/* The highlighted term in a headline. An underline swash, not a filled block:
   filled reads like a marker pen, the rule reads like design. Defined ONCE,
   here, because two definitions of .mark in two files is how the last one
   silently lost. */
.mark{position:relative;white-space:nowrap;color:var(--ob-black)}
.mark::after{content:"";position:absolute;left:-.02em;right:-.02em;bottom:-.04em;
  height:.13em;background:var(--ob-accent);border-radius:2px}
.js .mark::after{transform:scaleX(0);transform-origin:left center;
  transition:transform 620ms var(--ease) 520ms}
/* Two triggers, because there are two reveal systems in this build and a
   .mark that matches neither renders as plain text with an invisible swash,
   silently, which is the worst way for a highlighted figure to fail.
   `.is-lit` is the hero's own lighting pass (main.js lights the hero element
   directly). `.is-in` is the general IntersectionObserver reveal that every
   other section on every page uses. A .mark anywhere outside the hero needs
   the second one. */
.js .is-lit .mark::after,
.js .is-in .mark::after{transform:scaleX(1)}
.rule{height:2px;background:var(--ob-black);border:0;margin:0}
.rule--accent{height:5px;background:var(--ob-accent);border:0;width:48px;
  margin:0 auto 1.5rem;border-radius:var(--r-pill)}

/* ---- buttons ---- */
.btn{
  display:inline-flex;align-items:center;gap:.6em;
  background:var(--ob-accent);color:var(--ob-black);
  font-family:var(--font-label);font-size:.8125rem;letter-spacing:.12em;text-transform:uppercase;
  padding:1rem 1.75rem;border:0;border-radius:var(--r-pill);
  text-decoration:none;cursor:pointer;
  transition:transform var(--dur-fast) var(--ease),box-shadow var(--dur-fast) var(--ease),
             filter var(--dur-fast) var(--ease);
  box-shadow:0 2px 0 rgba(0,0,0,.9), 0 8px 24px rgba(0,0,0,.12);
  min-height:48px;
}
.btn:hover{transform:translateY(-1px);box-shadow:0 3px 0 rgba(0,0,0,.9), 0 12px 30px rgba(0,0,0,.16)}
.btn:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(0,0,0,.9), 0 4px 12px rgba(0,0,0,.14)}
.btn--ghost{background:transparent;box-shadow:inset 0 0 0 2px var(--ob-black)}
.btn--ghost:hover{background:var(--ob-accent-soft);transform:none;box-shadow:none}
:focus-visible{outline:3px solid var(--ob-black);outline-offset:3px}

/* ---- honesty tags ---- */
.confirm{
  display:inline-block;font-family:var(--font-label);font-size:.625rem;
  letter-spacing:.12em;text-transform:uppercase;
  background:var(--ob-accent-soft);color:var(--ob-black);
  border:1px solid var(--ob-black);padding:.2em .5em;border-radius:2px;
  vertical-align:middle;
}
.swap{
  display:flex;align-items:center;justify-content:center;
  background:repeating-linear-gradient(45deg,var(--ob-mist),var(--ob-mist) 10px,#e4e4e4 10px,#e4e4e4 20px);
  border:1.5px dashed rgba(0,0,0,.22);border-radius:var(--r);
  font-family:var(--font-label);font-size:.6875rem;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(0,0,0,.55);text-align:center;padding:1.5rem;min-height:120px;
}
.swap[data-ratio="16/9"]{aspect-ratio:16/9}
.swap[data-ratio="1/1"]{aspect-ratio:1/1}
.swap[data-ratio="4/5"]{aspect-ratio:4/5}

/* ---- .vid: a real video testimonial card, shared across the pitch site's
   case studies, the registration proof grid and the thank-you page's student
   wins. Never a screenshot pretending to be a video. A real YouTube thumbnail
   as the poster, a play button over it, swapping to a real iframe on click,
   never autoplaying. Neutral chrome, not a brand mark, so it reads correctly
   on both Operating Bureau's ground and a prospect's. Driven by main.js's
   initVideoSlots() from a `[data-video]` element carrying a bare video ID. */
.vid{position:relative;border-radius:var(--r);overflow:hidden;
  background:var(--ob-mist);aspect-ratio:16/9;cursor:pointer}
.vid[data-ratio="1/1"]{aspect-ratio:1/1}
.vid[data-ratio="4/5"]{aspect-ratio:4/5}
.vid__poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.vid__play{position:absolute;inset:0;margin:auto;width:56px;height:56px;
  border-radius:50%;background:rgba(0,0,0,.62);display:flex;align-items:center;
  justify-content:center;transition:transform var(--dur-fast) var(--ease),
  background var(--dur-fast) var(--ease)}
.vid__play svg{width:20px;height:20px;fill:#fff;margin-left:3px}
.vid:hover .vid__play{transform:scale(1.08);background:var(--ob-black)}
.vid iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vid__cap{margin-top:.6rem;font-size:.8125rem;opacity:.78;text-align:left}

/* ---- motion ---- */
.reveal{transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease)}
/* hidden ONLY when JS is running and can bring it back. No JS, no blank page. */
.js .reveal{opacity:0;transform:translateY(14px)}
.js .reveal.is-in{opacity:1;transform:none}

/* The hero headline gets a slower, softer arrival than everything else: it is
   the first thing read and a 420ms pop reads cheap on a line that large. */
.js .hero__head.reveal{transform:translateY(22px);filter:blur(7px);
  transition:opacity 900ms var(--ease),transform 900ms var(--ease),filter 900ms var(--ease)}
.js .hero__head.reveal.is-in{filter:blur(0)}
.js .hero__sub.reveal{transition-delay:160ms}
.js .hero__cta.reveal{transition-delay:260ms}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none!important;animation:none!important}
  .reveal{opacity:1!important;transform:none!important}
}

/* ---- a11y ---- */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px}
.skip:focus{left:16px;top:16px;z-index:99;background:var(--ob-accent);padding:.75rem 1rem}
