/* ─────────────────────────────────────────────────────────────
   ORIGAMI ACADEMY — site-specific styles.
   Built entirely on brand/tokens.css + brand/patterns.css. No hex
   codes below except where a token genuinely doesn't cover the
   case (see Press-System/BRAND.md, "Adding to the system").
   ───────────────────────────────────────────────────────────── */

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

/* [hidden] must always win: several elements below (.gate, .modal) also
   set their own `display`, which has equal specificity and would
   otherwise beat the UA stylesheet's [hidden] rule depending on
   cascade order. */
[hidden] { display: none !important; }

/* ---- scroll progress -------------------------------------------------- */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 300;
  pointer-events: none;
}
.scroll-progress-bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--ink-cornflower), var(--ink-plum));
}

/* ---- magnetic buttons --------------------------------------------------
   .is-magnetic gets its transform set inline by shared.js on mousemove;
   this transition is what makes that feel like a pull rather than a
   snap, and lets it spring back smoothly on mouseleave. */
.btn-primary.is-magnetic {
  transition: transform 200ms var(--ease-out), background var(--d-ui) var(--ease-out);
}

html {
  color-scheme: light;
}

body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-geist);
  font-size: var(--text-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4, h5 {
  margin: 0;
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--color-ink);
}

p { margin: 0; }

a {
  color: inherit;
}

/* ---- focus ------------------------------------------------------
   Vermilion is the ink drawer's tick, and BRAND.md names "a focus
   ring" as one of its sanctioned jobs — the one place the accent
   is allowed outside a label or a rule. */
:focus-visible {
  outline: 2px solid var(--ink-vermilion);
  outline-offset: 3px;
  border-radius: 3px;
}

button {
  font-family: inherit;
  cursor: pointer;
}

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

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* ================================================================
   WORDMARK — live text, not artwork (per BRAND.md, "The marks").
   ================================================================ */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-serif);
  font-size: 1.2rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--color-ink);
  text-decoration: none;
}
.wordmark img { width: 1.7rem; height: 1.7rem; }
.wordmark-sub {
  font-family: var(--font-grot);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted);
  padding-left: 0.6rem;
  border-left: var(--hair) solid var(--color-line);
}

/* ================================================================
   PASSCODE GATE
   ================================================================ */
.gate {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--page-gutter);
  background-color: var(--color-paper-warm);
}

.gate-card {
  width: 100%;
  max-width: 26rem;
  background: var(--color-off-white-40);
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  box-shadow: 0 1px 2px rgba(89, 83, 78, 0.06);
}

.gate-mark { margin-bottom: 0.25rem; }

.gate-card h1 {
  font-size: var(--text-h4);
}

.gate-copy {
  color: var(--color-muted);
  font-size: var(--text-body-sm);
}

.field-label {
  display: block;
  font-family: var(--font-grot);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 0.5rem;
}

.gate-input-row {
  display: flex;
  gap: 0.5rem;
}

.text-input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 1rem;
  padding: 0.75rem 0.9rem;
  min-height: 44px;
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  background: var(--color-off-white-30);
  color: var(--color-ink);
}
.text-input:focus-visible {
  outline: 2px solid var(--ink-vermilion);
  outline-offset: 1px;
}

.btn-toggle {
  min-height: 44px;
  padding: 0 1rem;
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  background: var(--color-off-white-40);
  color: var(--color-muted);
  font-size: var(--text-body-sm);
  font-family: var(--font-grot);
}
.btn-toggle:hover { color: var(--color-ink); }

.gate-error {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: var(--text-body-sm);
  color: var(--ink-vermilion);
  margin: -0.5rem 0 0;
}
.gate-error svg { flex: none; margin-top: 0.15em; }

.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 1.5rem;
  border: none;
  border-radius: 6px;
  background: var(--color-ink);
  color: var(--color-paper);
  font-family: var(--font-grot);
  font-weight: 600;
  font-size: var(--text-body-sm);
  letter-spacing: 0.02em;
  text-decoration: none;
  transition: transform var(--d-micro) var(--ease-out), background var(--d-ui) var(--ease-out);
}
.btn-primary:hover { background: var(--color-brown-90); }
.btn-primary:active { transform: scale(0.97); }
.btn-small { min-height: 40px; padding: 0 1.1rem; font-size: var(--text-caption); }
.btn-inverse { background: var(--ink-sunflower); color: var(--color-navy-deep); }
.btn-inverse:hover { background: var(--color-off-white-40); }

.gate-back {
  text-align: center;
  font-size: var(--text-body-sm);
  color: var(--color-muted);
  text-decoration: none;
}
.gate-back:hover { color: var(--color-ink); text-decoration: underline; }

