/* ============================================================================
   True North — Redesign: Page-specific styles
   Dashboard widgets, project wizard, reports, auth & guest pages.
   Filled out during the per-page pixel pass (Phase 4).
   ========================================================================= */

/* ---------- Dashboard stat cards ---------- */
.card.card-flush .card-header .card-title .fs-2hx,
.card .fs-2hx {
  color: var(--tn-text);
  letter-spacing: -0.02em;
}

#kt_content .card .fs-6.text-gray-400 {
  color: var(--tn-muted) !important;
}

/* ---------- Dashboard: themed stat-row icon squares ---------- */
.tn-stat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--tn-radius);
  flex-shrink: 0;
}

.card-body .tn-stat-icon.svg-icon.svg-icon-2hx svg {
  width: 18px !important;
  height: 18px !important;
}

.tn-stat-icon.tn-stat-icon-blue {
  background-color: var(--tn-blue-bg);
  color: var(--tn-blue);
}

.tn-stat-icon.tn-stat-icon-amber {
  background-color: var(--tn-amber-bg);
  color: var(--tn-amber);
}

.tn-stat-icon.tn-stat-icon-red {
  background-color: var(--tn-red-bg);
  color: var(--tn-red);
}

/* ---------- Dashboard: bar chart card ---------- */
.tn-chart-container {
  position: relative;
  width: 100%;
  height: 320px;
}

.tn-chart-container canvas {
  max-width: 100%;
}

/* when the chart sits beside the Plan Reviewer Workload card (2-col row, xl+),
   let it flex-fill the card so its height matches the taller card — no dead space
   below the canvas (Chart.js runs maintainAspectRatio:false, so it fills height). */
@media (min-width: 1200px) {
  .tn-chart-card { display: flex; flex-direction: column; }
  .tn-chart-card .card-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
  .tn-chart-card .tn-chart-container { flex: 1 1 auto; height: auto; min-height: 320px; }
}

/* ---------- Toolbar action search box ---------- */
.form-control.form-control-solid.w-250px,
[data-kt-docs-table-filter="search"] {
  background-color: var(--tn-surface-2);
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius);
}

/* ---------- Auth pages (login / reset) ---------- */
.app-blank {
  background-color: var(--tn-app-bg);
}

[data-theme="light"] .login-content .card,
.login-content .bg-body {
  background-color: var(--tn-surface);
  border-radius: var(--tn-radius-lg);
}

/* small screens: the layout's wrappers only grow/centre at lg+ (flex-lg-row-fluid),
   so below that fill the viewport to keep the card vertically centred, and cap the
   card width on tablets (w-lg-425px only bites at lg+). */
@media (max-width: 991.98px) {
  .app-blank .flex-root > .flex-column-fluid { min-height: 100vh; }
  .app-blank .flex-root .flex-column-fluid > div:first-child { flex: 1 1 auto; }
  .app-blank .flex-root .d-flex.flex-center.flex-column { flex: 1 1 auto; }
  .app-blank .bg-body.rounded-4 { width: 100%; max-width: 480px; margin-left: auto; margin-right: auto; }
}

/* ---------- Guest "Find My Project" ---------- */
/* (bespoke landing page — refined in Phase 4) */

/* ============================================================================
   Dashboard — modern enterprise micro-animations & polish (scoped to .tn-dashboard)
   Keeps existing layout/alignment; adds entrance + hover motion only.
   ========================================================================= */

/* --- staggered card entrance --- */
.tn-dashboard .card {
  animation: tnCardIn .55s cubic-bezier(.22, .61, .36, 1) both;
  transition: box-shadow .22s ease, transform .22s ease, border-color .22s ease;
  will-change: transform;
}

@keyframes tnCardIn {
  from {
    opacity: 0;
    transform: translateY(16px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* stagger — works whether the .card is inside a col or IS the col */
.tn-dashboard .row:first-child>[class*="col"]:nth-child(1) .card,
.tn-dashboard .row:first-child>[class*="col"]:nth-child(1).card {
  animation-delay: .05s;
}

.tn-dashboard .row:first-child>[class*="col"]:nth-child(2) .card,
.tn-dashboard .row:first-child>[class*="col"]:nth-child(2).card {
  animation-delay: .13s;
}

.tn-dashboard .row:nth-child(n+2) .card,
.tn-dashboard .row:nth-child(n+2)>[class*="col"].card {
  animation-delay: .21s;
}

/* --- card hover lift --- */
.tn-dashboard .card:hover {
  box-shadow: 0 10px 28px rgba(16, 24, 40, .10), 0 2px 6px rgba(16, 24, 40, .05);
  border-color: var(--tn-border-2);
  transform: translateY(-3px);
}

/* --- big total-projects number entrance --- */
.tn-dashboard #totalProjects {
  display: inline-block;
  animation: tnNumberIn .6s cubic-bezier(.22, .61, .36, 1) both;
  animation-delay: .18s;
}

@keyframes tnNumberIn {
  from {
    opacity: 0;
    transform: translateY(8px) scale(.96);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* --- stat rows: hover highlight + icon spring (direct children of card-body only) --- */
.tn-dashboard .card-body>.d-flex.flex-stack {
  border-radius: var(--tn-radius);
  padding: 8px;
  margin: 0 -8px;
  transition: background-color .18s ease;
}

.tn-dashboard .card-body>.d-flex.flex-stack:hover {
  background-color: var(--tn-surface-2);
}

.tn-dashboard .tn-stat-icon {
  transition: transform .22s cubic-bezier(.34, 1.56, .64, 1);
}

.tn-dashboard .card-body>.d-flex.flex-stack:hover .tn-stat-icon {
  transform: scale(1.09);
}

.tn-dashboard .card-body>.d-flex.flex-stack:hover a.text-hover-primary {
  color: var(--tn-primary) !important;
}

.tn-dashboard .card-body>.d-flex.flex-stack:hover span[id] {
  color: var(--tn-primary);
  transition: color .18s ease;
}

/* --- donut legend bullets: subtle grow on card hover --- */
.tn-dashboard .card .bullet {
  transition: transform .2s ease;
}

.tn-dashboard .card:hover .bullet {
  transform: scaleY(1.5);
}

/* --- bar-chart canvas fade-in --- */
.tn-dashboard .tn-chart-container canvas {
  animation: tnFadeIn .5s ease both;
  animation-delay: .3s;
}

@keyframes tnFadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* --- viewport-fit desktop layout (xl+): grid.js fitDashboard() locks
   #kt_content_container to the viewport height; these flex rules distribute it —
   row 1 (stats + donut) keeps its natural height, row 2 (chart + workload) fills
   the remainder, and the workload LIST scrolls inside its card (sticky header,
   pinned pager). Without the JS-set height the flex column collapses to normal
   block stacking, so this degrades safely. --- */
@media (min-width: 1200px) {
  .tn-dashboard #kt_content_container {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .tn-dashboard #kt_content_container > .row:first-child { flex: 0 0 auto; }
  .tn-dashboard #kt_content_container > .row:nth-child(2) { flex: 1 1 0; min-height: 0; }
  /* the cols' mb-xl-10 bottom margins would overflow the locked height —
     vertical spacing comes from the rows' own gutters instead */
  .tn-dashboard #kt_content_container > .row > [class*="col"] { margin-bottom: 0 !important; }
  .tn-dashboard #kt_content_container > .row:nth-child(2) > [class*="col"] { min-height: 0; }
  .tn-dashboard #kt_content_container > .row:nth-child(2) > [class*="col"] > .card { height: 100%; }

  /* workload card: header fixed, list scrolls, pager pinned */
  .tn-dashboard .tn-reviewer-workload.card { display: flex; flex-direction: column; }
  .tn-dashboard .tn-reviewer-workload .card-header { flex: 0 0 auto; }
  .tn-dashboard .tn-reviewer-workload .card-body {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  .tn-dashboard .tn-reviewer-workload .tn-workload-scroll {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
  }
  .tn-dashboard .tn-reviewer-workload .tn-workload-pager { flex: 0 0 auto; }
  .tn-dashboard .tn-workload-table thead th { position: sticky; top: 0; z-index: 2; }

  /* chart card: in the locked layout the container must be sized by the FLEX ROW,
     never by the canvas's last-painted pixel height (flex-basis:auto lets a stale
     tall canvas inflate the card past its row on shrink) — basis 0 + min-height 0
     lets Chart.js (responsive, no aspect ratio) follow the container both ways */
  .tn-dashboard .tn-chart-card .card-body { min-height: 0; }
  .tn-dashboard .tn-chart-card .tn-chart-container {
    flex: 1 1 0;
    min-height: 0;
    height: auto;
    overflow: hidden;
  }

  /* --- row 1 (Total Projects + Clients & Reviewer) carries the SMALLEST data,
     so it gets the compact treatment — the data-heavy row 2 takes the space.
     Fixed 290px: without it the donut card's centered body stretches the whole
     row to ~350px and the stats rows spread out to fill. --- */
  .tn-dashboard #kt_content_container > .row:first-child > [class*="col"] {
    height: 290px;
    min-height: 0;
  }
  .tn-dashboard #kt_content_container > .row:first-child > [class*="col"] > .card,
  .tn-dashboard #kt_content_container > .row:first-child > .card[class*="col"] {
    height: 290px !important;   /* beats h-xl-100 on both cards */
    overflow: hidden;
  }
  .tn-dashboard #kt_content_container > .row:first-child .card-header {
    padding-top: 14px;
    padding-bottom: 6px;
    min-height: 0;
  }
  .tn-dashboard #kt_content_container > .row:first-child .card-body {
    padding-top: 6px;
    padding-bottom: 12px;
  }
  .tn-dashboard #totalProjects { font-size: 1.9rem; }   /* fs-2hx (~2.5rem) → compact */
  .tn-dashboard #kt_content_container > .row:first-child .card-body > .d-flex.flex-stack {
    padding: 5px 8px;
  }
  /* tighter stat-row separators + smaller stat icons */
  .tn-dashboard #kt_content_container > .row:first-child .separator { margin: 6px 0 !important; }
  .tn-dashboard #kt_content_container > .row:first-child .tn-stat-icon svg { width: 20px; height: 20px; }
}

/* --- accessibility: honor reduced-motion --- */
@media (prefers-reduced-motion: reduce) {

  .tn-dashboard .card,
  .tn-dashboard #totalProjects,
  .tn-dashboard .tn-chart-container canvas {
    animation: none !important;
  }

  .tn-dashboard .card:hover {
    transform: none;
  }

  .tn-dashboard .card-body>.d-flex.flex-stack:hover .tn-stat-icon {
    transform: none;
  }
}

/* ---------- Dashboard year filter (select2) — proper width + label ---------- */
.tn-year-filter {
  padding: 2px 0;
}

.tn-year-filter .tn-year-filter-label {
  font-size: 13px;
  color: var(--tn-muted);
  white-space: nowrap;
}

.tn-year-filter .col-auto {
  padding: 0;
}

.tn-year-filter .select2-container {
  width: 150px !important;
  min-width: 150px;
}

.tn-year-filter .select2-container--bootstrap5 .select2-selection {
  min-height: 38px;
  display: flex;
  align-items: center;
}

/* year dropdown panel matches the control width */
.select2-dropdown {
  min-width: 150px;
}

/* ============================================================================
   Projects list — enterprise data-grid (scoped to .tn-projects*)
   Columns & their data are CLIENT-FROZEN — styling, scroll & animation only.
   ========================================================================= */
.tn-grid-card {
  /* fill-mode `backwards` (not `both`): the entrance still plays, but the card does
     NOT retain `transform: translateY(0)` afterwards — a retained transform makes the
     card a containing block for position:fixed, so its overflow:hidden would clip the
     row-action dropdowns (KTMenu opens them as position:fixed). */
  animation: tnCardIn .45s cubic-bezier(.22, .61, .36, 1) backwards;
  overflow: hidden;
  position: relative;   /* anchor for the ajax loader overlay */
}

/* ---- enterprise ajax loader (DataTables `processing:true`) — shown ONLY while a
   server request is in flight; DataTables toggles .dataTables_processing for us ---- */
:is(.tn-grid-card, .tn-report-results) .dataTables_processing {
  /* DataTables toggles this element's inline display (block/none) to show/hide it,
     so DON'T set display here — lay out with inline-block + vertical-align instead. */
  position: absolute !important;
  top: 50% !important; left: 50% !important; right: auto !important; bottom: auto !important;
  transform: translate(-50%, -50%) !important;
  z-index: 20;
  width: auto !important; height: auto !important; margin: 0 !important;
  padding: 10px 18px !important;
  background: var(--tn-surface) !important;
  border: 1px solid var(--tn-border) !important;
  border-radius: 999px !important;
  box-shadow: 0 8px 24px rgba(16, 24, 40, .14) !important;
  color: var(--tn-text-3) !important;
  font-size: 13px !important; font-weight: 500; line-height: 1;
  white-space: nowrap; text-align: left; text-indent: 0;
}
/* hide DataTables' default 4-dot animation — our ::before spinner replaces it */
:is(.tn-grid-card, .tn-report-results) .dataTables_processing > div { display: none !important; }
:is(.tn-grid-card, .tn-report-results) .dataTables_processing::before {
  content: '';
  display: inline-block; vertical-align: middle; margin-right: 10px;
  width: 17px; height: 17px;
  border: 2.5px solid var(--tn-border-2);
  border-top-color: var(--tn-primary);
  border-radius: 50%;
  animation: tnSpin .7s linear infinite;
}
@keyframes tnSpin { to { transform: rotate(360deg); } }
/* while a request is in flight, blur the rows behind the spinner (image reference);
   the loader pill stays sharp on top, centred in the visible grid */
