/* =====================================================================
   ZENTRO DESIGN SYSTEM — Apple-inspired UI primitives
   ---------------------------------------------------------------------
   Drop-in stylesheet. Framework-agnostic (works with plain HTML, React,
   Vue, Next.js, etc.). Uses only CSS custom properties + utility classes.
   No Tailwind required — but 100% compatible with it.
   ===================================================================== */

/* ---------- 1. DESIGN TOKENS (customize here) ---------- */
:root {
  /* Palette */
  --zx-ink:       #0B0B0F;
  --zx-muted:     #6E6E73;
  --zx-stroke:    #E8E8ED;
  --zx-paper:     #FBFBFD;
  --zx-cloud:     #F5F5F7;
  --zx-surface:   #FFFFFF;
  --zx-brand:     #2563EB;
  --zx-brand-ink: #ffffff;

  /* Radius scale */
  --zx-radius-sm: 10px;
  --zx-radius-md: 14px;
  --zx-radius-lg: 18px;
  --zx-radius-xl: 22px;   /* signature card radius */
  --zx-radius-2xl: 28px;

  /* Borders */
  --zx-border-hairline: 1px solid rgba(0, 0, 0, 0.05);
  --zx-border-hover:    1px solid rgba(0, 0, 0, 0.08);

  /* Shadows — layered for depth (Apple product-tile feel) */
  --zx-shadow-rest:
    0 1px 2px rgba(16, 24, 40, 0.04),
    0 8px 24px rgba(16, 24, 40, 0.06);
  --zx-shadow-hover:
    0 2px 4px rgba(16, 24, 40, 0.05),
    0 20px 40px rgba(16, 24, 40, 0.10);
  --zx-shadow-brand:
    0 6px 20px rgba(37, 99, 235, 0.25);

  /* Motion */
  --zx-ease:       cubic-bezier(0.22, 1, 0.36, 1);
  --zx-dur-fast:   .3s;
  --zx-dur-base:   .6s;
  --zx-dur-slow:   .9s;

  /* Typography (optional — only used if you apply .zx-type-* classes) */
  --zx-font-sans: "Inter Tight", ui-sans-serif, system-ui, -apple-system, "SF Pro Text", sans-serif;
}

/* ---------- 1b. THEME COLOR VARIABLES (Tailwind palette mapping) ----------
   Palette neutre Tailwind (gray, slate, zinc, neutral, stone) mappate a CSS variables
   che cambiano valore quando [data-theme="dark"] e' attivo. Combinato con la
   configurazione tailwind.config.js (themeAwareScale), tutte le classi tipo
   `text-gray-700`, `bg-slate-100`, `border-zinc-200` ecc. cambiano automaticamente
   colore in dark mode senza modifiche al JSX.

   Le variabili memorizzano i valori RGB come triplette space-separated (formato
   richiesto dalla sintassi `rgb(var(--c-X) / <alpha-value>)` di Tailwind).
   In dark mode la scala e' invertita: 50 ↔ 900, 100 ↔ 800, ecc., cosi' tutti
   gli sfondi chiari diventano scuri e tutti i testi scuri diventano chiari. */

:root {
  /* Gray (Tailwind default) */
  --c-gray-50:  249 250 251;
  --c-gray-100: 243 244 246;
  --c-gray-200: 229 231 235;
  --c-gray-300: 209 213 219;
  --c-gray-400: 156 163 175;
  --c-gray-500: 107 114 128;
  --c-gray-600:  75  85  99;
  --c-gray-700:  55  65  81;
  --c-gray-800:  31  41  55;
  --c-gray-900:  17  24  39;
  --c-gray-950:   3   7  18;

  /* Slate (Tailwind default) */
  --c-slate-50:  248 250 252;
  --c-slate-100: 241 245 249;
  --c-slate-200: 226 232 240;
  --c-slate-300: 203 213 225;
  --c-slate-400: 148 163 184;
  --c-slate-500: 100 116 139;
  --c-slate-600:  71  85 105;
  --c-slate-700:  51  65  85;
  --c-slate-800:  30  41  59;
  --c-slate-900:  15  23  42;
  --c-slate-950:   2   6  23;

  /* Zinc (Tailwind default) */
  --c-zinc-50:  250 250 250;
  --c-zinc-100: 244 244 245;
  --c-zinc-200: 228 228 231;
  --c-zinc-300: 212 212 216;
  --c-zinc-400: 161 161 170;
  --c-zinc-500: 113 113 122;
  --c-zinc-600:  82  82  91;
  --c-zinc-700:  63  63  70;
  --c-zinc-800:  39  39  42;
  --c-zinc-900:  24  24  27;
  --c-zinc-950:   9   9  11;

  /* Neutral (Tailwind default) */
  --c-neutral-50:  250 250 250;
  --c-neutral-100: 245 245 245;
  --c-neutral-200: 229 229 229;
  --c-neutral-300: 212 212 212;
  --c-neutral-400: 163 163 163;
  --c-neutral-500: 115 115 115;
  --c-neutral-600:  82  82  82;
  --c-neutral-700:  64  64  64;
  --c-neutral-800:  38  38  38;
  --c-neutral-900:  23  23  23;
  --c-neutral-950:  10  10  10;

  /* Stone (Tailwind default) */
  --c-stone-50:  250 250 249;
  --c-stone-100: 245 245 244;
  --c-stone-200: 231 229 228;
  --c-stone-300: 214 211 209;
  --c-stone-400: 168 162 158;
  --c-stone-500: 120 113 108;
  --c-stone-600:  87  83  78;
  --c-stone-700:  68  64  60;
  --c-stone-800:  41  37  36;
  --c-stone-900:  28  25  23;
  --c-stone-950:  12  10  9;
}

