/* ScanExpert backoffice — stratul de mișcare.
 *
 * O SINGURĂ FOAIE PENTRU TOATĂ CONSOLA, ultima din stivă. Mișcarea nu e a unei
 * pagini: dacă fiecare felie și-ar scrie tranzițiile ei, două liste desenate din
 * aceleași componente ar răspunde diferit la același gest — exact desincronizarea
 * pe care kitul o închide pentru culori și forme. Aici nu se declară nicio formă
 * și nicio culoare: numai `transition`, `animation` și transformările lor.
 *
 * Durate și curbe, cu numele lor:
 * - `quick` (120ms) — ce urmează cursorul: fundal, culoare, contur.
 * - `base` (180ms) — ce apare sau dispare: rânduri, meniuri, ferestre.
 * - `slow` (320ms) — ce se ridică o dată, la intrarea în pagină.
 * Curba e aceeași peste tot: pornire rapidă, oprire lină (`--ui-ease-out`); doar
 * ce sare (meniu, fereastră) primește `--ui-ease-pop`, care depășește puțin
 * ținta. Alpha și timpii n-au tokeni în `tokens.css` — scala de design nu are
 * mișcare — deci stau aici, adunate, exact cum stau umbrele în ui.css.
 *
 * FIECARE REGULĂ DE AICI TREBUIE SĂ FIE INERTĂ LA `prefers-reduced-motion`.
 * Blocul de la sfârșit oprește tot ce mișcă pentru cine a cerut asta din sistem;
 * o animație scrisă în altă foaie scapă de el și rămâne pornită pentru omul care
 * a cerut explicit să nu se miște nimic. De asta stratul e unul singur. */