:is(.tn-grid-card, .tn-report-results).tn-loading table.dataTable > tbody {
  filter: blur(2.5px);
  opacity: .5;
  pointer-events: none;
  user-select: none;
  transition: filter .18s ease, opacity .18s ease;
}
:is(.tn-grid-card, .tn-report-results) table.dataTable > tbody { transition: filter .18s ease, opacity .18s ease; }
@media (prefers-reduced-motion: reduce) {
  :is(.tn-grid-card, .tn-report-results) .dataTables_processing::before { animation-duration: 1.4s; }
}

/* ---- Freeze header + footer; ONLY the tbody scrolls; card auto-fits display ----
   Flex-fill chain from Metronic's flex-column #kt_content down to the DataTables
   inner .table-responsive (which holds ONLY the table). Its sibling .row
   (info + pagination) is pinned at the card bottom. Fully responsive — no fixed
   pixel height. Mobile uses a viewport-based max-height fallback. */
/* Flex-fill chain at ALL widths: header + footer frozen, ONLY the inner tbody scrolls,
   so the PAGE never scrolls (fixes the double-scroll that let rows peek above the sticky
   thead on mobile). tnFitGridCard() (grid.js) sets the card's explicit height to the
   viewport at every width; the per-band max-height below is only the pre-JS fallback. */
.tn-grid-card {
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
  max-height: calc(100vh - 196px);
}

.tn-grid-card>.card-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  padding: 0 !important;
}

.tn-grid-card #kt_table_users_wrapper {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.tn-grid-card .tn-grid-scroll {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow: visible;
  max-height: none;
}

.tn-grid-card .dataTables_wrapper .dataTables_wrapper {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.table-responsive {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: auto;
  max-height: none;
}

.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.row {
  flex: 0 0 auto;
}

@media (min-width: 992px) {
  .content { padding: 30px 0 0 0; }
}

/* Per-band card max-height (pre-JS fallback; tnFitGridCard refines it live). */
@media (min-width: 768px) and (max-width: 991.98px) {
  .tn-grid-card { max-height: calc(100vh - 210px); }
}
@media (max-width: 767.98px) {
  .tn-grid-card { max-height: calc(100vh - var(--tn-header-h) - var(--tn-bottomnav-h) - 150px); }
}

/* footer row (info + pagination) pinned below the scroll, inside the card —
   compact enterprise height (~46px) */
.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.row {
  margin: 0;
  padding: 6px 20px;
  border-top: 1px solid var(--tn-border);
  align-items: center;
  background-color: var(--tn-surface);
}

/* thin enterprise scrollbar */
.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.table-responsive::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}

.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.table-responsive::-webkit-scrollbar-thumb {
  background: var(--tn-border-2);
  border-radius: 999px;
  border: 3px solid var(--tn-surface);
}

.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.table-responsive::-webkit-scrollbar-thumb:hover {
  background: var(--tn-muted-3);
}

.tn-grid-card .dataTables_wrapper .dataTables_wrapper>.table-responsive::-webkit-scrollbar-track {
  background: transparent;
}

/* --- sticky header (opaque so rows don't bleed through) --- */
/* kill the table's top margin so the sticky header sits flush at the scroll top
   (the 6px margin was causing a white gap + header "jump"/flicker on scroll) */
.tn-grid-card table.dataTable {
  margin: 0 !important;
}

.tn-grid-card table.dataTable thead tr {
  background: transparent !important;
}

.tn-grid-card table.dataTable thead th {
  position: sticky !important;   /* beat DataTables' .sorting { position: relative } (id specificity was lost in the rename) */
  top: 0 !important;
  z-index: 3;
  /* distinct neutral header band (opaque for sticky scroll): clearly separates
     from the white/near-black body rows, readable in both themes */
  background: var(--tn-surface-3) !important;
  color: var(--tn-text-3) !important;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 11px 12px !important;
  border-bottom: 1px solid var(--tn-border-2) !important;
  white-space: nowrap;
}

/* --- rows: no zebra (striping is on the cells + .odd/.even), clean borders, hover --- */
.tn-grid-card table.dataTable {
  --bs-table-striped-bg: transparent !important;
  --bs-table-accent-bg: transparent !important;
}

.tn-grid-card table.dataTable>tbody>tr,
.tn-grid-card table.dataTable>tbody>tr.odd,
.tn-grid-card table.dataTable>tbody>tr.even {
  background-color: transparent !important;
}

.tn-grid-card table.dataTable>tbody>tr>td {
  padding: 12px !important;
  border-bottom: 1px solid var(--tn-border);
  color: var(--tn-text-2);
  vertical-align: middle;
  background-color: transparent !important;
  box-shadow: none !important;
  /* DataTables stripes via a 9999px inset box-shadow */
  transition: background-color .15s ease;
}

.tn-grid-card table.dataTable>tbody>tr:hover>td {
  background-color: var(--tn-surface-2) !important;
  box-shadow: none !important;
}

.tn-grid-card table.dataTable>tbody>tr:last-child>td {
  border-bottom: 0;
}

/* ========== CLIENT cell — dark, readable (was faint muted gray) ========== */
.tn-grid-card table.dataTable td.tn-cell-client {
  color: var(--tn-text-2) !important;
  font-weight: 600;
}

/* ========== JOB # — clearly a clickable link (opens edit page in new tab) ========== */
.tn-grid-card table.dataTable td.tn-cell-job { white-space: nowrap; }
.tn-grid-card table.dataTable td u,
.tn-grid-card table.dataTable td u a { text-decoration: none; }
.tn-grid-card table.dataTable td .tn-joblink {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--tn-primary);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--tn-primary) 32%, transparent);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  border-radius: var(--tn-radius-sm);
  transition: color .12s ease, text-decoration-color .12s ease;
}
.tn-grid-card table.dataTable td .tn-joblink:hover {
  color: var(--tn-primary-hover);
  text-decoration-color: currentColor;
}
.tn-grid-card table.dataTable td .tn-joblink-ext {
  font-size: 11px;
  opacity: 0;
  transform: translateX(-2px);
  transition: opacity .12s ease, transform .12s ease;
}
.tn-grid-card table.dataTable td .tn-joblink:hover .tn-joblink-ext,
.tn-grid-card table.dataTable td .tn-joblink:focus-visible .tn-joblink-ext {
  opacity: .8;
  transform: translateX(0);
}

/* ========== DAYS LEFT — colored pill (same <=1 urgent decision as before) ========== */
.tn-grid-card table.dataTable td .tn-days {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  padding: 3px 9px;
  border-radius: var(--tn-radius-pill);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
}
.tn-grid-card table.dataTable td .tn-days-danger { color: var(--tn-red);    background-color: var(--tn-red-bg); }
.tn-grid-card table.dataTable td .tn-days-ok     { color: var(--tn-text-3); background-color: var(--tn-surface-3); }
.tn-grid-card table.dataTable td .tn-days-empty  { color: var(--tn-muted); }

/* ========== REVIEWER — role badge + readable name + completion check (screenshot style) ========== */
.tn-grid-card table.dataTable td .tn-reviewer {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 2px 0;
  line-height: 1.25;
}
.tn-grid-card table.dataTable td .tn-reviewer + .tn-reviewer { margin-top: 3px; }
.tn-grid-card table.dataTable td .tn-reviewer-role {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--tn-radius-sm);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
}
/* preserves the original alternating (key % 2) chip colour — now on the role avatar */
.tn-grid-card table.dataTable td .tn-reviewer-role.tn-role-a { background-color: var(--tn-blue-bg);   color: var(--tn-blue); }
.tn-grid-card table.dataTable td .tn-reviewer-role.tn-role-b { background-color: var(--tn-purple-bg); color: var(--tn-purple); }
.tn-grid-card table.dataTable td .tn-reviewer-name {
  color: var(--tn-text-2);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}
