/* ==========================================================================
   QZONE OMS — COMPONENTS
   Overlays, tabs, alerts, calendar, auth, charts, KPI scorecards.
   ========================================================================== */

/* ==========================================================================
   MODALS  (Bootstrap markup, restyled)
   ========================================================================== */

.modal { z-index: var(--qz-z-modal); }
.modal-backdrop { z-index: calc(var(--qz-z-modal) - 20); background: #000; }
.modal-backdrop.show { opacity: 0.66 !important; }

.modal-dialog { margin: var(--qz-s-4) auto; }

.modal-content {
  border: 0 !important;
  border-radius: var(--qz-r-xl) !important;
  background: var(--qz-surface-2) !important;
  box-shadow: var(--qz-ring-strong), var(--qz-shadow-3) !important;
  overflow: hidden;
}

.modal-header {
  align-items: center;
  gap: var(--qz-s-3);
  padding: var(--qz-s-4) var(--qz-s-5) !important;
  background: var(--qz-surface-2) !important;
  border-bottom: 1px solid var(--qz-line) !important;
  color: var(--qz-text) !important;
}
.modal-title {
  font-family: var(--qz-font-display);
  font-size: var(--qz-fs-md);
  font-weight: 600;
  letter-spacing: var(--qz-track-tight);
  color: var(--qz-text);
}
.modal-body { padding: var(--qz-s-5) !important; background: var(--qz-surface-2); color: var(--qz-text-dim); font-size: var(--qz-fs-sm); }
.modal-footer {
  gap: var(--qz-s-2);
  padding: var(--qz-s-3) var(--qz-s-5) !important;
  background: var(--qz-surface-inset) !important;
  border-top: 1px solid var(--qz-line) !important;
}
.modal-footer > * { margin: 0 !important; }

.btn-close {
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: var(--qz-r-pill);
  opacity: 1;
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236c737f' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M4 4l8 8M12 4l-8 8'/%3E%3C/svg%3E") center/14px no-repeat;
  filter: none !important;
  transition: background-color var(--qz-dur-fast) var(--qz-ease);
}
.btn-close:hover { background-color: var(--qz-surface-4); }

/* A confirm dialog reads as a statement, not a decorated panel. */
.qz-confirm { text-align: center; padding: var(--qz-s-6) var(--qz-s-5); }
.qz-confirm__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0 auto var(--qz-s-4);
  border-radius: var(--qz-r-lg);
  background: var(--qz-crit-weak);
  box-shadow: inset 0 0 0 1px var(--qz-crit-line);
  color: var(--qz-crit);
  font-size: 17px;
}
.qz-confirm__icon--warn { background: var(--qz-warn-weak); box-shadow: inset 0 0 0 1px var(--qz-warn-line); color: var(--qz-warn); }
.qz-confirm__title { font-family: var(--qz-font-display); font-size: var(--qz-fs-md); font-weight: 600; margin-bottom: var(--qz-s-2); }
.qz-confirm__text { font-size: var(--qz-fs-sm); color: var(--qz-text-mute); margin-bottom: var(--qz-s-5); }
.qz-confirm__actions { display: flex; gap: var(--qz-s-2); justify-content: center; }
.qz-confirm__actions form { margin: 0; }

@media (max-width: 575.98px) {
  .modal-dialog { margin: var(--qz-s-3); }
  .qz-confirm__actions { flex-direction: column-reverse; }
  .qz-confirm__actions > *, .qz-confirm__actions form { width: 100%; }
  .qz-confirm__actions .qz-btn { width: 100%; }
}

/* ==========================================================================
   DROPDOWNS  (Bootstrap markup, restyled)
   ========================================================================== */

