/* Light dashboard theme with a dark labeled sidebar - restructured for
   clarity/density (stat cards, per-page header, filters) without touching
   any functional class hooks app.js depends on (.sidenav-item, .view). */
:root {
  color-scheme: light;

  /* === UNIFYRA brand - fixed, four colors, do not change === */
  --brand-50: #e3f2fd;
  --brand-200: #90caf9;
  --brand-500: #2196f3;
  --brand-900: #0d47a1;

  /* Surfaces - pure white throughout (neomorphism/soft-UI theme: surfaces
     sit at the SAME color as the page, separated only by soft dual-tone
     shadows, never by a visible fill/border difference). */
  --page-bg: #ffffff;
  --surface-primary: #ffffff;
  --surface-secondary: #f4f6f9;
  --surface-brand-soft: #e3f2fd;

  /* Text */
  --text-primary: #10213a;
  --text-secondary: #42526b;
  --text-muted: #64748b;
  --text-muted-soft: #94a3b8;
  --text-on-brand: #ffffff;

  /* Borders - neomorphism separates surfaces with shadow, not a drawn line;
     kept transparent so the ~250 existing usages just stop rendering a
     border instead of needing individual rewrites. */
  --border-subtle: transparent;
  --border-default: transparent;
  --border-brand: #90caf9;

  /* Interaction */
  --action-primary: #0d47a1;
  --action-primary-hover: #0a3b87;
  --action-primary-active: #082f6c;
  --action-secondary: #2196f3;
  --focus-ring: rgba(33, 150, 243, 0.28);

  /* Status - semantic feedback only, never decorative */
  --success: #15803d;
  --success-soft: rgba(21, 128, 61, 0.1);
  --warning: #b45309;
  --warning-soft: rgba(180, 83, 9, 0.1);
  --danger: #b91c1c;
  --danger-soft: rgba(185, 28, 28, 0.1);
  --info: #0d47a1;
  --info-soft: #e3f2fd;

  /* Radius - larger, soft/rounded (neomorphism reads as "pillowy", never
     sharp-cornered). */
  --radius-xs: 8px;
  --radius-sm: 12px;
  --radius-md: 16px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  /* Shadows - the neomorphic dual-tone pair (soft dark + soft light) that
     now carries every surface's depth, since borders are gone (see
     --border-* above). Grayscale, not brand-tinted, on purpose - a colored
     ambient shadow reads muddy on a pure white base. */
  --shadow-xs: 3px 3px 7px rgba(163, 177, 198, 0.35), -3px -3px 7px rgba(255, 255, 255, 0.8);
  --shadow-sm: 7px 7px 15px rgba(163, 177, 198, 0.4), -7px -7px 15px rgba(255, 255, 255, 0.75);
  --shadow-md: 12px 12px 26px rgba(163, 177, 198, 0.45), -10px -10px 22px rgba(255, 255, 255, 0.7);
  /* Pressed/active look - the shadow pair flips inward. */
  --shadow-inset: inset 4px 4px 8px rgba(163, 177, 198, 0.4), inset -4px -4px 8px rgba(255, 255, 255, 0.75);

  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 150ms;
  --duration-base: 180ms;
  --duration-slow: 240ms;

  /* Typography */
  --font-sans: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-md: 16px;
  --text-lg: 18px;
  --text-xl: 22px;
  --text-2xl: 28px;
  --line-tight: 1.25;
  --line-normal: 1.5;
  --line-relaxed: 1.65;

  /* Spacing - 8px scale, 4px step */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 40px;
  --space-8: 48px;
  --space-9: 64px;

  --sidebar-width: 240px;
  --sidebar-width-collapsed: 76px;

  /* === Legacy aliases ===
     Every existing rule below this point still references these names
     (--page, --card, --accent, etc) - ~250 usages across this file.
     Rather than rewrite every one in a single pass (high risk of breaking
     something), they're aliased to the real tokens above so the whole app
     repaints to the UNIFYRA palette correctly right now. Component work in
     later passes (buttons, sidebar, tables) will migrate call sites to the
     real token names directly and these aliases can shrink over time. */
  --page: var(--page-bg);
  --card: var(--surface-primary);
  --card-elevated: var(--surface-secondary);
  --card-hover: var(--surface-secondary);
  --border: var(--border-subtle);
  --border-strong: var(--border-default);
  --text: var(--text-primary);
  --muted: var(--text-muted);
  --muted-soft: var(--text-muted-soft);

  /* Neomorphism pass: sidebar is now the SAME pure white as the content
     area (a colored/dark rail would break the monochrome soft-UI look),
     separated from the content only by --shadow-sm on its own right edge.
     Active/hover read via shadow + a colored icon, not a fill block. */
  --sidebar: var(--page-bg);
  --sidebar-hover: rgba(16, 33, 58, 0.04);
  --sidebar-active: transparent;
  --sidebar-active-ink: var(--brand-500);
  --sidebar-text: var(--text-secondary);
  --sidebar-text-dim: var(--text-muted);

  --accent: var(--action-primary);
  --accent-ink: var(--text-on-brand);
  --accent-soft: var(--surface-brand-soft);
  --accent-soft-strong: rgba(33, 150, 243, 0.18);
  --accent-strong: var(--action-primary-hover);

  /* Base/unclassed buttons render as Secondary (most buttons in this app -
     Refresh, Tutup, Lihat Order, Download, etc); the explicit ID list below
     the button rules opts specific primary actions (Simpan, Trigger,
     Proses) into --action-primary fill instead. */
  --ink-fill: var(--surface-primary);
  --ink-fill-ink: var(--text-primary);
  --ok: var(--success);
  --ok-soft: var(--success-soft);
  --fail: var(--danger);
  --fail-soft: var(--danger-soft);
  --warn: var(--warning);
  --warn-soft: var(--warning-soft);

  --shadow-card: var(--shadow-sm);
  --shadow-focus: 0 0 0 3px var(--focus-ring);
  --radius-card: var(--radius-lg);

  --font-xs: var(--text-xs);
  --font-sm: var(--text-sm);
  --font-base: var(--text-base);
  --font-md: var(--text-md);
  --font-lg: var(--text-lg);
  --font-xl: var(--text-xl);
  --font-2xl: var(--text-2xl);
  --font-3xl: 32px;

  --transition-fast: var(--duration-fast) var(--ease-out);
  --transition-base: var(--duration-base) var(--ease-out);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--page-bg);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--line-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- App shell: fixed dark sidebar + light main area --- */