/* ================================================================
   SITE SHELL
   ================================================================ */
#site[hidden] { display: none; }

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.25rem var(--page-gutter);
  border-bottom: var(--hair) solid transparent;
  background: var(--color-paper);
  transition: background var(--d-ui) var(--ease-out),
    box-shadow var(--d-ui) var(--ease-out),
    border-radius var(--d-ui) var(--ease-out),
    margin var(--d-ui) var(--ease-out),
    max-width var(--d-ui) var(--ease-out),
    padding var(--d-ui) var(--ease-out);
}

/* Echoes the main site's floating capsule nav: once the page has
   scrolled past the hero, the header shrinks into a centered,
   blurred pill rather than staying a full-width flat bar. */
.nav.is-scrolled {
  max-width: calc(var(--page-measure) - 4rem);
  margin: 0.75rem auto 0;
  padding: 0.7rem 1.5rem;
  border-radius: 999px;
  border-bottom-color: transparent;
  background: rgba(248, 242, 237, 0.78);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  box-shadow: 0 8px 24px rgba(33, 46, 74, 0.1), 0 1px 0 var(--color-tan-60);
}

.nav-back {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-grot);
  font-size: var(--text-caption);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-muted);
  text-decoration: none;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.nav-back:hover { color: var(--color-ink); }

/* ---- hero -------------------------------------------------------- */
.hero {
  position: relative;
  padding: clamp(2rem, 6vw, 3.5rem) var(--page-gutter);
  overflow: hidden;
}

/* Follows the cursor (shared.js sets --mx/--my on mousemove); a soft
   cornflower glow that gives the board texture a sense of depth.
   Desktop mouse only — there's no cursor on touch to react to. */
.hero-spotlight {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    500px circle at var(--mx, 50%) var(--my, 10%),
    rgba(141, 173, 241, 0.16),
    transparent 70%
  );
}

/* Two ramps, soft, behind the card only — never behind type (the
   card's own solid surface sits on top of this, per BRAND.md's
   rule for .og-board). Purely decorative; each drifts slowly and
   independently so the hero feels alive without drawing the eye
   away from the words. */
.hero-glow {
  position: absolute;
  aspect-ratio: 1;
  filter: blur(70px);
  border-radius: 50%;
  pointer-events: none;
}
.hero-glow--a {
  top: -18%;
  right: 8%;
  width: min(38rem, 60vw);
  background: var(--ramp-dusk);
  opacity: 0.35;
  animation: hero-drift-a 16s var(--ease-inout) infinite alternate;
}
.hero-glow--b {
  bottom: -22%;
  left: -6%;
  width: min(26rem, 46vw);
  background: var(--ramp-field);
  opacity: 0.25;
  animation: hero-drift-b 20s var(--ease-inout) infinite alternate;
}
@keyframes hero-drift-a {
  from { transform: translate(0, 0); }
  to { transform: translate(-22px, 26px); }
}
@keyframes hero-drift-b {
  from { transform: translate(0, 0); }
  to { transform: translate(24px, -18px); }
}

/* Staggered load-in for the hero's own children — a single
   orchestrated moment on first paint, not a scroll effect (see
   BRAND.md, Motion: "one orchestrated moment lands better than
   scattered effects"). Triggered by shared.js adding .loaded to
   <body> shortly after DOMContentLoaded. */
.hero-stagger {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--d-enter) var(--ease-out), transform var(--d-enter) var(--ease-out);
  transition-delay: calc(var(--stagger, 0) * 90ms);
}
body.loaded .hero-stagger {
  opacity: 1;
  transform: none;
}

/* Flat tint pills, not a divider line — the brand's own Division
   rule flags a full-measure rule as the generic "editorial" tell.
   Each stat is its own small block of colour instead. */
.hero-stats {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.25rem;
}
.hero-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  background: var(--color-off-white-90);
  border: 1px solid var(--color-tan-60);
}
.hero-stat-value {
  font-family: var(--font-mono);
  font-size: var(--text-body-sm);
  font-weight: 600;
  color: var(--ink-vermilion);
  font-variant-numeric: tabular-nums;
}
.hero-stat-label {
  font-family: var(--font-grot);
  font-size: var(--text-caption);
  color: var(--color-muted);
}

/* ---- the crane ------------------------------------------------------
   An original low-poly paper crane, not the marketing site's own
   artwork (which isn't available here) — built from the same
   dither ramp BRAND.md describes as "cornflower into plum into
   night, the same journey the why-section sky makes." It flies in
   once on load (outer element, fill-mode both so it starts and ends
   in place) and idles with a slow bob afterward (inner element, so
   the two motions compose instead of overwriting one transform).
   Reduced motion zeroes both animation durations globally, so it
   simply appears already settled with no flight and no bob. */