/* checkbox comes FIRST and reads clearly as a checkbox (mark my review complete) */
.tn-grid-card table.dataTable td .tn-reviewer .plan_review_check {
  flex: 0 0 auto;
  order: -1;                              /* always first, before the role badge */
  width: 18px;
  height: 18px;
  margin: 0;
  border-radius: 5px;                     /* square = recognisable checkbox */
  border: 1.5px solid var(--tn-border-2);
  background-color: var(--tn-surface);
  cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.tn-grid-card table.dataTable td .tn-reviewer .plan_review_check:checked {
  background-color: var(--tn-primary);
  border-color: var(--tn-primary);
}
/* the current user's OWN, clickable checkbox — obvious affordance (primary ring) */
.tn-grid-card table.dataTable td .tn-reviewer .tn-review-check-mine {
  border-color: var(--tn-primary);
  box-shadow: 0 0 0 3px var(--tn-primary-tint);
}
.tn-grid-card table.dataTable td .tn-reviewer .tn-review-check-mine:hover {
  box-shadow: 0 0 0 4px var(--tn-focus-ring);
}
.tn-grid-card table.dataTable td .tn-reviewer .tn-review-check-mine:not(:checked) {
  background-color: var(--tn-surface);
}
/* read-only "done" indicator for other reviewers who completed */
.tn-grid-card table.dataTable td .tn-reviewer .plan_review_check:disabled {
  cursor: default;
  opacity: 1;
  border-color: var(--tn-primary);
}

/* --- pagination row inside the card, below the scroll area (compact) ---
   Metronic pads these control divs 13px top+bottom; collapse it so the footer
   height is driven only by the controls + the row's own 6px padding (~46px). */
.tn-grid-card .dataTables_length,
.tn-grid-card .dataTables_paginate,
.tn-grid-card .dataTables_info {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  margin: 0 !important;
}
/* breathing room between the "Rows per page" select and the "Showing…" label */
.tn-grid-card .dataTables_length { margin-right: 18px !important; }
.tn-grid-card .dataTables_info { color: var(--tn-muted); }

/* tighter pagination buttons + length select so the footer stays ~46px tall */
.tn-grid-card .dataTables_paginate .page-link {
  padding: 4px 9px !important;
  min-width: 30px;
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12.5px;
}
.tn-grid-card .dataTables_length .form-select,
.tn-grid-card .dataTables_length select {
  padding-top: 4px !important;
  padding-bottom: 4px !important;
  min-height: 32px;
  height: 32px;
}

/* --- subtle row fade-in on each draw (opacity only — safe with sticky header) --- */
.tn-grid-card table.dataTable>tbody>tr {
  animation: tnRowFade .35s ease both;
}

@keyframes tnRowFade {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* --- filter bar (kept in the page toolbar; cleaner spacing + wider search) --- */
.tn-grid-toolbar {
  row-gap: 8px;
}

.tn-grid-toolbar .form-control.w-250px {
  width: 280px !important;
}

@media (prefers-reduced-motion: reduce) {

  .tn-grid-card,
  .tn-grid-card table.dataTable>tbody>tr {
    animation: none !important;
  }
}

/* ============================================================================
   REUSABLE GRID TOOLBAR — search box, visible buttons, drawer/popup, mobile
   (generic: any list toolbar tagged .tn-grid-toolbar gets this; the projects
   Filter side-drawer + Favorites popup below stay project-specific)
   ========================================================================= */

/* ---- reusable rounded search box (icon + focus animation), per mock ---- */
.tn-grid-search { position: relative; display: flex; align-items: center; }
.tn-grid-search-icon {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  color: var(--tn-muted); pointer-events: none; display: inline-flex;
  transition: color .15s ease;
}
.tn-grid-search-input {
  width: 320px; max-width: 100%; height: 36px;   /* matches the mock (36px, 8px radius) */
  padding-left: 38px !important; padding-right: 14px !important;
  border-radius: var(--tn-radius) !important;
  background-color: var(--tn-surface) !important;
  border: 1px solid var(--tn-border-2) !important;
  color: var(--tn-text-2) !important;
  font-size: 13px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.tn-grid-search-input:focus {
  border-color: var(--tn-primary) !important;
  box-shadow: 0 0 0 4px var(--tn-focus-ring) !important;
  background-color: var(--tn-surface) !important;
}
.tn-grid-search:focus-within .tn-grid-search-icon { color: var(--tn-primary); }
/* ACTIVE state — grid.js (tnSyncGridSearch) adds `.tn-search-on` to .tn-grid-search
   whenever the keyword box holds a query, so a filtered grid's search box stands out
   (primary border + subtle tint + accent icon) instead of looking identical to an
   empty one. Same "this is filtered" language as the drawer's `.tn-field-on`. */
.tn-grid-search.tn-search-on .tn-grid-search-input {
  border-color: var(--tn-primary) !important;
  background-color: var(--tn-primary-tint) !important;
  color: var(--tn-text) !important;
}
.tn-grid-search.tn-search-on .tn-grid-search-icon { color: var(--tn-primary); }
[data-theme="dark"] .tn-grid-search.tn-search-on .tn-grid-search-input {
  border-color: #2F6BD8 !important;
}

.btn.tn-btn,
.tn-grid-toolbar .btn,
.tn-grid-toolbar .btn-primary,
.tn-grid-toolbar .btn-light-primary,
.tn-grid-toolbar .btn-light-danger,
.tn-grid-toolbar .btn-light-warning,
.tn-grid-toolbar .btn-light-success,
.tn-grid-toolbar .btn-light-info,
.tn-grid-toolbar .btn-light-dark,
.tn-grid-toolbar .btn-light,
.tn-grid-toolbar .btn-secondary {
  height: 36px;
  padding: 0 12px !important;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background-color: var(--tn-surface) !important;
  border: 1px solid var(--tn-border-2) !important;
  color: var(--tn-text-3) !important;         /* #57616E — mock label colour */
  box-shadow: var(--tn-shadow-xs) !important; /* subtle raise so it reads as a clickable button */
  border-radius: var(--tn-radius);            /* 8px */
  font-size: 13px;
  font-weight: 500 !important;                /* beat the markup's .fw-bold; mock is 500 */
  line-height: 1;
  text-decoration: none;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease, transform .15s ease;
}
/* icon shares the label colour (no blue) and the mock's ~15px size */
/* icons: inherit colour + robustly CENTER regardless of the svg's viewBox/baseline
   (svg { display:block } kills the inline-svg baseline gap that mis-aligns icons) */
.btn.tn-btn .svg-icon, .tn-grid-toolbar .btn .svg-icon {
  color: inherit; flex: 0 0 auto; line-height: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.btn.tn-btn .svg-icon svg, .tn-grid-toolbar .btn .svg-icon svg {
  width: 15px; height: 15px; display: block;
}
.btn.tn-btn > i, .tn-grid-toolbar .btn > i {
  color: inherit; flex: 0 0 auto; font-size: 14px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}

/* HOVER — subtle, NEUTRAL enterprise micro-interaction (no colour jump). The doubled
   class (.btn.tn-btn / .btn.btn) beats Metronic's aggressive .btn-primary:hover. */
.btn.tn-btn:hover, .btn.tn-btn:focus,
.tn-grid-toolbar .btn.btn:hover, .tn-grid-toolbar .btn.btn:focus {
  background-color: var(--tn-surface-2) !important;   /* #F7F8FA */
  border-color: var(--tn-muted-3) !important;
  color: var(--tn-text) !important;                   /* #12151B */
  box-shadow: 0 2px 6px rgba(16, 24, 40, .08) !important;
  transform: translateY(-1px);
}
.btn.tn-btn:hover .svg-icon, .btn.tn-btn:hover > i,
.btn.tn-btn:focus .svg-icon, .btn.tn-btn:focus > i,
.tn-grid-toolbar .btn.btn:hover .svg-icon, .tn-grid-toolbar .btn.btn:hover > i,
.tn-grid-toolbar .btn.btn:focus .svg-icon, .tn-grid-toolbar .btn.btn:focus > i { color: var(--tn-text) !important; }
.btn.tn-btn:active, .tn-grid-toolbar .btn.btn:active { transform: translateY(0); box-shadow: none !important; }
.btn.tn-btn:focus-visible, .tn-grid-toolbar .btn.btn:focus-visible { border-color: var(--tn-primary) !important; box-shadow: 0 0 0 3px var(--tn-focus-ring) !important; }

/* open state (dropdown / drawer trigger) — neutral "pressed" look, no blue */
.btn.tn-btn.show, .tn-grid-toolbar .btn.btn.show {
  background-color: var(--tn-surface-3) !important;   /* #EEF1F5 */
  border-color: var(--tn-muted-3) !important;
  color: var(--tn-text) !important;
  box-shadow: none !important;
  transform: translateY(0);
}
.btn.tn-btn.show .svg-icon, .btn.tn-btn.show > i,
.tn-grid-toolbar .btn.btn.show .svg-icon, .tn-grid-toolbar .btn.btn.show > i { color: var(--tn-text) !important; }

/* ---- variant: solid primary (for CTAs, e.g. "New Project" / "Add") ---- */
.btn.tn-btn.tn-btn-primary {
  background-color: var(--tn-primary) !important;
  border-color: var(--tn-primary) !important;
  color: #fff !important;
}
.btn.tn-btn.tn-btn-primary .svg-icon, .btn.tn-btn.tn-btn-primary > i { color: #fff !important; }
.btn.tn-btn.tn-btn-primary:hover, .btn.tn-btn.tn-btn-primary:focus {
  background-color: var(--tn-primary-hover) !important;
  border-color: var(--tn-primary-hover) !important;
  color: #fff !important;
  box-shadow: 0 4px 12px rgba(29, 91, 216, .25) !important;
}
.btn.tn-btn.tn-btn-primary:hover .svg-icon, .btn.tn-btn.tn-btn-primary:hover > i { color: #fff !important; }
/* dark: --tn-primary (#3B7BE8) is too light for white text (4.05:1) — darken the
   fill so white-on-blue clears AA (~5:1), matching the drawer's Find Project button */
[data-theme="dark"] .btn.tn-btn.tn-btn-primary {
  background-color: #2F6BD8 !important;
  border-color: #2F6BD8 !important;
}
[data-theme="dark"] .btn.tn-btn.tn-btn-primary:hover,
[data-theme="dark"] .btn.tn-btn.tn-btn-primary:focus {
  background-color: #295FC4 !important;
  border-color: #295FC4 !important;
}

/* ---- variant: icon-only (square) ---- */
.btn.tn-btn.tn-btn-icon { width: 36px; padding: 0 !important; }

/* Favorites caret flips when the popup is open */
.tn-fav-caret { display: inline-flex; transition: transform .2s ease; }
.btn.tn-btn.show .tn-fav-caret, .tn-grid-toolbar .btn.show .tn-fav-caret { transform: rotate(180deg); }
.tn-grid-toolbar .btn-icon .svg-icon { margin: 0; }
@media (prefers-reduced-motion: reduce) {
  .btn.tn-btn, .tn-grid-toolbar .btn { transition: background-color .1s ease, border-color .1s ease, color .1s ease; }
  .btn.tn-btn:hover, .tn-grid-toolbar .btn:hover { transform: none; }
}

/* ---- FILTER → right side drawer (overrides KTMenu/Popper positioning) ---- */
.tn-filter-drawer.menu-sub-dropdown {
  position: fixed !important;
  top: 0 !important; right: 0 !important; bottom: 0 !important; left: auto !important;
  inset: 0 0 0 auto !important;
  transform: none !important;              /* neutralise Popper's translate (never animate THIS) */
  margin: 0 !important;
  width: 460px !important;
  max-width: 92vw !important;
  height: 100vh !important;
  max-height: 100vh !important;
  padding: 0 !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  overflow: visible !important;
  z-index: 1065 !important;
}
/* the visible panel — Popper never touches this child, so it can slide safely */
.tn-filter-drawer .tn-drawer-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  background: var(--tn-surface);
  border-left: 1px solid var(--tn-border);
  box-shadow: -18px 0 44px rgba(16, 24, 40, .16);
  overflow-y: auto;
  overflow-x: hidden;
}
.tn-filter-drawer.show .tn-drawer-inner {
  animation: tnDrawerSlide .3s cubic-bezier(.22, .61, .36, 1) both;
}
@keyframes tnDrawerSlide { from { transform: translateX(100%); } to { transform: translateX(0); } }
.tn-filter-drawer .tn-drawer-head {
  position: sticky; top: 0; z-index: 2;
  background: var(--tn-surface);
  border-bottom: 1px solid var(--tn-border);
}
.tn-filter-drawer .tn-drawer-head + .separator { display: none; }
.tn-filter-drawer .tn-drawer-close {
  color: var(--tn-muted);
  border: 1px solid var(--tn-border);
  background: var(--tn-surface);
  width: 32px; height: 32px; border-radius: var(--tn-radius-sm);
}
.tn-filter-drawer .tn-drawer-close:hover { background: var(--tn-surface-3); color: var(--tn-text); }
/* filter action buttons stand out inside the drawer */
/* primary "Find Project" + neutral "Reset" (force past Metronic's btn defaults) */
.tn-filter-drawer #apply_filter {
  background-color: var(--tn-primary) !important; border: 1px solid var(--tn-primary) !important;
  color: #fff !important; font-weight: 600; height: 40px; padding: 0 20px; border-radius: var(--tn-radius);
}
.tn-filter-drawer #apply_filter:hover { background-color: var(--tn-primary-hover) !important; border-color: var(--tn-primary-hover) !important; }
[data-theme="dark"] .tn-filter-drawer #apply_filter { background-color: #2F6BD8 !important; border-color: #2F6BD8 !important; }
.tn-filter-drawer #reset_filter {
  background-color: var(--tn-surface) !important; border: 1px solid var(--tn-border-2) !important;
  color: var(--tn-text-3) !important; font-weight: 600; height: 40px; padding: 0 20px; border-radius: var(--tn-radius);
}
.tn-filter-drawer #reset_filter:hover { background-color: var(--tn-surface-2) !important; border-color: var(--tn-muted-3) !important; color: var(--tn-text) !important; }

/* ---- drawer form: enterprise controls + a tasteful staggered field entrance ---- */
.tn-filter-drawer .tn-drawer-inner .form-label { color: var(--tn-text-2); font-weight: 600; }
.tn-filter-drawer .tn-drawer-inner .form-control,
.tn-filter-drawer .tn-drawer-inner .form-select,
.tn-filter-drawer .tn-drawer-inner .select2-selection { height: 42px; min-height: 42px; }
.tn-filter-drawer .tn-drawer-inner .mb-5 { margin-bottom: 1.15rem !important; }
/* fade each column up with a slight stagger when the drawer opens */
.tn-filter-drawer.show .tn-drawer-inner .row > .col-12:nth-of-type(1) { animation: tnFieldIn .42s cubic-bezier(.22, .61, .36, 1) .06s both; }
.tn-filter-drawer.show .tn-drawer-inner .row > .col-12:nth-of-type(2) { animation: tnFieldIn .42s cubic-bezier(.22, .61, .36, 1) .13s both; }
.tn-filter-drawer.show .tn-drawer-inner .row > .d-flex.justify-content-center { animation: tnFieldIn .42s cubic-bezier(.22, .61, .36, 1) .2s both; }
@keyframes tnFieldIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) {
  .tn-filter-drawer.show .tn-drawer-inner .row > .col-12,
  .tn-filter-drawer.show .tn-drawer-inner .row > .d-flex.justify-content-center { animation: none !important; }
}

/* drawer backdrop (injected by JS) */
#tn-drawer-backdrop {
  position: fixed; inset: 0;
  background: rgba(16, 24, 40, .38);
  opacity: 0; visibility: hidden;
  transition: opacity .25s ease, visibility .25s ease;
  z-index: 1060;
}
#tn-drawer-backdrop.show { opacity: 1; visibility: visible; }

/* ---- FAVORITE FILTER popup — cleaner enterprise list + fade-in ---- */
.tn-fav-menu.menu-sub-dropdown {
  width: 300px !important;
  padding: 0 !important;
  border: 1px solid var(--tn-border) !important;
  border-radius: var(--tn-radius-lg) !important;
  box-shadow: var(--tn-shadow-md) !important;
  overflow: hidden;
}
.tn-fav-menu.show { animation: tnFavIn .18s ease both; }
@keyframes tnFavIn { from { opacity: 0; } to { opacity: 1; } }
.tn-fav-menu .tn-fav-head {
  padding: 13px 18px !important;
  border-bottom: 1px solid var(--tn-border);
  background: var(--tn-surface-2);
}
.tn-fav-menu .tn-fav-head + .separator { display: none; }
.tn-fav-menu > .px-7.py-5 { padding: 8px !important; max-height: 60vh; overflow-y: auto; }
.tn-fav-menu .apply-filter-element {
  display: flex; align-items: center; justify-content: space-between;
  margin: 0 !important; padding: 3px 6px 3px 10px !important;
  border-radius: var(--tn-radius);
  transition: background-color .12s ease;
}
.tn-fav-menu .apply-filter-element:hover { background-color: var(--tn-surface-2); }
/* favourite name reads like the JOB # link in the grid (blue, subtle underline) */
.tn-fav-menu .apply-filter {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 7px;
  padding: 6px 0 !important;
  color: var(--tn-primary); font-weight: 600; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--tn-primary) 32%, transparent);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color .12s ease, text-decoration-color .12s ease;
}
.tn-fav-menu .apply-filter:hover {
  color: var(--tn-primary-hover);
  text-decoration-color: currentColor;
}
.tn-fav-menu .apply-filter .bullet {
  flex: 0 0 auto; width: 6px; height: 6px; margin: 0 !important;
  border-radius: 50%; background: var(--tn-muted-3); text-decoration: none;
}
.tn-fav-menu .col-2, .tn-fav-menu .col-10 { padding: 0 !important; width: auto !important; flex: none; }
/* delete button — Metronic's btn-danger forces a WHITE icon (invisible here);
   make it a clear muted trash that turns solid red on hover */
.tn-fav-menu .btn-remove-filter {
  background: transparent !important; border: 0 !important;
  width: 30px; height: 30px; box-shadow: none !important; border-radius: var(--tn-radius-sm);
}
.tn-fav-menu .btn-remove-filter i {
  color: var(--tn-muted) !important;
  font-size: 14px !important;
  transition: color .12s ease;
}
.tn-fav-menu .btn-remove-filter:hover { background: var(--tn-red-bg) !important; }
.tn-fav-menu .btn-remove-filter:hover i { color: var(--tn-red) !important; }

/* ---- responsive toolbar (mobile / tablet) ---- */
@media (max-width: 991.98px) {
  .tn-grid-toolbar { flex-wrap: wrap; row-gap: 8px; column-gap: 8px; margin-right: 0 !important; }
  .tn-grid-toolbar > .col-auto { flex: 0 0 auto; }
}
/* phones ONLY: search goes full-width and the action buttons wrap below it. On tablet
   there's room, so the search stays auto-width and the Add button sits beside it. */
