/* ==========================================================================
   micro-transitions.css, BFS project-owned micro-transition library
   Personal site (bensachwitz.com), 2026-09-30.

   Cookbook adoption, copy-and-own: recipes studied from the Amicro registry
   (magnetic-button, tilt-card, fade-up) and the transitions-dev pattern set
   (toast, success check, accordion, tooltip), re-implemented here as original
   project source. No third-party imports, no copied code.

   Motion identity (matches the site's arcade-snap spec):
   entrances ~250ms, exits ~150ms, 40ms stagger steps, transform/opacity only.
   Every recipe honors prefers-reduced-motion (one block at the bottom).
   Brand tokens read from the site's own --r1-* custom properties first, with
   safe fallbacks so this sheet also works standalone.
   ========================================================================== */

:root {
  --m-in: 250ms;            /* entrance clock */
  --m-out: 150ms;           /* exit clock */
  --m-stagger: 40ms;        /* per-item stagger step */
  --m-ease: cubic-bezier(0.22, 1, 0.36, 1);  /* settle ease, no overshoot */
  --m-gold: var(--r1-gold, #c9a227);
  --m-gold-hi: var(--r1-gold-hi, #e8c77d);
  --m-ink: var(--r1-ink, #0b0b0c);
  --m-bone: var(--r1-bone, #faf8f3);
  --m-dim: var(--r1-text-dim, #a9a49a);
  --m-serif: var(--r1-serif, Georgia, serif);
  --m-mono: var(--r1-mono, ui-monospace, monospace);
}

/* ---------- 1. Button press (global standard: every CTA presses) ----------
   Uses the independent `scale` property so it composes with any existing
   transform on the button instead of clobbering it. */
.r1-btn,
.btn-ink,
.btn-outline,
.btn-gold,
.book-float-btn,
.r1-bmtabs [role="tab"],
#r1-cookie button {
  transition: scale var(--m-out) var(--m-ease), filter var(--m-out) var(--m-ease);
}
.r1-btn:active,
.btn-ink:active,
.btn-outline:active,
.btn-gold:active,
.book-float-btn:active,
.r1-bmtabs [role="tab"]:active,
#r1-cookie button:active {
  scale: 0.96;
}
.r1-btn-gold:active,
.btn-gold:active {
  filter: brightness(1.08);
}

/* ---------- 2. Magnetic pull (Amicro magnetic-button, vanilla port) --------
   JS (micro.js) writes --mx/--my via rAF; pointer:fine only, gated in JS.
   `translate` composes with `scale` from the press recipe above. */
[data-magnetic] {
  translate: var(--mx, 0px) var(--my, 0px);
  will-change: translate;
}

/* ---------- 3. Tilt card with cursor glare (Amicro tilt-card, restrained) --
   <=7deg per axis, pointer:fine only (JS gated). Glare is a soft light wash
   that follows the cursor; it never hides card content. */
[data-tilt] {
  --rx: 0deg;
  --ry: 0deg;
  transform: perspective(1000px) rotateX(var(--rx)) rotateY(var(--ry));
  transition: transform var(--m-out) var(--m-ease);
  position: relative;
}
[data-tilt]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(
    circle at var(--gx, 50%) var(--gy, 50%),
    rgba(232, 199, 125, 0.10),
    transparent 62%
  );
  opacity: 0;
  transition: opacity var(--m-in) var(--m-ease);
}
[data-tilt]:hover::after,
[data-tilt]:focus-within::after {
  opacity: 1;
}

/* ---------- 4. Toast (adopts the existing #r1-toast host) -----------------
   Rise + fade + cross-blur in (slower, deliberate), fast out (snappy).
   Items stack bottom-center; click dismisses. aria-live set in markup/JS. */
#r1-toast,
#m-toast {
  position: fixed;
  left: 50%;
  bottom: max(1.25rem, env(safe-area-inset-bottom));
  translate: -50% 0;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  pointer-events: none;
  max-width: min(92vw, 26rem);
}
#r1-toast:empty {
  display: none;
}
.m-toast-item {
  pointer-events: auto;
  cursor: pointer;
  background: #141311;
  color: var(--m-bone);
  border: 1px solid rgba(201, 162, 39, 0.35);
  border-radius: 999px;
  padding: 0.6rem 1.1rem;
  font-family: var(--m-mono);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  opacity: 0;
  transform: translateY(16px) scale(0.97);
  filter: blur(2px);
  transition:
    opacity var(--m-out) var(--m-ease),
    transform var(--m-out) var(--m-ease),
    filter var(--m-out) var(--m-ease);
}
.m-toast-item.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  filter: blur(0);
  transition:
    opacity 350ms var(--m-ease),
    transform 350ms var(--m-ease),
    filter 350ms var(--m-ease);
}
/* Direct text writes into #r1-toast (legacy callers) still get the rise. */
#r1-toast.m-bump {
  animation: m-toast-bump 350ms var(--m-ease);
}
@keyframes m-toast-bump {
  from { opacity: 0; transform: translateY(16px); filter: blur(2px); }
  to   { opacity: 1; transform: translateY(0);     filter: blur(0); }
}