.crane-fly {
  position: absolute;
  top: 6%;
  left: 44%;
  width: clamp(9rem, 16vw, 15rem);
  z-index: 2;
  pointer-events: none;
  animation: crane-flight 1.7s var(--ease-out) 0.3s both;
}
.crane-bob {
  animation: crane-idle 6s ease-in-out 2s infinite;
}
.crane-svg {
  width: 100%;
  height: auto;
  display: block;
  filter: drop-shadow(0 14px 20px rgba(33, 46, 74, 0.18));
}
@keyframes crane-flight {
  0% { transform: translate(120%, -70%) rotate(-30deg) scale(0.55); opacity: 0; }
  20% { opacity: 1; }
  65% { transform: translate(-6%, 8%) rotate(8deg) scale(1.04); }
  100% { transform: translate(0, 0) rotate(-3deg) scale(1); }
}
@keyframes crane-idle {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-8px) rotate(1.5deg); }
}

.hero-inner {
  position: relative;
  z-index: 1;
  max-width: var(--page-measure);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.85fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 4rem);
}

.hero-copy h1 {
  font-size: var(--text-h2);
  max-width: 16ch;
}
.hero-copy .lede {
  font-size: var(--text-lede);
  font-weight: 400;
  color: var(--color-muted);
  max-width: 38ch;
  margin-top: 1.25rem;
}
.hero-copy .eyebrow { margin-bottom: 0.5rem; }

.hero-actions {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin: 1.75rem 0 1.5rem;
}
.hero-note {
  font-size: var(--text-body-sm);
  color: var(--color-muted);
}

/* ---- hero visual: a fanned stack of preview plates -------------------
   Asymmetric on purpose, so the hero doesn't read as one centred box.
   The front plate mirrors a real video card (flat ink, watermark
   number, legible title) and is filled from data.js; the two behind
   it are pure colour, no text, so nothing there needs to be read. */
.hero-visual {
  position: relative;
  height: clamp(16rem, 28vw, 22rem);
  overflow: hidden;
  border-radius: 10px;
}
.hero-plate {
  position: absolute;
  inset: 1.5rem;
  border-radius: 6px;
}
.hero-plate--back {
  background: var(--ink-sunflower);
  opacity: 0.55;
  transform: rotate(5deg) translate(0.75rem, 0.4rem);
}
.hero-plate--mid {
  background: var(--ink-cornflower);
  opacity: 0.7;
  transform: rotate(-3deg) translate(-0.4rem, 0.2rem);
}
.hero-plate--front {
  background: var(--ink-plum);
  box-shadow: 0 18px 40px rgba(33, 46, 74, 0.16);
  transform: rotate(1deg);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
}
.hero-plate--front .hero-plate-num {
  position: absolute;
  right: 0.75rem;
  bottom: -0.3em;
  font-family: var(--font-mono);
  font-size: clamp(4rem, 3rem + 5vw, 7rem);
  color: var(--color-off-white-70);
  opacity: 0.14;
  line-height: 1;
}
.hero-plate--front .hero-plate-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
  z-index: 1;
}
.hero-plate--front .hero-plate-tag {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-off-white-60);
}
.hero-plate--front .hero-plate-play {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: rgba(248, 242, 237, 0.16);
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero-plate--front .hero-plate-play svg { width: 1.1rem; height: 1.1rem; color: var(--color-off-white-40); }
.hero-plate--front h3 {
  position: relative;
  z-index: 1;
  color: var(--color-off-white-30);
  font-size: var(--text-h5);
  font-weight: 500;
  max-width: 18ch;
}

/* ---- page head (library.html) -------------------------------------- */
.page-head {
  max-width: var(--page-measure);
  margin: 0 auto;
  padding: clamp(2.5rem, 6vw, 3.5rem) var(--page-gutter) 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.page-head h1 { font-size: var(--text-h2); max-width: 24ch; }
.page-head .lede { color: var(--color-muted); font-size: var(--text-body-lg); max-width: 48ch; }

/* ---- library ------------------------------------------------------ */
.library {
  max-width: var(--page-measure);
  margin: 0 auto;
  padding: clamp(2.5rem, 6vw, 4rem) var(--page-gutter);
}

.library-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.75rem;
  flex-wrap: wrap;
}

.library-head h2 {
  font-size: var(--text-h3);
}

.library-count {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--color-muted);
}