.app-shell {
  display: flex;
  align-items: stretch;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 var(--sidebar-width);
  width: var(--sidebar-width);
  /* Neomorphism: flat, same white as the page - only a soft shadow on the
     right edge separates it from the content area, no gradient/fill line. */
  background: var(--sidebar);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 5;
  transition: width var(--duration-base) var(--ease-out), flex-basis var(--duration-base) var(--ease-out);
  overflow: hidden;
}
.app-shell.sidebar-collapsed .sidebar {
  flex-basis: var(--sidebar-width-collapsed);
  width: var(--sidebar-width-collapsed);
}
/* Label fade/shrink is timed with the sidebar's own width transition above
   (same duration+easing) instead of vanishing instantly via display:none,
   so collapsing reads as one smooth motion rather than a jump-cut. */
.sidebar-brand-text,
.sidenav-label,
.sidebar-account-text {
  opacity: 1;
  max-width: 180px;
  overflow: hidden;
  transition: opacity var(--duration-base) var(--ease-out), max-width var(--duration-base) var(--ease-out);
}
.app-shell.sidebar-collapsed .sidebar-brand-text,
.app-shell.sidebar-collapsed .sidenav-label,
.app-shell.sidebar-collapsed .sidebar-account-text {
  opacity: 0;
  max-width: 0;
}
/* .sidebar-brand switches to a COLUMN stack when collapsed (logo, then this
   text block, then the toggle) - collapsing only its WIDTH (above) leaves
   its two lines of (invisible) text still taking up real HEIGHT in that
   column, which is exactly the gap pushing the toggle button away from the
   logo. Collapse its height too, only in this column layout. */
.app-shell.sidebar-collapsed .sidebar-brand-text {
  max-height: 0;
  margin: 0;
}
.app-shell.sidebar-collapsed .sidebar-account { justify-content: center; }
/* gap must collapse to 0 too, not just the label's own width - flexbox
   "gap" still reserves space between items even when one shrinks to
   max-width:0, which was pushing the icon off-center inside the collapsed
   (icon-only) button instead of true-centering it. */
.app-shell.sidebar-collapsed .sidenav-item { justify-content: center; padding: 10px 0; gap: 0; }
.app-shell.sidebar-collapsed .sidenav-item:not(.active):not(:hover) { background: transparent; }
/* Collapsed: items were all packed at the top with a big empty gap before
   the footer, needing no scroll but looking cramped/unbalanced. Spread them
   evenly down the whole available height instead - starting right under the
   toggle, not pushed down with extra top padding. */
.app-shell.sidebar-collapsed .sidebar-nav {
  justify-content: space-evenly;
  gap: 0;
}
/* Badge + collapse button side-by-side (34px + 12px gap + 24px = 70px) don't
   fit the 76px collapsed width once the brand's own 18px side padding is
   subtracted (only 40px left) - they were overflowing/clipping. Stack them
   instead so both stay fully visible and centered. */
/* Stacked, not side-by-side - squeezing both onto one row (even after
   shrinking the toggle button) made the logo itself look cramped/undersized.
   Stacking lets the logo stay full size; the toggle sits centered below it. */
.app-shell.sidebar-collapsed .sidebar-brand {
  flex-direction: column;
  padding: 16px 8px 8px;
  gap: 4px;
}
.app-shell.sidebar-collapsed .sidebar-collapse-btn {
  width: 24px;
  height: 24px;
  font-size: 13px;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 20px 18px;
  flex-shrink: 0;
  cursor: pointer;
  border-radius: var(--radius-md, 10px);
  transition: background var(--duration-base) var(--ease-out);
}
.sidebar-brand:hover { background: var(--surface-hover, rgba(0, 0, 0, 0.04)); }
/* The collapse toggle sits inside the now-clickable brand block but must
   keep its own separate click target, not the "go to Dashboard" one. */
.sidebar-brand .sidebar-collapse-btn { cursor: pointer; }
/* Full mark (with the sidebar-brand-text label) shows expanded; icon-only
   mark takes over once collapsed - swapped via the same .sidebar-collapsed
   ancestor class as the rest of the collapse behavior. */
.brand-logo-full { height: 34px; width: auto; flex-shrink: 0; }
.brand-logo-icon { display: none; height: 34px; width: 34px; flex-shrink: 0; }
.app-shell.sidebar-collapsed .brand-logo-full { display: none; }
.app-shell.sidebar-collapsed .brand-logo-icon { display: block; }
.sidebar-brand-text { flex: 1; min-width: 0; }
.sidebar-brand-text strong {
  display: block;
  color: var(--text-primary);
  font-size: 16px;
  letter-spacing: -0.01em;
}

