/*
 * Task-panel morph chrome (D55) — static file, deliberately OUTSIDE the
 * Tailwind pipeline: v4's --watch incremental rebuilds drop entry-authored
 * custom rules (one-shot builds keep them), which kept silently killing the
 * rules here. public/ assets are copied verbatim and served as-is.
 *
 * The task overlay's own backdrop rules (.pyr-task-backdrop, its fade-in and
 * its .is-leaving fade-out) are GONE: the overlay is a <dialog-panel> now
 * (views/TaskOverlay.pzl), and its scrim is the package's <dialog-backdrop>,
 * faded by the package's own stylesheet across the flight.
 */

/* Soften the skeleton → loaded swap inside the task panel — the bundle can
   land mid-morph, and a hard content pop reads as a hitch in the flight. */
.pyr-task-content-in {
  animation: pyr-content-in 200ms ease-out both;
}

@keyframes pyr-content-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/*
 * ---------------------------------------------------------------------------
 * COMMAND-PALETTE SCRIM (feat/search-morph)
 * ---------------------------------------------------------------------------
 *
 * Cory, 2026-09-18: "when the search panel opens up it should use the
 * dialog-backdrop with the bg blur and bg-noise effect."
 *
 * IT IS AN ELEMENT, NOT `::backdrop`, and that is forced by the morph. The
 * palette flies out of the top bar's search button with @magic-spells/morph-
 * engine, and the engine's <morph-blob> is an ordinary body child — the native
 * top layer paints ABOVE it (morph-engine README, "Current limitations"). So
 * the dialog spends the whole flight CLOSED, in normal flow, and is only
 * promoted with showModal() at the engine's `reveal` point. For roughly the
 * first three-quarters of an open there is no ::backdrop in existence to fade,
 * and at the promote/demote instant one would pop in and out at full strength.
 * A plain fixed element is one continuous surface across both phases, so the
 * scrim is unbroken while the blob crosses it. `[&::backdrop]:bg-transparent`
 * on the dialog keeps the UA's own scrim out of the way once it IS modal.
 *
 * WHY THE FILTER IS HAND-WRITTEN AND NOT `backdrop-blur-sm backdrop-saturate-115`.
 * Two reasons, both recorded on STYLE-COLORS already:
 *  - backdrop-filter has to be transitioned EXPLICITLY or Chrome applies the
 *    blur at full strength whatever the element's opacity, so an opacity-only
 *    fade leaves the app blurred and then pops (the same gotcha the old
 *    hand-rolled task backdrop hit before it became a <dialog-panel>).
 *  - a transition needs both ends written in the same property, and Tailwind's
 *    backdrop utilities compose one out of a stack of `--tw-backdrop-*`
 *    variables that a plain rule cannot interpolate against.
 * The values are READ FROM THE THEME rather than copied: `--blur-sm` is the
 * token `backdrop-blur-sm` itself compiles to, and `--saturate-scrim` is a
 * token added beside it in pieces.css because `backdrop-saturate-115` takes a
 * bare integer and leaves none. Tailwind v4 emits both on `:root`, so a plain
 * stylesheet outside the pipeline can still read them and cannot drift from the
 * overlays that do use the utilities. The scrim COLOUR and the noise tile stay Tailwind
 * (`bg-scrim noise`) — they interpolate fine through opacity.
 *
 * This file is outside the Tailwind pipeline on purpose; see the header.
 */
.pyr-palette-backdrop {
  opacity: 0;
  pointer-events: none;
  -webkit-backdrop-filter: blur(0) saturate(1);
  backdrop-filter: blur(0) saturate(1);
  transition:
    opacity 260ms ease-out,
    -webkit-backdrop-filter 260ms ease-out,
    backdrop-filter 260ms ease-out;
}

.pyr-palette-backdrop[data-visible] {
  opacity: 1;
  pointer-events: auto;
  -webkit-backdrop-filter: blur(var(--blur-sm)) saturate(var(--saturate-scrim));
  backdrop-filter: blur(var(--blur-sm)) saturate(var(--saturate-scrim));
}

/* No flight, so no long fade to cover it — the scrim still crossfades rather
   than snapping, because a hard cut to a blurred page is its own jolt.

   TWO SELECTORS FOR THE SAME RULE, because the motion axis is three-way: the OS
   flag unless the account preference says 'full', or an explicit 'reduced'.
   `data-motion` is written onto <html> by app/lib/appearance.js; the same split
   is `--motion-shift` in pieces.css and `reducedMotion()` in app/lib/motion.js.
   This file is outside the Tailwind pipeline (see the header), so it spells the
   rule out rather than using the `motion-reduce` variant. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion='full']) .pyr-palette-backdrop {
    transition:
      opacity 100ms linear,
      -webkit-backdrop-filter 100ms linear,
      backdrop-filter 100ms linear;
  }
}

:root[data-motion='reduced'] .pyr-palette-backdrop {
  transition:
    opacity 100ms linear,
    -webkit-backdrop-filter 100ms linear,
    backdrop-filter 100ms linear;
}