/* Dark theme override — add data-theme="dark" to <html> to activate */
[data-theme="dark"] {
  --zx-ink:     #F5F5F7;
  --zx-muted:   #A1A1A6;
  --zx-stroke:  #2C2C2E;
  --zx-paper:   #0B0B0F;
  --zx-cloud:   #1C1C1E;
  --zx-surface: #161618;
  --zx-border-hairline: 1px solid rgba(255, 255, 255, 0.08);
  --zx-border-hover:    1px solid rgba(255, 255, 255, 0.14);
  --zx-shadow-rest:
    0 1px 2px rgba(0,0,0,0.4),
    0 8px 24px rgba(0,0,0,0.35);
  --zx-shadow-hover:
    0 2px 4px rgba(0,0,0,0.5),
    0 20px 40px rgba(0,0,0,0.5);

  /* Palette neutre invertite: 50 ↔ 900, 100 ↔ 800, ecc.
     Cosi' tutti gli sfondi chiari diventano scuri e i testi scuri diventano chiari. */
  --c-gray-50:    17  24  39;
  --c-gray-100:   31  41  55;
  --c-gray-200:   55  65  81;
  --c-gray-300:   75  85  99;
  --c-gray-400:  107 114 128;
  --c-gray-500:  156 163 175;
  --c-gray-600:  209 213 219;
  --c-gray-700:  229 231 235;
  --c-gray-800:  243 244 246;
  --c-gray-900:  249 250 251;
  --c-gray-950:  253 254 255;

  --c-slate-50:    15  23  42;
  --c-slate-100:   30  41  59;
  --c-slate-200:   51  65  85;
  --c-slate-300:   71  85 105;
  --c-slate-400:  100 116 139;
  --c-slate-500:  148 163 184;
  --c-slate-600:  203 213 225;
  --c-slate-700:  226 232 240;
  --c-slate-800:  241 245 249;
  --c-slate-900:  248 250 252;
  --c-slate-950:  253 254 255;

  --c-zinc-50:    24  24  27;
  --c-zinc-100:   39  39  42;
  --c-zinc-200:   63  63  70;
  --c-zinc-300:   82  82  91;
  --c-zinc-400:  113 113 122;
  --c-zinc-500:  161 161 170;
  --c-zinc-600:  212 212 216;
  --c-zinc-700:  228 228 231;
  --c-zinc-800:  244 244 245;
  --c-zinc-900:  250 250 250;
  --c-zinc-950:  253 253 253;

  --c-neutral-50:    23  23  23;
  --c-neutral-100:   38  38  38;
  --c-neutral-200:   64  64  64;
  --c-neutral-300:   82  82  82;
  --c-neutral-400:  115 115 115;
  --c-neutral-500:  163 163 163;
  --c-neutral-600:  212 212 212;
  --c-neutral-700:  229 229 229;
  --c-neutral-800:  245 245 245;
  --c-neutral-900:  250 250 250;
  --c-neutral-950:  253 253 253;

  --c-stone-50:    28  25  23;
  --c-stone-100:   41  37  36;
  --c-stone-200:   68  64  60;
  --c-stone-300:   87  83  78;
  --c-stone-400:  120 113 108;
  --c-stone-500:  168 162 158;
  --c-stone-600:  214 211 209;
  --c-stone-700:  231 229 228;
  --c-stone-800:  245 245 244;
  --c-stone-900:  250 250 249;
  --c-stone-950:  253 253 252;
}

/* ---------- 2. CARD ---------- */
.zx-card {
  background: var(--zx-surface);
  border: var(--zx-border-hairline);
  border-radius: var(--zx-radius-xl);
  box-shadow: var(--zx-shadow-rest);
  transition:
    transform var(--zx-dur-base) var(--zx-ease),
    box-shadow var(--zx-dur-base) var(--zx-ease),
    border-color var(--zx-dur-fast) ease;
  will-change: transform;
  position: relative;
}
.zx-card:not(.zx-card-static):hover {
  transform: translateY(-4px);
  box-shadow: var(--zx-shadow-hover);
  border: var(--zx-border-hover);
}