.dropdown-menu {
  z-index: var(--qz-z-dropdown) !important;
  min-width: 190px;
  padding: var(--qz-s-1) !important;
  border: 0 !important;
  border-radius: var(--qz-r-lg) !important;
  background: var(--qz-surface-3) !important;
  box-shadow: var(--qz-ring-strong), var(--qz-shadow-2) !important;
}
.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--qz-s-3);
  padding: 7px var(--qz-s-3) !important;
  border-radius: var(--qz-r-md) !important;
  color: var(--qz-text-dim) !important;
  font-size: var(--qz-fs-sm);
  font-weight: 500;
}
.dropdown-item i { width: 15px; font-size: 12px; text-align: center; opacity: 0.8; }
.dropdown-item:hover, .dropdown-item:focus { background: var(--qz-surface-4) !important; color: var(--qz-text) !important; }
.dropdown-item.text-danger, .dropdown-item.qz-danger { color: var(--qz-crit) !important; }
.dropdown-item.text-danger:hover, .dropdown-item.qz-danger:hover { background: var(--qz-crit-weak) !important; color: var(--qz-crit) !important; }
.dropdown-divider { margin: var(--qz-s-1) !important; border-color: var(--qz-line) !important; }
.dropdown-header {
  padding: var(--qz-s-2) var(--qz-s-3) !important;
  font-size: var(--qz-fs-2xs);
  font-weight: 600;
  letter-spacing: var(--qz-track-label);
  text-transform: uppercase;
  color: var(--qz-text-faint);
}

/* ==========================================================================
   TABS
   ========================================================================== */

.qz-tabs {
  display: flex;
  align-items: center;
  gap: var(--qz-s-1);
  margin-bottom: var(--qz-s-5);
  border-bottom: 1px solid var(--qz-line);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.qz-tabs::-webkit-scrollbar { display: none; }

.qz-tab {
  position: relative;
  flex: 0 0 auto;
  padding: var(--qz-s-3) var(--qz-s-3);
  border: 0;
  background: transparent;
  color: var(--qz-text-mute);
  font-size: var(--qz-fs-sm);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--qz-dur-fast) var(--qz-ease);
}
.qz-tab:hover { color: var(--qz-text); }
.qz-tab.is-active { color: var(--qz-text); font-weight: 600; }
/* 2px underline that sits on the container's own rule */
.qz-tab.is-active::after {
  content: "";
  position: absolute;
  right: var(--qz-s-2);
  bottom: -1px;
  left: var(--qz-s-2);
  height: 2px;
  background: var(--qz-accent);
}
.qz-tab__count {
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: var(--qz-r-sm);
  background: var(--qz-surface-4);
  color: var(--qz-text-mute);
  font-family: var(--qz-font-mono);
  font-size: var(--qz-fs-2xs);
  font-weight: 600;
}
.qz-tab.is-active .qz-tab__count { background: var(--qz-accent-weak); color: var(--qz-accent); }

/* ==========================================================================
   ALERTS + FLASH TOASTS
   ========================================================================== */

.qz-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--qz-s-3);
  padding: var(--qz-s-3) var(--qz-s-4);
  margin-bottom: var(--qz-s-4);
  border-radius: var(--qz-r-md);
  border-left: 2px solid var(--qz-idle);
  background: var(--qz-idle-weak);
  color: var(--qz-text-dim);
  font-size: var(--qz-fs-sm);
}
.qz-alert__icon { flex: 0 0 auto; margin-top: 1px; font-size: 13px; }
.qz-alert__body { flex: 1 1 auto; min-width: 0; }
.qz-alert__title { font-weight: 600; color: var(--qz-text); }
.qz-alert--ok   { border-left-color: var(--qz-ok);   background: var(--qz-ok-weak); }
.qz-alert--ok   .qz-alert__icon { color: var(--qz-ok); }
.qz-alert--warn { border-left-color: var(--qz-warn); background: var(--qz-warn-weak); }
.qz-alert--warn .qz-alert__icon { color: var(--qz-warn); }
.qz-alert--crit { border-left-color: var(--qz-crit); background: var(--qz-crit-weak); }
.qz-alert--crit .qz-alert__icon { color: var(--qz-crit); }
.qz-alert--info { border-left-color: var(--qz-info); background: var(--qz-info-weak); }
.qz-alert--info .qz-alert__icon { color: var(--qz-info); }