/* The logo's own "UNIFYRA" wordmark is vector art (CorelDRAW converted the
   text to curves), so this is the same typeface as a real font file instead
   of an approximation - used anywhere the brand name appears as a heading. */
@font-face {
  font-family: 'Unifyra Wordmark';
  src: url('UnifyraWordmark-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
.brand-wordmark {
  font-family: 'Unifyra Wordmark', 'Segoe UI', sans-serif;
  font-weight: 400;
}
.brand-tagline {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  line-height: 1.3;
  color: var(--text-muted);
}
.brand-tagline-login {
  font-size: 13px;
  color: var(--muted);
  margin: 4px 0 0;
  white-space: normal;
}
.sidebar-collapse-btn {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  /* Same min-height:38px floor issue as .help-toggle - without this, the
     circle gets stretched into an oval. */
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  background: var(--surface-primary);
  border-color: transparent;
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1;
  box-shadow: var(--shadow-xs);
}
.sidebar-collapse-btn:hover { background: var(--surface-primary); opacity: 1; filter: none; box-shadow: var(--shadow-xs); }
.sidebar-collapse-btn { transition: background-color var(--transition-fast), transform var(--transition-base); }
.sidebar-collapse-btn:active { transform: rotate(0deg) scale(0.92); filter: none; box-shadow: var(--shadow-inset); }
.app-shell.sidebar-collapsed .sidebar-collapse-btn:active { transform: rotate(180deg) scale(0.92); }
.app-shell.sidebar-collapsed .sidebar-collapse-btn { transform: rotate(180deg); }

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Thin, translucent-white scrollbar instead of the default OS gray one -
     that default one reads as a harsh, out-of-place light bar against the
     navy sidebar. Firefox via scrollbar-color, WebKit/Blink via the
     pseudo-elements below. */
  scrollbar-width: thin;
  scrollbar-color: rgba(16, 33, 58, 0.15) transparent;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.sidebar-nav::-webkit-scrollbar-thumb {
  background-color: rgba(16, 33, 58, 0.15);
  border-radius: var(--radius-pill);
}
.sidebar-nav::-webkit-scrollbar-thumb:hover { background-color: rgba(16, 33, 58, 0.28); }
.sidebar-nav::-webkit-scrollbar-button { display: none; height: 0; width: 0; }
.sidenav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  /* Idle: flat, blends into the sidebar - no fill/border, matches the
     monochrome neomorphic panel around it. */
  background: transparent;
  border-color: transparent;
  color: var(--text-secondary);
  text-align: left;
  box-shadow: none;
  transition: background-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
}
.sidenav-icon { width: 18px; height: 18px; flex-shrink: 0; transition: transform var(--transition-fast); }
.sidenav-label { font-size: var(--font-base); font-weight: 600; white-space: nowrap; }
.sidenav-item:hover { background: var(--sidebar-hover); opacity: 1; filter: none; box-shadow: none; border-color: transparent; color: var(--text-primary); }
.sidenav-item:hover .sidenav-icon { transform: translateX(1px); }
/* Active state never relies on color alone - a pressed-in (inset) shadow
   AND a colored icon/label AND bolder weight all change together. */
.sidenav-item.active {
  background: var(--surface-primary);
  color: var(--sidebar-active-ink);
  font-weight: 700;
  box-shadow: var(--shadow-inset);
}
.app-shell.sidebar-collapsed .sidenav-item.active { box-shadow: var(--shadow-inset); }
.sidenav-item:active { transform: none; filter: none; }
.sidenav-item-debug { margin-top: 2px; }
.sidenav-divider {
  height: 1px;
  background: rgba(16, 33, 58, 0.1);
  margin: 8px 8px;
  flex-shrink: 0;
}

/* 2-level nav: a category button (Proses / Pengaturan / Admin & Lanjutan)
   opens a floating flyout of its own sub-pages instead of navigating
   directly - same pattern as JSTERP's own sidebar. The caret just mirrors
   whether that category's flyout is currently open. */
.sidenav-caret {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  margin-left: auto;
  opacity: 0.55;
  transition: transform var(--transition-fast);
}
.sidenav-category.flyout-open .sidenav-caret { transform: rotate(90deg); }
.app-shell.sidebar-collapsed .sidenav-caret { display: none; }

.sidenav-flyout {
  position: fixed;
  top: 0;
  left: var(--sidebar-width);
  height: 100vh;
  width: 260px;
  background: var(--surface-primary);
  box-shadow: var(--shadow-md);
  z-index: 6;
  padding: 18px 10px;
  overflow-y: auto;
  transition: left var(--duration-base) var(--ease-out);
}
.app-shell.sidebar-collapsed .sidenav-flyout { left: var(--sidebar-width-collapsed); }
.sidenav-flyout-group { display: none; flex-direction: column; gap: 2px; }
.sidenav-flyout-group.active { display: flex; }
.sidenav-flyout-heading {
  font-size: var(--font-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--sidebar-text-dim);
  padding: 6px 12px 10px;
}
.sidenav-flyout-item {
  display: block;
  width: 100%;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  background: transparent;
  border-color: transparent;
  color: var(--text-secondary);
  text-align: left;
  font-size: var(--font-base);
  font-weight: 600;
  box-shadow: none;
  transition: background-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
}
.sidenav-flyout-item:hover { background: var(--sidebar-hover); opacity: 1; filter: none; box-shadow: none; color: var(--text-primary); }
.sidenav-flyout-item.active {
  background: var(--surface-secondary);
  color: var(--sidebar-active-ink);
  font-weight: 700;
  box-shadow: var(--shadow-inset);
}
.sidenav-flyout-item:active { transform: none; filter: none; }
/* Back button - mobile only (see the 860px breakpoint below), lets the
   flyout act as its own full-screen step instead of a floating side panel
   there's no room for. */
.sidenav-flyout-back { display: none; }

.sidebar-footer {
  flex-shrink: 0;
  padding: 12px;
  border-top: none;
  box-shadow: inset 0 1px 0 rgba(16, 33, 58, 0.08);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sidebar-account {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: var(--radius-md);
  min-width: 0;
}
.sidebar-account-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--accent-strong);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
}
.sidebar-account-text { min-width: 0; }
.sidebar-account-email {
  display: block;
  color: var(--text-primary);
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-account-role { display: block; color: var(--sidebar-text-dim); font-size: var(--font-xs); }
.sidebar-account {
  transition: background-color var(--transition-fast);
}
.sidebar-account:hover { background: var(--sidebar-hover); }
.sidebar-logout {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--surface-primary);
  color: var(--sidebar-text);
  border: none;
  font-size: var(--font-sm);
  padding: 8px 12px;
  width: 100%;
  box-shadow: var(--shadow-xs);
}
.sidebar-logout-icon { width: 16px; height: 16px; flex-shrink: 0; }
.sidebar-logout-label {
  overflow: hidden;
  white-space: nowrap;
  transition: opacity var(--duration-base) var(--ease-out), max-width var(--duration-base) var(--ease-out);
}
.sidebar-logout:hover { background: var(--surface-primary); color: var(--danger); opacity: 1; filter: none; box-shadow: var(--shadow-xs); }
.sidebar-logout:active { filter: none; box-shadow: var(--shadow-inset); }
/* Collapsed: icon-only, no cramped/truncated "Keluar" text. */
.app-shell.sidebar-collapsed .sidebar-logout { padding: 8px 0; }
.app-shell.sidebar-collapsed .sidebar-logout-label { opacity: 0; max-width: 0; }