/* Modificatore: card statica senza lift/shadow/border-hover.
   Usare per wrapper di tabelle e calendari dove l'hover deve apparire SOLO
   sui singoli item (riga, day-cell), non sull'intera card. */
.zx-card.zx-card-static {
  will-change: auto;
}

/* Optional subtle noise overlay for premium feel */
.zx-card.zx-noise { overflow: hidden; }
.zx-card.zx-noise::before {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.03 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  mix-blend-mode: multiply;
}

/* ---------- 3. BUTTONS ---------- */
/* Shared base */
.zx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: 0 1rem;
  height: 44px;
  border-radius: var(--zx-radius-lg);
  font-family: var(--zx-font-sans);
  font-weight: 500;
  font-size: .95rem;
  line-height: 1;
  letter-spacing: -0.005em;
  cursor: pointer;
  border: 1px solid transparent;
  transition:
    transform var(--zx-dur-fast) var(--zx-ease),
    box-shadow var(--zx-dur-fast) var(--zx-ease),
    background-color var(--zx-dur-fast) ease,
    border-color var(--zx-dur-fast) ease,
    color var(--zx-dur-fast) ease;
  user-select: none;
  text-decoration: none;
  white-space: nowrap;
}
.zx-btn:active { transform: translateY(0) scale(0.98); }
.zx-btn:focus-visible {
  outline: 2px solid var(--zx-brand);
  outline-offset: 2px;
}

/* Disabled — neutralizza lift/shadow su hover (mantiene il bg originale del bottone:
   il primary disabled resta blu, il secondary resta bianco). Niente background: inherit
   altrimenti il primary disabled eredita il bg del parent e testo bianco diventa invisibile. */
.zx-btn:disabled,
.zx-btn[aria-disabled="true"] {
  cursor: not-allowed;
}
.zx-btn:disabled:hover,
.zx-btn[aria-disabled="true"]:hover,
.zx-btn:disabled:active,
.zx-btn[aria-disabled="true"]:active {
  transform: none;
  box-shadow: none;
}

/* Primary — filled, brand color, lift on hover */
/* Primary — fill scuro (ink) come il bottone "Nuova nota", testo chiaro (paper).
   In dark mode i token --zx-ink/--zx-paper si invertono automaticamente,
   mantenendo il contrasto. Hover con ombra neutra, non piu' il glow brand. */
.zx-btn-primary {
  background: var(--zx-ink);
  color: var(--zx-paper);
}
.zx-btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: var(--zx-shadow-hover);
}

/* Secondary — white surface, hairline border, icon-button style */
.zx-btn-secondary {
  background: var(--zx-surface);
  color: var(--zx-ink);
  border-color: var(--zx-stroke);
}
.zx-btn-secondary:hover {
  transform: translateY(-2px);
  box-shadow: var(--zx-shadow-rest);
  border-color: var(--zx-border-hover);
}

/* Ghost — flat, for nav links or low-emphasis actions */
.zx-btn-ghost {
  background: transparent;
  color: var(--zx-ink);
}
.zx-btn-ghost:hover { background: var(--zx-cloud); }

/* Icon-only — square */
.zx-btn-icon {
  width: 44px;
  height: 44px;
  padding: 0;
}

/* Small size variant */
.zx-btn-sm { height: 36px; padding: 0 .75rem; font-size: .875rem; border-radius: var(--zx-radius-md); }

/* ---------- 4. CHIP (icon badge inside cards) ---------- */
.zx-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--zx-radius-md);
  background: var(--zx-cloud);
  transition: transform var(--zx-dur-base) var(--zx-ease);
}
.zx-card:hover .zx-chip { transform: translateY(-2px) scale(1.05); }