/* ---- filters + search ----------------------------------------------- */
.library-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 2rem;
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.search-field {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  max-width: 16rem;
}
.search-icon {
  position: absolute;
  left: 0.9rem;
  width: 15px;
  height: 15px;
  color: var(--color-muted);
  pointer-events: none;
}
.search-input {
  width: 100%;
  min-height: 44px;
  padding: 0 0.9rem 0 2.25rem;
  border: 1px solid var(--color-tan-60);
  border-radius: 999px;
  background: var(--color-off-white-40);
  color: var(--color-ink);
  font: inherit;
  font-size: var(--text-body-sm);
}
.search-input:focus-visible { outline: 2px solid var(--ink-vermilion); outline-offset: 1px; }
.search-input::-webkit-search-cancel-button { cursor: pointer; }

.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
  padding: 0 1rem;
  border: 1px solid var(--color-tan-60);
  border-radius: 999px;
  background: var(--color-off-white-40);
  color: var(--color-muted);
  font-family: var(--font-grot);
  font-size: var(--text-body-sm);
  font-weight: 500;
  transition: background var(--d-ui) var(--ease-out), color var(--d-ui) var(--ease-out),
    border-color var(--d-ui) var(--ease-out);
}
.filter-pill:hover { border-color: var(--color-brown-70); color: var(--color-ink); }
.filter-pill.is-active {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-paper);
}
.filter-count {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  opacity: 0.7;
}

.library-empty {
  color: var(--color-muted);
  font-size: var(--text-body-sm);
  padding: 2rem 0;
  text-align: center;
  border: 1px dashed var(--color-tan-60);
  border-radius: 6px;
}

.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 1.25rem;
}

/* ---- scroll-reveal --------------------------------------------------
   One entrance per element, then it's done — not a scroll-tied
   effect, just a settle-in the first time it comes into view.
   Respects prefers-reduced-motion in app.js (elements get
   .is-visible immediately, no observer, no motion). */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--d-enter) var(--ease-out), transform var(--d-enter) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* The card is a plain, non-interactive shell; .video-open (a <button>
   for a ready video, a <div> otherwise) holds the part that opens the
   modal, and .video-resources holds download links as separate
   siblings — a link can't legally nest inside a button, and nesting
   it there would also fight the button's own click handler. */
.video-card {
  display: flex;
  flex-direction: column;
  background: var(--color-off-white-90);
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  overflow: hidden;
  transition: transform var(--d-ui) var(--ease-out), border-color var(--d-ui) var(--ease-out);
}
.video-card--ready { background: var(--color-off-white-40); }
.video-card--ready:hover,
.video-card--ready:focus-within {
  border-color: var(--color-brown-70);
  transform: translateY(-2px);
}

.video-open {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  width: 100%;
  padding: 1.5rem;
  text-align: left;
  font: inherit;
  color: inherit;
  background: none;
  border: none;
}
.video-card--ready .video-open { cursor: pointer; }

.video-resources {
  padding: 0.9rem 1.5rem 1.25rem;
  border-top: 1px solid var(--color-line);
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.video-resources-label {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 0.15rem;
}
.video-resource {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 32px;
  font-family: var(--font-grot);
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--color-ink);
  text-decoration: none;
}
.video-resource svg { flex: none; color: var(--color-muted); transition: color var(--d-ui) var(--ease-out); }
.video-resource:hover,
.video-resource:focus-visible {
  color: var(--ink-vermilion);
}
.video-resource:hover svg,
.video-resource:focus-visible svg {
  color: var(--ink-vermilion);
}
.video-resource-type { color: var(--color-muted); font-weight: 400; }

.video-plate {
  aspect-ratio: 16 / 9;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}
.video-plate .video-plate-num {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--text-h3);
  color: var(--ink-plum);
  opacity: 0.55;
}
.video-plate .play-glyph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.video-plate .play-glyph svg {
  width: 2.75rem;
  height: 2.75rem;
  color: var(--color-off-white-40);
  filter: drop-shadow(0 1px 4px rgba(33, 46, 74, 0.35));
  transition: transform var(--d-ui) var(--ease-out);
}
.video-card--ready:hover .play-glyph svg,
.video-card--ready:focus-visible .play-glyph svg {
  transform: scale(1.1);
}

.video-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.video-num {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--ink-vermilion);
  letter-spacing: 0.04em;
}

.tool-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  width: fit-content;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.tool-tag::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--tool-ink, var(--color-muted));
}

.video-status {
  font-family: var(--font-grot);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
  background: var(--color-tan-30);
  border-radius: 6px;
  padding: 0.25rem 0.55rem;
}
.video-status--ready {
  color: var(--color-off-white-40);
  background: var(--ink-plum);
}

.video-card h3 {
  font-size: var(--text-h5);
  font-weight: 500;
}

.video-card p {
  font-size: var(--text-body-sm);
  color: var(--color-muted);
}

/* ================================================================
   FEATURES — "what's inside" (landing)
   ================================================================ */