/* --- Main content area --- */
.main-area { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.main-topbar {
  padding: 22px clamp(18px, 3vw, 36px) 0;
  flex-shrink: 0;
}
.main-topbar-row { display: flex; align-items: flex-start; gap: var(--space-3); }
.main-topbar-heading { min-width: 0; }
.main-topbar h1 { margin: 0; font-size: var(--font-2xl); font-weight: 800; letter-spacing: -0.02em; }
.main-topbar .subtitle { margin: 4px 0 0; color: var(--muted); font-size: var(--font-base); }

/* Hamburger + drawer are desktop-invisible - the collapse-to-icons sidebar
   already handles narrow-but-not-mobile widths. */
.mobile-nav-toggle {
  display: none;
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  min-height: 0;
  padding: 0;
  align-items: center;
  justify-content: center;
  color: var(--text-primary);
}
.mobile-nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(16, 33, 58, 0.4);
  z-index: 40;
  animation: fadeIn var(--duration-fast) var(--ease-out);
}
.mobile-nav-backdrop[hidden] { display: none; }

.content {
  flex: 1;
  padding: 18px clamp(18px, 3vw, 36px) 60px;
  max-width: 1320px;
}

.view { display: none; }
.view.active { display: block; animation: fadeIn var(--transition-base); }

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Shared "elegant loading" marker - a small spinning ring next to text,
   used wherever a list/panel shows a "Memuat..." state instead of plain
   static text. */
