/* =============================================================================================
   cards-fx.css - visual-only card interactions for the retail console (v1.0.0, 2026-09-28 IST)
   Ported from the workplace console's .hs-row .hs-panel (ui-v3.css + cards3d.js), adapted to the
   retail tokens (--vx-*). Companion: fx/cards-fx.js. Spec: CARDS_FX_SPEC.md.

   Contract (nothing moves):
   - No rule here changes display, grid, gap, padding, margin, width, height, font or text.
   - position:relative + isolation:isolate on .glance>.gl and .zcard only: neither has an
     absolutely positioned child that depends on an outer ancestor (.gauge and .phw are their own
     containing blocks). Decorative children (.fx-deco) are absolute, aria-hidden, pointer-events
     none, z-index:-1 (painted above the card background, below the content).
   - Motion only on transform / opacity / box-shadow / border-color / background / custom props.
     The one exception the spec asks for: .segbar inner spans' width (inside a fixed-size,
     overflow:hidden bar, so the bar itself never changes size).
   - All motion sits in @media (prefers-reduced-motion:no-preference). Hover colour/shadow sits
     outside it, so reduced motion keeps a static but responsive page.
   - html.fx-off switches every transform/animation/transition in this file off (layout diff).
   Rollback: delete fx/cards-fx.css + fx/cards-fx.js and their two includes in index.html.
   ============================================================================================= */

:root{
  --fx-ease:cubic-bezier(.16,1,.3,1);
  --fx-shade:color-mix(in srgb,var(--vx-ink) 22%,transparent);
  --fx-glaze:rgba(255,255,255,.12);
  --fx-rim:rgba(255,255,255,.14);
}
[data-theme="night"],:root[data-theme="dark"]{
  --fx-shade:color-mix(in srgb,var(--vx-bg) 88%,transparent);
  --fx-glaze:rgba(255,255,255,.07);
  --fx-rim:rgba(255,255,255,.06);
}

/* ---------- containers for the decorative layer (no layout effect) ---------- */
.glance>.gl,.zcard{position:relative;isolation:isolate}
.fx-deco{position:absolute;inset:0;border-radius:inherit;overflow:hidden;pointer-events:none;z-index:-1}
.fx-deco>span{position:absolute;pointer-events:none}

/* ---------- tone (set by JS as data-fx-tone from the tile's own text) ---------- */
.glance>.gl{--fx-tone:var(--vx-line-strong)}
.glance>.gl[data-fx-tone="ok"]{--fx-tone:var(--vx-ok)}
.glance>.gl[data-fx-tone="live"]{--fx-tone:var(--vx-info)}
.glance>.gl[data-fx-tone="accent"]{--fx-tone:var(--vx-accent)}
.glance>.gl[data-fx-tone="warn"]{--fx-tone:var(--vx-med)}
.glance>.gl[data-fx-tone="crit"]{--fx-tone:var(--vx-crit)}

/* glaze: cursor-following specular sheen */
.fx-glaze{inset:0;border-radius:inherit;
  background:radial-gradient(circle 220px at var(--fx-mx,50%) var(--fx-my,20%),var(--fx-glaze),transparent 75%);
  opacity:.7}
/* status glow: top-right wash, max 140px, clipped by .fx-deco */
.fx-glow{top:0;right:0;width:min(140px,100%);height:min(140px,100%);
  background:radial-gradient(circle at 100% 0%,color-mix(in srgb,var(--fx-tone) 22%,transparent),transparent 70%);
  opacity:.65}
.glance>.gl:not([data-fx-tone]) .fx-glow,.glance>.gl[data-fx-tone="none"] .fx-glow{opacity:0}
/* status beacon: 8px dot in the top-right corner */
.fx-beacon{top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--fx-tone);
  box-shadow:0 0 6px color-mix(in srgb,var(--fx-tone) 70%,transparent)}
.glance>.gl:not([data-fx-tone]) .fx-beacon,.glance>.gl[data-fx-tone="none"] .fx-beacon{opacity:0}
.fx-beacon::after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--fx-tone);opacity:0}

/* ---------- KPI tiles: hover / press / focus (colour + shadow, works with reduced motion) ---------- */
.glance>.gl.click{transition:transform .35s var(--fx-ease),box-shadow .35s var(--fx-ease),border-color .35s var(--fx-ease)}
.glance>.gl.click:hover{
  box-shadow:0 4px 8px -2px var(--fx-shade),0 18px 36px -10px var(--fx-shade),inset 0 1px 0 var(--fx-rim)}
.glance>.gl.click:not(.sel):hover{border-color:color-mix(in srgb,var(--vx-accent) 24%,var(--vx-line))}
.glance>.gl.click.sel:hover{
  box-shadow:0 0 0 1px var(--vx-accent),0 4px 8px -2px var(--fx-shade),0 18px 36px -10px var(--fx-shade)}