@media (max-width: 767.98px) {
  /* Bootstrap gutters OFF — spacing comes from the 8px row/column-gap alone
     (col paddings + negative row margins made the icon-button gaps read huge
     and inset the search from the card edges) */
  .tn-grid-toolbar { --bs-gutter-x: 0; }

  /* the @yield('toolbar') actions div is a CONTENT-sized flex item in
     #kt_toolbar_container — when a grid toolbar lives inside, stretch it to the
     full container width so the search can actually fill the row */
  #kt_toolbar_container > div:has(> .tn-grid-toolbar) { width: 100%; flex: 1 1 100%; }
  #kt_toolbar_container > div:has(> .tn-grid-toolbar) > .tn-grid-toolbar { width: 100%; flex: 1 1 100%; }

  .tn-grid-toolbar > .col-auto:first-child,
  .tn-grid-toolbar > .tn-grid-search-col { flex: 1 1 100%; width: 100%; }
  .tn-grid-toolbar .tn-grid-search-input,
  .tn-grid-toolbar .form-control.w-250px { width: 100% !important; }
  /* match the 42px icon-button height (base is 36px) */
  .tn-grid-toolbar .tn-grid-search-input { height: 42px; }

  /* exactly ONE control after the search (Add button / role select): share the
     row — the search flexes and the control sits at its right side */
  .tn-grid-toolbar > .tn-grid-search-col:nth-last-child(2) {
    flex: 1 1 0%;
    width: auto;
    min-width: 0;
  }
  .tn-grid-toolbar > .tn-grid-search-col:nth-last-child(2) + .col-auto { flex: 0 0 auto; }
  /* role-filter select2 (user/archive) — cap the inline width select2 computes */
  .tn-grid-toolbar > .tn-grid-search-col:nth-last-child(2) + .col-auto .select2-container {
    width: 160px !important;
  }
}
/* phones: compact ICON-ONLY toolbar buttons — labels hidden visually (font-size:0)
   but kept in the DOM for screen readers; drawer buttons are unaffected (deeper nodes). */
@media (max-width: 767.98px) {
  .tn-grid-toolbar > .col-auto > .btn {
    width: 42px; height: 42px; min-width: 42px; padding: 0 !important;
    font-size: 0 !important; gap: 0 !important;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--tn-radius);
  }
  /* icon-only: a single centred icon — hide the label AND the Favorites caret */
  .tn-grid-toolbar > .col-auto > .btn .svg-icon {
    margin: 0 !important; display: inline-flex; align-items: center; justify-content: center;
  }
  .tn-grid-toolbar > .col-auto > .btn .tn-fav-caret { display: none !important; }
  .tn-grid-toolbar > .col-auto > .btn .svg-icon svg { width: 19px !important; height: 19px !important; }
  .tn-grid-toolbar > .col-auto > .btn > i { font-size: 17px !important; line-height: 1; }
  .tn-filter-drawer.menu-sub-dropdown { width: 100vw !important; max-width: 100vw !important; }

  /* ---- mobile DataTable footer: keep it a SINGLE row (rows-per-page · info · pagination);
     the info text is the flexible middle element (ellipsises) so the row never wraps ---- */
  .tn-grid-card .dataTables_wrapper .dataTables_wrapper > .row {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 10px !important;
    overflow-x: auto;            /* stay one row; scroll rather than clip on very small screens */
    scrollbar-width: none;
  }
  .tn-grid-card .dataTables_wrapper .dataTables_wrapper > .row::-webkit-scrollbar { height: 0; display: none; }
  .tn-grid-card .dataTables_wrapper .dataTables_wrapper > .row > [class*="col-"] {
    width: auto !important;
    max-width: none !important;
    flex: 0 1 auto !important;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: flex-start;
  }
  /* the verbose "Showing 1 to 50 of N" can't fit alongside full pagination at ~390px —
     drop it on mobile so the rows-per-page select + pagination read as one clean row */
  .tn-grid-card .dataTables_info { display: none !important; }
  .tn-grid-card .dataTables_length { flex: 0 0 auto; margin: 0 !important; }
  .tn-grid-card .dataTables_paginate { flex: 0 0 auto; margin-left: auto; }
  .tn-grid-card .dataTables_paginate .pagination { flex-wrap: nowrap !important; row-gap: 0; justify-content: flex-end; }
  .tn-grid-card .dataTables_paginate .page-link { padding: 4px 8px !important; min-width: 28px; }
}

/* ============================================================================
   /project-report — compact filter grid
   The 12 filter fields sit across a .card-body + TWO .card-footer blocks, each
   field padded p-3 (1rem). Tighten the field gutters and collapse the footer
   padding/borders so the three rows read as one continuous compact grid, while
   keeping the final "Generate Report" footer visually separated.
   ========================================================================= */
.tn-report-card .card-body { padding: .9rem 1.25rem .5rem; }
.tn-report-card .card-footer { padding: .25rem 1.25rem; border-top: 0; }
.tn-report-card .card-footer.text-center {
  padding: 1rem 1.25rem 1.25rem;
  border-top: 1px solid var(--tn-border);
  margin-top: .35rem;
}
/* field cells: p-3 (1rem) → .45rem, so ~.9rem between fields instead of 2rem */
.tn-report-card .row > [class*="col-"] { padding: .45rem !important; }
.tn-report-card .form-label { margin-bottom: .3rem !important; font-size: 13px; }
.tn-report-card .row { margin-bottom: 0; }

/* ============================================================================
   ENTERPRISE ROW ACTIONS — up to 2 inline icon buttons + a ⋮ "more" menu.
   Renderer outputs: <div class="tn-actions"> [ .tn-act-btn ×≤2 ] [ ⋮ .tn-act-more ] </div>
   The ⋮ trigger carries data-kt-menu-overflow="true" so KTMenu detaches the menu to
   <body> — it never gets clipped by the grid card, in any state.
   ========================================================================= */
.tn-actions { display: inline-flex; align-items: center; gap: 4px; justify-content: flex-end; }
.tn-act-btn {
  width: 30px; height: 30px; padding: 0; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--tn-radius-sm);
  border: 1px solid transparent;
  background: transparent;
  color: var(--tn-muted);
  transition: background-color .14s ease, color .14s ease, border-color .14s ease;
  cursor: pointer;
}
.tn-act-btn:hover { background: var(--tn-surface-3); color: var(--tn-text); }
.tn-act-btn:focus-visible { outline: 2px solid var(--tn-primary); outline-offset: 1px; }
.tn-act-btn svg { width: 16px; height: 16px; }
.tn-act-btn > i { font-size: 13px; }
.tn-act-btn.tn-act-primary:hover { background: var(--tn-primary-tint); color: var(--tn-primary); }
.tn-act-btn.tn-act-danger:hover  { background: var(--tn-red-bg);      color: var(--tn-red); }
.tn-act-btn.tn-act-success:hover { background: var(--tn-green-bg);    color: var(--tn-green); }
.tn-act-more.show { background: var(--tn-surface-3); color: var(--tn-text); }

/* the ⋮ more-menu panel (also skins any legacy grid Actions dropdown) */
.tn-act-menu,
.tn-grid-card .menu-sub-dropdown {
  background-color: var(--tn-surface) !important;
  border: 1px solid var(--tn-border) !important;
  border-radius: var(--tn-radius) !important;
  box-shadow: var(--tn-shadow-md) !important;
  padding: 6px !important;
  min-width: 180px;
}
.tn-act-menu .menu-item,
.tn-grid-card .menu-sub-dropdown .menu-item { margin: 0; }
.tn-act-menu .menu-link,
.tn-grid-card .menu-sub-dropdown .menu-link {
  border-radius: var(--tn-radius-sm) !important;
  padding: 8px 10px !important;
  color: var(--tn-text-3) !important;
  font-weight: 500 !important;
  font-size: 13px !important;
  transition: background-color .12s ease, color .12s ease;
}
.tn-act-menu .menu-link:hover,
.tn-grid-card .menu-sub-dropdown .menu-link:hover {
  background-color: var(--tn-surface-3) !important;
  color: var(--tn-text) !important;
}
/* destructive item in the more-menu */
.tn-act-menu .menu-link.tn-act-item-danger { color: var(--tn-red) !important; }
.tn-act-menu .menu-link.tn-act-item-danger:hover { background-color: var(--tn-red-bg) !important; color: var(--tn-red) !important; }
/* subtle open animation — opacity only (never transform: KTMenu owns the position transform) */
.tn-act-menu.show,
.tn-grid-card .menu-sub-dropdown.show { animation: tnActMenuIn .14s ease; }
@keyframes tnActMenuIn { from { opacity: 0; } to { opacity: 1; } }

/* ============================================================================
   TOOLBAR "FILTER" BUTTON — active state when grid filters are applied.
   grid.js (tnUpdateFilterBadges) toggles `.tn-filter-on` + injects a count badge
   on the Filter trigger whenever any drawer field has a value, on every draw.dt.
   ========================================================================= */
.tn-grid-toolbar .btn.tn-btn { position: relative; }   /* anchor for the corner badge */
.tn-grid-toolbar .btn.tn-btn.tn-filter-on {
  border-color: var(--tn-primary) !important;
  color: var(--tn-primary) !important;
  background-color: var(--tn-primary-tint) !important;
  font-weight: 600 !important;
  box-shadow: 0 0 0 3px var(--tn-focus-ring);
  transition: background-color .18s ease, border-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.tn-grid-toolbar .btn.tn-btn.tn-filter-on .svg-icon,
.tn-grid-toolbar .btn.tn-btn.tn-filter-on > i,
.tn-grid-toolbar .btn.tn-btn.tn-filter-on svg { color: var(--tn-primary) !important; }
/* count badge — notification-style, top-right corner (works on desktop + icon-only mobile) */
.tn-btn .tn-filter-count {
  position: absolute; top: -7px; right: -7px;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: var(--tn-primary); color: #fff;
  font-size: 10px !important; font-weight: 700; line-height: 1;
  box-shadow: 0 0 0 2px var(--tn-surface);   /* ring separates it from the button edge */
  pointer-events: none;
}
.tn-filter-count.tn-pop { animation: tnFilterPop .24s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes tnFilterPop { 0% { transform: scale(0); } 60% { transform: scale(1.18); } 100% { transform: scale(1); } }
/* dark mode */
[data-theme="dark"] .tn-grid-toolbar .btn.tn-btn.tn-filter-on {
  border-color: #2F6BD8 !important;
  color: var(--tn-blue) !important;
  background-color: var(--tn-primary-tint) !important;
}
[data-theme="dark"] .tn-grid-toolbar .btn.tn-btn.tn-filter-on .svg-icon,
[data-theme="dark"] .tn-grid-toolbar .btn.tn-btn.tn-filter-on > i,
[data-theme="dark"] .tn-grid-toolbar .btn.tn-btn.tn-filter-on svg { color: var(--tn-blue) !important; }
[data-theme="dark"] .tn-btn .tn-filter-count { background: #2F6BD8; box-shadow: 0 0 0 2px var(--tn-surface); }
@media (prefers-reduced-motion: reduce) { .tn-filter-count.tn-pop { animation: none; } }

/* ---------------------------------------------------------------------------
   Per-FIELD active state inside the drawer — grid.js marks each field that
   currently holds a filter value with `.tn-field-on` (the <input>/<select> and,
   for a select2, its visible container). This makes the SET filters stand out
   from the empty ones so the user can see WHICH fields are filtered, not just
   how many. Left accent bar + primary border + subtle tint + primary label.
   --------------------------------------------------------------------------- */
.tn-filter-drawer .tn-drawer-inner .form-control.tn-field-on,
.tn-filter-drawer .tn-drawer-inner .form-select.tn-field-on {
  border-color: var(--tn-primary) !important;
  background-color: var(--tn-primary-tint) !important;
  color: var(--tn-text) !important;
}
.tn-filter-drawer .tn-drawer-inner .select2-container.tn-field-on .select2-selection {
  border-color: var(--tn-primary) !important;
  background-color: var(--tn-primary-tint) !important;
}
.tn-filter-drawer .tn-drawer-inner .select2-container.tn-field-on .select2-selection__rendered,
.tn-filter-drawer .tn-drawer-inner .select2-container.tn-field-on .select2-selection__choice {
  color: var(--tn-text) !important;
}
/* label of an active field turns primary (needs :has — modern browsers; the
   border/tint above is the fallback indicator where :has is unsupported) */
.tn-filter-drawer .tn-drawer-inner .mb-5:has(.tn-field-on) > .form-label {
  color: var(--tn-primary) !important;
}
/* dark mode: brighter blue border + readable label */
[data-theme="dark"] .tn-filter-drawer .tn-drawer-inner .form-control.tn-field-on,
[data-theme="dark"] .tn-filter-drawer .tn-drawer-inner .form-select.tn-field-on,
[data-theme="dark"] .tn-filter-drawer .tn-drawer-inner .select2-container.tn-field-on .select2-selection {
  border-color: #2F6BD8 !important;
}
[data-theme="dark"] .tn-filter-drawer .tn-drawer-inner .mb-5:has(.tn-field-on) > .form-label {
  color: var(--tn-blue) !important;
}

/* ============================================================================
   Dashboard — Plan Reviewer Workload table (scoped to .tn-reviewer-workload)
   Enterprise list: In-Review project count per reviewer, click-through to /project.
   The card lives inside .tn-dashboard so it already gets the tnCardIn entrance;
   here we add the table skin, the click-through count pill, and polish.
   ========================================================================= */
.tn-reviewer-workload.card { overflow: hidden; }

/* this card is a wide data table — suppress the .tn-dashboard whole-card hover LIFT
   (a lifting table reads oddly); keep only a soft elevation on hover instead. */
.tn-dashboard .tn-reviewer-workload.card:hover {
  transform: none;
  box-shadow: var(--tn-shadow-md);
  border-color: var(--tn-border-2);
}

/* ---- header: title left, search right; wrap on small screens ---- */
.tn-reviewer-workload .card-header {
  flex-wrap: wrap;
  gap: 12px;
  border-bottom: 1px solid var(--tn-border);
}
.tn-reviewer-workload .card-toolbar { margin-left: auto; }

/* ---- table skin (matches the app's neutral grid headers) ---- */
.tn-reviewer-workload .tn-workload-scroll { overflow-x: auto; }
.tn-reviewer-workload .tn-workload-table { width: 100%; margin: 0; }
.tn-reviewer-workload .tn-workload-table thead th {
  background: var(--tn-surface-3);
  color: var(--tn-text-3);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 11px 16px;
  border-bottom: 1px solid var(--tn-border);
  white-space: nowrap;
}
.tn-reviewer-workload .tn-workload-table thead th:first-child { border-top-left-radius: var(--tn-radius-sm); }
.tn-reviewer-workload .tn-workload-table thead th:last-child  { border-top-right-radius: var(--tn-radius-sm); }
.tn-reviewer-workload .tn-workload-table tbody td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--tn-border);
  vertical-align: middle;
}
/* comfortable outer gutter so header text / avatar / count aren't jammed to the edges */
.tn-reviewer-workload .tn-workload-table th:first-child,
.tn-reviewer-workload .tn-workload-table td:first-child { padding-left: 22px; }
.tn-reviewer-workload .tn-workload-table th:last-child,
.tn-reviewer-workload .tn-workload-table td:last-child { padding-right: 22px; }
.tn-reviewer-workload .tn-workload-table tbody tr:last-child td { border-bottom: 0; }
.tn-reviewer-workload .tn-workload-table tbody tr {
  transition: background-color .15s ease;
}
.tn-reviewer-workload .tn-workload-table tbody tr:hover { background-color: var(--tn-surface-2); }

/* identity block: avatar + (name over email) */
.tn-reviewer-workload .tn-workload-identity { min-width: 0; }   /* let the email ellipsis */
.tn-reviewer-workload .tn-workload-name {
  color: var(--tn-text-2);
  font-weight: 600;
  line-height: 1.25;
}
.tn-reviewer-workload .tn-workload-email {
  color: var(--tn-muted);
  font-size: 12px;
  line-height: 1.3;
  text-decoration: none;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color .15s ease;
}
.tn-reviewer-workload .tn-workload-email:hover {
  color: var(--tn-primary);
  text-decoration: underline;
}
.tn-reviewer-workload .tn-workload-email:focus-visible {
  outline: 2px solid var(--tn-primary);
  outline-offset: 2px;
  border-radius: var(--tn-radius-sm);
}

/* avatar — keep the symbol AND its label the SAME size so initials stay centred */
.tn-reviewer-workload .symbol.symbol-40px,
.tn-reviewer-workload .symbol.symbol-40px .symbol-label { width: 38px; height: 38px; }
.tn-reviewer-workload .symbol-label.tn-avatar-initials { font-size: 13px; }

/* sortable column headers (Livewire wire:click) */
.tn-reviewer-workload .tn-sort-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  transition: color .15s ease;
}
.tn-reviewer-workload .tn-sort-btn:hover { color: var(--tn-primary); }
.tn-reviewer-workload .tn-sort-btn:focus-visible {
  outline: 2px solid var(--tn-primary);
  outline-offset: 3px;
  border-radius: var(--tn-radius-sm);
}
.tn-reviewer-workload .tn-sort-btn-end { justify-content: flex-end; }
.tn-reviewer-workload th.text-end .tn-sort-btn { margin-left: auto; }
.tn-reviewer-workload .tn-sort-ind { font-size: 11px; line-height: 1; }
.tn-reviewer-workload .tn-sort-ind.is-idle { color: var(--tn-muted-3); }
.tn-reviewer-workload .tn-sort-ind.is-active { color: var(--tn-primary); }