.features, .how-pin, .tools {
  max-width: var(--page-measure);
  margin: 0 auto;
  padding: clamp(2.5rem, 6vw, 4rem) var(--page-gutter);
}
.features h2, .how-pin h2, .tools h2 {
  font-size: var(--text-h3);
  max-width: 26ch;
  margin: 0.5rem 0 2rem;
}

/* ---- pinned scroll sequence ------------------------------------------
   The wrapper is tall (steps × 90vh via --how-steps, set inline by
   landing.js); the inner panel is sticky, so it stays in view for the
   whole scroll range while landing.js swaps the active step by scroll
   progress. Pure CSS position:sticky — nothing hijacks scroll speed
   or direction, so it stays safe on trackpads and touch. */
.how-scroll {
  position: relative;
  height: calc(var(--how-steps, 4) * 85vh);
}
.how-pin {
  position: sticky;
  top: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.5rem;
}
.feature-card {
  position: relative;
  overflow: hidden;
  padding: 1.75rem;
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  background: var(--color-off-white-90);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  transition: transform var(--d-ui) var(--ease-out), border-color var(--d-ui) var(--ease-out);
}
.feature-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 3px;
  width: 0;
  background: var(--ink-vermilion);
  transition: width var(--d-ui) var(--ease-out);
}
.feature-card:hover {
  border-color: var(--color-brown-70);
  transform: translateY(-2px);
}
.feature-card:hover::before { width: 100%; }
.feature-num {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--ink-vermilion);
}
.feature-card h3 { font-size: var(--text-h5); font-weight: 500; }
.feature-card p { font-size: var(--text-body-sm); color: var(--color-muted); }

/* ================================================================
   HOW IT WORKS — interactive rail + detail panel (landing).
   Echoes origami.build's numbered click-to-expand feature panel:
   a rail of steps, one active at a time, with the detail swapped
   into a single plate rather than every step carrying its own.
   ================================================================ */
.how-panel {
  display: grid;
  grid-template-columns: minmax(14rem, 20rem) 1fr;
  gap: 2rem;
  border: 1px solid var(--color-tan-60);
  border-radius: var(--radius-card);
  background: var(--color-off-white-40);
  padding: 1.5rem;
}

.how-list {
  display: flex;
  flex-direction: column;
}
.how-item {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  text-align: left;
  padding: 1rem 0.75rem;
  border: none;
  border-left: 2px solid transparent;
  background: transparent;
  color: var(--color-muted);
  transition: color var(--d-ui) var(--ease-out), border-color var(--d-ui) var(--ease-out);
}
.how-item-num {
  font-family: var(--font-mono);
  font-size: var(--text-body-sm);
}
.how-item-title {
  font-family: var(--font-grot);
  font-weight: 500;
  font-size: var(--text-body-sm);
}
.how-item.is-active {
  border-left-color: var(--ink-vermilion);
  color: var(--color-ink);
  background: var(--color-off-white-90);
  border-radius: 0 6px 6px 0;
}
.how-item.is-active .how-item-num { color: var(--ink-vermilion); }
.how-item:hover:not(.is-active) { color: var(--color-ink); }

/* A flat ink panel, not a texture behind type (per BRAND.md's own
   rule for og-board — a busy screen under readable text is hard to
   read regardless of brand). The big number is an absolutely
   positioned watermark, low-opacity and behind the copy, so it
   never competes with the words for space or contrast. */
.how-detail {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  background: var(--ink-plum);
  padding: clamp(1.75rem, 3vw, 2.5rem);
  display: flex;
  align-items: flex-end;
  min-height: 14rem;
}
.how-detail-num {
  position: absolute;
  right: 1rem;
  bottom: -0.35em;
  z-index: 0;
  font-family: var(--font-mono);
  font-size: clamp(5rem, 4rem + 6vw, 9rem);
  color: var(--color-off-white-70);
  opacity: 0.16;
  line-height: 1;
  pointer-events: none;
}
.how-detail-copy {
  position: relative;
  z-index: 1;
  max-width: 30rem;
}
.how-detail-copy h3 {
  font-size: var(--text-h4);
  color: var(--color-off-white-30);
  margin-bottom: 0.5rem;
}
.how-detail-copy p {
  font-size: var(--text-body-sm);
  color: var(--color-off-white-60);
  max-width: 32ch;
}

.how-progress {
  grid-column: 1 / -1;
  height: 3px;
  background: var(--color-tan-60);
  border-radius: 999px;
  overflow: hidden;
}
.how-progress-bar {
  height: 100%;
  width: 0%;
  background: var(--ink-vermilion);
  transition: width var(--d-micro) linear;
}

