/* ---------------------------------------------------------------- *
 * Design tokens (CSS custom properties)
 * Consumed by Tailwind config below via arbitrary values where needed.
 * Tailwind is loaded via the Play CDN in partials/shell/head.ejs — this
 * file handles the few things Tailwind doesn't cover in-config.
 * ---------------------------------------------------------------- */

:root {
  /* Neutrals */
  --app-bg: #f8fafc;              /* slate-50 */
  --app-surface: #ffffff;
  --app-surface-2: #f1f5f9;       /* slate-100 */
  --app-border: #e2e8f0;          /* slate-200 */
  --app-border-strong: #cbd5e1;   /* slate-300 */

  /* Text */
  --app-text: #0f172a;            /* slate-900 */
  --app-text-muted: #64748b;      /* slate-500 */
  --app-text-subtle: #94a3b8;     /* slate-400 */

  /* Brand / accent */
  --app-accent: #4f46e5;          /* indigo-600 */
  --app-accent-hover: #4338ca;    /* indigo-700 */
  --app-accent-soft: #eef2ff;     /* indigo-50 */

  /* Status */
  --app-success: #059669;         /* emerald-600 */
  --app-warn: #d97706;            /* amber-600 */
  --app-danger: #dc2626;          /* red-600 */

  /* Sidebar */
  --app-sidebar-bg: #0f172a;      /* slate-900 */
  --app-sidebar-bg-hover: #1e293b; /* slate-800 */
  --app-sidebar-text: #cbd5e1;    /* slate-300 */
  --app-sidebar-text-active: #ffffff;
  --app-sidebar-border: #1e293b;

  /* Shadows */
  --app-shadow-sm: 0 1px 2px 0 rgb(15 23 42 / 0.04);
  --app-shadow: 0 1px 3px 0 rgb(15 23 42 / 0.06), 0 1px 2px -1px rgb(15 23 42 / 0.06);
  --app-shadow-md: 0 4px 6px -1px rgb(15 23 42 / 0.08), 0 2px 4px -2px rgb(15 23 42 / 0.04);

  /* Radii */
  --app-radius: 8px;
  --app-radius-sm: 6px;
  --app-radius-lg: 12px;

  /* Motion */
  --app-ease: cubic-bezier(0.2, 0.6, 0.2, 1);
}

/* Reset body defaults so the Tailwind utility classes are what drives layout. */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
  background: var(--app-bg);
  color: var(--app-text);
  font-family:
    "Inter",
    ui-sans-serif,
    system-ui,
    -apple-system,
    "Segoe UI",
    Roboto,
    "Helvetica Neue",
    Arial,
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "cv02", "cv03", "cv04", "cv11";
}

* {
  box-sizing: border-box;
}