/* Tinted chip variants */
.zx-chip-blue    { background: #EEF4FF; color: #2563EB; }
.zx-chip-green   { background: #E7F7EE; color: #059669; }
.zx-chip-purple  { background: #F7EEFB; color: #9333EA; }
.zx-chip-amber   { background: #FDF1E3; color: #D97706; }
.zx-chip-pink    { background: #FCE7F3; color: #DB2777; }

/* Dark mode: chip diventano scuri (rgba 8% del colore brand) mantenendo l'icona
   nel colore originale acceso. Niente piu' "rettangolo chiaro" attorno all'icona. */
[data-theme="dark"] .zx-chip-blue    { background: rgba(37, 99, 235, 0.18); color: #60A5FA; }
[data-theme="dark"] .zx-chip-green   { background: rgba(5, 150, 105, 0.18); color: #34D399; }
[data-theme="dark"] .zx-chip-purple  { background: rgba(147, 51, 234, 0.18); color: #C084FC; }
[data-theme="dark"] .zx-chip-amber   { background: rgba(217, 119, 6, 0.18); color: #FBBF24; }
[data-theme="dark"] .zx-chip-pink    { background: rgba(219, 39, 119, 0.18); color: #F472B6; }

/* ---------- 5. BADGE (status pills) ---------- */
.zx-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--zx-radius-sm);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.zx-badge-valid  { background: #D1FAE5; color: #047857; }
.zx-badge-risky  { background: #FEF3C7; color: #B45309; }
.zx-badge-error  { background: #FEE2E2; color: #B91C1C; }

/* ---------- 6. INPUT ---------- */
.zx-input {
  height: 44px;
  padding: 0 1rem;
  border-radius: var(--zx-radius-lg);
  background: var(--zx-surface);
  border: 1px solid var(--zx-stroke);
  font-family: var(--zx-font-sans);
  font-size: .9rem;
  color: var(--zx-ink);
  transition: border-color var(--zx-dur-fast) ease, box-shadow var(--zx-dur-fast) ease;
  width: 100%;
}
.zx-input::placeholder { color: var(--zx-muted); }
.zx-input:focus {
  outline: none;
  border-color: var(--zx-brand);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
}

/* ---------- 7. NAV LINK (sidebar item) ---------- */
.zx-nav-link {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .625rem .75rem;
  border-radius: var(--zx-radius-md);
  color: var(--zx-ink);
  text-decoration: none;
  font-size: .95rem;
  transition: background-color var(--zx-dur-fast) ease, box-shadow var(--zx-dur-fast) ease;
}
.zx-nav-link:hover { background: var(--zx-cloud); }
.zx-nav-link.is-active {
  background: var(--zx-surface);
  box-shadow: var(--zx-shadow-rest);
}

/* ---------- 7b. NAV ICON HOVER ANIMATIONS ----------
   Animazioni applicate alle icone (Lucide o custom) nelle voci di navigazione.
   Ogni icona riceve un data-nav-icon derivato dal label (lowercase, kebab-case).
   Animazione attiva solo su hover/focus della voce.

   overflow:visible permette ai sotto-elementi (flap, lid, ecc.) di uscire dal
   viewBox quando sono trasformati (rotazioni grandi, scale > 1) senza essere clippati. */
.zx-nav-icon {
  transition: transform var(--zx-dur-fast) ease, color var(--zx-dur-fast) ease;
  transform-origin: center;
  will-change: transform;
  overflow: visible;
}

/* ---------- Ordini — la scatola apre i flap su hover ----------
   I due flap sono drawn come rettangoli ~9x2 sopra il bordo superiore del corpo.
   A riposo giacciono piatti, formando un coperchio chiuso con una giuntura
   visibile al centro a x=12 (l'edge condivisa fra i due path).
   In hover ruotano verso l'esterno attorno al proprio cardine (angolo basso-esterno),
   con un easing back-out che da' la sensazione di "molla". */
.zx-nav-icon .zx-box-flap {
  transform-box: fill-box;
  transition: transform 380ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.zx-nav-icon .zx-box-flap-left {
  /* cardine = angolo basso-sinistro del bounding box del path = (3, 10) in coord SVG */
  transform-origin: 0% 100%;
}
.zx-nav-icon .zx-box-flap-right {
  /* cardine = angolo basso-destro del bounding box del path = (21, 10) in coord SVG */
  transform-origin: 100% 100%;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="ordini"] .zx-box-flap-left,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="ordini"] .zx-box-flap-left {
  transform: rotate(-100deg);
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="ordini"] .zx-box-flap-right,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="ordini"] .zx-box-flap-right {
  transform: rotate(100deg);
}

/* ---------- Stock — il cancello del magazzino apre le due ante ----------
   Le due ante a riposo si toccano al centro a x=12 formando un cancello chiuso.
   In hover scorrono lateralmente verso l'esterno (translateX 100% = piena larghezza
   dell'anta) e sfumano opacita', come se rientrassero nelle pareti del magazzino. */
.zx-nav-icon .zx-gate-panel {
  transform-box: fill-box;
  transform-origin: center;
  transition:
    transform 420ms cubic-bezier(0.65, 0.05, 0.36, 1),
    opacity 360ms ease;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="stock"] .zx-gate-panel-left,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="stock"] .zx-gate-panel-left {
  transform: translateX(-100%);
  opacity: 0.15;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="stock"] .zx-gate-panel-right,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="stock"] .zx-gate-panel-right {
  transform: translateX(100%);
  opacity: 0.15;
}

/* ---------- Spedizioni — il camion guida sul posto ----------
   Le due ruote ruotano in continuo (loop infinito) attorno al loro centro.
   Il corpo (cassone + cabina) sobbalza verticalmente di 1px per simulare il motore acceso.
   transform-box: fill-box assicura che la rotazione del cerchio avvenga attorno al
   centro geometrico del path, non attorno all'origine 0,0 dell'SVG. */
.zx-nav-icon .zx-truck-wheel {
  transform-box: fill-box;
  transform-origin: center;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="spedizioni"] .zx-truck-wheel,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="spedizioni"] .zx-truck-wheel {
  animation: zx-icon-wheel-spin 700ms linear infinite;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="spedizioni"] .zx-truck-body,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="spedizioni"] .zx-truck-body {
  animation: zx-icon-truck-bump 360ms ease-in-out infinite;
}
@keyframes zx-icon-wheel-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes zx-icon-truck-bump {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-0.6px); }
}

/* ---------- Tracking — il radar emette onde concentriche ----------
   Tre cerchi a raggio 2 partono dal centro (12,12) invisibili (opacity 0).
   In hover si materializzano e si scalano fino a 3.5x (raggio effettivo ~7,
   appena dentro l'anello esterno statico a r=8) sfumando opacita' a 0.
   I delay scaglionati (0/500/1000ms) su loop 1500ms creano un sweep continuo. */
.zx-nav-icon .zx-radar-wave {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="tracking"] .zx-radar-wave,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="tracking"] .zx-radar-wave {
  animation: zx-icon-radar-pulse 1500ms ease-out infinite;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="tracking"] .zx-radar-wave-2,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="tracking"] .zx-radar-wave-2 {
  animation-delay: 500ms;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="tracking"] .zx-radar-wave-3,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="tracking"] .zx-radar-wave-3 {
  animation-delay: 1000ms;
}
@keyframes zx-icon-radar-pulse {
  0%   { transform: scale(0.4); opacity: 0.9; }
  100% { transform: scale(3.5); opacity: 0; }
}

/* ---------- Brand — la maglietta ondeggia come un capo appeso ----------
   La t-shirt oscilla a pendolo attorno al colletto (transform-origin in alto al
   centro), simulando un capo appeso che dondola. Loop continuo solo su hover/focus. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="brand"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="brand"] {
  transform-box: fill-box;
  transform-origin: 50% 12%;
  animation: zx-icon-shirt-sway 1400ms cubic-bezier(0.45, 0, 0.55, 1) infinite;
}
@keyframes zx-icon-shirt-sway {
  0%, 100% { transform: rotate(0deg); }
  25%      { transform: rotate(-6deg); }
  75%      { transform: rotate(6deg); }
}

/* ---------- Impostazioni — l'ingranaggio ruota lentamente in continuo ----------
   Lucide Settings e' gia' un ingranaggio simmetrico: bastano 4s di rotazione lineare
   sull'intero SVG per avere l'effetto meccanico desiderato. transform-origin: center
   e' gia' definito sulla classe base .zx-nav-icon, quindi la rotazione e' centrata. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="impostazioni"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="impostazioni"] {
  animation: zx-icon-gear-spin 4s linear infinite;
}
@keyframes zx-icon-gear-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ---------- Pick & Pack — operatore che cammina spingendo il carrello ----------
   La ruota del carrello gira in continuo (700ms/giro, lineare) attorno al suo centro.
   In contemporanea l'intero SVG fa un piccolo bob verticale (0.6px ogni 600ms),
   sincronizzato col passo dell'operatore. Le due animazioni non confliggono perche'
   transform e' applicato per-elemento nello stack SVG (il padre trasla, il figlio ruota). */
.zx-nav-icon .zx-cart-wheel {
  transform-box: fill-box;
  transform-origin: center;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="pick-and-pack"] .zx-cart-wheel,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="pick-and-pack"] .zx-cart-wheel {
  animation: zx-icon-cart-wheel-spin 700ms linear infinite;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="pick-and-pack"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="pick-and-pack"] {
  animation: zx-icon-cart-walk 600ms ease-in-out infinite;
}
@keyframes zx-icon-cart-wheel-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes zx-icon-cart-walk {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-0.6px); }
}