.glance>.gl.click:hover .fx-glaze{opacity:1}
.glance>.gl.click:hover .fx-glow{opacity:.9}
.glance>.gl.click:focus-visible{outline:2px solid var(--vx-accent);outline-offset:3px;
  box-shadow:0 0 0 4px color-mix(in srgb,var(--vx-accent) 18%,transparent),var(--vx-shadow-h)}
.glance>.gl .v{font-variant-numeric:tabular-nums}

/* ---------- Store Pulse zone cards (lighter: no tilt) ---------- */
.zcard:hover{box-shadow:0 2px 6px -2px var(--fx-shade),0 12px 26px -10px var(--fx-shade),inset 0 1px 0 var(--fx-rim)}
.zcard:hover .fx-glaze{opacity:1}
.zcard:focus-visible{outline:2px solid var(--vx-accent);outline-offset:3px}

/* ---------- Quiet-now chips: hover tint (existing) + press ---------- */
#ovQuiet .chip{transition:border-color .12s,background .12s,transform .08s ease}

/* ---------- large panels: hover border tint + shadow step-up, never a transform ---------- */
.card.c4,.card.c6,.card.c8,.card.c12{transition:border-color .2s var(--fx-ease),box-shadow .2s var(--fx-ease)}
.card.c4:hover,.card.c6:hover,.card.c8:hover,.card.c12:hover{
  border-color:color-mix(in srgb,var(--vx-accent) 24%,var(--vx-line));box-shadow:var(--vx-shadow-h)}

/* =========================== motion (only when the user allows it) =========================== */
@media (prefers-reduced-motion:no-preference){
  .fx-glaze,.fx-glow{transition:opacity .3s ease}

  /* entrance: once per grid per page load (JS adds .fx-enter from a module flag, never on re-render) */
  .glance>.gl.fx-enter{animation:fx-rise .75s var(--fx-ease) backwards}
  .glance>.gl.fx-enter:nth-child(1){animation-delay:.04s}
  .glance>.gl.fx-enter:nth-child(2){animation-delay:.10s}
  .glance>.gl.fx-enter:nth-child(3){animation-delay:.16s}
  .glance>.gl.fx-enter:nth-child(4){animation-delay:.22s}
  .glance>.gl.fx-enter:nth-child(n+5){animation-delay:.28s}
  .glance>.gl.fx-enter .segbar>span{animation:fx-seg .9s var(--fx-ease) .2s backwards}
  /* later segbar changes: JS rewinds the span to its old width, this transition carries it */
  .glance>.gl .segbar>span{transition:width .6s var(--fx-ease)}

  /* status beacon pulse: ok / live only; compositor-only (transform + opacity) */
  .glance>.gl[data-fx-tone="ok"] .fx-beacon::after,
  .glance>.gl[data-fx-tone="live"] .fx-beacon::after{animation:fx-beacon 2.4s ease-out infinite}

  /* zone cards */
  .zcard.fx-zin{animation:fx-zin .45s var(--fx-ease) backwards}
  .zcard.fx-ping{animation:fx-ping .6s ease-out}
  #ovQuiet .chip:active{transform:scale(.96)}
}
/* tilt + press: only for a fine hover pointer (the JS writes --fx-rx/ry/mx/my/lift) */
@media (prefers-reduced-motion:no-preference) and (hover:hover) and (pointer:fine){
  .glance>.gl.click:hover{
    --fx-lift:-4px;will-change:transform;
    transform:perspective(1000px) translateY(var(--fx-lift)) rotateX(var(--fx-rx,0deg)) rotateY(var(--fx-ry,0deg))}
  .glance>.gl.click:active{
    transform:perspective(1000px) translateY(1px) scale(.985);
    transition:transform .08s ease,box-shadow .08s ease}
}

@keyframes fx-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes fx-seg{from{width:0}}
@keyframes fx-beacon{0%{transform:scale(1);opacity:.55}80%,100%{transform:scale(2.6);opacity:0}}
@keyframes fx-zin{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}
@keyframes fx-ping{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--vx-accent) 45%,transparent),var(--vx-shadow)}
  100%{box-shadow:0 0 0 9px color-mix(in srgb,var(--vx-accent) 0%,transparent),var(--vx-shadow)}}

/* ============== fx-off: freeze everything for the layout diff (and as a kill switch) ============== */
html.fx-off .glance>.gl,html.fx-off .glance>.gl:hover,html.fx-off .glance>.gl:active,
html.fx-off .zcard,html.fx-off .zcard:hover,html.fx-off #ovQuiet .chip,
html.fx-off .card.c4,html.fx-off .card.c6,html.fx-off .card.c8,html.fx-off .card.c12,
html.fx-off .glance>.gl .segbar>span,html.fx-off .fx-deco,html.fx-off .fx-deco *,html.fx-off .fx-deco *::after{
  transform:none!important;animation:none!important;transition:none!important;will-change:auto!important}

/* Reduced motion: the page must be static. The console's own hover lift (.gl.click:hover
   translateY(-1px), index.html) is neutralised here too; colour and shadow hover stay. */
@media (prefers-reduced-motion: reduce) {
  .glance > .gl.click:hover, .zcard:hover { transform: none !important; }
}