/* ================================================================
   TOOL COVERAGE STRIP (landing)
   ================================================================ */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1.25rem;
}
.tool-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.5rem;
  border: 1px solid var(--color-tan-60);
  border-top: 3px solid var(--tool-ink, var(--color-tan-60));
  border-radius: 6px;
  background: var(--color-off-white-90);
  text-decoration: none;
  transition: transform var(--d-ui) var(--ease-out), border-color var(--d-ui) var(--ease-out);
}
.tool-card:hover, .tool-card:focus-visible {
  border-color: var(--color-brown-70);
  border-top-color: var(--tool-ink, var(--color-brown-70));
  transform: translateY(-2px);
}
.tool-card h3 { font-size: var(--text-h5); font-weight: 500; color: var(--color-ink); }
.tool-card p { font-size: var(--text-body-sm); color: var(--color-muted); }
.tool-card-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--tool-ink, var(--color-muted));
}
.tool-card-dot.is-live { animation: dot-pulse 2.2s ease-in-out infinite; }
@keyframes dot-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.5); opacity: 0.55; }
}
.tool-card--all {
  background: var(--color-ink);
  border-color: var(--color-ink);
  border-top-color: var(--ink-vermilion);
}
.tool-card--all h3, .tool-card--all p { color: var(--color-paper); }

/* ================================================================
   WHY THIS MATTERS — dark contrast band (landing).
   A second dark surface besides the closing band, for rhythm: the
   page shouldn't read as one long light scroll with a single dark
   note at the very end.
   ================================================================ */
.why {
  position: relative;
  overflow: hidden;
  margin: 0 var(--page-gutter);
  padding: clamp(3rem, 8vw, 5rem) var(--page-gutter);
  border-radius: var(--radius-card);
  background-color: var(--color-navy);
  color: var(--color-off-white-70);
}
.why.og-board { background-image: none; }
.why-field {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--color-line-ink-soft) 1px, transparent 1px);
  background-size: 22px 22px;
  /* Spread across the whole card, not just the upper-left corner —
     a mask that fades out by the halfway point is what left the
     right side of a wide card reading as bare navy. */
  mask-image: radial-gradient(ellipse 90% 90% at 35% 30%, #000 0%, transparent 90%);
  -webkit-mask-image: radial-gradient(ellipse 90% 90% at 35% 30%, #000 0%, transparent 90%);
}
.why-inner {
  position: relative;
  max-width: 52rem;
}
.why h2 {
  color: var(--color-off-white-30);
  font-size: var(--text-h2);
  margin: 0.75rem 0 1.25rem;
}
.why-lede {
  font-size: var(--text-body-lg);
  color: rgba(248, 242, 237, 0.75);
  max-width: 62ch;
}
.why .eyebrow { color: var(--ink-sunflower); }

/* ================================================================
   FAQ ACCORDION (landing)
   ================================================================ */
.faq {
  max-width: 46rem;
  margin: 0 auto;
  padding: clamp(2.5rem, 6vw, 4rem) var(--page-gutter);
}
.faq h2 { font-size: var(--text-h3); margin: 0.5rem 0 2rem; }

.faq-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.faq-item {
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  background: var(--color-off-white-90);
  overflow: hidden;
}
.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 56px;
  padding: 1rem 1.25rem;
  background: none;
  border: none;
  text-align: left;
  font-family: var(--font-grot);
  font-size: var(--text-body);
  font-weight: 500;
  color: var(--color-ink);
}
.faq-icon {
  flex: none;
  position: relative;
  width: 18px;
  height: 18px;
}
.faq-icon::before, .faq-icon::after {
  content: "";
  position: absolute;
  background: var(--color-muted);
  transition: transform var(--d-ui) var(--ease-out), opacity var(--d-ui) var(--ease-out);
}
.faq-icon::before { top: 50%; left: 0; right: 0; height: 1.5px; transform: translateY(-50%); }
.faq-icon::after { left: 50%; top: 0; bottom: 0; width: 1.5px; transform: translateX(-50%); }
.faq-question[aria-expanded="true"] .faq-icon::after { transform: translateX(-50%) rotate(90deg); opacity: 0; }
.faq-question[aria-expanded="true"] .faq-icon::before { background: var(--ink-vermilion); }

.faq-answer {
  padding: 0 1.25rem 1.25rem;
}
.faq-answer p {
  font-size: var(--text-body-sm);
  color: var(--color-muted);
  max-width: 60ch;
}

/* ---- ticker ---------------------------------------------------------
   A wire-service strip of what the library covers — continuous,
   quiet motion between the hero and the page's static sections.
   Two identical copies of the same track sit back to back and the
   whole thing slides exactly half its width, so the loop is
   seamless. Reduced motion zeroes the animation duration globally,
   which freezes it as a plain static list. */