.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  animation: spin 0.7s linear infinite;
  vertical-align: -2px;
  margin-right: 8px;
}
.loading-text { color: var(--muted); font-size: var(--font-base); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

@media (max-width: 860px) {
  /* Below this width the sidebar stops being an inline column (collapse-to-
     icons doesn't work well once there's no room beside it anyway) and
     becomes an off-canvas drawer instead - opened by the hamburger button,
     never a row of nav buttons wrapping across the top of the page. */
  .sidebar-collapse-btn { display: none; }
  .mobile-nav-toggle { display: flex; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    width: min(300px, 84vw);
    flex-basis: min(300px, 84vw);
    transform: translateX(-100%);
    transition: transform var(--duration-base) var(--ease-out);
    z-index: 50;
  }
  .app-shell.sidebar-collapsed .sidebar { width: min(300px, 84vw); flex-basis: min(300px, 84vw); }
  .app-shell.sidebar-collapsed .sidebar-brand-text,
  .app-shell.sidebar-collapsed .sidenav-label,
  .app-shell.sidebar-collapsed .sidebar-account-text {
    opacity: 1;
    max-width: 180px;
  }
  .app-shell.mobile-nav-open .sidebar { transform: translateX(0); }
  .app-shell.mobile-nav-open .mobile-nav-backdrop { display: block; }

  /* No room for a side-by-side flyout here - it takes over the full drawer
     instead, with its own back button to return to the top-level list
     (same open/close mechanics, just full-width instead of floating). */
  .sidenav-flyout {
    position: fixed;
    inset: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    z-index: 55;
    padding: 16px;
    transform: translateX(100%);
    transition: transform var(--duration-base) var(--ease-out);
  }
  .app-shell.sidebar-collapsed .sidenav-flyout { left: 0; }
  .sidenav-flyout.mobile-open { transform: translateX(0); }
  .sidenav-flyout-back {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 10px 12px;
    margin-bottom: 10px;
    border-radius: var(--radius-md);
    background: var(--surface-secondary);
    color: var(--text-secondary);
    font-weight: 600;
    box-shadow: none;
  }
}

h2 { margin: 0 0 8px; font-size: var(--font-lg); font-weight: 700; letter-spacing: -0.01em; }
.card-subtitle { margin: 0 0 6px; font-size: var(--font-sm); font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }
.group-label {
  margin: 0 0 10px 2px;
  font-size: var(--font-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 22px 24px;
  margin-bottom: 14px;
  animation: fadeSlideIn var(--transition-base);
}
.card:last-child { margin-bottom: 0; }

.hero {
  margin-bottom: 24px;
  background: var(--surface-primary);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}
.hero:has(#toggle-enabled:checked) {
  border-color: var(--border-brand);
  box-shadow: 0 0 0 1px var(--border-brand);
}

/* --- Dashboard stat cards --- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: 14px;
}
/* Small stagger so stat cards settle in one after another instead of all
   popping on the exact same frame - subtle, not a distraction. */
.stat-grid .stat-card:nth-child(1) { animation-delay: 0ms; }
.stat-grid .stat-card:nth-child(2) { animation-delay: 30ms; }
.stat-grid .stat-card:nth-child(3) { animation-delay: 60ms; }
.stat-grid .stat-card:nth-child(4) { animation-delay: 90ms; }
.stat-grid .stat-card:nth-child(5) { animation-delay: 120ms; }
.stat-grid .stat-card:nth-child(n+6) { animation-delay: 150ms; }
.stat-grid .stat-card { animation-fill-mode: backwards; }
.stat-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 18px 20px;
  animation: fadeSlideIn var(--transition-base);
  transition: box-shadow var(--transition-base), border-color var(--transition-base), transform var(--transition-base);
}
.stat-card:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); transform: translateY(-1px); }
.stat-card-label {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-size: var(--font-sm);
  font-weight: 600;
  margin-bottom: 10px;
}
.stat-card-icon {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: var(--accent-soft);
  color: var(--accent);
}
.stat-card-icon svg { width: 16px; height: 16px; }
.stat-card.stat-ok .stat-card-icon { background: var(--ok-soft); color: var(--ok); }
.stat-card.stat-warn .stat-card-icon { background: var(--warn-soft); color: var(--warn); }
.stat-card.stat-fail .stat-card-icon { background: var(--fail-soft); color: var(--fail); }
.stat-card-value { font-size: var(--font-3xl); font-weight: 800; letter-spacing: -0.02em; }
.stat-card-hint { margin-top: 4px; color: var(--muted); font-size: var(--font-sm); }

.segmented {
  display: inline-flex;
  padding: 3px;
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  gap: 2px;
}
.segmented button {
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--muted);
  font-size: var(--font-sm);
  font-weight: 600;
  box-shadow: none;
  transition: background-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
}
.segmented button:hover { opacity: 1; color: var(--text); filter: none; box-shadow: none; }
.segmented button:active { transform: none; filter: none; }
.segmented button.active { background: var(--card); color: var(--text); box-shadow: var(--shadow-xs); }

/* Custom date-range calendar popup, opened from the "Custom" segment. */
.calendar-popup {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 30;
  width: 300px;
  padding: 16px;
  background: var(--surface-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  animation: fadeSlideIn var(--duration-base) var(--ease-out);
}
.calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.calendar-month-label {
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 4px 0;
  min-height: 0;
  font-weight: 700;
  font-size: var(--font-base);
  color: var(--text-primary);
}
.calendar-month-label:hover { background: transparent; opacity: 1; filter: none; }
.calendar-nav-btn {
  width: 26px;
  height: 26px;
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border-color: transparent;
  color: var(--text-secondary);
  font-size: 15px;
}
.calendar-nav-btn:hover { background: var(--surface-secondary); border-color: transparent; }
.calendar-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 4px;
}
.calendar-weekdays span {
  text-align: center;
  font-size: var(--font-xs);
  font-weight: 700;
  color: var(--text-muted);
}
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  row-gap: 4px;
}
.calendar-day {
  aspect-ratio: 1;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: transparent;
  border-color: transparent;
  min-height: 0;
  padding: 0;
  font-size: var(--font-sm);
  font-weight: 600;
  color: var(--text-primary);
  transition: background-color var(--transition-fast), color var(--transition-fast);
}
.calendar-day:hover { background: var(--surface-secondary); border-color: transparent; }
.calendar-day:disabled { visibility: hidden; }
.calendar-day.is-today { box-shadow: inset 0 0 0 1.5px var(--brand-500); }
.calendar-day.is-selected-start,
.calendar-day.is-selected-end {
  background: #90caf9;
}
.calendar-day.is-in-range { background: #90caf9; border-radius: 0; }
.calendar-day.is-selected-start.is-in-range { border-radius: 50% 0 0 50%; }
.calendar-day.is-selected-end.is-in-range { border-radius: 0 50% 50% 0; }
.calendar-hint { margin: 10px 0 0; text-align: center; font-size: var(--font-xs); }

.help-toggle {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  /* The base button rule sets min-height:38px for normal-sized buttons -
     without overriding it here, that floor wins over this button's own
     smaller height, stretching the circle into an oval. */
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  background: var(--card-hover);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: var(--font-xs);
  font-weight: 700;
  line-height: 1;
  box-shadow: none;
  transition: color var(--transition-fast), border-color var(--transition-fast), background-color var(--transition-fast);
}
.help-toggle:hover { color: var(--text); border-color: var(--accent); opacity: 1; filter: none; box-shadow: none; }
.help-toggle:active { transform: none; filter: none; }
.help-toggle.active { background: var(--accent-soft); color: var(--accent-strong); border-color: var(--accent); }

.help-body {
  display: none;
  margin-top: 10px;
  padding: 14px 16px;
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--font-base);
  color: var(--muted);
  line-height: 1.6;
}
.help-body.open { display: block; animation: fadeSlideIn var(--transition-base); }
.help-body p { margin: 0 0 8px; }
.help-body p:last-child { margin-bottom: 0; }
.help-body ul { margin: 8px 0 0; padding-left: 18px; }
.help-body li { margin-bottom: 4px; }

