/* ============================================================================
   VESTRA — MOTION & INTERACTION LAYER
   Tommy · 2026-08-27 · v1.179.0

   WHY THIS FILE EXISTS (Migs, 2026-08-27)
     "all of it are not modern... the transitions as well, clicking buttons as
      well, i want it clean... i need them all to sync specially the buyer side
      and the admin side, we need an absolute [consistency]."

   WHAT WAS ACTUALLY WRONG — MEASURED, NOT FELT
     The palette is not the problem: css/vr_variables.css is a measured system
     (33 contrast pairs, 0 failures). The problem is that NOTHING ANSWERS BACK.
     Counted across css/*.css before this file:
       · `:active` appears 41 times in the WHOLE app, and `.vr-admin-btn` — used
         256 times — had none of them. A quarter of the product's buttons went
         down under the cursor and moved by zero pixels.
       · `:focus-visible` appears in 5 files. Keyboard users had no ring on most
         controls.
     A button that does not move when pressed reads as "the app didn't hear me",
     and no amount of colour fixes that. That is the "not modern" feeling.

   WHY ONE FILE INSTEAD OF EDITING TWENTY
     Buyer and admin already share `.vr-portal-panel`, `.vr-btn` and the token
     layer, so they can be synced from one place. Loaded LAST on every page, this
     file is additive and reversible: delete one <link> and the app is exactly as
     it was. Twenty hand-edits across twenty files could not make that promise.

   WHY IT INHERITS INSTEAD OF ENUMERATING
     The base rules key off the ELEMENT (`button`, `a`, `[role="button"]`), not a
     list of the 25 `vr-*btn*` class names in use today. An enumerated list is
     wrong the moment somebody adds the 26th — it fails silently and the new
     button is the dead-feeling one. Opt OUT with `.vr-no-press` where a control
     must not move (nothing uses it yet; it exists so the escape hatch is not a
     future !important).

   NOTHING HERE CHANGES A COLOUR, A SIZE, OR A LAYOUT.
     No !important, no palette values, no spacing. It adds press, focus and
     entrance behaviour only — so it cannot silently overrule a deliberate design
     choice somebody made in a module stylesheet.
   ============================================================================ */

/* ── 1. PRESS: every button answers the finger ──────────────────────────────
   90ms (--vr-duration-instant) because press feedback must feel simultaneous
   with the click; anything slower reads as lag rather than response.
   `filter: brightness` rather than a background override, so it works on all
   five button variants — primary, ghost, approve, reject, danger — without this
   file needing to know any of their colours. */
/* IT MUST COMPOSE WITH `transform`, NOT REPLACE IT — caught by probing, not by
   reading. The first button I sampled on the live login page computed to
   `matrix(1,0,0,1,0,-13)`: a 26x26 icon control POSITIONED with
   transform: translateY(-13px). A blanket `transform` on :active overwrites that,
   so the button would have JUMPED 14px down on every press — a new defect
   shipped inside a polish fix, and invisible in any file I could have read.
   `translate` and `scale` are separate CSS properties (Transforms Level 2) that
   compose ON TOP of an element's existing `transform`, so a control that uses
   transform to sit where it sits keeps sitting there. */
button:not(:disabled):not(.vr-no-press):active,
[role="button"]:not([aria-disabled="true"]):not(.vr-no-press):active,
a.vr-btn:not(.vr-no-press):active,
label.vr-ad-optin:active {
  translate: 0 1px;
  scale: 0.988;
  filter: brightness(0.95);
}

button:not(.vr-no-press),
[role="button"]:not(.vr-no-press),
a.vr-btn:not(.vr-no-press) {
  transition:
    translate var(--vr-duration-instant) var(--vr-ease-smooth),
    scale     var(--vr-duration-instant) var(--vr-ease-smooth),
    filter    var(--vr-duration-instant) var(--vr-ease-smooth),
    box-shadow var(--vr-duration-fast)   var(--vr-ease-smooth),
    background-color var(--vr-duration-fast) var(--vr-ease-smooth),
    border-color     var(--vr-duration-fast) var(--vr-ease-smooth),
    color            var(--vr-duration-fast) var(--vr-ease-smooth);
}

/* A disabled control must look unavailable and must NOT move — a press response
   on a button that will not act is a lie told in motion. */
button:disabled,
[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.55;
}

/* ── 2. FOCUS: one ring, and it works on BOTH grounds ──────────────────────
   The app has two surfaces: LIGHT CREAM (#fcf7f0) and DEEP GREEN (#0a3b25) — the
   sidebar, the map shell, every dark panel. A green ring vanishes on the green
   ground, which is where the sidebar's own controls live.
   --vr-gold-line (#a88248) is the one brand token measured to clear 3:1 on BOTH:
   3.31:1 on cream, and gold on deep green is 7.31:1 (vr_variables.css).
   The outer white/dark halo means the ring survives even against a photo. */
:where(button, a, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--vr-gold-line, #a88248);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(10, 59, 37, 0.14);
}