.ticker {
  overflow: hidden;
  border-top: var(--hair) solid var(--color-line);
  border-bottom: var(--hair) solid var(--color-line);
  background: var(--color-paper-deep);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.ticker-track {
  display: flex;
  width: max-content;
  gap: 1.25rem;
  padding: 1rem 0;
  animation: ticker-scroll 30s linear infinite;
}
.ticker-track span {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
  white-space: nowrap;
}
.ticker-track span::after { content: "\00b7"; color: var(--color-tan-60); }
@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ---- closing band: cloud sky --------------------------------------
   The reference recording of origami.build's own closing section
   shows a LIGHT cloud/sky ground here, not the dark navy BRAND.md
   describes for most dark surfaces — the sky tokens (--color-sky-*,
   sampled from the same cloud-sky.js the hero uses) are a distinct
   material from the flat dark grounds, reserved for exactly this
   kind of atmospheric moment. .closing-sky gets a gentle scroll
   parallax from landing.js (data-parallax), which is the "moving
   clouds" quality — the video showed no idle animation, only
   movement tied to scrolling past it. */
.closing {
  position: relative;
  margin: 0 var(--page-gutter) clamp(1.5rem, 4vw, 3rem);
  padding: clamp(3.5rem, 9vw, 6rem) 2rem;
  overflow: hidden;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  color: var(--color-ink);
}
.closing-sky {
  position: absolute;
  /* Fixed-length overscan, not percentage — percentage insets on an
     absolutely positioned child can't resolve against a parent whose
     height is auto (the bug that made this invisible at first: it
     collapsed to 0×0). A pixel buffer avoids that while still
     giving the parallax transform room before the edge shows. */
  inset: -60px -20px;
  z-index: 0;
  background:
    radial-gradient(ellipse 55% 40% at 18% 12%, rgba(255,255,255,0.75), transparent 62%),
    radial-gradient(ellipse 45% 32% at 82% 68%, rgba(255,255,255,0.55), transparent 58%),
    linear-gradient(160deg, var(--color-sky-peri) 0%, var(--color-sky-haze) 45%, var(--color-sky-lilac) 100%);
}
.closing-sky::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(89, 83, 78, 0.14) 1px, transparent 1.4px);
  background-size: 7px 7px;
  mix-blend-mode: multiply;
}
/* Scoped to the actual text/button, not `.closing > *` — a blanket
   rule at equal specificity to .closing-sky (both single-class
   selectors) and later in the file silently won the cascade and
   flipped its position back to relative, collapsing it to 0×0
   (absolute insets need position: absolute to do anything). Each
   layer now owns its own stacking. */
.closing h2, .closing p, .closing > a { position: relative; z-index: 2; }

.closing-frame {
  position: relative;
  z-index: 2;
  width: 5.5rem;
  height: 5.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-navy);
  border-radius: 6px;
  margin-bottom: 0.5rem;
}
.closing-frame::before {
  content: "";
  position: absolute;
  inset: 10px;
  border: 1px dashed rgba(248, 242, 237, 0.3);
  border-radius: 2px;
}
.closing-mark { filter: brightness(0) invert(1); opacity: 0.92; }
.reg-mark--closing { width: 10px; height: 10px; opacity: 0.7; }

.closing h2 {
  color: var(--color-ink);
  font-size: var(--text-h3);
  max-width: 26ch;
}
.closing h2 em {
  font-style: italic;
  color: var(--ink-plum);
}
.closing p {
  max-width: 38ch;
  color: var(--color-muted);
  font-size: var(--text-body-sm);
}

/* ---- mega wordmark ---------------------------------------------------
   A huge, low-opacity wordmark bleeding off both edges, between the
   closing band and the footer — the "big Origami across the page"
   moment from the reference. It's live text (one more place the
   wordmark stays typographic rather than artwork, per BRAND.md's
   "The marks"), sized in vw so it scales with the viewport, and
   scroll-parallaxed slightly slower than the page. */
.mega-wordmark {
  overflow: hidden;
  text-align: center;
  padding: 0 0 clamp(1.5rem, 4vw, 2.5rem);
}
.mega-wordmark span {
  display: inline-block;
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(6rem, 22vw, 16rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--color-ink);
  opacity: 0.08;
  white-space: nowrap;
}

/* A printer's registration cross. Default ink is vermilion (the
   drawer's "tick" — a small mark is exactly its sanctioned job).
   .reg-mark--float adds a slow, independent bob — respects
   prefers-reduced-motion via the global animation-duration reset. */
