/* Moody AI motion system.
   Two speeds, two curves, applied everywhere. Modeled on the timing
   discipline measured on cofounder.co (see Business/cofounder-teardown.md):
   micro-interactions are near-instant, entrances are slow and expressive.
   Nothing here needs a JS animation library. */

:root {
  /* curves */
  --ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);  /* big expressive moves */
  --ease-ui:        cubic-bezier(0.4, 0, 0.2, 1);    /* everyday UI changes */
  --ease-spring:    cubic-bezier(0.34, 1.56, 0.64, 1); /* buttons only, slight overshoot */

  /* durations */
  --t-press: 60ms;    /* hover and press feedback: must feel instant */
  --t-ui:    150ms;   /* color, border, background */
  --t-lift:  220ms;   /* card lift */
  --t-enter: 700ms;   /* scroll reveals and page entrances */
  --t-theme: 500ms;   /* day/night crossfade */
}

/* ---------- pressable things: fast in, fast out ----------
   One selector for the whole pill family, because after 2026-07-26 there IS one
   family. This used to name four classes individually -- a.btn-primary, a.btn-invert,
   a.btn-band -- and that list had rotted: .btn-band was never defined in any
   stylesheet, .btn-primary and .btn-ghost lost their last index.html call sites when
   the CTAs became call/text pairs, and .btn-invert was folded into .btn.
   `.btn` now covers every pill on the site, so the list cannot drift out of sync
   with the markup again. Note this GIVES press feedback to .btn--secondary and the
   two card skins, which never had it -- that is the point, all pills press alike. */
a.btn,
a.cta,
button.copy,
#theme-toggle {
  transition:
    transform var(--t-press) var(--ease-spring),
    background-color var(--t-ui) var(--ease-ui),
    box-shadow var(--t-ui) var(--ease-ui),
    color var(--t-ui) var(--ease-ui);
}
a.btn:active,
a.cta:active,
button.copy:active,
#theme-toggle:active {
  transform: translateY(0) scale(0.985);
  transition-duration: var(--t-press);
}

/* text links: only the underline moves, and it moves fast.
   a.btn-ghost stays here and ONLY means "text link" now. It used to be both: a pill
   on the homepage and an underline link in learn.css, which is why its homepage hover
   background snapped instead of fading -- this rule gave it no background transition.
   The homepage no longer uses the class at all, so the two definitions agree.
   .contact .email-plain is gone with the email address. */
a.navlink,
a.btn-ghost,
footer .top-link {
  transition: border-color var(--t-press) var(--ease-ui),
              color var(--t-press) var(--ease-ui);
}

/* ---------- cards: slower, softer lift ---------- */
.card,
.proof,
.chap,
.pager a,
.module-card {
  transition: transform var(--t-lift) var(--ease-out-quint),
              box-shadow var(--t-lift) var(--ease-out-quint),
              border-color var(--t-ui) var(--ease-ui);
}

/* ---------- scroll reveals: the expressive end of the scale ---------- */
html.js .sr {
  transition:
    opacity var(--t-enter) var(--ease-out-quint),
    transform var(--t-enter) var(--ease-out-quint);
}

/* hero entrance stagger, retuned to the same curve */
.hero .reveal {
  animation-duration: var(--t-enter);
  animation-timing-function: var(--ease-out-quint);
}

/* ---------- theme crossfade ---------- */
body,
header,
section.tint,
.card,
.proof,
.chap {
  transition-property: background-color, color, border-color;
  transition-duration: var(--t-theme);
  transition-timing-function: var(--ease-ui);
}
/* cards keep their lift transition on top of the theme crossfade */
.card, .proof, .chap, .pager a, .module-card {
  transition:
    transform var(--t-lift) var(--ease-out-quint),
    box-shadow var(--t-lift) var(--ease-out-quint),
    background-color var(--t-theme) var(--ease-ui),
    border-color var(--t-theme) var(--ease-ui),
    color var(--t-theme) var(--ease-ui);
}

/* ---------- hero: pixel dissolve edge ----------
   REMOVED, superseded by .hero::after in index.html.

   This used a `repeating-linear-gradient(90deg, ...)` at a 14px period as part of a
   mask on the art itself, which produced hard VERTICAL BARS across the bottom 90px
   rather than a dissolve -- it read as a barcode, not as pixels breaking up. It also
   faded the art to `transparent`, so the strip showed whatever was behind the hero
   instead of dissolving into the next section.

   The replacement is a scattered block pattern with a real density falloff, masking
   a solid var(--paper) fill, so the art genuinely disintegrates into the page
   background in both themes. Keeping both stacked two dissolves on top of each
   other. */

/* ---------- hero drift: REMOVED 2026-07-26 ----------

   The plate used to scale 1 -> 1.045 over 40s about `100% 100%` to give the art a
   slow sense of life. It is gone, and the reason is geometric rather than taste.

   Scaling about the BOTTOM edge holds the bottom still and pushes everything above
   it upward. The horizon is above the bottom, so the dithered haze climbed ~20px
   INTO the copy over the animation's life. index.html compensated by baking the
   settled 1.045 into --horizon, which is correct but spends 20px of the flat band
   permanently -- the copy paid the full cost of the drift at every moment, including
   the 40s it spent not yet drifted.

   Measured at 1512x830 the lede finished 10px BELOW the horizon, sitting on the
   dither. That is the defect Tate reported, and the drift was two thirds of it.

   Deleting it hands ~20px of flat band back to the copy at every viewport and makes
   the horizon a static, measurable line again. If motion is ever wanted here, do NOT
   scale about the bottom. Scale about `50% 0` so the art grows DOWNWARD away from the
   text, and re-run tools/hero-strip-check.py, because that direction pushes the
   laptop toward the 64px dissolve strip instead.

   A --hero-shift custom property also lived here to fold a mobile art-direction
   translate into the keyframes. It went earlier: phones no longer overlay copy on the
   art at all (see the max-width:640px block in index.html), so there is nothing to
   shift, and leaving it in slid the banner sideways and exposed a bare strip. */

/* ---------- respect the setting ---------- */
@media (prefers-reduced-motion: reduce) {
  /* .hero .scene img no longer needs an override here: the drift it disabled is gone. */
  a.btn, a.cta, button.copy, #theme-toggle,
  .card, .proof, .chap, .pager a, .module-card,
  a.navlink, a.btn-ghost, body, header, section.tint {
    transition: none !important;
  }
  .hero .reveal { animation: none; }
}