/* Flash toast stack — top-right on desktop, top-full-width on mobile */
.qz-toasts {
  position: fixed;
  top: var(--qz-s-3);
  right: var(--qz-s-3);
  z-index: var(--qz-z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--qz-s-2);
  width: min(380px, calc(100vw - var(--qz-s-6)));
  pointer-events: none;
}
.qz-toasts > * { pointer-events: auto; }

.qz-toast {
  display: flex;
  align-items: flex-start;
  gap: var(--qz-s-3);
  padding: var(--qz-s-3) var(--qz-s-4);
  border-radius: var(--qz-r-lg);
  border-left: 2px solid var(--qz-accent);
  background: var(--qz-surface-3);
  box-shadow: var(--qz-ring-strong), var(--qz-shadow-2);
  color: var(--qz-text);
  font-size: var(--qz-fs-sm);
  animation: qz-toast-in var(--qz-dur-slow) var(--qz-ease-out);
}
.qz-toast--ok   { border-left-color: var(--qz-ok); }
.qz-toast--warn { border-left-color: var(--qz-warn); }
.qz-toast--crit { border-left-color: var(--qz-crit); }
.qz-toast--info { border-left-color: var(--qz-info); }
.qz-toast__icon { flex: 0 0 auto; margin-top: 1px; }
.qz-toast--ok   .qz-toast__icon { color: var(--qz-ok); }
.qz-toast--warn .qz-toast__icon { color: var(--qz-warn); }
.qz-toast--crit .qz-toast__icon { color: var(--qz-crit); }
.qz-toast--info .qz-toast__icon { color: var(--qz-info); }
.qz-toast__body { flex: 1 1 auto; min-width: 0; }
.qz-toast__close {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: var(--qz-r-pill);
  background: transparent;
  color: var(--qz-text-faint);
  font-size: 11px;
  cursor: pointer;
}
.qz-toast__close:hover { background: var(--qz-surface-4); color: var(--qz-text); }
/* `.slide-out` is what the existing flash Stimulus controller adds on close. */
.qz-toast.is-leaving,
.qz-toast.slide-out { animation: qz-toast-out var(--qz-dur) var(--qz-ease) forwards; }

@keyframes qz-toast-in  { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
@keyframes qz-toast-out { to { opacity: 0; transform: translateX(16px); } }

@media (max-width: 575.98px) {
  .qz-toasts { top: var(--qz-s-2); right: var(--qz-s-2); left: var(--qz-s-2); width: auto; }
  @keyframes qz-toast-in  { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
  @keyframes qz-toast-out { to { opacity: 0; transform: translateY(-14px); } }
}

/* ==========================================================================
   AUTH PAGES — login, OTP, password reset
   Split layout: brand panel + form. Collapses to form-only on mobile.
   ========================================================================== */

.qz-auth {
  display: grid;
  grid-template-columns: 1fr;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--qz-bg);
}
@media (min-width: 992px) { .qz-auth { grid-template-columns: 1fr 1fr; } }

/* Left: identity. A quiet technical grid, not a photo or a gradient wash.
   The mark stays anchored top-left where it has always sat; the pitch and
   stats centre in the panel over the grid and the drifting-icon canvas. */
.qz-auth__aside {
  position: relative;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--qz-s-8);
  padding: var(--qz-s-16) var(--qz-s-10) var(--qz-s-10);
  background: var(--qz-surface-1);
  border-right: 1px solid var(--qz-line);
  overflow: hidden;
  text-align: center;
}
@media (min-width: 992px) { .qz-auth__aside { display: flex; } }

