/* =============================================================
   Queue — Motion layer
   Subtle, token-driven entrance + reveal + micro-interactions.

   • Activated by `html.mq-anim`, which a tiny inline script in the
     page <head> adds PRE-PAINT — but only when the visitor allows
     motion AND the page was not an auto-reload (keeps the polling
     customer pages and the 5s waiting-list refresh calm).
   • Fully additive & progressive: with no JS, a failed stylesheet,
     or prefers-reduced-motion, every element is visible and static.
   • Uses opacity / translateY / scale only — never translateX — so
     it behaves identically in RTL (Arabic) and LTR (English).
   ============================================================= */

:root{
  --mq-ease-out: var(--ease-out, cubic-bezier(.22,.61,.36,1));
  --mq-ease-spring: cubic-bezier(.34,1.40,.64,1);
  --mq-enter: 560ms;
  --mq-rise: 12px;
}

/* ----------------------------- Keyframes ----------------------------- */
@keyframes mqFadeUp   { from{ opacity:0; transform:translateY(var(--mq-rise)); } to{ opacity:1; transform:none; } }
@keyframes mqFadeDown { from{ opacity:0; transform:translateY(-8px); }           to{ opacity:1; transform:none; } }
@keyframes mqFade     { from{ opacity:0; }                                       to{ opacity:1; } }
@keyframes mqBubbleIn { 0%{ opacity:0; transform:scale(.72); } 70%{ transform:scale(1.04); } 100%{ opacity:1; transform:scale(1); } }
@keyframes mqDotPulse { 0%{ box-shadow:0 0 0 0 var(--mq-dot-ring); } 70%{ box-shadow:0 0 0 7px transparent; } 100%{ box-shadow:0 0 0 0 transparent; } }
@keyframes mqShake    { 10%,90%{ transform:translateX(-1px); } 20%,80%{ transform:translateX(2px); } 30%,50%,70%{ transform:translateX(-4px); } 40%,60%{ transform:translateX(4px); } }

/* ------------------------- System A: page entrance ------------------------- */
/* One animation per structural region — no per-template work, no conflicts. */
html.mq-anim nav.mq-nav,
html.mq-anim header.brand-bar   { animation: mqFadeDown .5s var(--mq-ease-out) both; }
html.mq-anim main.container     { animation: mqFadeUp var(--mq-enter) var(--mq-ease-out) both; }
html.mq-anim .mq-footer         { animation: mqFade .8s var(--mq-ease-out) .15s both; }
html.mq-anim main .alert        { animation: mqFadeUp .5s var(--mq-ease-out) both; }

/* ------------------------- System B: scroll reveal ------------------------- */
/* Opt-in via data-reveal. Hidden state is gated by .mq-anim so that without
   JS/CSS the content is simply visible. JS adds .mq-in when it enters view
   (or immediately for above-the-fold items), with a sibling stagger. */
html.mq-anim [data-reveal]{
  opacity:0;
  transform:translateY(18px);
  transition: opacity .6s var(--mq-ease-out), transform .6s var(--mq-ease-out);
  will-change: opacity, transform;
}
html.mq-anim [data-reveal].mq-in{ opacity:1; transform:none; }

/* --------------------------- Focal elements --------------------------- */
html.mq-anim .position-bubble{ animation: mqBubbleIn .62s var(--mq-ease-spring) both; }
html.mq-anim .display-count  { animation: mqFadeUp .6s var(--mq-ease-out) both; }

/* Ambient: the "open" status dot gently pulses to signal a live queue.
   Intentionally NOT gated by .mq-anim so it stays alive across auto-reloads;
   the reduced-motion block below switches it off. */
.badge-status-open::before{
  --mq-dot-ring: color-mix(in oklab, var(--status-open-fg) 45%, transparent);
  animation: mqDotPulse 2.6s var(--mq-ease-out) infinite;
}

/* --------------------------- Micro-interactions --------------------------- */
/* Hover/press affordances. These are not entrance effects, so they run on
   every visit; the reduced-motion block neutralises the transforms. */