:root {
  --ui-motion-quick: 120ms;
  --ui-motion-base: 180ms;
  --ui-motion-slow: 320ms;
  --ui-ease-out: cubic-bezier(0.2, 0, 0, 1);
  --ui-ease-pop: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---- ce urmează cursorul ------------------------------------------------------
 * Toate stările consolei sunt perechi fundal+culoare (vezi ui.css); tranziția le
 * ia pe amândouă, plus conturul câmpului și umbra pastilei de tab. `transform` e
 * în listă pentru apăsarea de mai jos.
 *
 * SE NUMESC PROPRIETĂȚILE, nu `all`: `all` prinde și `height`, `width`, `top` —
 * adică meniul care se așază `position: fixed` ar aluneca din colțul ecranului
 * spre rândul lui la fiecare deschidere. */
.btn-primary,
.btn-add,
.btn-secondary,
.btn-tertiary,
.btn-danger,
.danger-outline,
.detail-tab,
.tag,
.status-pill,
.row-menu-item,
.action-menu-item,
.row-actions-btn,
.icon-btn-plain,
.view-link,
.nav-item,
.table-search,
.filter-select,
.date-select,
input,
select,
textarea {
  transition:
    background-color var(--ui-motion-quick) var(--ui-ease-out),
    color var(--ui-motion-quick) var(--ui-ease-out),
    border-color var(--ui-motion-quick) var(--ui-ease-out),
    box-shadow var(--ui-motion-quick) var(--ui-ease-out),
    transform var(--ui-motion-quick) var(--ui-ease-out);
}

/* Apăsarea are adâncime: butonul coboară un pixel sub deget și se întoarce. Un
 * pixel, nu doi — pastilele stau în rânduri strânse, iar o săritură mai mare le
 * dezaliniază vizibil față de vecinele lor. */
.btn-primary:active:not(:disabled),
.btn-add:active:not(:disabled),
.btn-secondary:active:not(:disabled),
.btn-tertiary:active:not(:disabled),
.btn-danger:active:not(:disabled) {
  transform: translateY(1px);
}

/* Rândul de tabel: banda de hover se aprinde, nu apare. Regula stă pe `td`
 * fiindcă acolo se desenează fundalul (ui-tables.css). */
.data-table tbody td {
  transition: background-color var(--ui-motion-quick) var(--ui-ease-out);
}

/* ---- ce apare ------------------------------------------------------------------
 * Trei mișcări, nu mai multe: RIDICARE (conținut care intră), SĂRITURĂ (meniu sau
 * fereastră care se deschide dintr-un punct) și STINGERE (fundalul ferestrei). */

/* `backwards`, NICIODATĂ `both`, ORIUNDE ANIMAȚIA ATINGE `transform`.
 *
 * `both` ține efectul aplicat pentru totdeauna după ce animația s-a terminat, iar
 * un element cu o animație de `transform` ÎN EFECT e bloc conținător pentru orice
 * `position: fixed` dinăuntrul lui. Cu `both` pe `.page-card` și pe rândul de
 * tabel, meniul de rând — care e `fixed` și se așază din `getBoundingClientRect`
 * (se-row-menu.js) — se desena la coordonatele documentului, adică sub pagină:
 * butonul răspundea, meniul nu apărea nicăieri. Se vede NUMAI în browser; toate
 * testele treceau. `backwards` aplică starea de start doar ÎNAINTE de pornire,
 * deci după ce animația s-a consumat elementul redevine obișnuit. */

@keyframes ui-rise {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

@keyframes ui-pop {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
}

@keyframes ui-fade {
  from {
    opacity: 0;
  }
}

/* Pagina se ridică o dată, la intrare. Pe `.page-card`, nu pe `body`: bara din
 * stânga rămâne pe loc între pagini — ea nu se schimbă — iar mișcarea spune
 * exact ce s-a schimbat. */
.page-card {
  animation: ui-rise var(--ui-motion-slow) var(--ui-ease-out) backwards;
}

/* Rândurile intră în cascadă, ca lista să se citească de sus în jos în loc să
 * clipească întreagă. Întârzierea se oprește la al zecelea rând: pe o listă de o
 * sută, un rând care intră la 2,4 secunde e un rând care lipsește.
 *
 * Se repetă la fiecare schimb htmx, și e de dorit: o scriere care schimbă lista
 * se VEDE că a schimbat-o. */
.data-table tbody tr {
  animation: ui-rise var(--ui-motion-base) var(--ui-ease-out) backwards;
}

.data-table tbody tr:nth-child(1) {
  animation-delay: 0ms;
}
.data-table tbody tr:nth-child(2) {
  animation-delay: 20ms;
}
.data-table tbody tr:nth-child(3) {
  animation-delay: 40ms;
}
.data-table tbody tr:nth-child(4) {
  animation-delay: 60ms;
}
.data-table tbody tr:nth-child(5) {
  animation-delay: 80ms;
}
.data-table tbody tr:nth-child(6) {
  animation-delay: 100ms;
}
.data-table tbody tr:nth-child(7) {
  animation-delay: 120ms;
}
.data-table tbody tr:nth-child(8) {
  animation-delay: 140ms;
}
.data-table tbody tr:nth-child(9) {
  animation-delay: 160ms;
}
.data-table tbody tr:nth-child(n + 10) {
  animation-delay: 180ms;
}

/* Meniul de rând și panoul de sucursale sar din butonul lor. Originea e colțul
 * din dreapta sus fiindcă amândouă se așază sub un declanșator aflat la capătul
 * din dreapta al rândului. */
.row-menu:not(.hidden),
.action-menu:not(.hidden) {
  animation: ui-pop var(--ui-motion-base) var(--ui-ease-pop) backwards;
  transform-origin: top right;
}

.confirm-modal-overlay:not(.hidden),
.welcome-overlay:not(.hidden) {
  animation: ui-fade var(--ui-motion-base) var(--ui-ease-out) backwards;
}

.confirm-modal-overlay:not(.hidden) .confirm-modal-card,
.welcome-overlay:not(.hidden) .welcome-card {
  animation: ui-pop var(--ui-motion-base) var(--ui-ease-pop) backwards;
}

/* ---- cât ține scrierea ---------------------------------------------------------
 * Nu mai e a foii ăsteia: butonul apăsat poartă sigla scanată, iar regiunea care se
 * reîncarcă își face rândurile schelet — kitul comun (se-loader.js/.css), după 200 ms
 * și cel puțin 400 ms, pentru fiecare cerere htmx pornită de un om (hotărârea
 * proprietarului, 2026-10-06: o singură încărcare în toată familia). Pulsul de
 * opacitate de aici a fost ȘTERS — două semne pentru aceeași așteptare ar fi
 * dublura pe care familia o scoate. */

/* Fragmentul care pleacă se stinge; cel care vine se ridică. `htmx-swapping` și
 * `htmx-settling` sunt clasele lui htmx pe FRAGMENT, deci mișcarea e a bucății
 * schimbate, nu a paginii. Durata trebuie să fie ≤ `hx-swap`-ul implicit (0) —
 * htmx citește durata din CSS, deci se scrie aici și nicăieri altundeva. */
.htmx-swapping {
  opacity: 0;
  transition: opacity var(--ui-motion-quick) var(--ui-ease-out);
}

.htmx-settling {
  animation: ui-rise var(--ui-motion-base) var(--ui-ease-out) backwards;
}

/* ---- Setări → „Integrări" --------------------------------------------------------
 * Pagina cheilor (features/integrations): cardurile intră în cascadă, panoul unui tab
 * se ridică, un sertar se desface pe înălțimea lui (0fr → 1fr, deci exact cât conținutul),
 * comutatorul alunecă, iar un verdict pulsează o dată — verde când trece, o scuturare
 * scurtă când e refuzat. Clasele `in-flash-*` le pune și le scoate scriptul paginii. */
.in-grid > .in-card {
  animation: ui-rise var(--ui-motion-slow) var(--ui-ease-out) backwards;
}

.in-grid > .in-card:nth-child(2) {
  animation-delay: 60ms;
}

.in-grid > .in-card:nth-child(3) {
  animation-delay: 120ms;
}

.in-banner {
  animation: ui-pop var(--ui-motion-base) var(--ui-ease-pop) backwards;
}

.in-js .in-tab-panel:not([hidden]) {
  animation: ui-rise var(--ui-motion-base) var(--ui-ease-out) backwards;
}

.in-js .in-drawer {
  transition: grid-template-rows var(--ui-motion-base) var(--ui-ease-out);
}

.in-js .in-drawer > .in-drawer-inner {
  opacity: 0;
  transition: opacity var(--ui-motion-base) var(--ui-ease-out);
}

.in-js .in-drawer.is-open > .in-drawer-inner {
  opacity: 1;
}

.in-combo-pop:not([hidden]) {
  animation: ui-pop var(--ui-motion-base) var(--ui-ease-pop) backwards;
}

.in-toggle,
.in-icon-btn,
.in-disclosure,
.in-combo-option,
.in-key,
.in-step-num,
.in-voice-play {
  transition:
    background-color var(--ui-motion-quick) var(--ui-ease-out),
    color var(--ui-motion-quick) var(--ui-ease-out);
}

.in-toggle::after {
  transition: transform var(--ui-motion-base) var(--ui-ease-pop);
}

.in-disclosure .ph-caret-down,
.in-combo-trigger .ph-caret-down {
  transition: transform var(--ui-motion-base) var(--ui-ease-out);
}

.chk:not([hidden]) {
  animation: ui-fade var(--ui-motion-base) var(--ui-ease-out) backwards;
}

@keyframes in-pulse-ok {
  from {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--se-color-badge-green-600) 40%, transparent);
  }
  to {
    box-shadow: 0 0 0 8px transparent;
  }
}

