/* core/liquid-engine.css
 * Liquid UI — Apple-style fluid motion, compositor-only + tier-gated.
 *
 * Everything here animates only `scale` / `translate` (independent properties
 * that COMPOSE with existing `transform`, so we never clobber it), `opacity`,
 * `box-shadow`, and `filter` — all cheap for the GPU compositor. No layout.
 *
 * Gating: rules apply only when <html data-liquid-on> is present (set by
 * core/liquid-engine.js when the Liquid UI setting is on, animations aren't
 * disabled, and reduced-motion isn't requested). Tier lives in
 * <html data-liquid-tier="full|lite|off"> — `full` adds inertia scroll +
 * magnetic (driven by JS), everything below runs on both full and lite.
 */


/* ---- Hover / press spring (every clickable) ------------------------------ */
/* :where() keeps specificity at 0 so existing styles always win. */
html[data-liquid-on] :where(button, [role="button"], .btn, .u-btn, .u-x, .chip, [data-liquid]):not(:disabled):not([aria-disabled="true"]) {
  transition: scale .42s var(--lq-spring), translate .5s var(--lq-spring), box-shadow .4s var(--lq-glass);
}
html[data-liquid-on] :where(button, [role="button"], .btn, .u-btn, .chip, [data-liquid]):not(:disabled):not([aria-disabled="true"]):hover {
  scale: 1.025;
}
html[data-liquid-on] :where(button, [role="button"], .btn, .u-btn, .u-x, .chip, [data-liquid]):not(:disabled):not([aria-disabled="true"]):active {
  scale: .92;
  transition-duration: .12s, .12s, .2s;
}
/* Opt-in card lift. */
html[data-liquid-on] :where([data-liquid="card"], .liquid-card) {
  transition: scale .5s var(--lq-spring), translate .55s var(--lq-spring), box-shadow .45s var(--lq-glass);
}
html[data-liquid-on] :where([data-liquid="card"], .liquid-card):hover {
  scale: 1.022;
  translate: 0 -3px;
  box-shadow: 0 26px 60px -20px rgba(0, 0, 0, .45);
}

/* ---- Water-drop ripple (canvas-driven; see core/liquid-engine.js) -------- */
/* The layer is a `popover="manual"` so its canvas can render in the top layer,
 * above modals. That means the UA popover stylesheet applies (fit-content size,
 * `border: solid`, `padding: .25em`, opaque `background: Canvas`, `margin: auto`)
 * — left unreset it collapses to a tiny bordered opaque box (worse under size
 * containment). Every one of those must be neutralised here. */
#lq-ripple-layer {
  position: fixed;
  inset: 0;
  /* Fill the viewport and defeat the UA `width/height: fit-content`. */
  width: 100vw;
  height: 100vh;
  max-width: none;
  max-height: none;
  min-width: 0;
  min-height: 0;
  margin: 0;
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  pointer-events: none;
  z-index: 2147483000; /* above app chrome, below nothing critical */
  /* layout+paint containment (NOT size — that would revive fit-content → 0). */
  contain: layout paint;
  overflow: hidden;
}
/* Amoebic pop-in: the engine stamps every freshly-opened menu / popover /
 * tooltip / toast with .lq-pop and a transform-origin at the press point that
 * summoned it, so each pop-out independently blooms out of where you touched —
 * squirting out flat, snapping past its rest size, and wobbling like jelly
 * finding its surface tension. The attribute gate keeps it liquid-setting-only
 * AND out-specifies component entrance animations (e.g. bits-drop). */
/* Uses the INDEPENDENT `scale` property (not the `transform` shorthand) so the
 * jelly COMPOSES with — never clobbers — a pop-out's own positioning transform.
 * Many popovers/menus/drawers anchor themselves with `transform: translate(...)`;
 * animating the shorthand here (with `both` fill) used to pin them at
 * `transform: none` for their whole life, yanking them to the top-left corner. */
