/*
 * theme.css — WRITTEN BY THE PLATFORM. Do not edit.
 *
 * Palette: Your colours (custom)
 * Source colours: #09081c #101828 #667085 #f6f7f9 #ffffff #4338ca
 *
 * Every value below is either one of those five or derived from them, and each
 * one is contrast-corrected against this palette's own background. Consume
 * them with var(--token); never write a colour value in app code.
 */

:root {
  --canvas: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #eef0f4;
  --border: #e6e8ee;
  --border-strong: #afafb7;
  --ink: #101828;
  --muted: #667085;
  --accent: #4338ca;
  --accent-hover: #372fb0;
  --accent-ink: #ffffff;
  --accent-text: #4338ca;
  --accent-strong: #4338ca;
  --accent-soft: #dddcf2;
  --accent-border: #a5a1e4;
  --success: #15803d;
  --success-ink: #ffffff;
  --success-soft: #dbe9e2;
  --success-strong: #137638;
  --warning: #b45309;
  --warning-ink: #ffffff;
  --warning-soft: #eee3dc;
  --warning-strong: #a64c08;
  --danger: #b91c1c;
  --danger-ink: #ffffff;
  --danger-soft: #efddde;
  --danger-strong: #b91c1c;}

/* The same palette on a dark page — written here, never by the app. It
   applies while <html> carries data-theme="dark", which the platform's own
   toggle sets and remembers; an app that never renders that toggle is exactly
   as it was. Do not repoint any of these from app code: a token that
   references another token here is a cycle, and CSS makes every property in
   a cycle invalid. */
html[data-theme="dark"] {
  --canvas: #070614;
  --surface: #201f2c;
  --surface-2: #131220;
  --border: #2a2935;
  --border-strong: #51515b;
  --ink: #f6f7f9;
  --muted: #96979d;
  --accent: #4338ca;
  --accent-hover: #5f56d2;
  --accent-ink: #ffffff;
  --accent-text: #7970d9;
  --accent-strong: #847bdc;
  --accent-soft: #14113c;
  --accent-border: #221c66;
  --success: #15803d;
  --success-ink: #ffffff;
  --success-soft: #0a211d;
  --success-strong: #499c68;
  --warning: #b45309;
  --warning-ink: #ffffff;
  --warning-soft: #2d1712;
  --warning-strong: #c57a40;
  --danger: #b91c1c;
  --danger-ink: #ffffff;
  --danger-soft: #2e0b16;
  --danger-strong: #d16969;
}

/* ====================================================================
 * app.css — NTS Workforce's own stylesheet.
 * Loads after design.css and theme.css, so everything here wins.
 * Every colour is a var(--token) from theme.css — nothing here is a
 * literal hex/rgb/hsl. ==================================================================== */

/* ---- Retune: a corporate HR console with a little more warmth --------- */
:root {
  --radius-sm: 4px;
  --radius: 7px;
  --radius-lg: 10px;
  --shadow: 0 1px 2px color-mix(in srgb, var(--ink) 4%, transparent);
  --shadow-raised: 0 1px 2px color-mix(in srgb, var(--ink) 5%, transparent),
    0 6px 16px color-mix(in srgb, var(--ink) 6%, transparent);
  --nts-glow: 0 10px 30px -10px color-mix(in srgb, var(--accent) 45%, transparent);
}

/* ====================================================================
 * ENTRANCE MOTION — a small, consistent rise-and-fade used for anything
 * that should feel like it just arrived: table rows, grid cards, the
 * hero. Delays are staggered per row/card so a list draws in like a
 * ripple instead of a single flat pop.
 * ==================================================================== */
@keyframes nts-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes nts-pop {
  from { opacity: 0; transform: scale(0.96) translateY(6px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes nts-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}
@keyframes nts-drift {
  0%   { transform: translate(0, 0) scale(1); }
  50%  { transform: translate(-10px, 12px) scale(1.06); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes nts-pulse-ring {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); }
  70%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}
@keyframes nts-shimmer-bar {
  0%   { background-position: 0% 0; }
  100% { background-position: 200% 0; }
}

[data-animate] .table tbody tr,
.page > .grid-auto-md > *,
.page > .grid-2 > .card,
.page > .grid-3 > .card {
  animation: nts-rise 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
[data-animate] .grid-auto-md > * { animation: nts-pop 0.4s cubic-bezier(0.16, 1, 0.3, 1) both; }

/* Stagger — first ~14 siblings step forward, the rest share the tail delay. */
[data-animate] .table tbody tr:nth-child(1),  .page > .grid-auto-md > *:nth-child(1)  { animation-delay: 0.01s; }
[data-animate] .table tbody tr:nth-child(2),  .page > .grid-auto-md > *:nth-child(2)  { animation-delay: 0.05s; }
[data-animate] .table tbody tr:nth-child(3),  .page > .grid-auto-md > *:nth-child(3)  { animation-delay: 0.09s; }
[data-animate] .table tbody tr:nth-child(4),  .page > .grid-auto-md > *:nth-child(4)  { animation-delay: 0.13s; }
[data-animate] .table tbody tr:nth-child(5)   { animation-delay: 0.17s; }
[data-animate] .table tbody tr:nth-child(6)   { animation-delay: 0.21s; }
[data-animate] .table tbody tr:nth-child(7)   { animation-delay: 0.25s; }
[data-animate] .table tbody tr:nth-child(8)   { animation-delay: 0.29s; }
[data-animate] .table tbody tr:nth-child(9)   { animation-delay: 0.33s; }
[data-animate] .table tbody tr:nth-child(10)  { animation-delay: 0.37s; }
[data-animate] .table tbody tr:nth-child(n+11) { animation-delay: 0.4s; }
[data-animate] .grid-auto-md > *:nth-child(n+5) { animation-delay: 0.16s; }

.page > .grid-2 > .card:nth-child(1) { animation-delay: 0.05s; }
.page > .grid-2 > .card:nth-child(2) { animation-delay: 0.12s; }
.page > .card-flush { animation: nts-rise 0.45s cubic-bezier(0.16, 1, 0.3, 1) 0.16s both; }
.page > .rounded-2xl:first-child { animation: nts-rise 0.5s cubic-bezier(0.16, 1, 0.3, 1) both; }

/* ====================================================================
 * SIDEBAR — a flat white column at a narrower, denser width. Everything
 * else about .sidebar (the sticky column, the border, the padding) is the
 * component as it comes.
 * ==================================================================== */
@media (min-width: 901px) {
  .shell, .shell-sidebar { grid-template-columns: 248px minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .sidebar { width: min(280px, 84vw); }
}

/* The brand mark gets real depth — this is new furniture (a wordmark
   tile), not a component the platform already ships. */
.brand-mark {
  background: linear-gradient(135deg, var(--accent), var(--accent-hover));
  box-shadow: var(--nts-glow);
  animation: nts-pop 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* The company's own logo, in place of a text mark — new furniture too. */
.brand-logo {
  height: 34px;
  width: auto;
  display: block;
  animation: nts-pop 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* The nav's own pending-leave count — sized to sit quietly in a nav row,
   never below the type floor. */
.nav-count {
  font-size: var(--t-xs);
  line-height: 1;
  padding: 2px 7px;
  animation: nts-pulse-ring 2.4s ease-out infinite;
}

.sidebar-foot { padding-bottom: var(--s-2); }
.sidebar-foot .avatar {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--accent-border);
}

/* Grouped nav — a labelled section needs air above it that the raw
   `.nav-label` rule does not carry on its own (it only sets the gap below
   itself), and the FIRST group (Dashboard, unlabelled) must not get it. */
.sidebar .nav-label { margin-top: var(--s-2); }

/* ====================================================================
 * TOPBAR — a quick directory search and a notifications bell, both new
 * furniture the flat topbar was missing. Sized to sit quietly beside the
 * theme toggle and to shrink before anything overflows.
 * ==================================================================== */
.topbar-search {
  flex: 1 1 240px;
  max-width: 360px;
  min-width: 0;
}
.topbar-search .input { height: 38px; background: var(--surface-2); border-color: transparent; }
.topbar-search .input:hover { border-color: var(--border); }
.topbar-search .input:focus { background: var(--surface); border-color: var(--accent); }

.topbar-actions details.dropdown > summary.btn-icon { position: relative; }
.notif-dot {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--t-xs);
  line-height: 1;
  box-shadow: 0 0 0 2px var(--canvas);
}
.notif-menu { width: 280px; max-width: calc(100vw - 32px); }
.notif-menu .menu-item { white-space: normal; align-items: flex-start; }
.notif-empty { color: var(--muted); cursor: default; }
.notif-empty:hover { background: transparent; }

@media (max-width: 720px) {
  .topbar-search { display: none; }
}

/* ====================================================================
 * HERO — the dashboard greeting band gets two soft drifting light pools
 * instead of a flat gradient fill, kept behind the copy with z-index.
 * This is a one-off screen element, not a reusable component.
 * ==================================================================== */
.page > .rounded-2xl.bg-gradient-to-br {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.page > .rounded-2xl.bg-gradient-to-br::before,
.page > .rounded-2xl.bg-gradient-to-br::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent-ink) 35%, transparent);
  filter: blur(30px);
  z-index: -1;
  animation: nts-drift 9s ease-in-out infinite;
}
.page > .rounded-2xl.bg-gradient-to-br::before {
  width: 220px;
  height: 220px;
  top: -90px;
  right: 8%;
}
.page > .rounded-2xl.bg-gradient-to-br::after {
  width: 160px;
  height: 160px;
  bottom: -80px;
  left: 20%;
  animation-delay: -4s;
  animation-duration: 11s;
}
.page > .rounded-2xl.bg-gradient-to-br .hero-date {
  position: relative;
  background: color-mix(in srgb, var(--primary-ink) 16%, transparent);
  color: var(--primary-ink);
  border: 1px solid color-mix(in srgb, var(--primary-ink) 24%, transparent);
}
.page > .rounded-2xl.bg-gradient-to-br .btn {
  transition: transform var(--dur-2, 0.2s) var(--ease-out, ease), box-shadow var(--dur-2, 0.2s) var(--ease-out, ease);
}
.page > .rounded-2xl.bg-gradient-to-br .btn:hover { transform: translateY(-2px); }

/* ====================================================================
 * STAT & DEPARTMENT GRIDS — a restrained icon-tile lift, and each card
 * gets a slim accent rail on hover. Scoped to this app's own grid
 * layout, not a redeclaration of .card itself.
 * ==================================================================== */
.grid-auto-md > .card:hover .size-9,
.grid-auto-md > .card:hover .size-10 {
  transform: scale(1.06);
}
.size-9, .size-10 {
  transition: transform var(--dur-2, 0.2s) var(--ease-out, ease);
}

.grid-auto-md > .card {
  position: relative;
}
.grid-auto-md > .card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-hover));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-3, 0.3s) var(--ease-out, ease);
}
.grid-auto-md > .card:hover::before { transform: scaleX(1); }