.reg-mark {
  position: absolute;
  width: 14px;
  height: 14px;
  opacity: 0.5;
  pointer-events: none;
}
.reg-mark::before, .reg-mark::after {
  content: "";
  position: absolute;
  background: var(--mark-ink, var(--ink-vermilion));
}
.reg-mark::before { top: 50%; left: 0; right: 0; height: 1px; transform: translateY(-50%); }
.reg-mark::after { left: 50%; top: 0; bottom: 0; width: 1px; transform: translateX(-50%); }
.reg-mark--float { animation: mark-float 7s ease-in-out infinite; }
@keyframes mark-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

/* ---- footer -------------------------------------------------------- */
.site-footer {
  padding: 2rem var(--page-gutter) 3rem;
  border-top: var(--hair) solid var(--color-line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-body-sm);
  color: var(--color-muted);
}
.site-footer a { text-decoration: underline; text-underline-offset: 2px; }

/* ================================================================
   VIDEO MODAL
   ================================================================ */
.modal[hidden] { display: none; }
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--page-gutter);
}
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(33, 46, 74, 0.55);
  opacity: 0;
  transition: opacity var(--d-ui) var(--ease-out);
}
.modal.is-open .modal-backdrop { opacity: 1; }

/* Opens from the card that triggered it (scale + fade), per
   BRAND.md's modal-motion guidance; the close is quicker than the
   open, per "exits undercut entrances". */
.modal-panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 52rem;
  max-height: 100%;
  overflow-y: auto;
  background: var(--color-paper);
  border-radius: 6px;
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  opacity: 0;
  transform: scale(0.96) translateY(6px);
  transition: opacity var(--d-ui) var(--ease-out), transform var(--d-ui) var(--ease-snap);
}
.modal.is-open .modal-panel {
  opacity: 1;
  transform: none;
}
.modal-panel h2 { font-size: var(--text-h4); padding-right: 2.5rem; }
.modal-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  color: var(--color-muted);
  font-size: 1.5rem;
  line-height: 1;
  border-radius: 6px;
}
.modal-close:hover { color: var(--color-ink); background: var(--color-tan-30); }
.modal-video-wrap {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 4px;
  overflow: hidden;
  background: var(--color-navy);
}
.modal-video-wrap iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.modal-feedback:empty { display: none; }
.modal-feedback {
  border-top: 1px solid var(--color-tan-60);
  padding-top: 1rem;
}
.modal-feedback-heading {
  font-size: var(--text-body);
  font-weight: 600;
  margin: 0 0 0.75rem;
}
.feedback-form { display: flex; flex-direction: column; gap: 0.9rem; }
.feedback-hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.rating-row { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.rating-btn {
  width: 36px;
  height: 36px;
  border: 1px solid var(--color-tan-60);
  border-radius: 6px;
  background: var(--color-off-white-40);
  color: var(--color-muted);
  font-family: var(--font-grot);
  font-size: var(--text-body-sm);
  font-weight: 600;
  transition: background var(--d-ui) var(--ease-out), color var(--d-ui) var(--ease-out), border-color var(--d-ui) var(--ease-out);
}
.rating-btn:hover { color: var(--color-ink); border-color: var(--color-brown-70); }
.rating-btn.is-selected { background: var(--color-ink); color: var(--color-paper); border-color: var(--color-ink); }
.feedback-scale { display: flex; justify-content: space-between; margin-top: 0.35rem; }
.feedback-scale-label { font-size: var(--text-caption); color: var(--color-muted); }
.feedback-textarea { min-height: 4.5rem; resize: vertical; font-family: inherit; width: 100%; }
select.text-input { width: 100%; }
.feedback-error {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: var(--text-body-sm);
  color: var(--ink-vermilion);
  margin: 0;
}
.feedback-actions { display: flex; align-items: center; gap: 0.9rem; flex-wrap: wrap; }
.feedback-status { font-size: var(--text-body-sm); color: var(--color-muted); display: inline-flex; align-items: center; gap: 0.4rem; }
.feedback-status--ok { color: var(--color-teal); }
.feedback-status--error { color: var(--ink-vermilion); }

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

@media (max-width: 47.99rem) {
  .nav { padding: 1rem var(--page-gutter); }
  .gate-input-row { flex-direction: column; }
  .btn-toggle { align-self: flex-start; }
  .how-panel { grid-template-columns: 1fr; }
  .hero-inner { grid-template-columns: 1fr; }
  .hero-visual { height: 12rem; order: -1; margin-bottom: 2rem; }
  .hero-copy h1 { max-width: none; }
  .crane-fly { width: 6rem; top: 0.5rem; left: 58%; }
  .how-scroll { height: calc(var(--how-steps, 4) * 62vh); }
  .library-controls { flex-direction: column; align-items: stretch; }
  .search-field { max-width: none; }
}