.field-row { margin-bottom: 16px; }
.field-row:last-child { margin-bottom: 0; }
.field-row > label { display: block; margin-bottom: 6px; }

.row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.space-between { justify-content: space-between; }
.muted { color: var(--muted); font-size: var(--font-base); }

label { font-size: var(--font-base); color: var(--text); }

input[type="text"], input[type="password"], input[type="date"], input[type="time"] {
  /* flex:1 alone only sizes an input when its direct parent happens to be a
     flex container (e.g. .password-field) - a plain input dropped straight
     into a block-level wrapper like .field-row (no wrapper div) got the
     browser's tiny intrinsic default width instead, which is exactly what
     made the login page's Username field render narrower than Password.
     width:100% makes every plain text/password/date/time input fill its
     container regardless of what that container's own display is. */
  width: 100%;
  flex: 1;
  min-width: 200px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--page);
  color: var(--text);
  font-size: var(--font-md);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast), background-color var(--transition-fast);
}
input[type="text"]:focus, input[type="password"]:focus, input[type="date"]:focus, input[type="time"]:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--card);
  box-shadow: var(--shadow-focus);
}
input::placeholder { color: var(--muted-soft); }

button {
  min-height: 38px;
  padding: 0 16px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--ink-fill);
  color: var(--ink-fill-ink);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--font-base);
  font-weight: 600;
  letter-spacing: -0.01em;
  transition:
    background-color var(--duration-base) var(--ease-out),
    border-color var(--duration-base) var(--ease-out),
    color var(--duration-base) var(--ease-out),
    box-shadow var(--duration-base) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
  white-space: nowrap;
  box-shadow: var(--shadow-xs);
}
button:hover { background: var(--ink-fill); border-color: transparent; transform: translateY(-1px); box-shadow: var(--shadow-sm); }
button:active { transform: translateY(0) scale(0.98); box-shadow: var(--shadow-inset); }
button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }
button:disabled { opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: var(--shadow-xs); }
button:disabled:hover { background: var(--ink-fill); border-color: var(--border-default); transform: none; box-shadow: var(--shadow-xs); }

/* Primary action buttons - the real "start work" / "save" CTAs, filled with
   the brand color per spec (#0D47A1 reserved for high-priority actions),
   everything else stays Secondary (the base button style above). */
#save-employee, #save-shipper, #save-dispatch-delay, #save-restrict, #save-exclude,
#save-jubelio-credentials, #admin-create-tenant,
#add-print-agent,
#trigger-picklist, #trigger-print, #trigger-dispatch,
#manual-picklist, #manual-print-resi, #manual-siap-kirim,
#manual-selesaikan, #manual-buat-pengiriman, #manual-panggil-driver,
#reguler-refresh-btn,
.admin-link-user-btn, .reguler-process-btn,
.btn-primary {
  background: var(--action-primary);
  border-color: var(--action-primary);
  color: var(--text-on-brand);
}
#save-employee:hover, #save-shipper:hover, #save-dispatch-delay:hover, #save-restrict:hover, #save-exclude:hover,
#save-jubelio-credentials:hover, #admin-create-tenant:hover,
#add-print-agent:hover,
#trigger-picklist:hover, #trigger-print:hover, #trigger-dispatch:hover,
#manual-picklist:hover, #manual-print-resi:hover, #manual-siap-kirim:hover,
#manual-selesaikan:hover, #manual-buat-pengiriman:hover, #manual-panggil-driver:hover,
#reguler-refresh-btn:hover,
.admin-link-user-btn:hover, .reguler-process-btn:hover,
.btn-primary:hover {
  background: var(--action-primary-hover);
  border-color: var(--action-primary-hover);
}
#save-employee:active, #save-shipper:active, #save-dispatch-delay:active, #save-restrict:active, #save-exclude:active,
#save-jubelio-credentials:active, #admin-create-tenant:active,
#add-print-agent:active,
#trigger-picklist:active, #trigger-print:active, #trigger-dispatch:active,
#manual-picklist:active, #manual-print-resi:active, #manual-siap-kirim:active,
#manual-selesaikan:active, #manual-buat-pengiriman:active, #manual-panggil-driver:active,
#reguler-refresh-btn:active,
.admin-link-user-btn:active, .reguler-process-btn:active,
.btn-primary:active {
  background: var(--action-primary-active);
  border-color: var(--action-primary-active);
}

/* Danger - every "Hapus" button in the app already shares this one class
   (print agents, tenants, sub-accounts). */
.delete-print-agent,
.btn-danger {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: transparent;
  box-shadow: none;
}
.delete-print-agent:hover,
.btn-danger:hover {
  background: var(--danger);
  color: var(--text-on-brand);
  border-color: var(--danger);
}
.delete-print-agent:active,
.btn-danger:active { background: #991616; border-color: #991616; }

/* Tertiary/ghost - no fill or border at rest, for the lowest-emphasis
   actions (e.g. inline text-like buttons); not currently used anywhere but
   available for future components instead of every button defaulting to
   the bordered Secondary look. */
.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-secondary);
  box-shadow: none;
}
.btn-ghost:hover { background: var(--surface-secondary); border-color: transparent; color: var(--text-primary); }