/* ---------- Documenti — l'angolo della pagina si arriccia (page peel) ----------
   Il triangolino dell'angolo ruota di -25deg attorno al suo punto di piegatura
   (angolo basso-sinistro del triangolo = punto 14,8 in coord SVG = bottom-left del bbox).
   In contemporanea l'intero documento si inclina lievissimamente per dare profondita'. */
.zx-nav-icon .zx-doc-corner {
  transform-box: fill-box;
  transform-origin: 0% 100%;
  transition: transform 380ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="documenti"] .zx-doc-corner,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="documenti"] .zx-doc-corner {
  transform: rotate(-30deg) translateY(-1px);
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="documenti"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="documenti"] {
  transform: rotate(-2deg);
}

/* ---------- Note — la penna oscilla come se stesse scrivendo (scribble) ----------
   La penna ruota leggermente avanti/indietro attorno alla sua punta (basso-sinistra)
   con un movimento veloce ripetuto, dando l'effetto "sta scribacchiando un appunto". */
.zx-nav-icon .zx-pen-body {
  transform-box: fill-box;
  transform-origin: 0% 100%;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="note"] .zx-pen-body,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="note"] .zx-pen-body {
  animation: zx-icon-pen-scribble 520ms ease-in-out infinite;
}
@keyframes zx-icon-pen-scribble {
  0%, 100% { transform: rotate(0deg) translateX(0); }
  25%      { transform: rotate(-6deg) translateX(-0.5px); }
  50%      { transform: rotate(0deg) translateX(0); }
  75%      { transform: rotate(6deg) translateX(0.5px); }
}

