/* ============================================================================
   Augurea · motion.css — the "moving parts" foundation.
   Doctrine: animate ONLY transform/opacity; motion must communicate (hierarchy,
   feedback, state) not decorate; honor prefers-reduced-motion; skeletons not
   spinners; marquee at most once per page. Reveal behavior is driven by
   the legacy motion script (IntersectionObserver → .is-revealed). Only the HIDDEN start
   state depends on scripting: it is gated by (scripting:enabled), so with JavaScript off
   (or in a browser that cannot report the feature as enabled) every [data-reveal] block
   simply paints visible. The transition and the revealed end state stay unconditional.
   ============================================================================ */

:root{
  --ease-out:cubic-bezier(0.16,1,0.3,1);
  --ease-soft:cubic-bezier(0.32,0.72,0,1);
  --dur-fast:200ms; --dur-mid:400ms; --dur-slow:700ms;
  /* Scroll-entry duration — BRAND_BRIEF fade-up spec: 16px rise over 800ms on
     --ease-out, 90ms stagger (stagger is per-element via data-reveal-delay). */
  --dur-reveal:800ms;
}

/* ---------- scroll reveal ----------
   JS adds .is-revealed at ~30% visibility, then disconnects the observer.
   Default: fade + short rise. Communicates "new content entered view". */
@media (scripting:enabled){
  [data-reveal]{opacity:0;transform:translateY(16px)}
  .reveal-soft[data-reveal]{transform:translateY(32px)}
}
[data-reveal]{transition:opacity var(--dur-reveal) var(--ease-out),transform var(--dur-reveal) var(--ease-out);will-change:opacity,transform}
[data-reveal].is-revealed{opacity:1;transform:none}

/* Softer, longer entrance (more travel, slower settle). transform/opacity
   only — the brief bans filter animation, so no blur (was a prior non-compliant tell). */
.reveal-soft[data-reveal]{transition:opacity 900ms var(--ease-soft),transform 900ms var(--ease-soft)}
.reveal-soft[data-reveal].is-revealed{transform:none}

/* ---------- button micro-physics (transform + the diffuse lift shadow) ----------
   Hover lifts 1px + gains the ultra-diffuse shadow (affordance); active presses to
   .98 (the "seal press" — tactile feedback). The trailing arrow tile slides on hover
   (BRAND_BRIEF: "the CTA's arrow tile translates on hover"). */
.btn{transition:background var(--dur-fast) var(--ease-out),transform var(--dur-fast) var(--ease-out),box-shadow var(--dur-mid) var(--ease-out)}
.btn:hover{transform:translateY(-1px);box-shadow:var(--lift)}
.btn:active{transform:scale(.98)}
.btn-ghost{transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),box-shadow var(--dur-mid) var(--ease-out),transform var(--dur-fast) var(--ease-out)}
.btn .arrow{transition:transform var(--dur-fast) var(--ease-out)}
.btn:hover .arrow{transform:translateX(3px)}
.btn:disabled{cursor:not-allowed}
.btn:disabled:hover,.btn:disabled:active{transform:none;box-shadow:none}
.btn:disabled:not(.is-loading):not(.is-added):not(.is-soldout):not([aria-busy="true"]){opacity:.55}
.btn.is-loading,.btn[aria-busy="true"]{cursor:progress}

/* ---------- product-card pointer/keyboard/touch physics (transform/shadow only) ----------
   The whole card rises 4px so photo and caption travel together (no detachment);
   the photo tile carries the diffuse lift shadow. This is the ONE card-hover
   effect (restrained-motion pass: catalog.css's former extra image-scale zoom was
   removed so home + catalog cards share a single consistent hover language).
   Composes with the arrow slide (components.css). BRAND_BRIEF card lift.

   animacion-8 (R19 entrega 2): the card is the component that repeats most on
   the site (24 per catalog page, 28 on home) and until now only the MOUSE got
   the full gesture. Two of the four card affordances already had keyboard
   parity — the sheen sweep (catalog.css `.card:hover .ph::after,
   .card:focus-visible .ph::after`) and the second photo (transitions.css
   `.card:hover/.card:focus-visible .card-hover-img`) — while the lift and its
   shadow, which live here, did not; and no pointer-less/hover-less device had
   any pressed state at all, although `.btn:active` above has had one forever.
   Closing the parity invents nothing: the same two declarations gain
   `:focus-visible`, and `:active` echoes the button's seal-press. The two
   sheets that outrank this one had to be joined in the same pass (correccion):
   catalog.css re-spells the three states at `.catalog .grid .card` specificity
   — without that the 24-tile catalog grid kept the mouse-only gesture — and
   components.css's `.card:hover .arrow` gained its own twin, so the arrow tile
   no longer stays behind on Tab (which is why the reduced-motion line below
   names it in both spellings).

   `:active` presses (not `scale(.98)` like the button): a card is a large
   surface, so the button's 2% would read as a jolt across a 24-tile grid. It
   takes the movement brief's card vocabulary instead — a fifth of the hover
   travel plus a whisper of scale — and shortens the settle to --dur-fast so
   the tap answers inside the 0.5-0.8s the server takes to reply.

   `scroll-margin`: the ring is the house's global one (base.css :focus-visible,
   2px at 3px offset), and the lift raises the card another 4px, so a card
   tabbed into view would otherwise land with ~9px of ring under the 72px
   sticky header (`.hdr`). 88px is the same header-plus-air value `.launch`
   already uses (launch.css); 24px at the bottom matches `.archivo-section`
   and covers the 5px the ring hangs below the tile on a Shift+Tab landing. */