/* :focus-visible only fires for keyboard/AT, so a mouse press never draws it. */

/* ── 3. CARDS: a liftable thing looks liftable ─────────────────────────────
   The reference (FourthWall / the real-estate landing board Migs sent) leans on
   large calm cards that respond quietly. 1px and one shadow step — enough to say
   "this is a surface you can pick up", not enough to bounce.
   Applied only to cards that ALREADY lead somewhere, so movement never promises
   an action that is not there. */
.vr-feed-card,
.vr-stat-card,
.vr-doc-card,
.vr-cta-card,
.vr-listing-card,
.vr-dev-card {
  transition:
    box-shadow var(--vr-duration-base) var(--vr-ease-smooth),
    translate  var(--vr-duration-base) var(--vr-ease-smooth);
}
/* `translate`, not `transform`, for the same reason as the press above: a card
   that positions itself with transform must keep its position. */
.vr-feed-card:hover,
.vr-stat-card:hover,
.vr-doc-card:hover,
.vr-listing-card:hover,
.vr-dev-card:hover {
  translate: 0 -2px;
  box-shadow: var(--vr-shadow-lg);
}

/* ── 4. PANELS: buyer and admin now enter the same way ─────────────────────
   Both sides already share `.vr-portal-panel`, and vr_portal.css already gives
   it a fade-and-rise. Admin loads that file, so admin ALREADY had it — the
   sync break was not the panel, it was everything inside it standing still.
   What is added here is the STAGGER: the panel's first rows arrive fractionally
   after the panel, which is what makes a switch feel authored rather than
   instant-swapped. Purely decorative, so it is the first thing reduced-motion
   drops. */
/* `backwards`, NEVER `both`. With `both` the final keyframe is RETAINED, so
   `to { transform: none }` would permanently clobber the transform of every
   panel child that positions itself with one — the same defect as the press
   above, except it would never wear off. `backwards` applies only the FROM state
   during the delay and leaves nothing behind when the animation ends. The
   keyframe also animates `translate`, so it composes rather than replaces. */
.vr-portal-panel.active > * {
  animation: vr-rise-in var(--vr-duration-base) var(--vr-ease-enter) backwards;
}
.vr-portal-panel.active > *:nth-child(1) { animation-delay: 0ms; }
.vr-portal-panel.active > *:nth-child(2) { animation-delay: 40ms; }
.vr-portal-panel.active > *:nth-child(3) { animation-delay: 80ms; }
.vr-portal-panel.active > *:nth-child(n+4) { animation-delay: 110ms; }

@keyframes vr-rise-in {
  from { opacity: 0; translate: 0 6px; }
  to   { opacity: 1; translate: 0 0; }
}

/* ── 5. INPUTS: the field you are typing in should be obvious ──────────────
   Colour-only focus is the weakest signal in the app; this adds the ring above
   plus a quiet border transition, without touching any size or padding. */
input, select, textarea {
  transition:
    border-color var(--vr-duration-fast) var(--vr-ease-smooth),
    box-shadow   var(--vr-duration-fast) var(--vr-ease-smooth),
    background-color var(--vr-duration-fast) var(--vr-ease-smooth);
}

/* ── 6. REDUCED MOTION — the whole file stands down, except the ring ───────
   Accessibility is never on the chopping block: the focus outline is the one
   thing here that is a CONTROL rather than a flourish, so it survives. */
/* ── 7. THE GLOBAL REDUCED-MOTION BACKSTOP ─────────────────────────────────
   Measured: `prefers-reduced-motion` appears in 3 of 22 stylesheets. ELEVEN
   declare @keyframes with no guard at all — including css/vr_portal.css (8
   keyframes, 9 animations, zero guards), which every dashboard loads, and
   css/vr_storefront.css, whose .vr-feed-card fades and translates on every card
   in the feed. A user who has asked their operating system to stop animations
   was still getting them on every panel and every card.
   Guarding eleven files one at a time is eleven chances to miss one and no
   protection for the twelfth. This is the backstop: it INHERITS to everything,
   including code not written yet. The named opt-outs below still apply on top.
   `1ms` rather than `0s` on purpose — a zero-length animation never fires its
   `animationend` event, and JS that waits for one would hang forever. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  button:not(:disabled):active,
  [role="button"]:active,
  a.vr-btn:active,
  label.vr-ad-optin:active {
    translate: none;
    scale: none;
  }
  .vr-feed-card:hover,
  .vr-stat-card:hover,
  .vr-doc-card:hover,
  .vr-listing-card:hover,
  .vr-dev-card:hover {
    translate: none;
  }
  .vr-portal-panel.active > *,
  .vr-portal-panel {
    animation: none !important;   /* the one !important: a motion OFF switch must win */
  }
  button, [role="button"], a.vr-btn, input, select, textarea,
  .vr-feed-card, .vr-stat-card, .vr-doc-card, .vr-cta-card,
  .vr-listing-card, .vr-dev-card {
    transition-duration: 1ms;
  }
}