/* ---------- 5. Success check stroke-draw ----------------------------------
   Markup carries pathLength="100" so dash math is exact without measuring.
   Static icon when JS is off; micro.js adds .m-check-go on reveal. */
html.m-ready .m-check circle,
html.m-ready .m-check path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}
html.m-ready .m-check-go circle {
  transition: stroke-dashoffset 600ms var(--m-ease);
  stroke-dashoffset: 0;
}
html.m-ready .m-check-go path {
  transition: stroke-dashoffset 400ms var(--m-ease) 450ms;
  stroke-dashoffset: 0;
}

/* ---------- 6. FAQ open (native details, gentle content rise) -------------
   No JS, no markup change. The native marker stays as the site styles it;
   only the revealed content gets the soft rise. */
.r1-faq[open] > :not(summary) {
  animation: m-rise 220ms var(--m-ease);
}
@keyframes m-rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- 7. Tooltip (delayed fade + scale in, instant out) -------------
   Hook: data-tip="label" on any element. Delayed so it never flashes on
   a passing cursor; instant out so it never lingers. */
[data-tip] {
  position: relative;
}
[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  translate: -50% 4px;
  scale: 0.98;
  white-space: nowrap;
  background: #141311;
  color: var(--m-bone);
  border: 1px solid rgba(201, 162, 39, 0.35);
  border-radius: 6px;
  padding: 0.35rem 0.6rem;
  font-family: var(--m-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--m-out) ease-out,
    translate var(--m-out) ease-out,
    scale var(--m-out) ease-out;
  z-index: 1100;
}
[data-tip]:hover::after,
[data-tip]:focus-visible::after {
  opacity: 1;
  translate: -50% 0;
  scale: 1;
  transition-delay: 250ms;
}

/* ---------- 8. Brand focus (modal rule: no raw browser rings) -------------
   One gold ring everywhere keyboard focus can land. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--m-gold);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------- 9. Entrance utility (Amicro fade-up, vanilla port) ------------
   Opt-in: [data-m-rise] starts settled; JS adds .m-in on intersection.
   Pairs with the site's existing reveal system, never replaces it. */
[data-m-rise] {
  opacity: 0;
  transform: translateY(14px);
}
[data-m-rise].m-in {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--m-in) var(--m-ease), transform var(--m-in) var(--m-ease);
}

/* ---------- 9b. No-JS failsafe: [data-m-rise] is JS-driven (micro.js adds
   .m-ready to <html> at start, then .m-in per element on intersection).
   If micro.js never runs, elements must stay visible. Never remove. ------- */
html:not(.m-ready) [data-m-rise] {
  opacity: 1;
  transform: none;
}

/* ---------- 10. Reduced motion: everything off, final states kept --------
   Magnetic/tilt never engage (JS gates too); entrances render settled. */
@media (prefers-reduced-motion: reduce) {
  [data-magnetic] { translate: none; }
  [data-tilt] { transform: none; }
  [data-tilt]::after { display: none; }
  [data-m-rise] { opacity: 1; transform: none; }
  .m-toast-item,
  .m-toast-item.is-open,
  [data-tip]::after {
    transition: none;
  }
  #r1-toast.m-bump,
  .r1-faq[open] > :not(summary) {
    animation: none;
  }
  html.m-ready .m-check circle,
  html.m-ready .m-check path {
    stroke-dashoffset: 0;
    transition: none;
  }
}