/* ---------- Integrazioni — la spina vibra, elettricita' che scorre nei pin ----------
   I due pin oscillano lateralmente di mezzo pixel a velocita' alta (180ms),
   con direzioni opposte per simulare il "buzz" elettrico. */
.zx-nav-icon .zx-plug-prong {
  transform-box: fill-box;
  transform-origin: center;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="integrazioni"] .zx-plug-prong-left,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="integrazioni"] .zx-plug-prong-left {
  animation: zx-icon-plug-buzz-left 180ms ease-in-out infinite;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="integrazioni"] .zx-plug-prong-right,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="integrazioni"] .zx-plug-prong-right {
  animation: zx-icon-plug-buzz-right 180ms ease-in-out infinite;
}
@keyframes zx-icon-plug-buzz-left {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(-0.5px); }
}
@keyframes zx-icon-plug-buzz-right {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(0.5px); }
}

/* ---------- Smartphone ("Network" / Social) — vibrazione notifica ----------
   Il corpo del telefono ruota +/-5deg con origine al bottom (telefono tenuto in mano)
   per simulare la vibrazione di una notifica in arrivo. */
.zx-nav-icon .zx-phone-body {
  transform-box: fill-box;
  transform-origin: 50% 100%;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="network"] .zx-phone-body,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="network"] .zx-phone-body {
  animation: zx-icon-phone-vibrate 350ms ease-in-out infinite;
}
@keyframes zx-icon-phone-vibrate {
  0%, 100% { transform: rotate(0deg); }
  20%      { transform: rotate(-5deg); }
  40%      { transform: rotate(4deg); }
  60%      { transform: rotate(-3deg); }
  80%      { transform: rotate(2deg); }
}

/* ---------- Dashboard — i 4 tile della grid pulsano in sequenza ----------
   Lucide LayoutDashboard emette 4 <rect> come figli diretti dell'SVG.
   Targettiamo ogni rect via nth-child con delay scaglionati (0/200/400/600ms)
   su una pulse che fa scendere l'opacita' a 0.45 e tornare. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="dashboard"] > *,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="dashboard"] > * {
  animation: zx-icon-dash-tile-pulse 1.6s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="dashboard"] > *:nth-child(2),
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="dashboard"] > *:nth-child(2) {
  animation-delay: 200ms;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="dashboard"] > *:nth-child(3),
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="dashboard"] > *:nth-child(3) {
  animation-delay: 400ms;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="dashboard"] > *:nth-child(4),
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="dashboard"] > *:nth-child(4) {
  animation-delay: 600ms;
}
@keyframes zx-icon-dash-tile-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(0.92); }
}

/* ---------- Operatori — pulse leggera del gruppo utenti ----------
   Lucide Users e' indivisibile in modo pulito: facciamo un breath sull'intero icona
   con scale 1 ↔ 1.06 lento. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="operatori"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="operatori"] {
  animation: zx-icon-users-breath 1.4s ease-in-out infinite;
}
@keyframes zx-icon-users-breath {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.08); }
}

/* ---------- Chat — la bolla del messaggio pulsa ----------
   Effetto "messaggio in arrivo": pulse rapida con opacita' che oscilla leggermente. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="chat"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="chat"] {
  animation: zx-icon-bubble-pulse 1s ease-in-out infinite;
}
@keyframes zx-icon-bubble-pulse {
  0%, 100% { transform: scale(1); }
  35%      { transform: scale(1.12); }
  60%      { transform: scale(0.98); }
}

/* ---------- Tickets — il braccio del microfono oscilla come se si stesse parlando ----------
   Il braccio mic e' incernierato al cuscinetto destro, punto SVG (21, 19).
   Bounding box del path L-shape: da (14, 19) a (21, 21) — angolo top-right del bbox = (21, 19),
   quindi transform-origin: 100% 0% (con transform-box: fill-box) corrisponde al cardine.
   Oscillazione ±4deg, ease-in-out, ciclo 1s — naturale, non robotica. */