@keyframes in-shake {
  20%,
  60% {
    transform: translateX(-3px);
  }
  40%,
  80% {
    transform: translateX(3px);
  }
}

/* Pe `#in-body`, ca pulsul să bată intrarea pastilei (`.chk`) când cad pe același nod. */
#in-body .in-flash-ok {
  animation: in-pulse-ok var(--ui-motion-slow) var(--ui-ease-out);
}

#in-body .in-flash-bad {
  animation: in-shake var(--ui-motion-slow) var(--ui-ease-out);
}

/* ---- Panou: linia punctată de sub titlul unui card (ui-panou.css) ---------------
 * Nota designerului (Figma 505:970): la hover pe titlu linia „se micșorează și se
 * mărește din nou", iar clicul deschide pagina cardului. Punctele curg spre dreapta
 * cât timp linia se strânge spre stânga și crește la loc — o singură trecere, fără
 * fill-mode: după animație linia e exact cea desenată. */
@keyframes pn-underline {
  0% {
    transform: scaleX(1);
    background-position: 0 0;
  }
  45% {
    transform: scaleX(0.35);
    background-position: 8px 0;
  }
  100% {
    transform: scaleX(1);
    background-position: 16px 0;
  }
}

a.pn-card-title:hover::after,
a.pn-card-title:focus-visible::after {
  animation: pn-underline 560ms var(--ui-ease-pop);
}

/* ---- Panou: „Personalizează" (ui-panou-actions.css) -----------------------------
 * The backdrop fades (the shared overlay rule above); the card rises 12px while it
 * grows from 96%, 200ms ease-out; under 640px it is a bottom sheet and slides up
 * from below the screen. `backwards` only (the rule at the top of this file). Same
 * weight as the shared card rule, declared after it, so this one wins. */
@keyframes pn-sheet-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.96);
  }
}

@keyframes pn-sheet-up {
  from {
    transform: translateY(100%);
  }
}

.confirm-modal-overlay:not(.hidden) .pn-prefs-card {
  animation: pn-sheet-in 200ms var(--ui-ease-out) backwards;
}

@media (max-width: 640px) {
  .confirm-modal-overlay:not(.hidden) .pn-prefs-card {
    animation: pn-sheet-up 240ms var(--ui-ease-out) backwards;
  }
}

/* ---- cine a cerut liniște -------------------------------------------------------
 * `reduce` nu înseamnă „mai încet": pentru cineva cu tulburări vestibulare o
 * mișcare mică e tot o mișcare. Se oprește tot, inclusiv cascada rândurilor, și
 * rămân stările — fundal, culoare, contur — care sunt informație, nu decor. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }

  .btn-primary:active:not(:disabled),
  .btn-add:active:not(:disabled),
  .btn-secondary:active:not(:disabled),
  .btn-tertiary:active:not(:disabled),
  .btn-danger:active:not(:disabled) {
    transform: none;
  }

  a.pn-card-title:hover::after,
  a.pn-card-title:focus-visible::after {
    animation: none;
  }
}