/* Denser, table-forward reading rhythm — one property on the component's
   own heading cells, not a redeclaration of the table itself. */
.table thead th {
  font-size: var(--t-xs);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  font-weight: var(--fw-semi);
}

/* Table rows: a soft accent rail that slides in on hover, and the row's
   avatar nudges up slightly. Scoped to the row, not a redeclaration of
   .avatar or the table component. */
.table tbody tr td:first-child { position: relative; }
.table tbody tr td:first-child::before {
  content: "";
  position: absolute;
  left: -1px;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  opacity: 0;
  transform: scaleY(0.4);
  transition: opacity var(--dur-1, 0.15s) var(--ease, ease), transform var(--dur-1, 0.15s) var(--ease, ease);
}
.table tbody tr:hover td:first-child::before { opacity: 1; transform: scaleY(1); }
.table tbody tr:hover .avatar { transform: scale(1.08); }

/* Avatars: the one property that was flat — a two-tone wash instead of a
   single pastel fill. Everything else (size, shape, the initials) is the
   component as it comes. */
.avatar {
  background: linear-gradient(135deg, var(--accent-soft), color-mix(in srgb, var(--accent-hover) 22%, var(--accent-soft)));
}

/* Progress bars: a faint moving sheen so headcount bars feel like live
   data — one property (the fill image) on top of the component's own bar. */