/* ---- click-through count pill ---- */
.tn-reviewer-workload .tn-workload-count {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 34px;
  justify-content: center;
  padding: 3px 10px;
  border-radius: var(--tn-radius-pill);
  font-size: 13px;
  font-weight: 700;
  line-height: 18px;
  color: var(--tn-blue);
  background: var(--tn-blue-bg);
  text-decoration: none;
  transition: transform .15s ease, box-shadow .15s ease, background-color .15s ease;
}
a.tn-reviewer-workload .tn-workload-count,
.tn-reviewer-workload a.tn-workload-count { cursor: pointer; }
.tn-reviewer-workload a.tn-workload-count:hover {
  transform: translateY(-1px);
  box-shadow: var(--tn-shadow-xs);
}
.tn-reviewer-workload a.tn-workload-count:hover .tn-workload-count-arrow { opacity: 1; }
.tn-reviewer-workload a.tn-workload-count:focus-visible {
  outline: 2px solid var(--tn-primary);
  outline-offset: 2px;
}
.tn-reviewer-workload .tn-workload-count-arrow {
  font-size: 11px;
  opacity: .55;
  transition: opacity .15s ease;
}
/* zero = quiet, non-interactive */
.tn-reviewer-workload .tn-workload-count.is-zero {
  color: var(--tn-muted);
  background: transparent;
  font-weight: 600;
}

/* ---- empty state ---- */
.tn-reviewer-workload .tn-workload-empty {
  text-align: center;
  color: var(--tn-muted);
  padding: 22px 8px;
  font-size: 13px;
}

/* ---- pagination footer (page-item/link already skinned globally) ---- */
.tn-reviewer-workload .tn-workload-pager .pagination { margin-bottom: 0; }

/* ---- in-flight veil (Livewire wire:loading) ---- */
.tn-reviewer-workload .tn-workload-loading {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: color-mix(in srgb, var(--tn-surface) 62%, transparent);
  border-radius: var(--tn-radius);
}
.tn-reviewer-workload .tn-workload-loading::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 26px; height: 26px;
  margin: -13px 0 0 -13px;
  border-radius: 50%;
  border: 2.5px solid var(--tn-border-2);
  border-top-color: var(--tn-primary);
  animation: tnWlSpin .7s linear infinite;
}

@keyframes tnWlSpin { to { transform: rotate(360deg); } }

/* ---- subtle row entrance (replays on page/search change for feedback) ---- */
.tn-reviewer-workload .tn-workload-table tbody tr {
  animation: tnWlRowIn .4s ease both;
}
@keyframes tnWlRowIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }

/* ---- responsive ---- */
@media (max-width: 767.98px) {
  .tn-reviewer-workload .card-toolbar { margin-left: 0; width: 100%; }
  .tn-reviewer-workload .tn-grid-search,
  .tn-reviewer-workload .tn-grid-search-input { width: 100% !important; }

  /* NO horizontal scroll for a 2-column list: fixed table layout — the count
     column gets a set width, the identity column takes the rest and ellipsises
     (auto layout let the nowrap email + gutters push the table past the phone) */
  .tn-reviewer-workload .tn-workload-scroll { overflow-x: hidden; }
  .tn-reviewer-workload .tn-workload-table { table-layout: fixed; }
  .tn-reviewer-workload .tn-workload-table th,
  .tn-reviewer-workload .tn-workload-table td { overflow: hidden; }
  .tn-reviewer-workload .tn-workload-table th:last-child,
  .tn-reviewer-workload .tn-workload-table td:last-child { width: 92px; padding-right: 14px; }
  .tn-reviewer-workload .tn-workload-table th:first-child,
  .tn-reviewer-workload .tn-workload-table td:first-child { padding-left: 14px; }
  .tn-reviewer-workload .tn-workload-table tbody td { padding: 10px 12px; }
  .tn-reviewer-workload .tn-workload-identity { flex: 1 1 0; }
  .tn-reviewer-workload .tn-workload-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .tn-reviewer-workload .tn-workload-email { max-width: 100%; display: block; }
}

/* ---- accessibility: honor reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .tn-reviewer-workload .tn-workload-table tbody tr { animation: none !important; }
  .tn-reviewer-workload a.tn-workload-count:hover { transform: none; }
  .tn-reviewer-workload .tn-workload-loading::after { animation-duration: 1.6s; }
}

/* ============================================================================
   PROJECT create / edit — enterprise form (scoped to .tn-project-form on the card)
   CSS-only reskin: every field name/id/class, select2, repeater DOM and fee-type
   toggle logic is untouched. Adds section hierarchy, chip checkboxes, repeater
   sub-cards, a sticky action bar, and a staggered entrance.
   ========================================================================= */
.tn-project-form {
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius-lg);
  box-shadow: 0 1px 3px rgba(16, 24, 40, .06), 0 1px 2px rgba(16, 24, 40, .04);
  overflow: visible;
  animation: tnFadeIn .45s ease both;
}
.tn-project-form .card-body { padding: 8px 28px 24px; }

/* ---- section headers: primary accent bar + divider ----
   `.card-body > form > h3` covers the multi-form my-profile page (its h3s are nested
   one level inside per-section <form>s, not direct children of .card-body) */
.tn-project-form .card-body > h3,
.tn-project-form .card-body > form > h3,
.tn-project-form [id$="_repeater"] h3 {
  position: relative;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--tn-text);
  margin: 34px 0 20px;
  padding: 0 0 11px 14px;
  border-bottom: 1px solid var(--tn-border);
}
.tn-project-form .card-body > h3::before,
.tn-project-form .card-body > form > h3::before,
.tn-project-form [id$="_repeater"] h3::before {
  content: "";
  position: absolute;
  left: 0; top: 1px; bottom: 12px;
  width: 4px; border-radius: 2px;
  background: var(--tn-primary);
}
.tn-project-form .card-body > h3:first-child,
.tn-project-form .card-body > form:first-of-type > h3 { margin-top: 8px; }
/* section dividers are replaced by the header spacing */
.tn-project-form .separator.my-10 { display: none; }
/* the two repeater blocks are top-level sections too — restore the section gap
   the hidden separators used to provide (fixes the cramped Add→Plan Reviewer join) */
.tn-project-form .card-body > [id$="_repeater"] { margin-top: 32px; }

/* ---- consistent field cell spacing (tighter, even enterprise grid) ---- */
.tn-project-form .card-body .row > [class*="col-"].p-3 { padding: 9px 10px !important; }
.tn-project-form .form-label { color: var(--tn-text-2); font-weight: 600; margin-bottom: 6px; }
.tn-project-form .required::after { color: var(--tn-red); }
.tn-project-form .form-control,
.tn-project-form .form-select { transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease; }

/* ============================================================================
   INPUT PARITY — every control (native input, textarea, select2, file input,
   input-group, disabled) renders with the SAME font / colour / surface / border
   / height, in the main sections AND inside the surface-2 repeater sub-cards.
   Reference control = 13px/500 Geist, text --tn-text, bg --tn-surface-2,
   1px --tn-input-border, 42px tall.
   ========================================================================= */
/* select2 SELECTED VALUE text must match native input value colour (was the
   lighter --tn-text-2, so client/reviewer names looked greyer than typed text) */
.tn-project-form .select2-container--bootstrap5 .select2-selection__rendered {
  color: var(--tn-text) !important;
  font-weight: 500;
  font-size: 13px;
}
.tn-project-form .select2-container--bootstrap5 .select2-selection__placeholder { color: var(--tn-muted) !important; }
/* multi-select (plan reviewer) resting height = 42px to match single controls;
   still grows when chips wrap to a second line */
.tn-project-form .select2-container--bootstrap5 .select2-selection--multiple {
  min-height: 42px !important;
  padding-top: 2px !important;
  padding-bottom: 2px !important;
}
.tn-project-form .select2-container--bootstrap5 .select2-selection--multiple .select2-selection__choice { margin-top: 2px; margin-bottom: 2px; }
/* uniform surface + border for text inputs, selects, textareas, file inputs
   (Metronic's solid style gave file inputs bg #F5F8FA + an invisible border) */
.tn-project-form .form-control,
.tn-project-form .form-select,
.tn-project-form input[type="file"].form-control {
  background-color: var(--tn-surface-2);
  border: 1px solid var(--tn-input-border);
  color: var(--tn-text);
}
/* focus: keep the surface, add a clear primary ring (Metronic's solid :focus
   otherwise shifts the bg to a muted grey with no ring — looked off, esp. on the
   autofocused first field) */
.tn-project-form .form-control:focus,
.tn-project-form .form-select:focus {
  background-color: var(--tn-surface-2);
  border-color: var(--tn-primary);
  box-shadow: 0 0 0 3px var(--tn-focus-ring);
}
.tn-project-form .form-control.is-invalid:focus,
.tn-project-form .form-select.is-invalid:focus { border-color: var(--tn-red) !important; }
/* file input: style the "Choose File" button to read as an attached prefix */
.tn-project-form input[type="file"].form-control { padding-top: 0; padding-bottom: 0; height: 42px; line-height: 40px; }
.tn-project-form input[type="file"].form-control::file-selector-button {
  height: 40px;
  margin: 0 12px 0 -13px;
  padding: 0 14px;
  border: 0;
  border-right: 1px solid var(--tn-input-border);
  background: var(--tn-surface-3);
  color: var(--tn-text-2);
  font-weight: 600;
}

/* input-group ($ / hourglass prefix) → ONE bordered control, not a borderless
   pill. Group owns the border/radius; children are borderless + transparent. */
.tn-project-form .input-group {
  border: 1px solid var(--tn-input-border);
  border-radius: var(--tn-radius);
  background: var(--tn-surface-2);
  /* NOT position:relative (Bootstrap default) — else an .invalid-feedback appended
     inside the group anchors to the GROUP (overlapping the input); static lets it
     fall through to the field cell's reserved space like every other field */
  position: static;
}
/* round the opaque prefix's left corners to the group radius (replaces overflow:hidden,
   which would otherwise clip an absolutely-positioned .invalid-feedback) */
.tn-project-form .input-group > .input-group-text:first-child {
  border-top-left-radius: calc(var(--tn-radius) - 1px);
  border-bottom-left-radius: calc(var(--tn-radius) - 1px);
}
.tn-project-form .input-group > .form-control,
.tn-project-form .input-group > .input-group-text {
  border: 0 !important;
  background: transparent !important;
  height: 40px;
  box-shadow: none !important;
}
/* file input inside a group must also be 40px (its own 42px rule would otherwise
   swell the group to 44px, misaligning File/Submittal vs sibling fields) */