.zx-nav-icon .zx-mic-boom {
  transform-box: fill-box;
  transform-origin: 100% 0%;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="tickets"] .zx-mic-boom,
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="tickets"] .zx-mic-boom {
  animation: zx-icon-mic-talk 0.8s ease-in-out infinite;
}
@keyframes zx-icon-mic-talk {
  0%, 100% { transform: rotate(-12deg); }
  50%      { transform: rotate(15deg); }
}

/* ---------- Abbonamento — la carta di credito viene "swippata" lateralmente ----------
   translateX oscillante lento per simulare lo swipe POS. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="abbonamento"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="abbonamento"] {
  animation: zx-icon-card-swipe 1.2s ease-in-out infinite;
}
@keyframes zx-icon-card-swipe {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-1.5px); }
  75%      { transform: translateX(1.5px); }
}

/* ---------- Admin Dashboard — le barre del grafico crescono in sequenza ----------
   Lucide BarChart3 ha 4 path: il primo e' l'asse, gli altri 3 sono le barre.
   Targettiamo le barre (nth-child 2,3,4) facendole scalare verticalmente
   dall'origine in basso (transform-origin: 50% 100%) con stagger. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="admin-dashboard"] > *:nth-child(n+2),
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="admin-dashboard"] > *:nth-child(n+2) {
  animation: zx-icon-bar-grow 1.4s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: 50% 100%;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="admin-dashboard"] > *:nth-child(3),
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="admin-dashboard"] > *:nth-child(3) {
  animation-delay: 150ms;
}
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="admin-dashboard"] > *:nth-child(4),
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="admin-dashboard"] > *:nth-child(4) {
  animation-delay: 300ms;
}
@keyframes zx-icon-bar-grow {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(0.55); }
}

/* ---------- Audit Log — la pergamena/scroll si srotola con ondulazione verticale ----------
   Sutile movimento up-down che evoca lo scroll del log. */
.zx-nav-link:hover .zx-nav-icon[data-nav-icon="audit-log"],
.zx-nav-link:focus-visible .zx-nav-icon[data-nav-icon="audit-log"] {
  animation: zx-icon-scroll-bounce 1.1s ease-in-out infinite;
}
@keyframes zx-icon-scroll-bounce {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-1.2px); }
}

/* ---------- 8. DIVIDER ---------- */
.zx-divider { height: 1px; background: var(--zx-stroke); border: 0; }

/* ---------- 9. ANIMATIONS (hook classes) ---------- */

/* Reveal on scroll — add .zx-reveal to any element,
   then the JS adds .is-visible when it enters viewport */
.zx-reveal {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--zx-dur-slow) var(--zx-ease),
    transform var(--zx-dur-slow) var(--zx-ease);
}
.zx-reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* Staggered children — wrap siblings with .zx-stagger + .zx-reveal */
.zx-stagger > * {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--zx-dur-base) var(--zx-ease),
    transform var(--zx-dur-base) var(--zx-ease);
}
.zx-stagger.is-visible > *:nth-child(1) { transition-delay: .05s; opacity: 1; transform: none; }
.zx-stagger.is-visible > *:nth-child(2) { transition-delay: .15s; opacity: 1; transform: none; }
.zx-stagger.is-visible > *:nth-child(3) { transition-delay: .25s; opacity: 1; transform: none; }
.zx-stagger.is-visible > *:nth-child(4) { transition-delay: .35s; opacity: 1; transform: none; }
.zx-stagger.is-visible > *:nth-child(5) { transition-delay: .45s; opacity: 1; transform: none; }
.zx-stagger.is-visible > *:nth-child(6) { transition-delay: .55s; opacity: 1; transform: none; }

/* SVG line draw (charts) — add .zx-draw to a <path> */
.zx-draw {
  stroke-dasharray: 2000;
  stroke-dashoffset: 2000;
  animation: zx-draw 2.2s var(--zx-ease) forwards .3s;
}
.zx-draw-delay-1 { animation-delay: .6s; }
.zx-draw-delay-2 { animation-delay: .9s; }
@keyframes zx-draw { to { stroke-dashoffset: 0; } }

/* Progress bar fill — wrap inside .zx-reveal and set --w: 0..1 */
.zx-bar-fill {
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 1.4s var(--zx-ease);
}
.zx-reveal.is-visible .zx-bar-fill { transform: scaleX(var(--w, 1)); }