/* Active-filter chip (e.g. "Verifikasi Resi"'s Riwayat Scan kurir filter) -
   icon + label on one line, explicitly centered since a plain button's
   default centering isn't reliable once it holds two separate inline
   children with different glyph metrics (the ✕ has a taller natural line-
   height than the label text, which pushed the whole line toward the top
   of the pill instead of centering it). */
.btn-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  line-height: 1;
}
.btn-chip-x { line-height: 1; }

/* Text-only link styled as a button - the courier name in the Ekspedisi
   summary table, which navigates to that courier's detail page on click. */
.link-btn {
  background: transparent;
  border: none;
  box-shadow: none;
  min-height: 0;
  padding: 0;
  color: var(--action-primary);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.link-btn:hover { background: transparent; opacity: 0.8; filter: none; box-shadow: none; }

/* "Kembali" back button on the dashboard detail page - the plain ghost
   look (transparent fill, no border) read as barely-there/hard to spot
   against the card's white background. Gives it a visible outline plus the
   requested hover/click feedback colors. */
#dashboard-detail-back {
  border: 1px solid var(--border-default);
}
#dashboard-detail-back:hover { background: #99c2ff; border-color: transparent; color: var(--text-primary); }
#dashboard-detail-back:active { background: #cfebff; border-color: transparent; }

/* Icon-only - square, centered, no visible label (aria-label required on
   the element itself). Sidebar collapse button already hand-rolls this
   look; this class is for icon buttons anywhere else in the app. */
.btn-icon {
  width: 38px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Button groups line up in a tidy grid instead of ragged wrapped pills. */
.btn-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
  margin: 14px 0 4px;
}
.btn-grid button { width: 100%; white-space: normal; }

.switch { position: relative; display: inline-block; width: 46px; height: 26px; flex-shrink: 0; }
.switch-lg { width: 54px; height: 30px; }
.switch input { opacity: 0; width: 0; height: 0; }
.slider {
  position: absolute; cursor: pointer; inset: 0;
  background-color: var(--border); border-radius: var(--radius-pill); transition: background-color var(--transition-base);
}
.slider::before {
  position: absolute; content: ""; height: 20px; width: 20px; left: 3px; bottom: 3px;
  background-color: #fff; border-radius: 50%; transition: transform var(--transition-base);
  box-shadow: var(--shadow-xs);
}
.switch-lg .slider::before { height: 24px; width: 24px; }
input:checked + .slider { background-color: var(--accent); }
input:checked + .slider::before { transform: translateX(20px); }
.switch-lg input:checked + .slider::before { transform: translateX(24px); }

.status-grid { display: grid; grid-template-columns: 1fr; gap: 10px; }
.status-grid > div {
  position: relative;
  padding-left: 16px;
  color: var(--text);
  font-size: 13.5px;
}
.status-grid > div::before {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-strong);
}
.status-grid strong { font-weight: 700; }

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--font-base); }
th, td { text-align: left; padding: 9px 8px; border-bottom: 1px solid var(--border); }
/* Critical data (order numbers, dates, status, actions) must never wrap -
   only free-text columns like Detail should reflow. The table itself can
   still scroll horizontally on narrow screens (.table-wrap above) instead. */
.td-nowrap { white-space: nowrap; }
th { color: var(--muted); font-weight: 600; font-size: var(--font-sm); text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
tr:last-child td { border-bottom: none; }
tbody tr { transition: background-color var(--transition-fast); }
tbody tr:hover { background: var(--card-hover); }
tbody tr.clickable-row { cursor: pointer; }

.badge-ok, .badge-fail {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  white-space: nowrap;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-weight: 700;
  font-size: var(--font-xs);
  letter-spacing: 0.02em;
}
.badge-ok { color: var(--ok); background: var(--ok-soft); }
.badge-fail { color: var(--fail); background: var(--fail-soft); }

.restrict-card { border-color: var(--border-brand); background: var(--surface-brand-soft); }

.log-group {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 8px;
  overflow: hidden;
  background: var(--card-elevated);
}
.log-group:last-child { margin-bottom: 0; }
.admin-tenant-inactive { opacity: 0.6; }
.log-group-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
  font-size: var(--font-base);
  user-select: none;
  transition: background-color var(--transition-fast);
}
.log-group-header:hover { background: var(--card-hover); }
.log-group-caret { width: 12px; color: var(--muted); flex-shrink: 0; }
.log-group-title { font-weight: 700; flex: 1; min-width: 0; overflow-wrap: break-word; }
.log-group-time { margin-left: auto; color: var(--muted); flex-shrink: 0; white-space: nowrap; }
.log-group-retry-actions { display: flex; gap: 6px; flex-shrink: 0; }
.log-retry-btn {
  min-height: 0;
  padding: 5px 10px;
  font-size: var(--font-xs);
  font-weight: 600;
  white-space: nowrap;
}
.log-retry-btn:disabled { opacity: 0.6; }

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(16, 33, 58, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}
.modal-box {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 22px 24px;
  width: 100%;
  max-width: 520px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}