.progress-bar {
  background-image: linear-gradient(90deg, var(--accent), var(--accent-hover), var(--accent));
  background-size: 200% 100%;
  animation: nts-shimmer-bar 3.5s linear infinite;
  transition: width 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Empty states: the icon breathes gently rather than sitting inert. */
.empty-art {
  animation: nts-float 3.2s ease-in-out infinite;
}

/* Primary buttons: a plain, confident hover — a touch darker and a hair
   of lift, the way a corporate console reads rather than a marketing
   page. */
.btn-primary {
  transition: transform var(--dur-1, 0.15s) var(--ease, ease), box-shadow var(--dur-1, 0.15s) var(--ease, ease);
}
.btn-primary:hover { transform: translateY(-1px); box-shadow: var(--shadow-raised); }

/* ====================================================================
 * SALARY SLIP — the one screen in this app meant to be printed. New
 * furniture: a letterhead strip and a highlighted net-pay row, plus a
 * print stylesheet that drops the app chrome and leaves only the slip.
 * ==================================================================== */
.payslip-head {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--border);
}
.payslip-logo {
  height: 44px;
  width: auto;
  display: block;
}
.payslip-head-meta { min-width: 0; }

@media print {
  .topbar,
  .page-head-actions,
  .theme-toggle {
    display: none;
  }
  body, .content { background: var(--canvas); }
  .payslip, .page { box-shadow: none; }
}

/* ====================================================================
 * MOTION SAFETY — every animation above stands down for anyone who has
 * asked their system for reduced motion. Layout and colour are unaffected.
 * Unlayered rules already beat design.css's layered ones on ordinary
 * specificity, so none of this needs !important.
 * ==================================================================== */
@media (prefers-reduced-motion: reduce) {
  [data-animate] .table tbody tr,
  [data-animate] .grid-auto-md > *,
  .page > .grid-auto-md > *,
  .page > .grid-2 > .card,
  .page > .grid-3 > .card,
  .page > .card-flush,
  .page > .rounded-2xl:first-child,
  .brand-mark,
  .brand-logo,
  .nav-count,
  .page > .rounded-2xl.bg-gradient-to-br::before,
  .page > .rounded-2xl.bg-gradient-to-br::after,
  .progress-bar,
  .empty-art {
    animation: none;
  }
  .btn-primary:hover { transform: none; }
  .size-9, .size-10, .grid-auto-md > .card::before {
    transition: none;
  }
}

@media (max-width: 640px) {
  .page > .rounded-2xl.bg-gradient-to-br::before,
  .page > .rounded-2xl.bg-gradient-to-br::after {
    display: none;
  }
}