.card{transition:transform var(--dur-mid) var(--ease-out);scroll-margin-top:88px;scroll-margin-bottom:24px}
.card .ph{transition:box-shadow var(--dur-mid) var(--ease-out)}
.card:hover,.card:focus-visible{transform:translateY(-4px)}
.card:hover .ph,.card:focus-visible .ph{box-shadow:var(--lift)}
.card:active{transform:translateY(-1px) scale(.995);transition-duration:var(--dur-fast)}

/* ---------- skeleton shimmer (loading feedback, not a spinner) ---------- */
@keyframes sh{to{background-position:-200% 0}}

/* ---------- marquee utility (duplicated track; use AT MOST once per page) ----------
   Markup: <div class="marquee"><div class="marquee-track">…</div><div class="marquee-track" aria-hidden="true">…</div></div> */
.marquee{overflow:hidden;display:flex;width:100%;user-select:none}
.marquee-track{display:flex;flex:0 0 auto;min-width:100%;gap:48px;padding-right:48px;white-space:nowrap;animation:marquee 30s linear infinite}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-100%)}}

/* ---------- cross-document View Transitions: NAMES ONLY (progressive enhancement)
   The opt-in at-rule NO LONGER LIVES HERE (E1, 2026-09-16): motion.css is linked
   on every one of the 22 surfaces, so the opt-in was also being paid by cart,
   checkout, account, confirmation and legal, which have no pair to morph. It now
   lives in static/css/view-transition.css, hand-linked from the six templates
   that do have a live pair (home, catalog list, casas, casa detail, origin page,
   PDP). The origin page was added by E1-CORR on 2026-09-16: it renders _card.html
   like the list does, so dropping its opt-in had silently killed the card->PDP
   morph on that surface.
   What stays here are the NAMING utilities, which are inert on their own: a
   `view-transition-name` with no opt-in (and no document.startViewTransition()
   anywhere in the repo) animates nothing.
   .vt-product-image names an element so a shared-element morph can run across a
   product-photo→PDP navigation (set --vt-name per product to pair them).
   Paired surfaces: catalog cards (_card.html), the PDP cover (detail.html), the
   home documented-reference spotlight, the home Casa hero, and the home
   Próximamente strip — all via _product_img.html's vt/class_attr params. */
.vt-product-image{view-transition-name:var(--vt-name)}

/* ATLAS FOLD (casas): same contract, a different pairing — the house NAME on the
   casas-index tile shares --vt-name: house-<slug> with the casa-detail <h1>, so
   clicking a house morphs its name in place across the navigation (turning to
   that entry in a bound ledger). Progressive enhancement only: unsupported
   browsers just ignore view-transition-name and navigate plainly. */
.vt-house-name{view-transition-name:var(--vt-name)}

/* ---------- reduced motion: no travel, no lift, no shimmer, no marquee ----------
   Content is revealed instantly (never stuck hidden); every hover keeps its non-motion
   feedback (background/colour, and the underline still marks state) but drops all
   transform movement and the lift shadow. Opacity-only, per the brief. */
@media(prefers-reduced-motion:reduce){
  [data-reveal],[data-reveal].is-revealed,.reveal-soft[data-reveal]{
    opacity:1!important;transform:none!important;transition:none!important;
  }
  .btn:hover,.btn:active{transform:none;box-shadow:none}
  .btn:hover .arrow{transform:none}
  /* animacion-8: the three card states travel together here too — reduced
     motion drops the movement and the lift shadow, never the state itself
     (the sheen, the second photo and the focus ring all still happen). */
  .card:hover,.card:focus-visible,.card:active{transform:none}
  .card:hover .ph,.card:focus-visible .ph{box-shadow:none}
  .card:hover .arrow,.card:focus-visible .arrow{transform:none}
  .skeleton .ph{animation:none}
  .marquee-track{animation:none}
  *{scroll-behavior:auto!important}
  /* The pseudo-element kill for the navigation opt-in moved with the opt-in
     itself, to static/css/view-transition.css (E1, 2026-09-16): it is only
     meaningful on the surfaces that still opt in. */
}