.tn-project-form .input-group > input[type="file"].form-control { height: 40px; line-height: 38px; }
.tn-project-form .input-group > .input-group-text {
  background: var(--tn-surface-3) !important;
  border-right: 1px solid var(--tn-input-border) !important;
  color: var(--tn-text-2);
  font-size: 13px;
  font-weight: 600;
}
.tn-project-form .input-group:focus-within {
  border-color: var(--tn-primary);
  box-shadow: 0 0 0 3px var(--tn-focus-ring);
}
/* the GROUP owns the focus indicator (border + ring above) — suppress the inner
   input's own outline/ring, which otherwise drew a 2px :focus-visible outline
   INSIDE the group border (a box-in-box, non-standard look) */
.tn-project-form .input-group > .form-control:focus,
.tn-project-form .input-group > .form-control:focus-visible {
  outline: none !important;
  box-shadow: none !important;
}
/* number inputs (hourly rate / percentage / zip): drop the native spinner arrows —
   they read cluttered, and these are typed not stepped */
.tn-project-form input[type="number"]::-webkit-inner-spin-button,
.tn-project-form input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.tn-project-form input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* ---- Client Rates repeaters (Hourly Rate / Percentage): render as PLAIN full-width
   fields (no sub-card bg), size = a normal col field, delete = an icon at the END of
   the input-group, with the standard absolute validation-message reserve (no overlap) --- */
.tn-project-form #hourly_rate_repeater [data-repeater-item],
.tn-project-form #percentage_repeater [data-repeater-item] {
  position: relative;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 9px 10px 20px;
  margin: 0;
  animation: none;
}
.tn-project-form #hourly_rate_repeater [data-repeater-item] .input-group,
.tn-project-form #percentage_repeater [data-repeater-item] .input-group { margin-bottom: 0 !important; }
/* delete = trash button appended at the END of the input-group (mirrors the $/% prefix
   cap): left separator, muted → red on hover, rounded right corners */
.tn-project-form .input-group > .tn-rate-remove {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 40px;
  padding: 0;
  border: 0 !important;
  border-left: 1px solid var(--tn-input-border) !important;
  border-radius: 0;
  background: transparent !important;
  color: var(--tn-red);                 /* always red — clearly visible (WCAG-safe icon) */
  cursor: pointer;
  transition: color .15s ease, background-color .15s ease;
}
/* colour the ICON explicitly — Metronic's global `i{color:var(--kt-text-muted)}`
   pins every <i> to muted grey and does NOT inherit the anchor's colour, so the
   trash was grey (invisible on the red hover-fill) until set here. */
.tn-project-form .input-group > .tn-rate-remove i {
  font-size: 14px;
  margin: 0;
  color: var(--tn-red) !important;       /* red trash — visible (WCAG) */
  transition: transform .15s ease, color .15s ease;
}
.tn-project-form .input-group > .tn-rate-remove:hover {
  color: #fff;
  background: var(--tn-red) !important;  /* fill red on hover */
}
.tn-project-form .input-group > .tn-rate-remove:hover i { color: #fff !important; transform: scale(1.18); }
/* dark: --tn-red (#FF6F63) fails white-on-fill — use the darker red so white icon clears AA */
[data-theme="dark"] .tn-project-form .input-group > .tn-rate-remove:hover { background: #C42B1D !important; }
.tn-project-form .input-group > .tn-rate-remove:last-child {
  border-top-right-radius: calc(var(--tn-radius) - 1px);
  border-bottom-right-radius: calc(var(--tn-radius) - 1px);
}
@media (prefers-reduced-motion: reduce) {
  .tn-project-form .input-group > .tn-rate-remove:hover i { transform: none; }
}

/* ---- field-label help icon (hover tooltip) — e.g. Client Email "used as login" ---- */
.tn-project-form .tn-field-info {
  font-size: 13px;
  color: var(--tn-muted);
  cursor: help;
  transition: color .15s ease;
}
.tn-project-form .tn-field-info:hover { color: var(--tn-primary); }

/* disabled / readonly: stay bordered (via the group or their own border) but
   read as inactive with muted text */
.tn-project-form .form-control:disabled,
.tn-project-form .form-control[readonly] { color: var(--tn-muted); }
.tn-project-form .input-group:has(> .form-control:disabled) { background: var(--tn-surface-3); }

/* ============================================================================
   VALIDATION STATE (ajax-submit.js injects .is-invalid + .invalid-feedback)
   - red border must WIN over the parity border (which the parity rules removed)
   - messages are absolutely-positioned so they DON'T reflow the grid (kills the
     "page flickers / fields jump down" on submit)
   ========================================================================= */
.tn-project-form .form-control.is-invalid,
.tn-project-form .form-select.is-invalid,
.tn-project-form textarea.is-invalid { border-color: var(--tn-red) !important; }
.tn-project-form .input-group:has(.is-invalid) { border-color: var(--tn-red) !important; }
/* select2: the hidden <select> gets .is-invalid → colour its sibling widget */
.tn-project-form select.is-invalid ~ .select2-container .select2-selection { border-color: var(--tn-red) !important; }
/* field cell is the positioning context; the message floats in reserved space
   below the control instead of pushing the next row */
.tn-project-form .card-body .row > [class*="col-"].p-3 { position: relative; padding-bottom: 20px !important; }
.tn-project-form .invalid-feedback {
  display: block;
  position: absolute;
  left: 10px; right: 10px; bottom: 2px;
  margin: 0; padding: 0;
  font-size: 11px; line-height: 1.25;
  color: var(--tn-red);
  z-index: 2;
}

/* ============================================================================
   SUBMIT LOADER — blur the form content + a viewport-centred spinner pill.
   ajaxFormSubmit() (layouts/app.blade.php) calls blockUI.block(), which appends
   `.blockui-overlay` + `.blockui-message`. The overlay lands on <body> for most
   forms (client/user/teams/my-profile use the global body-target KTBlockUI) or
   INSIDE the <form> on the project page (its blade builds a form-target KTBlockUI).
   So key the blur off ANY overlay in the page — `body:has(.blockui-overlay)` is
   true in BOTH cases — which finally gives every enterprise form the same loader.
   `.release()` removes the overlay (the `.blockui` class lingers — never key off
   that or the blur sticks), so the blur clears cleanly. ========================= */
body:has(.blockui-overlay) .tn-project-form .card-body,
body:has(.blockui-overlay) .tn-project-form .card-footer {
  filter: blur(2.5px);
  opacity: .55;
  pointer-events: none;
  transition: filter .2s ease, opacity .2s ease;
}
/* FORM-SCOPED loader (no full-page dim): the KTBlockUI overlay covers the whole <body>
   on client/user/teams/profile (page-level block target) but only the form on project —
   an inconsistent full-viewport grey. We don't want a page dim at all; the form-scoped
   blur/fade above IS the visual cue (with the button's "Please wait…" indicator). So make
   the overlay invisible + non-blocking: the blurred card content already has
   pointer-events:none and the submit button is disabled, so re-submit is still prevented,
   and the sidebar/rest of the page stays usable. */
.blockui-overlay {
  background: transparent !important;
  pointer-events: none !important;
}
/* the Loading… pill — FIXED to the viewport centre so it stays visible while the
   user scrolls a long form. It was position:static, centred inside the full-height
   overlay → on a tall form it sat at the form's midpoint and scrolled out of view.
   Scoped to `.blockui .blockui-message` to match Metronic's own `.blockui
   .blockui-message` specificity (0,2,0) — redesign CSS loads later so it wins the
   pill look; matches both blockUI targets (the <form> OR <body> carries `.blockui`). */
.blockui .blockui-message {
  position: fixed !important;
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%) !important;
  z-index: 1090 !important;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--tn-surface);
  border: 1px solid var(--tn-border);
  border-radius: 999px;
  padding: 9px 18px;
  box-shadow: 0 6px 24px rgba(16, 24, 40, .14);
  color: var(--tn-text-2);
  font-weight: 600;
  font-size: 13px;
}
.blockui .blockui-message .spinner-border {
  width: 18px; height: 18px;
  border-width: 2px;
  color: var(--tn-primary);
}

/* ---- checkbox chips (project flags, user roles, …) — NOT toggle switches ----
   `.form-switch` (invoice-setting column toggles, my-profile enable-search) must
   keep their native switch look, so every chip rule excludes `:not(.form-switch)`. */
.tn-project-form .form-check:not(.form-switch) {
  position: relative;
  display: flex;
  align-items: center;
  margin: 0;
  min-height: 44px;
  padding: 10px 14px 10px 40px;
  border: 1px solid var(--tn-input-border);
  border-radius: var(--tn-radius);
  background: var(--tn-surface);
  transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
  cursor: pointer;
}
.tn-project-form .form-check:not(.form-switch):hover { border-color: var(--tn-muted-3); background: var(--tn-surface-2); }
.tn-project-form .form-check:not(.form-switch) .form-check-input {
  position: absolute;
  left: 14px; top: 50%;
  width: 18px; height: 18px;
  margin: 0;
  transform: translateY(-50%);
  float: none;
  cursor: pointer;
  /* Metronic's default unchecked box is a near-invisible pale square — give it
     a clearly visible border + surface bg (non-text contrast ~3:1) */
  background-color: var(--tn-surface);
  border: 1.5px solid var(--tn-muted-3);
  border-radius: 5px;
}
/* checked: cobalt fill (this rule out-specifies components.css's generic
   `.form-check-input:checked`, so restate it here) */
.tn-project-form .form-check:not(.form-switch) .form-check-input:checked {
  background-color: var(--tn-primary);
  border-color: var(--tn-primary);
}
.tn-project-form .form-check:not(.form-switch) .form-check-label {
  margin: 0 !important;
  padding: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--tn-text-2);
  cursor: pointer;
  line-height: 1.2;
}
.tn-project-form .form-check:not(.form-switch).tn-checked,
.tn-project-form .form-check:not(.form-switch):has(.form-check-input:checked) {
  border-color: var(--tn-primary);
  background: var(--tn-primary-tint);
}
.tn-project-form .form-check:not(.form-switch).tn-checked .form-check-label,
.tn-project-form .form-check:not(.form-switch):has(.form-check-input:checked) .form-check-label { color: var(--tn-primary); }
/* dark: primary text on the tint is only ~3.9:1 — use the lighter blue (AA ~5.9:1) */
[data-theme="dark"] .tn-project-form .form-check:not(.form-switch).tn-checked .form-check-label,
[data-theme="dark"] .tn-project-form .form-check:not(.form-switch):has(.form-check-input:checked) .form-check-label { color: var(--tn-blue); }

/* ---- role-assignment chips (user create/edit): equal-width single line on
       desktop + tablet; one full-width chip per row on phones ---- */
.tn-role-chips { display: flex; flex-wrap: wrap; gap: 12px; }
.tn-role-chips .form-check { flex: 1 1 0; min-width: 150px; }
@media (max-width: 575.98px) {
  .tn-role-chips { flex-direction: column; }
  .tn-role-chips .form-check { flex: 1 1 auto; min-width: 0; width: 100%; }
}

/* ============================================================================
   Section tabs (.tn-tabs / .tn-tabpane — my-profile) — enterprise underline
   tabs: tab bar with animated pane switch; behaviour in grid.js (click,
   arrow keys, #hash deep-link). Light + dark, scrolls horizontally on phones.
   ========================================================================= */
.tn-profile-tabs .tn-tabs {
  display: flex;
  align-items: stretch;
  gap: 2px;
  margin: 6px 0 14px;
  border-bottom: 1px solid var(--tn-border);
  overflow-x: auto;
  scrollbar-width: none;
}
.tn-profile-tabs .tn-tabs::-webkit-scrollbar { display: none; }
.tn-profile-tabs .tn-tab {
  appearance: none;
  background: transparent;
  border: 0;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -.006em;
  color: var(--tn-muted);
  white-space: nowrap;
  cursor: pointer;
  border-radius: var(--tn-radius) var(--tn-radius) 0 0;
  transition: color .15s ease, background-color .15s ease;
}
.tn-profile-tabs .tn-tab svg { flex: 0 0 auto; }
.tn-profile-tabs .tn-tab:hover { color: var(--tn-text-2); background: var(--tn-surface-2); }
.tn-profile-tabs .tn-tab:focus-visible { outline: 2px solid var(--tn-primary); outline-offset: -2px; }
.tn-profile-tabs .tn-tab.is-active { color: var(--tn-primary); }
.tn-profile-tabs .tn-tab.is-active::after {
  content: "";
  position: absolute;
  left: 10px; right: 10px; bottom: 0;
  height: 2.5px;
  border-radius: 2px 2px 0 0;
  background: var(--tn-primary);
}
/* dark: primary as small text on near-black is weak — use the lighter blue */
[data-theme="dark"] .tn-profile-tabs .tn-tab.is-active { color: var(--tn-blue); }
[data-theme="dark"] .tn-profile-tabs .tn-tab.is-active::after { background: var(--tn-blue); }

.tn-profile-tabs .tn-tabpane { display: none; }
.tn-profile-tabs .tn-tabpane.is-active {
  display: block;
  animation: tnFormRise .38s cubic-bezier(.22, .61, .36, 1) both;
}
@media (max-width: 575.98px) {
  .tn-profile-tabs .tn-tab { padding: 10px 11px; font-size: 13px; }
  .tn-profile-tabs .tn-tab svg { display: none; }   /* labels only — the 3 tabs fit */
}
/* phones: submit buttons go full-width — parity with the project form's footer */
@media (max-width: 767.98px) {
  .tn-profile-tabs .tn-tabpane [class*="col-"].pull-right { flex: 0 0 100%; max-width: 100%; }
  .tn-profile-tabs .tn-tabpane .pull-right .btn {
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 4px !important;   /* tame mt-3/mt-md-8 in the compact pane */
  }
}
@media (prefers-reduced-motion: reduce) {
  .tn-profile-tabs .tn-tabpane.is-active { animation: none !important; }
}