/* Tabular numerals for metrics — keeps digits aligned column-to-column. */
.num,
.num * {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* Fine-grained scrollbar inside the app shell (WebKit only). */
.app-scroll::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.app-scroll::-webkit-scrollbar-track {
  background: transparent;
}
.app-scroll::-webkit-scrollbar-thumb {
  background: var(--app-border-strong);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.app-scroll::-webkit-scrollbar-thumb:hover {
  background: #94a3b8;
  background-clip: content-box;
}

/* Skeleton shimmer. */
@keyframes app-skeleton-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
.skeleton {
  background: linear-gradient(90deg, #e2e8f0, #eef2f7, #e2e8f0);
  background-size: 200% 100%;
  animation: app-skeleton-pulse 1.4s ease-in-out infinite;
  border-radius: var(--app-radius-sm);
}

/* Focus ring — subtle, consistent. */
:focus-visible {
  outline: 2px solid var(--app-accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Buttons (Tailwind-friendly component classes). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border-radius: var(--app-radius-sm);
  font-weight: 500;
  padding: 0.5rem 0.875rem;
  transition: background 150ms var(--app-ease),
              border-color 150ms var(--app-ease),
              color 150ms var(--app-ease),
              box-shadow 150ms var(--app-ease);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn-primary {
  background: var(--app-accent);
  color: #fff;
  box-shadow: var(--app-shadow-sm);
}
.btn-primary:hover { background: var(--app-accent-hover); }
.btn-secondary {
  background: #fff;
  color: var(--app-text);
  border-color: var(--app-border);
}
.btn-secondary:hover { background: var(--app-surface-2); border-color: var(--app-border-strong); }
.btn-ghost {
  background: transparent;
  color: var(--app-text-muted);
}
.btn-ghost:hover { background: var(--app-surface-2); color: var(--app-text); }

/* App shell layout helpers. */
.app-shell { display: flex; min-height: 100%; }

/* -------------------------------------------------------------------
   Shell element-default normalizer
   -------------------------------------------------------------------
   Pages in this app use one of two heads:
     - head.ejs        → Tailwind preflight ON (aggressive reset)
     - head-compat.ejs → Bootstrap reboot + Tailwind preflight OFF
   Those two baselines leave native <h1>, <a>, <ul>, <p>, etc. with
   different default margins, link color/underline, and list padding.
   Tailwind utility classes on the shell markup can only override
   properties they set explicitly, so h1 margin-bottom / a underline
   leak through on compat pages and make the topbar + sidebar look
   subtly shorter/taller/offset vs. the same code on a clean page.

   These rules only neutralize the small set of native defaults that
   affect shell primitives, scoped to `.app-sidebar` and `.app-topbar`
   so page content is never touched.
   ------------------------------------------------------------------- */
.app-sidebar,
.app-topbar,
.app-sidebar *,
.app-topbar * {
  box-sizing: border-box;
}
/* Tailwind preflight-equivalent border reset.
   Tailwind's `border-b`, `border-t`, `border` utilities only set
   border-*-width; they assume preflight has already set
   `border-style: solid` on every element. On compat pages preflight
   is OFF, so those utilities produce zero-width-looking "none" borders
   and the sidebar dividers (brand row, user footer) disappear —
   making the layout look "uneven" vs the clean-head pages.
   Scoping to .app-sidebar / .app-topbar keeps this change out of
   Bootstrap page content. */
.app-sidebar, .app-topbar,
.app-sidebar *, .app-topbar *,
.app-sidebar *::before, .app-sidebar *::after,
.app-topbar *::before,  .app-topbar *::after {
  border-width: 0;
  border-style: solid;
  border-color: currentColor;
}
/* Tailwind preflight also sets media elements to `display: block`;
   without it, the sidebar brand icon <svg>/<img> (if ever used) and
   the topbar freshness badge icon can have baseline-gap quirks. */
.app-sidebar img, .app-sidebar svg, .app-sidebar video, .app-sidebar canvas,
.app-topbar  img, .app-topbar  svg, .app-topbar  video, .app-topbar  canvas {
  display: block;
  vertical-align: middle;
}
.app-sidebar h1, .app-sidebar h2, .app-sidebar h3,
.app-sidebar h4, .app-sidebar h5, .app-sidebar h6,
.app-sidebar p,  .app-sidebar figure, .app-sidebar blockquote,
.app-sidebar dl, .app-sidebar dd,
.app-topbar  h1, .app-topbar  h2, .app-topbar  h3,
.app-topbar  h4, .app-topbar  h5, .app-topbar  h6,
.app-topbar  p,  .app-topbar  figure {
  margin: 0;
}
.app-sidebar ul, .app-sidebar ol,
.app-topbar  ul, .app-topbar  ol {
  margin: 0;
  padding-left: 0;
  list-style: none;
}
.app-sidebar a,
.app-topbar  a {
  color: inherit;
  text-decoration: none;
}
.app-sidebar button,
.app-topbar  button {
  font-family: inherit;
  line-height: inherit;
}
/* Bootstrap sets form elements' line-height to 1.5 and adds a
   small border-color reset — irrelevant in the shell but forces a
   consistent baseline for the mobile hamburger <button>. */
.app-sidebar button,
.app-topbar  button {
  line-height: 1.5;
}
.app-sidebar {
  width: 256px;
  flex: 0 0 256px;
  background: var(--app-sidebar-bg);
  color: var(--app-sidebar-text);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  transition: width 200ms var(--app-ease);
}
.app-main {
  flex: 1 1 auto;
  min-width: 0; /* critical: allows inner overflow-x to work */
  display: flex;
  flex-direction: column;
}

@media (max-width: 1024px) {
  .app-sidebar {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 50;
    transform: translateX(-100%);
  }
  .app-sidebar.is-open { transform: translateX(0); }
  .app-sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgb(15 23 42 / 0.4);
    z-index: 40;
  }
  .app-sidebar-backdrop.is-open { display: block; }
}

/* Sidebar nav items. */
.app-nav-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.875rem;
  border-radius: var(--app-radius-sm);
  color: var(--app-sidebar-text);
  font-weight: 500;
  font-size: 0.875rem;
  text-decoration: none;
  transition: background 150ms var(--app-ease), color 150ms var(--app-ease);
}
.app-nav-item:hover { background: var(--app-sidebar-bg-hover); color: var(--app-sidebar-text-active); }
.app-nav-item.is-active {
  background: var(--app-sidebar-bg-hover);
  color: var(--app-sidebar-text-active);
}
.app-nav-item.is-active::before {
  content: "";
  width: 3px;
  height: 18px;
  background: var(--app-accent);
  border-radius: 2px;
  margin-left: -0.875rem;
  margin-right: 0.5rem;
}
.app-nav-icon {
  width: 1.125rem;
  height: 1.125rem;
  flex-shrink: 0;
  opacity: 0.85;
}
.app-nav-section {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--app-text-subtle);
  padding: 0 0.875rem;
  margin-top: 1rem;
  margin-bottom: 0.5rem;
}

/* Topbar. */
.app-topbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  height: 60px;
  padding: 0 1.5rem;
  background: var(--app-surface);
  border-bottom: 1px solid var(--app-border);
  position: sticky;
  top: 0;
  z-index: 30;
}

/* Content container. */
.app-content {
  padding: 1.5rem;
  flex: 1;
  overflow-y: auto;
}

/* Card primitive. */
.card-v2 {
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: var(--app-radius);
  box-shadow: var(--app-shadow-sm);
}
.card-v2-header {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--app-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}
.card-v2-title {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--app-text);
  margin: 0;
}
.card-v2-body { padding: 1.25rem; }
.card-v2-body.no-pad { padding: 0; }