.qz-auth__aside::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--qz-line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--qz-line-soft) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 70% 62% at 50% 50%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 70% 62% at 50% 50%, #000 0%, transparent 78%);
  pointer-events: none;
}
.qz-auth__aside > * { position: relative; z-index: 2; }

/* Decorative animation layer: above the grid, under the copy. Sized in JS to
   the panel's own box, so it never bleeds under the form column. The mask
   thins it out behind the centred headline — icons stay legible drifting
   around the copy instead of crossing it. */
.qz-auth__canvas {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  mask-image: radial-gradient(ellipse 52% 42% at 50% 50%,
              rgba(0,0,0,0.12) 0%, rgba(0,0,0,0.45) 55%, #000 82%);
  -webkit-mask-image: radial-gradient(ellipse 52% 42% at 50% 50%,
              rgba(0,0,0,0.12) 0%, rgba(0,0,0,0.45) 55%, #000 82%);
}

@media (prefers-reduced-motion: reduce) {
  .qz-auth__canvas { opacity: 0.5; }
}

/* The mark is a wide, transparent PNG drawn in navy — it needs a light plate
   to stay legible on the dark surface, never the accent tile. */
.qz-auth__brand { display: flex; align-items: center; gap: var(--qz-s-3); }

/* Out of the flex flow so the copy below centres on the panel itself, not on
   the space left under the mark. The wordmark rides alongside it. */
.qz-auth__aside .qz-auth__brand {
  position: absolute;
  top: var(--qz-s-10);
  left: var(--qz-s-10);
  text-align: left;
}
/* Short acronym over a much wider descriptor — it needs the size and a little
   tracking to hold its own as the mark rather than read as a caption. */
.qz-auth__brand-name {
  display: block;
  font-family: var(--qz-font-display);
  font-size: var(--qz-fs-lg);
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.1;
}
.qz-auth__brand-sub {
  display: block;
  font-size: var(--qz-fs-2xs);
  letter-spacing: var(--qz-track-label);
  text-transform: uppercase;
  color: var(--qz-text-faint);
}
/* No fill behind the mark — the lockup is transparent artwork and sits
   directly on the auth panel. */
.qz-auth__logo {
  display: grid;
  place-items: center;
  padding: var(--qz-s-2) var(--qz-s-3);
  overflow: hidden;
}
.qz-auth__logo img { display: block; width: auto; height: 40px; max-width: 100%; object-fit: contain; }

/* Mobile card carries the same mark, one size down. */
.qz-auth__mobile-brand .qz-auth__logo img { height: 44px; }

.qz-auth__pitch { max-width: 34ch; }
.qz-auth__pitch h2 {
  font-size: clamp(1.75rem, 2.4vw, 2.5rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.025em;
  margin-bottom: var(--qz-s-4);
}
.qz-auth__pitch p { color: var(--qz-text-mute); font-size: var(--qz-fs-sm); }

/* What the portal covers. Two columns of icon + label, no card surface, so
   the drifting icons stay visible between the rows. */
.qz-auth__modules {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--qz-s-4) var(--qz-s-6);
  width: 100%;
  max-width: 520px;
  text-align: left;
}
.qz-auth__module { display: flex; align-items: flex-start; gap: var(--qz-s-3); }
.qz-auth__module-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--qz-r-lg);
  background: var(--qz-accent-weak);
  box-shadow: inset 0 0 0 1px var(--qz-accent-line);
  color: var(--qz-accent);
  font-size: var(--qz-fs-xs);
}
.qz-auth__module-name { display: block; font-size: var(--qz-fs-sm); font-weight: 600; line-height: 1.3; }
.qz-auth__module-desc { display: block; font-size: var(--qz-fs-2xs); color: var(--qz-text-mute); line-height: 1.4; }