.modal-box h3 { margin: 0; }
.reprint-modal-list {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-input, 8px);
  padding: 4px 0;
}
.reprint-modal-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: var(--font-sm);
}
.reprint-modal-row:last-child { border-bottom: none; }
.reprint-modal-row input[type="checkbox"] { flex-shrink: 0; }
.reprint-modal-order { flex: 1; min-width: 0; overflow-wrap: break-word; }
.reprint-modal-status { flex-shrink: 0; }
/* Smooth expand/collapse via the CSS grid 0fr/1fr trick - no JS height
   measuring needed, works even though the content inside is fully
   re-rendered on every toggle (loadLogs() re-fetches and rebuilds this).
   Padding lives on the inner wrapper, not this grid container, so the row
   genuinely collapses to 0 instead of being held open by its own padding. */
.log-group-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-base) var(--ease-out);
}
.log-group-body.open { grid-template-rows: 1fr; }
.log-group-body > .accordion-body-inner { min-height: 0; overflow: hidden; padding: 0 14px 14px; }
.log-group-body table { font-size: 12px; }

.log-date-group {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 10px;
  overflow: hidden;
  background: var(--card);
}
.log-date-group:last-child { margin-bottom: 0; }
.log-date-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  cursor: pointer;
  font-size: var(--font-lg);
  user-select: none;
  background: var(--card-elevated);
  transition: background-color var(--transition-fast);
}
.log-date-header:hover { background: var(--card-hover); }
.log-date-header .log-group-title { font-weight: 800; }
.log-date-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-base) var(--ease-out);
}
.log-date-body.open { grid-template-rows: 1fr; }
.log-date-body > .accordion-body-inner { min-height: 0; overflow: hidden; padding: 10px; }
.log-date-body .log-group { margin-bottom: 6px; }
.log-date-body .log-group:last-child { margin-bottom: 0; }

/* Label-left / actions-right list row - the label wraps and shrinks inside
   its own column, but the action buttons never get pushed onto their own
   line (the bug: plain .row's flex-wrap:wrap let a long label shove the
   whole button group down below instead of just wrapping its own text). */
.list-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: nowrap;
}
.list-row-label { min-width: 0; flex: 1 1 auto; overflow-wrap: break-word; }
.list-row-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }

@media (max-width: 560px) {
  /* Only on genuinely narrow screens does the label get the row to itself
     and actions drop below it - deliberate, not the same as the bug above. */
  .list-row { flex-wrap: wrap; }
  .list-row-actions { flex-basis: 100%; justify-content: flex-start; }
}

/* Proses Reguler group checkboxes only show up once "Pilih Gelombang" is
   active (#reguler-groups-list gets the .select-mode class) - otherwise the
   list looks the same as a single-select list. */
#reguler-groups-list .reguler-group-checkbox { display: none; }
#reguler-groups-list.select-mode .reguler-group-checkbox { display: inline-block; }

/* --- Login page (self-contained, not part of the app shell) ---
   One unified panel (not two stacked cards) on a quiet neutral page, with a
   single soft brand-tinted shape for compositional weight - no gradient, no
   blur/glow. Auth logic in login.html is untouched; only structure/classes. */
.auth-shell {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background: var(--page-bg);
  overflow: hidden;
}
.auth-shell-accent {
  position: absolute;
  top: -18%;
  right: -14%;
  width: 560px;
  height: 560px;
  border-radius: var(--radius-lg);
  transform: rotate(18deg);
  background: var(--surface-brand-soft);
  z-index: 0;
}
.auth-panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  background: var(--surface-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-7) var(--space-6);
}
.auth-brand { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-5); }
.auth-brand-mark { width: 32px; height: 32px; flex-shrink: 0; }
.auth-brand-word { font-size: var(--text-lg); color: var(--action-primary); }
.auth-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  line-height: var(--line-tight);
}
.auth-subtitle {
  margin: 0 0 var(--space-6);
  color: var(--text-secondary);
  font-size: var(--text-base);
  line-height: var(--line-relaxed);
}
.auth-google-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  background: var(--surface-primary);
  color: var(--text-primary);
}
.auth-error {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  color: var(--danger);
}
.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-5) 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.auth-divider::before, .auth-divider::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--border-subtle);
}
.auth-form .field-row { margin-bottom: var(--space-4); }
.auth-form .field-row:last-of-type { margin-bottom: 0; }

/* Reusable show/hide-password wrapper - used on the login form and any
   password field in the dashboard (Jubelio credentials, sub-account
   creation), not just login. */
.password-field { position: relative; display: flex; flex: 1; min-width: 200px; }
.password-field input { padding-right: 44px; width: 100%; }
.password-toggle {
  position: absolute;
  right: 2px;
  top: 2px;
  bottom: 2px;
  width: 38px;
  min-height: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-muted);
  box-shadow: none;
}
.password-toggle:hover { background: var(--surface-secondary); border: none; transform: none; color: var(--text-primary); }
.auth-submit-btn {
  width: 100%;
  margin-top: var(--space-5);
  background: var(--action-primary);
  border-color: var(--action-primary);
  color: var(--text-on-brand);
  position: relative;
}
.auth-submit-btn:hover { background: var(--action-primary-hover); border-color: var(--action-primary-hover); }
.auth-submit-btn:active { background: var(--action-primary-active); border-color: var(--action-primary-active); }
.auth-submit-btn.is-loading .auth-submit-label { visibility: hidden; }
.auth-submit-btn.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  animation: spin 0.7s linear infinite;
}
.auth-help {
  margin: var(--space-5) 0 0;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

@media (max-width: 520px) {
  .auth-shell { padding: var(--space-5); }
  .auth-panel { padding: var(--space-6) var(--space-5); box-shadow: none; border: none; }
  .auth-shell-accent { display: none; }
}