/* KPI card. */
.kpi {
  background: var(--app-surface);
  border: 1px solid var(--app-border);
  border-radius: var(--app-radius);
  padding: 1.125rem 1.25rem;
  box-shadow: var(--app-shadow-sm);
  transition: box-shadow 150ms var(--app-ease), transform 150ms var(--app-ease);
}
.kpi:hover { box-shadow: var(--app-shadow-md); }
.kpi-label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--app-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.kpi-value {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--app-text);
  line-height: 1.15;
  margin-top: 0.375rem;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.kpi-delta {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--app-text-muted);
}
.kpi-delta.is-up { color: var(--app-success); }
.kpi-delta.is-down { color: var(--app-danger); }

/* Data tables. */
.table-v2 {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.table-v2 thead th {
  text-align: left;
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--app-text-muted);
  padding: 0.75rem 1.25rem;
  background: var(--app-surface-2);
  border-bottom: 1px solid var(--app-border);
  white-space: nowrap;
  /* Sticky header so column labels stay visible while rows scroll.
     Works against the nearest scrolling ancestor (the .app-content
     scroller on dashboard pages); harmless on non-scrolled tables. */
  position: sticky;
  top: 0;
  z-index: 2;
}
.table-v2 tbody td {
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--app-border);
  color: var(--app-text);
  font-variant-numeric: tabular-nums;
}
.table-v2 tbody tr:last-child td { border-bottom: none; }
.table-v2 tbody tr:hover { background: var(--app-surface-2); }

/* Sortable table column headers */
.table-v2 thead th.sortable {
  cursor: pointer;
  user-select: none;
  transition: background 0.15s, color 0.15s;
}
.table-v2 thead th.sortable:hover {
  background: var(--app-border);
  color: var(--app-text);
}
.table-v2 thead th.sort-active {
  color: var(--accent-600, #2563eb);
  background: var(--app-surface-2);
}
.sort-icon {
  display: inline-block;
  margin-left: 4px;
  font-style: normal;
  font-size: 0.65rem;
  opacity: 0.35;
  transition: opacity 0.15s;
  vertical-align: middle;
}
.table-v2 thead th.sort-active .sort-icon {
  opacity: 1;
}

/* Badge. */
.badge-v2 {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 999px;
  font-size: 0.6875rem;
  font-weight: 500;
  background: var(--app-surface-2);
  color: var(--app-text-muted);
}
.badge-v2.is-success { background: #ecfdf5; color: #047857; }
.badge-v2.is-warn    { background: #fffbeb; color: #b45309; }
.badge-v2.is-danger  { background: #fef2f2; color: #b91c1c; }
.badge-v2.is-accent  { background: var(--app-accent-soft); color: var(--app-accent-hover); }

/* Filter chips (date range, etc.) */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  border-radius: 999px;
  background: #fff;
  border: 1px solid var(--app-border);
  color: var(--app-text);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 150ms var(--app-ease), border-color 150ms var(--app-ease);
}
.chip:hover { background: var(--app-surface-2); border-color: var(--app-border-strong); }
.chip.is-active {
  background: var(--app-accent-soft);
  border-color: #c7d2fe;
  color: var(--app-accent-hover);
}