html[data-liquid-on] .lq-pop {
  animation: lq-pop-jelly .46s cubic-bezier(.3, .85, .4, 1) both;
}
@keyframes lq-pop-jelly {
  0%   { opacity: 0; scale: .5 .68; }
  32%  { opacity: 1; scale: 1.05 .93; }
  54%  { scale: .965 1.045; }
  74%  { scale: 1.015 .985; }
  88%  { scale: .995 1.005; }
  100% { opacity: 1; scale: 1; }
}
@media (prefers-reduced-motion: reduce) {
  html[data-liquid-on] .lq-pop { animation: none; }
}

/* Water-warp overlays: pooled manual popovers whose backdrop-filter bends
 * EVERYTHING painted beneath the press point (all layers at that spot, modals
 * included — top layer). Never interactive; geometry set inline per wave.
 * UA popover styles (inset:0, fit-content sizing, border, padding, Canvas
 * background, margin:auto) must all be neutralised, like the ripple layer. */
.lq-warp {
  position: fixed;
  inset: auto;
  margin: 0;
  border: 0;
  padding: 0;
  background: transparent;
  overflow: visible;
  max-width: none;
  max-height: none;
  min-width: 0;
  min-height: 0;
  pointer-events: none;
  z-index: 2147482900; /* fallback stacking if the popover API is unavailable */
}

#lq-ripple-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  padding: 0;
  background: transparent;
  pointer-events: none;
}

/* ---- Scroll reveal ------------------------------------------------------- */
/* JS only adds .lq-reveal to elements currently BELOW the fold, so nothing
 * visible is ever hidden; a failsafe reveals stragglers after ~1.5s. */
html[data-liquid-on] .lq-reveal {
  opacity: 0;
  translate: 0 30px;
  scale: .97;
  transition: opacity .55s var(--lq-settle), translate .75s var(--lq-spring), scale .75s var(--lq-spring);
  will-change: transform, opacity;
}
html[data-liquid-on] .lq-reveal.lq-revealed {
  opacity: 1;
  translate: 0 0;
  scale: 1;
}

/* Route settle is fully JS-driven (spring-sampled WAAPI in liquid-engine.js). */

/* ---- Modal / sheet fluidity ----------------------------------------------- */
/* The card's entrance/exit is fully JS-driven (spring container transform in
 * utilities.js) — no CSS motion on the card here, so nothing double-animates.
 * The backdrop blooms in ONLY after the morph lands: .is-morphing (set by the
 * morph for its whole flight) holds it completely clear, and removing the class
 * starts the backdrop animation from the top. */
html[data-liquid-on] .sheet-panel,
html[data-liquid-on] .drawer-panel {
  transition: scale .5s var(--lq-spring), translate .55s var(--lq-spring), opacity .35s var(--lq-glass);
}

/* Modal backdrop intensity is owned SOLELY by the base rule in core/bits.css
 * (u-modal-backdrop-in → blur(3px) / rgba(0,0,0,.22)). Liquid UI used to layer a
 * second, heavier backdrop animation on top (blur(9px) / .32), which stacked
 * into a visibly different, over-blurred backdrop the moment Liquid was on.
 * There is now ONE intensity in both modes; only the card's spring entrance
 * (utilities.js) changes under Liquid UI. Do not reintroduce a ::backdrop
 * override here. */

/* ---- Gooey (special moments only, via LiquidUI.goo / data-liquid-goo) ---- */
html[data-liquid-tier="full"] [data-liquid-goo] {
  filter: url(#lq-goo);
}
#lq-goo-defs { position: absolute; width: 0; height: 0; pointer-events: none; }

/* ---- Magnetic elements get a snappier translate transition when released - */
html[data-liquid-tier="full"] :where([data-liquid-magnetic], .btn.primary, .u-btn.primary) {
  transition: scale .42s var(--lq-spring), translate .45s var(--lq-spring), box-shadow .4s var(--lq-glass);
}

/* ---- Per-element opt-out ------------------------------------------------- */
html[data-liquid-on] :where([data-liquid="none"], [data-no-ripple]) {
  scale: 1 !important;
  translate: 0 !important;
}

/* ---- Absolute safety: never let liquidity fight accessibility ------------ */
@media (prefers-reduced-motion: reduce) {
  html[data-liquid-on] * { transition: none !important; animation: none !important; }
  html[data-liquid-on] .lq-reveal { opacity: 1 !important; translate: 0 !important; scale: 1 !important; }
}