.btn{
  transition: background var(--dur-base,180ms) var(--mq-ease-out),
              box-shadow  var(--dur-base,180ms) var(--mq-ease-out),
              transform   var(--dur-fast,120ms) var(--mq-ease-out);
}
.btn-lg:hover   { transform: translateY(-1px); }
.btn-lg:active  { transform: translateY(0); }

.chip{ transition: transform .16s var(--mq-ease-out), box-shadow .16s var(--mq-ease-out), border-color .16s var(--mq-ease-out); }
.chip:hover{ transform: translateY(-1px); box-shadow: var(--shadow-sm); }

.icon-btn{ transition: transform .16s var(--mq-ease-out), border-color .16s var(--mq-ease-out), color .16s var(--mq-ease-out), box-shadow .16s var(--mq-ease-out); }
.icon-btn:hover{ transform: translateY(-1px); }

.step-mini .n{ transition: transform .18s var(--mq-ease-spring); }
.step-mini:hover .n{ transform: scale(1.08); }

/* Inputs: smooth, branded focus with a feather-light lift.
   Works for both the owner palette (--clay-500) and the per-queue brand. */
.form-control,
.form-select{
  transition: border-color .18s var(--mq-ease-out),
              box-shadow  .18s var(--mq-ease-out),
              transform   .18s var(--mq-ease-out);
}
.form-control:focus,
.form-select:focus{ transform: translateY(-1px); }

/* Reusable utility: add the class to shake an invalid field. */
.mq-shake{ animation: mqShake .42s var(--mq-ease-out) both; }

/* Smooth in-page scrolling for reveal anchors. */
html{ scroll-behavior: smooth; }

/* --------------------- Unread-message attention cue --------------------- */
/* A waiting-list row with unread customer messages gets .mq-attn: it wiggles
   briefly every ~2.8s until the owner opens the thread. Functional alert, so
   like the status dot it is NOT gated by .mq-anim (it must survive the 5s
   list refresh); the reduced-motion block below silences it, leaving the
   static "!" bubble as the cue. Horizontal motion is fine here: the wiggle
   is symmetric, so RTL and LTR read identically. */
@keyframes mqWiggle{
  0%, 16%, 100% { transform: translateX(0) rotate(0); }
  2%  { transform: translateX(-4px) rotate(-.4deg); }
  5%  { transform: translateX(4px)  rotate(.4deg); }
  8%  { transform: translateX(-3px) rotate(-.3deg); }
  11% { transform: translateX(3px)  rotate(.3deg); }
  14% { transform: translateX(-1px); }
}
.mq-attn{
  animation: mqWiggle 2.8s ease-in-out .4s infinite;
  border-color: var(--status-closed-fg, #c0392b) !important;
}

/* The "!" rides on the chat button itself, pinned to its outer top corner.
   `inset-inline-end` (not `right`) keeps it on the correct side in both the
   Arabic RTL and English LTR shells. */
@keyframes mqAttnPop{ 0%{ transform:scale(.4); } 70%{ transform:scale(1.15); } 100%{ transform:scale(1); } }
.chat-btn{ position:relative; overflow:visible; transition:opacity .16s var(--mq-ease-out); }
/* No conversation yet: de-emphasised, but still clickable so the owner can
   start one. Full opacity on hover/focus so it never feels disabled. */
.chat-btn.chat-idle{ opacity:.4; }
.chat-btn.chat-idle:hover,
.chat-btn.chat-idle:focus-visible{ opacity:1; }
.attn-bubble{
  position:absolute; top:-7px; inset-inline-end:-7px; z-index:2;
  display:grid; place-items:center;
  width:18px; height:18px; border-radius:50%;
  background: var(--status-closed-fg, #c0392b); color:#fff;
  font-size:.72rem; font-weight:800; line-height:1;
  box-shadow: 0 0 0 2px var(--surface-card, #fff);
  animation: mqAttnPop .3s var(--mq-ease-spring) both;
  pointer-events:none;
}

/* --------------------- Reduced motion: stop everything --------------------- */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal]{ opacity:1 !important; transform:none !important; }
  html{ scroll-behavior:auto !important; }
}