.qz-auth__stats {
  display: flex;
  justify-content: center;
  gap: var(--qz-s-8);
  width: 100%;
  max-width: 520px;
  padding-top: var(--qz-s-6);
  border-top: 1px solid var(--qz-line);
}
.qz-auth__stat-val { font-family: var(--qz-font-mono); font-size: var(--qz-fs-lg); font-weight: 600; color: var(--qz-text); }
.qz-auth__stat-key { font-size: var(--qz-fs-2xs); letter-spacing: var(--qz-track-label); text-transform: uppercase; color: var(--qz-text-faint); }

/* Pinned to the panel foot, mirroring the mark at the head. */
.qz-auth__aside-foot {
  position: absolute;
  left: var(--qz-s-10);
  right: var(--qz-s-10);
  bottom: var(--qz-s-8);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--qz-s-4);
  font-size: var(--qz-fs-2xs);
  color: var(--qz-text-faint);
}
.qz-auth__aside-foot span { display: inline-flex; align-items: center; gap: var(--qz-s-2); }

/* Short panels (laptops, split screens) drop the extras rather than scroll. */
@media (min-width: 992px) and (max-height: 760px) {
  .qz-auth__modules,
  .qz-auth__aside-foot { display: none; }
  .qz-auth__aside { gap: var(--qz-s-10); }
}

/* Right: the form */
.qz-auth__main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--qz-s-8) var(--qz-s-5);
}
.qz-auth__form { width: 100%; max-width: 380px; margin: 0 auto; }

.qz-auth__mobile-brand { display: flex; align-items: center; gap: var(--qz-s-3); margin-bottom: var(--qz-s-8); }
@media (min-width: 992px) { .qz-auth__mobile-brand { display: none; } }

.qz-auth__title { font-size: var(--qz-fs-xl); font-weight: 600; letter-spacing: var(--qz-track-tight); margin-bottom: var(--qz-s-2); }
.qz-auth__sub { font-size: var(--qz-fs-sm); color: var(--qz-text-mute); margin-bottom: var(--qz-s-6); }
.qz-auth__foot { margin-top: var(--qz-s-6); padding-top: var(--qz-s-4); border-top: 1px solid var(--qz-line); font-size: var(--qz-fs-xs); color: var(--qz-text-mute); text-align: center; }

@media (max-width: 575.98px) {
  .qz-auth__main { padding: var(--qz-s-6) var(--qz-s-4); }
}

/* ==========================================================================
   CALENDAR
   ========================================================================== */