/* ---- repeater items (each review / plan-reviewer) as sub-cards ---- */
.tn-project-form [data-repeater-item] {
  position: relative;
  background: var(--tn-surface-2);
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius-lg);
  padding: 4px 18px 12px;
  margin-bottom: 16px;
  animation: tnFormRise .45s cubic-bezier(.22, .61, .36, 1) backwards;
}
.tn-project-form [data-repeater-item] > h3,
.tn-project-form [id$="_repeater"] h3 { margin-top: 14px; }
.tn-project-form [id$="_repeater"] > [data-repeater-list] > h3 { margin-top: 8px; }
/* add / delete repeater buttons */
.tn-project-form [data-repeater-create],
.tn-project-form .add_review_level_pricing { border-radius: var(--tn-radius); font-weight: 600; }

/* ---- sticky action bar ---- */
.tn-project-form .card-footer {
  position: sticky;
  bottom: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin: 0;
  padding: 14px 24px;
  background: var(--tn-surface);
  border-top: 1px solid var(--tn-border);
  border-radius: 0 0 var(--tn-radius-lg) var(--tn-radius-lg);
}
.tn-project-form .card-footer .btn { margin: 0 !important; }

/* ---- staggered entrance for the top-level sections ---- */
.tn-project-form .card-body > h3,
.tn-project-form .card-body > .row,
.tn-project-form .card-body > [id$="_repeater"] {
  animation: tnFormRise .5s cubic-bezier(.22, .61, .36, 1) backwards;
}
@keyframes tnFormRise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.tn-project-form .card-body > h3:nth-of-type(1) { animation-delay: .04s; }
.tn-project-form .card-body > h3:nth-of-type(2) { animation-delay: .12s; }
.tn-project-form .card-body > h3:nth-of-type(3) { animation-delay: .20s; }
.tn-project-form .card-body > .row:nth-of-type(1) { animation-delay: .08s; }
.tn-project-form .card-body > .row:nth-of-type(2) { animation-delay: .16s; }
.tn-project-form .card-body > .row:nth-of-type(3) { animation-delay: .24s; }
.tn-project-form .card-body > [id$="_repeater"]:nth-of-type(1) { animation-delay: .28s; }
.tn-project-form .card-body > [id$="_repeater"]:nth-of-type(2) { animation-delay: .34s; }

/* ---- mobile ---- */
@media (max-width: 767.98px) {
  .tn-project-form .card-body { padding: 4px 14px 18px; }
  .tn-project-form .card-body > h3,
  .tn-project-form [id$="_repeater"] h3 { margin-top: 24px; }
  .tn-project-form [data-repeater-item] { padding: 4px 12px 10px; }
  .tn-project-form .card-footer { flex-direction: column-reverse; padding: 12px 14px; }
  .tn-project-form .card-footer .btn { width: 100%; justify-content: center; }
}
/* flag chips → 2-up on phones (they are col-12 by default) */
@media (max-width: 575.98px) {
  .tn-project-form .row > [class*="col-"].p-3:has(> .form-check) { flex: 0 0 50%; max-width: 50%; }
}
/* flag chips → 3-up on tablets (their col-sm-2 = 6-up is too cramped, labels wrap) */
@media (min-width: 576px) and (max-width: 991.98px) {
  .tn-project-form .row > [class*="col-"].p-3:has(> .form-check) { flex: 0 0 33.3333%; max-width: 33.3333%; }
}

@media (prefers-reduced-motion: reduce) {
  .tn-project-form,
  .tn-project-form .card-body > h3,
  .tn-project-form .card-body > .row,
  .tn-project-form .card-body > [id$="_repeater"],
  .tn-project-form [data-repeater-item] { animation: none !important; }
  /* keep the loading blur, drop its transition */
  body:has(.blockui-overlay) .tn-project-form .card-body,
  body:has(.blockui-overlay) .tn-project-form .card-footer { transition: none !important; }
}

/* ============================================================================
   flatpickr DATE PICKER — replaces the native <input type=date> picker (bound in
   grid.js). flatpickr converts the input to type=text, so add a calendar icon,
   and theme its calendar popup (appended to <body>) to True North, both modes.
   ========================================================================= */
.tn-project-form input.flatpickr-input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235B6573' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
  padding-right: 36px !important;
  cursor: pointer;
}
[data-theme="dark"] .tn-project-form input.flatpickr-input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238A94A2' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E");
}

/* ---- calendar popup (global .flatpickr-calendar — only the project form uses it) ---- */
.flatpickr-calendar {
  background: var(--tn-surface);
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius);
  box-shadow: 0 12px 32px rgba(16, 24, 40, .16);
  color: var(--tn-text);
}
.flatpickr-calendar.arrowTop::before { border-bottom-color: var(--tn-border); }
.flatpickr-calendar.arrowTop::after { border-bottom-color: var(--tn-surface); }
.flatpickr-calendar.arrowBottom::before { border-top-color: var(--tn-border); }
.flatpickr-calendar.arrowBottom::after { border-top-color: var(--tn-surface); }
.flatpickr-months .flatpickr-month,
.flatpickr-current-month,
.flatpickr-current-month input.cur-year,
.flatpickr-current-month .flatpickr-monthDropdown-months { color: var(--tn-text); fill: var(--tn-text); background: transparent; }
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg { fill: var(--tn-text-2); }
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg { fill: var(--tn-primary); }
span.flatpickr-weekday { color: var(--tn-muted); font-weight: 600; }
.flatpickr-day {
  color: var(--tn-text);
  border-radius: var(--tn-radius);
  border-color: transparent;
}
.flatpickr-day:hover,
.flatpickr-day:focus { background: var(--tn-surface-2); border-color: var(--tn-surface-2); color: var(--tn-text); }
.flatpickr-day.today { border-color: var(--tn-primary); }
.flatpickr-day.today:hover,
.flatpickr-day.today:focus { background: var(--tn-primary); border-color: var(--tn-primary); color: #fff; }
.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange,
.flatpickr-day.endRange { background: var(--tn-primary); border-color: var(--tn-primary); color: #fff; }
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay { color: var(--tn-muted-2); }
.flatpickr-monthDropdown-months .flatpickr-monthDropdown-month { background: var(--tn-surface); color: var(--tn-text); }
.numInputWrapper span.arrowUp,
.numInputWrapper span.arrowDown { border-color: var(--tn-border); }
.numInputWrapper span:hover { background: var(--tn-surface-2); }
/* dark: darker primary fill so white day-text clears AA */
[data-theme="dark"] .flatpickr-day.selected,
[data-theme="dark"] .flatpickr-day.selected:hover,
[data-theme="dark"] .flatpickr-day.today:hover { background: #2F6BD8; border-color: #2F6BD8; color: #fff; }
[data-theme="dark"] .flatpickr-day:hover,
[data-theme="dark"] .flatpickr-day:focus { background: var(--tn-surface-2); border-color: var(--tn-surface-2); }

/* ---- Today / Clear action bar (injected by grid.js tnFpFooter) ---- */
.flatpickr-calendar .tn-fp-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding: 8px 10px;
  border-top: 1px solid var(--tn-border);
}
.flatpickr-calendar .tn-fp-btn {
  border: 1px solid var(--tn-input-border);
  background: var(--tn-surface);
  color: var(--tn-text-2);
  font-size: 12px;
  font-weight: 600;
  border-radius: var(--tn-radius);
  padding: 5px 14px;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.flatpickr-calendar .tn-fp-btn:hover { background: var(--tn-surface-2); border-color: var(--tn-muted-3); color: var(--tn-text); }
.flatpickr-calendar .tn-fp-btn.tn-fp-today {
  background: var(--tn-primary);
  border-color: var(--tn-primary);
  color: #fff;
}
.flatpickr-calendar .tn-fp-btn.tn-fp-today:hover { background: var(--tn-primary-hover); border-color: var(--tn-primary-hover); color: #fff; }
[data-theme="dark"] .flatpickr-calendar .tn-fp-btn.tn-fp-today { background: #2F6BD8; border-color: #2F6BD8; }

/* ============================================================================
   Activity Log — enterprise audit timeline (scoped to .tn-audit)
   Colour-coded events (created/updated/deleted), actor identity (name + role +
   email), IP, connector rail, staggered entrance, Livewire pagination.
   ========================================================================= */
.tn-audit-card {
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius-lg);
  box-shadow: var(--tn-shadow-sm);
  animation: tnFadeIn .4s ease both;
}
.tn-audit-card .card-header { border-bottom: 1px solid var(--tn-border); }

/* ---- timeline item: [rail with node + connector] [body] ---- */
.tn-audit-timeline { padding-top: 6px; }
.tn-audit-item {
  display: flex;
  gap: 16px;
  position: relative;
  padding-bottom: 26px;
  animation: tnAuditIn .45s cubic-bezier(.22, .61, .36, 1) both;
  animation-delay: calc(var(--i, 0) * .06s);
}
.tn-audit-rail { position: relative; width: 40px; flex-shrink: 0; }
.tn-audit-node {
  position: relative;
  z-index: 1;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
}
/* vertical connector: from each node's centre down to the next node */
.tn-audit-item:not(:last-child) .tn-audit-rail::before {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 40px;
  bottom: -6px;
  width: 2px;
  background: var(--tn-border);
}
/* node colours by event type */
.tn-audit-created .tn-audit-node { background: var(--tn-green-bg); color: var(--tn-green); }
.tn-audit-updated .tn-audit-node { background: var(--tn-blue-bg);  color: var(--tn-blue); }
.tn-audit-deleted .tn-audit-node { background: var(--tn-red-bg);   color: var(--tn-red); }

/* ---- body ---- */
.tn-audit-body { flex: 1 1 auto; min-width: 0; padding-top: 2px; }
.tn-audit-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tn-audit-title { font-size: 14px; font-weight: 600; color: var(--tn-text-2); line-height: 1.35; }
.tn-audit-badge {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 2px 8px;
  border-radius: var(--tn-radius-pill);
  flex-shrink: 0;
}
.tn-audit-badge.tn-audit-created { background: var(--tn-green-bg); color: var(--tn-green); }
.tn-audit-badge.tn-audit-updated { background: var(--tn-blue-bg);  color: var(--tn-blue); }
.tn-audit-badge.tn-audit-deleted { background: var(--tn-red-bg);   color: var(--tn-red); }

/* ---- meta (time + ip) ---- */
.tn-audit-meta { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 6px; }
.tn-audit-time,
.tn-audit-ip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--tn-muted);
}
.tn-audit-ip { font-variant-numeric: tabular-nums; }
.tn-audit-time svg, .tn-audit-ip svg { opacity: .8; flex-shrink: 0; }

/* ---- actor row: avatar + (name/role over email) + view action ---- */
.tn-audit-actor { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.tn-audit .symbol.symbol-35px,
.tn-audit .symbol.symbol-35px .symbol-label { width: 34px; height: 34px; }
.tn-audit .symbol-label.tn-avatar-initials { font-size: 12px; }
.tn-audit-actor-info { display: flex; flex-direction: column; min-width: 0; }
.tn-audit-actor-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tn-audit-actor-name { font-size: 13px; font-weight: 600; color: var(--tn-text-2); }
.tn-audit-role {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  padding: 2px 7px;
  border-radius: var(--tn-radius-pill);
  background: var(--tn-surface-3);
  color: var(--tn-text-3);
}
.tn-audit-role-more { font-size: 10px; font-weight: 600; color: var(--tn-muted); }
.tn-audit-actor-email {
  font-size: 12px;
  color: var(--tn-muted);
  text-decoration: none;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color .15s ease;
}
.tn-audit-actor-email:hover { color: var(--tn-primary); text-decoration: underline; }
.tn-audit-actor-email:focus-visible { outline: 2px solid var(--tn-primary); outline-offset: 2px; border-radius: var(--tn-radius-sm); }

/* ---- view-changes action (right-aligned) ---- */
.tn-audit-view {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--tn-text-3);
  text-decoration: none;
  padding: 6px 12px;
  border: 1px solid var(--tn-border-2);
  border-radius: var(--tn-radius);
  background: var(--tn-surface);
  transition: color .15s ease, border-color .15s ease, background-color .15s ease, transform .15s ease;
}
.tn-audit-view:hover {
  color: var(--tn-primary);
  border-color: var(--tn-primary);
  background: var(--tn-surface-2);
  transform: translateY(-1px);
}
.tn-audit-view:focus-visible { outline: 2px solid var(--tn-primary); outline-offset: 2px; }

/* ---- empty state ---- */
.tn-audit-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 52px 16px;
  color: var(--tn-muted);
  font-size: 13px;
}
.tn-audit-empty svg { color: var(--tn-muted-3); }

/* ---- pagination footer ---- */
.tn-audit-pager { border-top: 1px solid var(--tn-border); margin-top: 6px; }
.tn-audit-count { font-size: 13px; color: var(--tn-muted); }
.tn-audit-pager .pagination { margin-bottom: 0; }

/* ---- in-flight veil (Livewire wire:loading) ---- */
.tn-audit-loading {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: color-mix(in srgb, var(--tn-surface) 62%, transparent);
  border-radius: var(--tn-radius);
}
.tn-audit-loading::after {
  content: "";
  position: absolute;
  top: 60px; left: 50%;
  width: 26px; height: 26px;
  margin-left: -13px;
  border-radius: 50%;
  border: 2.5px solid var(--tn-border-2);
  border-top-color: var(--tn-primary);
  animation: tnWlSpin .7s linear infinite;
}

@keyframes tnAuditIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* ---- responsive ---- */
@media (max-width: 575.98px) {
  .tn-audit-item { gap: 12px; }
  .tn-audit-actor { flex-wrap: wrap; }
  .tn-audit-view { margin-left: 46px; margin-top: 4px; }
  .tn-audit-actor-email { max-width: 70vw; }
}

/* ---- accessibility: honor reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .tn-audit-card,
  .tn-audit-item { animation: none !important; }
  .tn-audit-view:hover { transform: none; }
  .tn-audit-loading::after { animation-duration: 1.6s; }
}

/* ============================================================================
   Activity Log — DETAIL / diff view (scoped to .tn-audit-detail)
   Field-level change view: created/deleted = label→value, updated = old → new.
   ========================================================================= */
.tn-audit-node-lg { width: 44px; height: 44px; flex-shrink: 0; }
.tn-audit-detail-title { font-size: 16px; font-weight: 700; color: var(--tn-text); line-height: 1.3; }

/* ---- diff / values grid ---- */
.tn-diff { display: flex; flex-direction: column; }
.tn-diff-row {
  padding: 11px 4px;
  border-bottom: 1px solid var(--tn-border);
  align-items: center;
  animation: tnAuditIn .4s cubic-bezier(.22, .61, .36, 1) both;
  animation-delay: min(calc(var(--i, 0) * .03s), .45s);
}
.tn-diff-row:last-child { border-bottom: 0; }
.tn-diff-1col .tn-diff-row { display: grid; grid-template-columns: minmax(160px, 260px) 1fr; gap: 14px; }
.tn-diff-2col .tn-diff-row { display: grid; grid-template-columns: minmax(150px, 230px) 1fr auto 1fr; gap: 12px; }

.tn-diff-head {
  animation: none !important;
  border-bottom: 1px solid var(--tn-border);
  padding-bottom: 8px;
}
.tn-diff-head > div {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--tn-muted);
}
.tn-diff-field { font-size: 13px; font-weight: 600; color: var(--tn-muted); }
.tn-diff-head .tn-diff-field { color: var(--tn-muted); }
.tn-diff-value { font-size: 13px; font-weight: 500; color: var(--tn-text-2); word-break: break-word; }