/* ---------- 10. TYPOGRAPHY UTILITIES ---------- */
.zx-type-display {
  font-family: var(--zx-font-sans);
  font-size: clamp(2.25rem, 4vw, 3.75rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1;
}
.zx-type-metric {
  font-feature-settings: "tnum", "lnum";
  letter-spacing: -0.02em;
  font-weight: 600;
}
.zx-text-muted { color: var(--zx-muted); }

/* ---------- 11. SCROLLBAR POLISH ---------- */
.zx-scroll::-webkit-scrollbar         { width: 10px; height: 10px; }
.zx-scroll::-webkit-scrollbar-thumb   { background: var(--zx-stroke); border-radius: 10px; border: 2px solid transparent; background-clip: padding-box; }
.zx-scroll::-webkit-scrollbar-thumb:hover { background: #D1D1D6; background-clip: padding-box; }

/* ---------- 12. REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
  .zx-card,
  .zx-chip,
  .zx-btn,
  .zx-reveal,
  .zx-stagger > *,
  .zx-bar-fill,
  .zx-draw {
    transition: none !important;
    animation: none !important;
    transform: none !important;
    opacity: 1 !important;
    stroke-dashoffset: 0 !important;
  }
  /* Tutorial pulse: spegniamo il pulsare ma teniamo l'outline statico cosi' l'utente
     vede comunque dove cliccare. */
  .zx-tutorial-pulse {
    animation: none !important;
    box-shadow: 0 0 0 4px #FFB800, 0 0 16px 2px rgba(255, 184, 0, 0.5) !important;
  }
}

/* ---------- 13. TUTORIAL ONBOARDING ---------- */
/* .zx-tutorial-pulse: bordo giallo pulsante intorno all'elemento target del tutorial.
   Applicato via JS (SpotlightPulse) sull'elemento corrispondente a [data-tour="<key>"]
   della task corrente. Colore warning #FFB800 per attirare lo sguardo (piu' visibile del
   brand blu, che si confonde con bottoni gia' presenti nella pagina). Solo box-shadow
   = GPU-friendly, niente reflow. L'animazione pulsa per tutta la durata (max 15s, vedi
   SpotlightManager PULSE_AUTO_REMOVE_MS) o finche' l'utente clicca l'elemento. */
.zx-tutorial-pulse {
  position: relative;
  z-index: 1; /* poco sopra il flow normale, ma sotto modal (1000) */
  border-radius: var(--zx-radius-md, 12px);
  animation: zxTutorialPulse 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes zxTutorialPulse {
  0%, 100% {
    /* Glow esterno + outline solid giallo: il bordo e' sempre visibile, il glow respira. */
    box-shadow:
      0 0 0 0 rgba(255, 184, 0, 0.7),
      0 0 0 4px #FFB800,
      0 0 16px 2px rgba(255, 184, 0, 0.4);
  }
  50% {
    /* Glow espande verso fuori fino a ~16px diventando trasparente: effetto "ping" radar. */
    box-shadow:
      0 0 0 16px rgba(255, 184, 0, 0),
      0 0 0 4px #FFB800,
      0 0 24px 4px rgba(255, 184, 0, 0.6);
  }
}

/* .zx-fab-tutorial: positioning del FAB "Riapri tutorial".
   Mobile (< 768px): bottom-right, sopra la MobileQuickActionBar (110px + safe-area iOS).
   Desktop (>= 768px): top-right, appena sotto l'Header (~80px dal top).
   Non collide con AssistantFab (desktop bottom-center) ne con NotificationCenter (top-right
   nell'Header, ma il FAB sta SOTTO l'Header quindi non sovrappone). */
.zx-fab-tutorial {
  position: fixed;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 110px);
  right: 16px;
  z-index: 9000;
}
@media (min-width: 768px) {
  .zx-fab-tutorial {
    top: 80px;
    bottom: auto;
    right: 24px;
  }
}

/* ---------- FAB Home mobile — alone dorato pulsante ----------
   Il FAB Home (giallo-oro) della MobileQuickActionBar emette un alone dorato che
   si espande e svanisce in loop, per attirare l'occhio sul tasto di navigazione.
   I primi due layer di box-shadow (anello charcoal + drop shadow) restano fissi;
   solo il terzo layer (alone oro) pulsa. L'animazione sovrascrive il boxShadow inline. */
.zx-fab-home-pulse {
  animation: zx-fab-gold-pulse 1800ms ease-out infinite;
}
@keyframes zx-fab-gold-pulse {
  0% {
    box-shadow:
      0 0 0 4px var(--zx-ink),
      0 8px 22px -4px rgba(11, 11, 15, 0.45),
      0 0 0 0 rgba(244, 196, 48, 0.6);
  }
  70% {
    box-shadow:
      0 0 0 4px var(--zx-ink),
      0 8px 22px -4px rgba(11, 11, 15, 0.45),
      0 0 0 12px rgba(244, 196, 48, 0);
  }
  100% {
    box-shadow:
      0 0 0 4px var(--zx-ink),
      0 8px 22px -4px rgba(11, 11, 15, 0.45),
      0 0 0 0 rgba(244, 196, 48, 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .zx-fab-home-pulse {
    animation: none;
  }
}