.qz-cal { border-radius: var(--qz-r-lg); background: var(--qz-surface-2); box-shadow: var(--qz-ring); overflow: hidden; }
.qz-cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--qz-s-3);
  padding: var(--qz-s-3) var(--qz-s-4);
  border-bottom: 1px solid var(--qz-line);
}
.qz-cal__month { font-family: var(--qz-font-display); font-size: var(--qz-fs-base); font-weight: 600; }
.qz-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.qz-cal__dow {
  padding: var(--qz-s-2);
  border-bottom: 1px solid var(--qz-line);
  background: var(--qz-surface-inset);
  font-size: var(--qz-fs-2xs);
  font-weight: 600;
  letter-spacing: var(--qz-track-label);
  text-transform: uppercase;
  color: var(--qz-text-mute);
  text-align: center;
}
.qz-cal__day {
  position: relative;
  min-height: 104px;
  padding: var(--qz-s-2);
  border-right: 1px solid var(--qz-line-soft);
  border-bottom: 1px solid var(--qz-line-soft);
  transition: background-color var(--qz-dur-fast) var(--qz-ease);
}
.qz-cal__day:nth-child(7n) { border-right: 0; }
.qz-cal__day:hover { background: var(--qz-surface-3); }
.qz-cal__day--out { background: var(--qz-surface-inset); opacity: 0.5; }
.qz-cal__day--today { box-shadow: inset 0 0 0 1px var(--qz-accent-line); }
.qz-cal__date { font-family: var(--qz-font-mono); font-size: var(--qz-fs-xs); font-weight: 600; color: var(--qz-text-mute); }
.qz-cal__day--today .qz-cal__date { color: var(--qz-accent); }
.qz-cal__event {
  display: block;
  margin-top: 3px;
  padding: 2px 5px;
  border-left: 2px solid var(--qz-accent);
  border-radius: var(--qz-r-xs);
  background: var(--qz-accent-weak);
  color: var(--qz-text);
  font-size: var(--qz-fs-2xs);
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.qz-cal__event--ok   { border-left-color: var(--qz-ok);   background: var(--qz-ok-weak); }
.qz-cal__event--warn { border-left-color: var(--qz-warn); background: var(--qz-warn-weak); }
.qz-cal__event--crit { border-left-color: var(--qz-crit); background: var(--qz-crit-weak); }
.qz-cal__event--info { border-left-color: var(--qz-info); background: var(--qz-info-weak); }

@media (max-width: 767.98px) {
  .qz-cal__day { min-height: 62px; padding: 4px; }
  .qz-cal__event { padding: 1px 3px; font-size: 9px; }
  .qz-cal__dow { font-size: 9px; padding: 5px 2px; }
}

/* ==========================================================================
   SCORECARD / KPI RATING
   ========================================================================== */

.qz-score {
  display: flex;
  align-items: center;
  gap: var(--qz-s-4);
  padding: var(--qz-s-4);
  border-radius: var(--qz-r-lg);
  border-left: 2px solid var(--qz-idle);
  background: var(--qz-surface-2);
  box-shadow: var(--qz-ring);
}
.qz-score + .qz-score { margin-top: var(--qz-s-2); }
.qz-score__val { font-family: var(--qz-font-mono); font-size: var(--qz-fs-xl); font-weight: 600; line-height: 1; min-width: 60px; }
.qz-score__main { flex: 1 1 auto; min-width: 0; }
.qz-score__name { font-size: var(--qz-fs-sm); font-weight: 600; color: var(--qz-text); }
.qz-score__meta { font-size: var(--qz-fs-xs); color: var(--qz-text-mute); }

.qz-score--outstanding { border-left-color: var(--qz-info); }
.qz-score--outstanding .qz-score__val { color: var(--qz-info); }
.qz-score--excellent   { border-left-color: var(--qz-ok); }
.qz-score--excellent   .qz-score__val { color: var(--qz-ok); }
.qz-score--good        { border-left-color: var(--qz-accent); }
.qz-score--good        .qz-score__val { color: var(--qz-accent); }
.qz-score--satisfactory{ border-left-color: var(--qz-warn); }
.qz-score--satisfactory .qz-score__val { color: var(--qz-warn); }
.qz-score--poor        { border-left-color: var(--qz-crit); }
.qz-score--poor        .qz-score__val { color: var(--qz-crit); }

@media (max-width: 575.98px) {
  .qz-score { flex-wrap: wrap; gap: var(--qz-s-2); }
  .qz-score__val { min-width: 0; }
}

/* ==========================================================================
   CHARTS
   Chart.js draws into a canvas; the container controls the box. Fixed aspect
   so the canvas never collapses or overflows its column.
   ========================================================================== */

.qz-chart { position: relative; width: 100%; height: 260px; }
.qz-chart--sm { height: 180px; }
.qz-chart--lg { height: 340px; }
.qz-chart canvas { display: block; width: 100% !important; height: 100% !important; }

@media (max-width: 767.98px) {
  .qz-chart { height: 220px; }
  .qz-chart--lg { height: 260px; }
}

.qz-legend { display: flex; flex-wrap: wrap; gap: var(--qz-s-2) var(--qz-s-4); margin-top: var(--qz-s-3); }
.qz-legend__item { display: flex; align-items: center; gap: 6px; font-size: var(--qz-fs-xs); color: var(--qz-text-mute); }
.qz-legend__swatch { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }

/* ==========================================================================
   TIMELINE — audit trails, activity history
   ========================================================================== */

.qz-timeline { position: relative; margin: 0; padding: 0 0 0 var(--qz-s-5); list-style: none; }
.qz-timeline::before { content: ""; position: absolute; top: 4px; bottom: 4px; left: 4px; width: 1px; background: var(--qz-line); }
.qz-timeline__item { position: relative; padding-bottom: var(--qz-s-4); }
.qz-timeline__item:last-child { padding-bottom: 0; }
.qz-timeline__item::before {
  content: "";
  position: absolute;
  top: 5px;
  left: calc(-1 * var(--qz-s-5) + 1px);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--qz-surface-4);
  box-shadow: 0 0 0 2px var(--qz-bg);
}
.qz-timeline__item--accent::before { background: var(--qz-accent); }
.qz-timeline__item--ok::before   { background: var(--qz-ok); }
.qz-timeline__item--crit::before { background: var(--qz-crit); }
.qz-timeline__time { font-family: var(--qz-font-mono); font-size: var(--qz-fs-2xs); color: var(--qz-text-faint); }
.qz-timeline__title { font-size: var(--qz-fs-sm); font-weight: 500; color: var(--qz-text); }
.qz-timeline__text { font-size: var(--qz-fs-xs); color: var(--qz-text-mute); }