.tn-diff-val {
  display: inline-block;
  max-width: 100%;
  font-size: 13px;
  font-weight: 500;
  padding: 2px 9px;
  border-radius: var(--tn-radius-sm);
  word-break: break-word;
}
.tn-diff-val.is-old {
  color: var(--tn-red);
  background: var(--tn-red-bg);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.tn-diff-val.is-new { color: var(--tn-green); background: var(--tn-green-bg); }
.tn-diff-arrow { display: inline-flex; align-items: center; justify-content: center; color: var(--tn-muted-3); }

/* ---- people chips (plan reviewers / reviews) ---- */
.tn-audit-people { display: flex; flex-direction: column; gap: 8px; }
.tn-audit-person {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius);
  background: var(--tn-surface);
  animation: tnAuditIn .4s cubic-bezier(.22, .61, .36, 1) both;
  animation-delay: min(calc(var(--i, 0) * .05s), .35s);
}
.tn-audit-person-name { font-size: 13px; font-weight: 600; color: var(--tn-text-2); }
.tn-audit-person-tag {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  padding: 2px 8px;
  border-radius: var(--tn-radius-pill);
  background: var(--tn-blue-bg);
  color: var(--tn-blue);
}
.tn-audit-person-dates { font-size: 12px; color: var(--tn-muted); margin-left: auto; font-variant-numeric: tabular-nums; }

/* ---- responsive: stack the diff on small screens ---- */
@media (max-width: 640px) {
  .tn-diff-head { display: none !important; }
  .tn-diff-2col .tn-diff-row { grid-template-columns: 1fr auto 1fr; row-gap: 6px; }
  .tn-diff-2col .tn-diff-field { grid-column: 1 / -1; }
  .tn-diff-1col .tn-diff-row { grid-template-columns: 1fr; row-gap: 3px; }
  .tn-audit-person { flex-wrap: wrap; }
  .tn-audit-person-dates { margin-left: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .tn-diff-row,
  .tn-audit-person { animation: none !important; }
}

/* ============================================================================
   GRID CELL STANDARD — shared cell-value design system for EVERY .tn-grid-card
   list (client, user/*, teams, …). Rendered by window.tnCell (grid.js). These are
   class-based (NOT column-position/id) so all grids read the SAME. Recipe = grid.js.
   ========================================================================= */

/* identity: [avatar | tile] + name (+ email / sub / #number) */
:is(.tn-grid-card, .tn-report-results) .tn-cell-id { display: flex; align-items: center; gap: 10px; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-id-info { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-avatar,
:is(.tn-grid-card, .tn-report-results) .tn-cell-tile {
  width: 38px; height: 38px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 12px; letter-spacing: .02em;
}
:is(.tn-grid-card, .tn-report-results) .tn-cell-avatar { border-radius: 50%; }                          /* PERSON = circle */
:is(.tn-grid-card, .tn-report-results) .tn-cell-tile { border-radius: var(--tn-radius); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14); } /* ORG = squircle */
:is(.tn-grid-card, .tn-report-results) .tn-cell-title { font-size: 13px; font-weight: 600; color: var(--tn-text-2); line-height: 1.3; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-sub { font-size: 12px; font-weight: 500; color: var(--tn-muted); font-variant-numeric: tabular-nums; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-no {
  align-self: flex-start; margin-top: 2px; padding: 0 7px;
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 17px;
  color: var(--tn-muted); background: var(--tn-surface-3);
  border: 1px solid var(--tn-border); border-radius: var(--tn-radius-sm);
}
:is(.tn-grid-card, .tn-report-results) .tn-cell-email {
  font-size: 12px; font-weight: 500; color: var(--tn-muted); text-decoration: none;
  max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: color .15s ease;
}
:is(.tn-grid-card, .tn-report-results) .tn-cell-email-solo { display: inline-block; font-size: 13px; max-width: 320px; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-email:hover { color: var(--tn-primary); text-decoration: underline; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-email:focus-visible { outline: 2px solid var(--tn-primary); outline-offset: 2px; border-radius: var(--tn-radius-sm); }
:is(.tn-grid-card, .tn-report-results) .tn-cell-muted { font-size: 13px; color: var(--tn-text-3); font-variant-numeric: tabular-nums; }
:is(.tn-grid-card, .tn-report-results) .tn-cell-empty { color: var(--tn-muted-3); }

/* money / percentage pills (stacked) + "+N more" */
:is(.tn-grid-card, .tn-report-results) .tn-cell-pills { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
:is(.tn-grid-card, .tn-report-results) .tn-money-pill,
:is(.tn-grid-card, .tn-report-results) .tn-pct-pill {
  display: inline-block; padding: 3px 9px; font-size: 12px; font-weight: 700; line-height: 1.3;
  border-radius: var(--tn-radius-pill); font-variant-numeric: tabular-nums;
}
:is(.tn-grid-card, .tn-report-results) .tn-money-pill { color: var(--tn-green); background: var(--tn-green-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-pct-pill { color: var(--tn-blue); background: var(--tn-blue-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-cell-more {
  display: inline-block; margin-top: 2px; font-size: 11px; font-weight: 600;
  color: var(--tn-primary); text-decoration: none; cursor: pointer; transition: color .15s ease;
}
:is(.tn-grid-card, .tn-report-results) .tn-cell-more:hover { color: var(--tn-primary-hover); text-decoration: underline; }

/* status = dot + pill (active green / inactive RED / pending amber) */
:is(.tn-grid-card, .tn-report-results) .tn-status-pill {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  border-radius: var(--tn-radius-pill); line-height: 1.5;
}
:is(.tn-grid-card, .tn-report-results) .tn-status-pill .tn-status-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
:is(.tn-grid-card, .tn-report-results) .tn-status-pill.is-active { color: var(--tn-green); background: var(--tn-green-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-status-pill.is-inactive { color: var(--tn-red); background: var(--tn-red-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-status-pill.is-pending { color: var(--tn-amber); background: var(--tn-amber-bg); }

/* category / role tags */
:is(.tn-grid-card, .tn-report-results) .tn-cell-tags { display: flex; flex-wrap: wrap; gap: 4px; }
:is(.tn-grid-card, .tn-report-results) .tn-tag {
  display: inline-block; padding: 2px 8px; font-size: 11px; font-weight: 700;
  letter-spacing: .02em; border-radius: var(--tn-radius-pill); white-space: nowrap;
}
:is(.tn-grid-card, .tn-report-results) .tn-tag-blue { color: var(--tn-blue); background: var(--tn-blue-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-tag-green { color: var(--tn-green); background: var(--tn-green-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-tag-red { color: var(--tn-red); background: var(--tn-red-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-tag-amber { color: var(--tn-amber); background: var(--tn-amber-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-tag-purple { color: var(--tn-purple); background: var(--tn-purple-bg); }
:is(.tn-grid-card, .tn-report-results) .tn-tag-neutral { color: var(--tn-text-3); background: var(--tn-surface-3); }

/* staggered row entrance — EVERY grid (replays on search / paginate).
   fill-mode BACKWARDS (not both): no retained transform, so a <tr> never becomes a
   containing block that clips the position:fixed row-action (KTMenu) dropdowns. */
.tn-grid-card table.dataTable > tbody > tr { animation: tnGridRowIn .4s cubic-bezier(.22, .61, .36, 1) backwards; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(1) { animation-delay: .02s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(2) { animation-delay: .05s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(3) { animation-delay: .08s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(4) { animation-delay: .11s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(5) { animation-delay: .14s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(6) { animation-delay: .17s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(7) { animation-delay: .20s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(8) { animation-delay: .23s; }
.tn-grid-card table.dataTable > tbody > tr:nth-child(n+9) { animation-delay: .26s; }
@keyframes tnGridRowIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

@media (prefers-reduced-motion: reduce) {
  .tn-grid-card table.dataTable > tbody > tr { animation: none !important; }
}

/* ============================================================================
   /project-report — results table gets the STANDARD grid SKIN (card + header
   band + no-zebra + hover + cell padding + compact pagination + loader) but
   grows naturally: it is hidden-until-Generate, variable-length and exported,
   so it does NOT use the frozen-header / tbody-scroll / viewport auto-fit that
   full-page management grids use. Cell values already use the tnCell standard.
   ========================================================================= */
/* the results wrapper (#kt_table_users_wrapper.tn-report-results) IS the card */
.tn-report-results {
  border: 1px solid var(--tn-border);
  border-radius: var(--tn-radius-lg);
  background: var(--tn-surface);
  box-shadow: var(--tn-shadow-sm);
  padding: 6px 16px 12px;
  position: relative;
  margin-top: 4px;
  animation: tnFadeIn .4s ease both;
}
/* before Generate the inner .table-responsive is display:none → hide the empty card */
.tn-report-results:has(> .table-responsive[style*="none"]) { display: none !important; }

/* header band (not sticky — the report grows with content, no tbody scroll) */
.tn-report-results table.dataTable { margin: 0 !important; --bs-table-striped-bg: transparent !important; --bs-table-accent-bg: transparent !important; }
.tn-report-results table.dataTable thead tr { background: transparent !important; }
.tn-report-results table.dataTable thead th {
  background: var(--tn-surface-3) !important;
  color: var(--tn-text-3) !important;
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  padding: 11px 12px !important;
  border-bottom: 1px solid var(--tn-border-2) !important;
  white-space: nowrap;
}
.tn-report-results table.dataTable thead th:first-child { border-top-left-radius: var(--tn-radius-sm); }
.tn-report-results table.dataTable thead th:last-child  { border-top-right-radius: var(--tn-radius-sm); }

/* rows: no zebra, clean borders, hover */
.tn-report-results table.dataTable > tbody > tr,
.tn-report-results table.dataTable > tbody > tr.odd,
.tn-report-results table.dataTable > tbody > tr.even { background-color: transparent !important; }
.tn-report-results table.dataTable > tbody > tr > td {
  padding: 12px !important;
  border-bottom: 1px solid var(--tn-border);
  color: var(--tn-text-2);
  vertical-align: middle;
  background-color: transparent !important;
  box-shadow: none !important;
  transition: background-color .15s ease;
}
.tn-report-results table.dataTable > tbody > tr:hover > td { background-color: var(--tn-surface-2) !important; box-shadow: none !important; }
.tn-report-results table.dataTable > tbody > tr:last-child > td { border-bottom: 0; }

/* footer: length / info / pagination — compact + muted (page-link skin is global) */
.tn-report-results .dataTables_length,
.tn-report-results .dataTables_paginate,
.tn-report-results .dataTables_info { padding-top: 12px; }
.tn-report-results .dataTables_info { color: var(--tn-muted); font-size: 13px; }
.tn-report-results .dataTables_length { margin-right: 18px; }
.tn-report-results .dataTables_paginate .pagination { margin-bottom: 0; }


/* --- /project-report: kill the spurious horizontal scrollbar + responsive ---
   The Export/column-visibility toolbar lives INSIDE the overflow-x:auto
   .table-responsive; its Bootstrap .row has negative -0.75rem gutters that push
   ~12px past the content box → a horizontal scrollbar even for a 2-column table.
   Neutralise the row gutters and keep the table at 100%; nothing overflows, so no
   scrollbar. On phones the toolbar cols (col-12) already stack. */
.tn-report-results .row { margin-left: 0 !important; margin-right: 0 !important; }  /* toolbar AND DataTables footer rows */
.tn-report-results table.dataTable { width: 100% !important; }
.tn-report-results .table-responsive { overflow-x: auto; }
@media (max-width: 575.98px) {
  .tn-report-results { padding: 6px 10px 10px; }
  .tn-report-results .card-toolbar .row > [class*="col-"] { padding: 7px !important; }
}