/* ==========================================================================
   KEY / VALUE INLINE PAIRS — compact meta strips
   ========================================================================== */

.qz-kv { display: flex; flex-wrap: wrap; gap: var(--qz-s-2) var(--qz-s-5); }
.qz-kv__item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.qz-kv__k { font-size: var(--qz-fs-2xs); font-weight: 600; letter-spacing: var(--qz-track-label); text-transform: uppercase; color: var(--qz-text-faint); }
.qz-kv__v { font-size: var(--qz-fs-sm); color: var(--qz-text); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   SEGMENTED STATUS FILTER — client-side tabs over a rendered table
   --------------------------------------------------------------------------
   Used by the leave queue. The tabs filter rows already in the DOM, so there is
   no request to wait on and the motion below is the whole of the feedback: a
   ring that closes around the tab you picked, and a body that fades out, swaps
   and comes back staggered.

   Every tab wears its status colour in the label, so the palette reads before
   anything is picked and the colour never moves. Selection is the border
   arriving — the one thing that differs between a tab at rest and a tab chosen.
   `--qz-tone*` is set per tab by [data-tone]; the rules below are written once
   against it rather than four times over.
   ========================================================================== */

/* The track. Holds all four tabs as one control rather than four loose links,
   and gives the selected tab's ring something to sit inside. */
.qz-segment {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--qz-line);
  border-radius: var(--qz-r-pill);
  background: var(--qz-surface-inset);
  /* Narrow screens scroll the strip rather than wrapping it, so the row stays a
     single readable scale of statuses. */
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.qz-segment::-webkit-scrollbar { display: none; }

.qz-segment__tab {
  --qz-tone:      var(--qz-accent);
  --qz-tone-hi:   var(--qz-accent-hi);
  --qz-tone-weak: var(--qz-accent-weak);
  --qz-tone-line: var(--qz-accent-line);

  display: inline-flex;
  align-items: center;
  gap: var(--qz-s-2);
  padding: 6px 16px;
  /* Transparent, not absent: the box measures the same whether or not the tab
     is selected, so the border arriving does not nudge the row sideways. */
  border: 1px solid transparent;
  border-radius: var(--qz-r-pill);
  background: transparent;
  font-size: var(--qz-fs-sm);
  font-weight: 600;
  line-height: 1;
  color: var(--qz-tone-hi);
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color var(--qz-dur) var(--qz-ease),
              border-color     var(--qz-dur) var(--qz-ease),
              color            var(--qz-dur) var(--qz-ease);
}

.qz-segment__tab[data-tone="warn"] {
  --qz-tone: var(--qz-warn); --qz-tone-hi: var(--qz-warn);
  --qz-tone-weak: var(--qz-warn-weak); --qz-tone-line: var(--qz-warn-line);
}
.qz-segment__tab[data-tone="ok"] {
  --qz-tone: var(--qz-ok); --qz-tone-hi: var(--qz-ok);
  --qz-tone-weak: var(--qz-ok-weak); --qz-tone-line: var(--qz-ok-line);
}
.qz-segment__tab[data-tone="info"] {
  --qz-tone: var(--qz-info); --qz-tone-hi: var(--qz-info);
  --qz-tone-weak: var(--qz-info-weak); --qz-tone-line: var(--qz-info-line);
}
.qz-segment__tab[data-tone="crit"] {
  --qz-tone: var(--qz-crit); --qz-tone-hi: var(--qz-crit);
  --qz-tone-weak: var(--qz-crit-weak); --qz-tone-line: var(--qz-crit-line);
}

/* Hover tints the bed but never borrows the border — that belongs to the
   selected tab alone, and is the whole of how selection reads.

   The colour is restated here only to hold off base.css's `a:hover`, which
   paints every link accent blue and, at (0,1,1), outranks this rule's class on
   its own. A tab must keep its own status colour under the cursor. */
.qz-segment__tab:hover,
.qz-segment__tab:focus {
  background: var(--qz-tone-weak);
  color: var(--qz-tone-hi);
  text-decoration: none;
}
.qz-segment__tab:active { transform: translateY(1px); }
.qz-segment__tab:focus-visible { outline: 2px solid var(--qz-tone); outline-offset: 2px; }

/* Selected: ringed in its own colour, over a tint just strong enough to seat
   the ring. The label keeps the colour it already had. */
.qz-segment__tab.is-active {
  border-color: var(--qz-tone);
  background: var(--qz-tone-weak);
}

/* Per-tab tally, tinted to match its tab. */
.qz-segment__count {
  min-width: 1.5em;
  padding: 1px 6px;
  border-radius: var(--qz-r-pill);
  background: var(--qz-tone-weak);
  font-family: var(--qz-font-mono);
  font-size: var(--qz-fs-2xs);
  font-weight: 600;
  color: currentColor;
  font-variant-numeric: tabular-nums;
  text-align: center;
  transition: background-color var(--qz-dur) var(--qz-ease);
}
/* Firms up alongside the ring so the selected tab reads as one piece. */
.qz-segment__tab.is-active .qz-segment__count { background: var(--qz-tone-line); }

/* --- the filtered table itself ------------------------------------------- */

.qz-filterable__summary {
  font-family: var(--qz-font-mono);
  font-size: var(--qz-fs-2xs);
  color: var(--qz-text-faint);
  font-variant-numeric: tabular-nums;
}

/* Out: the whole body dims and drops a hair while rows are swapped. */
.qz-filterable tbody {
  transition: opacity var(--qz-dur-fast) var(--qz-ease),
              transform var(--qz-dur-fast) var(--qz-ease);
}
.qz-filterable.is-swapping tbody {
  opacity: 0;
  transform: translateY(-4px);
}

/* In: rows arrive one after another, the stagger index set by the controller
   and capped there so a long queue still finishes promptly. */
.qz-filterable:not(.is-swapping) tbody > tr {
  animation: qz-row-in var(--qz-dur) var(--qz-ease-out) both;
  animation-delay: calc(var(--qz-row-step, 0) * 18ms);
}

/* Filtered-out rows and the empty-state row. `!important` because Bootstrap's
   table rules are specific enough to resurrect a row the UA sheet hid. */
.qz-filterable tbody > tr[hidden] { display: none !important; }

@keyframes qz-row-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .qz-segment__tab,
  .qz-filterable tbody { transition: none; }
  .qz-filterable:not(.is-swapping) tbody > tr { animation: none; }
}
