@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Poppins:wght@400;500;600&display=swap');

:root {
  --ig-navy:        #162a3c;
  --ig-navy-deep:   #0b1a26;
  --ig-navy-darker: #131e2f;
  --ig-off-white:   #edeff2;
  --ig-white:       #ffffff;
  --ig-slate:       #53606b;
  --ig-slate-2:     #54595f;
  --ig-text:        #7a7a7a;
  --ig-border:      #dfe1e5;
  --ig-blue:        #6ec1e4;
  --ig-teal:        #00d2a9;
  --ig-green:       #61ce70;
  --ig-red:         #c0392b;
}

html, body {
  margin: 0; background: var(--ig-off-white); color: #1f2933;
  font-family: 'Poppins', system-ui, sans-serif; font-size: 14px; line-height: 1.45;
}
* { box-sizing: border-box; }

/* ---- Layout modes ---- */
body.fixed-viewport, body.scroll-page { margin: 0; height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
body.fixed-viewport .app-header, body.scroll-page .app-header { flex: 0 0 auto; }
body.fixed-viewport .app-footer, body.scroll-page .app-footer { position: static; flex: 0 0 auto; }
body.fixed-viewport .app-body, body.scroll-page .app-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: row; overflow: hidden; }
body.scroll-page   .app-main { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 12px 18px; }
body.fixed-viewport .app-main { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding: 12px 18px; gap: 10px; overflow: hidden; }

/* ---- Header / footer ---- */
.app-header {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 24px;
  background: var(--ig-navy); color: var(--ig-white);
  padding: 12px 24px;
  border-bottom: 3px solid var(--ig-teal);
}
.brand { display: flex; align-items: center; gap: 12px; color: var(--ig-white); text-decoration: none; font-weight: 600; }
.brand-logo { height: 32px; width: auto; display: block; }
.brand-divider { width: 1px; height: 22px; background: rgba(255,255,255,0.3); }
.brand-name { font-weight: 500; font-size: 20px; letter-spacing: 0.01em; color: var(--ig-off-white); }

.user-strip { margin-left: auto; display: flex; align-items: center; gap: 14px; font-size: 13px; }
.logout { color: var(--ig-blue); text-decoration: none; }

/* ---- Left sidebar nav ----
   Hierarchy the eye can parse in a narrow rail: bold folders, muted leaves, a
   hairline guide down each nesting level (instead of ever-deeper padding), and a
   teal accent bar on the active page. */
.app-sidebar {
  flex: 0 0 300px; background: var(--ig-navy); border-right: 1px solid var(--ig-navy-deep);
  padding: 0 8px 18px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px;
  font-size: 13px; line-height: 1.3;
}

/* Leaf links: the lightest weight in the tree, so folders read as folders.
   Muted until hover/active; the active item gets a teal bar on its guide line. */
.sidebar-link {
  display: flex; align-items: center; gap: 8px; position: relative; min-width: 0;
  color: var(--ig-off-white); text-decoration: none;
  padding: 4px 8px; border-radius: 5px;
  font-weight: 400; font-size: 12.5px; opacity: 0.66;
}
.sidebar-link svg { width: 13px; height: 13px; flex: 0 0 auto; opacity: 0.8; }
.sidebar-link span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-link:hover { background: rgba(255,255,255,0.06); opacity: 1; }
.sidebar-link.active { background: rgba(0,210,169,0.12); color: var(--ig-teal); opacity: 1; font-weight: 500; }
.sidebar-link.active::before {
  content: ""; position: absolute; left: -11px; top: 6px; bottom: 6px;
  width: 2px; border-radius: 2px; background: var(--ig-teal);
}
.sidebar-divider { height: 1px; background: rgba(255,255,255,0.12); margin: 6px 8px; }
.sidebar-section-label {
  color: rgba(255,255,255,0.4); font-size: 9.5px; text-transform: uppercase;
  letter-spacing: 0.06em; font-weight: 600; padding: 6px 8px 2px;
}

/* ---- Collapsible sidebar groups (folders) ---- */
.sidebar-group-toggle {
  display: flex; align-items: center; gap: 8px;
  cursor: pointer; list-style: none; color: var(--ig-white);
  font-weight: 600; font-size: 13px; letter-spacing: 0.01em;
  padding: 5px 8px; border-radius: 5px;
}
.sidebar-group-toggle::-webkit-details-marker { display: none; }
.sidebar-group-icon { width: 15px; height: 15px; flex: 0 0 auto; color: var(--ig-teal); opacity: 0.85; }
.sidebar-group-toggle span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-chevron { width: 11px; height: 11px; flex: 0 0 auto; color: rgba(255,255,255,0.35); transition: transform .15s ease; }
.sidebar-group[open] > .sidebar-group-toggle .sidebar-chevron { transform: rotate(90deg); }
.sidebar-group-toggle:hover { background: rgba(255,255,255,0.06); }

/* Nested submenu: a hairline guide down the left + a small indent, instead of
   compounding padding, so four levels of nesting stay legible in a narrow rail. */
.sidebar-group-menu {
  display: flex; flex-direction: column; gap: 1px;
  margin: 1px 0 3px 12px; padding-left: 8px;
  border-left: 1px solid rgba(255,255,255,0.08);
}

/* Depth de-emphasis: a folder nested under another (Reports > Sales 3 months)
   reads lighter + smaller than a top-level folder, its leaves smaller still. */
.sidebar-group-nested > .sidebar-group-toggle { font-size: 12.5px; font-weight: 500; color: var(--ig-off-white); }
.sidebar-group-nested .sidebar-group-icon { width: 13px; height: 13px; color: rgba(255,255,255,0.5); }
.sidebar-group-nested .sidebar-link { font-size: 12px; }

/* ---- Sidebar report search (progressive enhancement, see app.js) ----
   Sticky at the top of the rail so it stays reachable in a long tree; the
   navy background matches the rail so the sticky edge is invisible. */
.sidebar-search {
  position: sticky; top: 0; z-index: 10;   /* above the scrolling folders/links */
  margin: 0 -8px 6px; padding: 10px 8px 8px;
  background: var(--ig-navy);
}
.sidebar-search-box { position: relative; }
.sidebar-search-icon {
  position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: rgba(255,255,255,0.45); pointer-events: none;
}
.sidebar-search-input {
  width: 100%; box-sizing: border-box;
  padding: 6px 8px 6px 28px;
  background: var(--ig-navy-deep); color: var(--ig-off-white);
  border: 1px solid rgba(255,255,255,0.12); border-radius: 6px;
  font-size: 12.5px; line-height: 1.2; outline: none;
}
.sidebar-search-input::placeholder { color: rgba(255,255,255,0.4); }
.sidebar-search-input:focus { border-color: var(--ig-teal); }
.sidebar-search-empty {
  color: rgba(255,255,255,0.5); font-size: 12px; font-style: italic;
  padding: 2px 10px 8px;
}
/* Filter hides non-matching links/folders without collapsing the tree. */
.app-sidebar .sb-hidden { display: none !important; }
/* External app links (CIP / EMS / Qiniseka QA) sit among the app *group* headers
   under CX > Apps, so give them the same bold, full-opacity white look instead of
   the muted leaf-link treatment (overrides .sidebar-link's opacity 0.66 + wt 400). */
.sidebar-link.sidebar-link-app { opacity: 1; color: var(--ig-white); font-weight: 600; font-size: 12.5px; }

.app-footer {
  padding: 8px 24px; background: var(--ig-navy-darker);
  color: var(--ig-off-white); font-size: 12px;
  border-top: 1px solid rgba(255,255,255,0.05);
}
.app-footer code { color: var(--ig-teal); }

/* ---- Buttons ---- */
.btn-export, .btn-download {
  font: 500 13px/1 inherit; padding: 8px 18px;
  background: var(--ig-teal); color: var(--ig-navy);
  border: 1px solid transparent; border-radius: 4px; cursor: pointer; white-space: nowrap;
}
.btn-export:hover, .btn-download:hover { background: #00b797; }
.btn-export:active, .btn-download:active { transform: translateY(1px); }

.btn-reload {
  font: 500 13px/1 inherit; padding: 7px 16px;
  background: var(--ig-white); color: var(--ig-navy);
  border: 1px solid var(--ig-teal); border-radius: 4px; cursor: pointer;
}
.btn-reload:hover { background: rgba(0,210,169,0.10); }

.btn-link {
  font-size: 12px; font-weight: 600; color: var(--ig-teal); text-decoration: none;
  padding: 4px 10px; border: 1px solid var(--ig-teal); border-radius: 4px; display: inline-block;
}
.btn-link:hover { background: rgba(0,210,169,0.10); }

.btn-header-reload {
  background: transparent; color: var(--ig-off-white);
  border: 1px solid rgba(255,255,255,0.35); border-radius: 4px;
  font: 500 12px/1 inherit; padding: 6px 12px; cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.btn-header-reload:hover { background: rgba(0,210,169,0.18); border-color: var(--ig-teal); color: var(--ig-teal); }

/* ---- Cards & KPI tiles ---- */
.card {
  background: var(--ig-white); border: 1px solid var(--ig-border);
  border-radius: 6px; box-shadow: 0 1px 2px rgba(22,42,60,0.04);
}

.tree-table tr[data-depth] td:first-child, .tree-table tr[data-depth] td:nth-child(2) { cursor: default; }
.tree-table tr[data-depth="1"] td:nth-child(2), .tree-table tr[data-depth="2"] td:nth-child(3) { padding-left: 22px; }
.tree-table .tree-toggle { display: inline-block; width: 14px; cursor: pointer; color: var(--ig-slate); font-size: 11px; }
.tree-table tr[data-depth="0"] { cursor: pointer; font-weight: 600; }
.tree-table tr[data-depth="1"] { cursor: pointer; }

.checkbox-dropdown { position: relative; display: inline-block; }
.checkbox-dropdown summary {
  list-style: none; cursor: pointer; user-select: none;
  background: var(--ig-white); color: var(--ig-navy);
  border: 1px solid var(--ig-border); border-radius: 4px;
  padding: 7px 12px; font-size: 13px; min-width: 220px;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.checkbox-dropdown summary::-webkit-details-marker { display: none; }
.checkbox-dropdown summary::after { content: "\25BE"; color: var(--ig-slate); }
.checkbox-dropdown[open] summary { border-color: var(--ig-teal); }
.checkbox-dropdown-panel {
  position: absolute; z-index: 20; top: calc(100% + 4px); left: 0;
  background: var(--ig-white); border: 1px solid var(--ig-border); border-radius: 6px;
  box-shadow: 0 4px 14px rgba(22,42,60,0.14); padding: 10px 12px;
  min-width: 260px; max-height: 260px; overflow-y: auto;
}
.checkbox-dropdown-panel label { display: block; padding: 4px 0; font-size: 13px; white-space: nowrap; }

.kpi-grid { display: grid; gap: 8px; grid-template-columns: repeat(6, minmax(0,1fr)); }
.kpi-card { background: var(--ig-white); border: 1px solid var(--ig-border); border-radius: 6px;
            padding: 8px 10px; box-shadow: 0 1px 2px rgba(22,42,60,0.04); }
.kpi-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ig-slate); margin-bottom: 4px; }
.kpi-value { font-size: 18px; font-weight: 700; color: var(--ig-navy); line-height: 1.1; }
.kpi-delta { display: inline-block; margin-top: 5px; font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 10px; }
.kpi-up   { color: #0a7d57; background: rgba(0,210,169,0.14); }
.kpi-down { color: #b42318; background: rgba(211,51,51,0.12); }
.kpi-flat { color: var(--ig-slate); background: rgba(100,116,139,0.12); }
@media (max-width: 1280px) { .kpi-grid { grid-template-columns: repeat(4, minmax(0,1fr)); } }
@media (max-width: 768px)  { .kpi-grid { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 480px)  { .kpi-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }

.filters { background: var(--ig-white); border: 1px solid var(--ig-teal); border-radius: 6px; padding: 10px 14px;
           display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.filters label { display: flex; flex-direction: column; gap: 3px; font-size: 10.5px; text-transform: uppercase;
                  letter-spacing: 0.04em; color: var(--ig-slate); }
.filters input, .filters select { border: 1px solid var(--ig-teal); border-radius: 4px; padding: 5px 9px; font: inherit; }
.filters input:focus, .filters select:focus { outline: none; box-shadow: 0 0 0 2px rgba(0,210,169,0.18); }

/* Vertical filter rail (Attendance Register pages) */
.filters-layout { display: flex; gap: 14px; align-items: flex-start; }
.filters-vertical { background: var(--ig-white); border: 1px solid var(--ig-teal); border-radius: 6px;
                     padding: 10px; display: flex; flex-direction: column; gap: 10px;
                     flex: 0 0 200px; width: 200px; }
.filters-vertical label { display: flex; flex-direction: column; gap: 3px; font-size: 10.5px; text-transform: uppercase;
                           letter-spacing: 0.04em; color: var(--ig-slate); }
.filters-vertical input, .filters-vertical select { border: 1px solid var(--ig-teal); border-radius: 4px;
                                                      padding: 5px 7px; font: inherit; width: 100%; }
.filters-vertical input:focus, .filters-vertical select:focus { outline: none; box-shadow: 0 0 0 2px rgba(0,210,169,0.18); }
.filters-content { flex: 1 1 auto; min-width: 0; }
/* .filters-vertical (a flex item) has no top margin of its own, but
   .section-title's 12px top margin pushes .filters-content's rendered text
   down that much, visually misaligning the two flex siblings' contents even
   though their boxes start at the same flex-start line. Zero it on the
   first title so the rail and the content visibly start flush together. */
.filters-content > .section-title:first-child { margin-top: 0; }
.filter-toggle-group { display: flex; border: 1px solid var(--ig-teal); border-radius: 4px; overflow: hidden; }
.filter-toggle-group button { flex: 1; padding: 6px 4px; border: none; background: var(--ig-white); color: var(--ig-slate);
                               font-size: 12px; cursor: pointer; }
.filter-toggle-group button.active { background: var(--ig-teal); color: var(--ig-navy); font-weight: 600; }

.kpi-card-mini { background: var(--ig-white); border: 1px solid var(--ig-border); border-radius: 6px;
                 padding: 10px 12px; }
.kpi-card-mini .kpi-mini-title { background: var(--ig-navy); color: #fff; font-size: 11px; font-weight: 700;
                                  text-transform: uppercase; letter-spacing: 0.03em; padding: 6px 8px;
                                  margin: -10px -12px 8px; border-radius: 6px 6px 0 0; }
.kpi-card-mini .kpi-mini-value { font-size: 22px; font-weight: 700; color: var(--ig-navy); text-align: center; }
.kpi-card-mini .kpi-mini-yesterday { font-size: 11px; color: var(--ig-slate); text-align: center; margin-top: 4px; }

.attreg-toggle { cursor: pointer; }
.attreg-toggle:hover td { background: rgba(0,210,169,0.08); }
.attreg-toggle.attreg-expanded > td strong { color: var(--ig-teal); }

.kpi-card-big { background: var(--ig-white); border: 1px solid var(--ig-navy); border-radius: 6px;
                padding: 24px 16px; text-align: center; }
.kpi-card-big .kpi-big-value { font-size: 40px; font-weight: 700; color: #1f2933; line-height: 1; }
.kpi-card-big .kpi-big-label { font-size: 13px; color: var(--ig-slate); margin-top: 8px; }

.banner-dummy {
  background: #fff7d6; border: 1px solid #e8c547; border-radius: 6px;
  padding: 8px 14px; font-size: 12.5px; color: #6c5500;
}

.banner-success {
  background: rgba(46,204,113,0.14); border: 1px solid rgba(46,204,113,0.5); border-radius: 6px;
  padding: 8px 14px; font-size: 12.5px; color: #1a6b3a;
  margin-bottom: 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  transition: opacity 0.4s ease;
}
.banner-success .btn-link { color: #1a6b3a; }

/* ---- Data tables ---- */
.table-scroll { overflow: auto; border: 1px solid var(--ig-border); border-radius: 6px; background: var(--ig-white);
                flex: 1 1 auto; min-height: 0; }

.data-table { border-collapse: separate; border-spacing: 0; width: 100%;
  font-family: 'Poppins', system-ui, sans-serif; font-size: 12.5px;
  font-feature-settings: 'tnum' 1, 'lnum' 1; color: #1f2933; }

.data-table thead th {
  background: var(--ig-teal); color: var(--ig-navy);
  position: sticky; top: 0; z-index: 2;
  padding: 5px 8px; text-align: left; font-weight: 600; white-space: nowrap;
  box-shadow: inset 0 -1px 0 rgba(22,42,60,0.20);
  border-right: 1px solid rgba(22,42,60,0.40);
}
.data-table td {
  padding: 3px 8px; white-space: nowrap;
  border-top: 1px solid rgba(0,210,169,0.35);
  border-right: 1px solid var(--ig-border);
}
.data-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table td.neg { color: var(--ig-red); }

.data-table tbody td                    { background: var(--ig-white); }
.data-table tbody tr:nth-child(even) td { background: #f7f8fa; }
.data-table tbody tr:hover td           { background: #eef5fb; }

.data-table thead th.col-total { background: var(--ig-navy); color: var(--ig-teal); font-weight: 600; }
.data-table tbody td.col-total { background: #fff7d6; font-weight: 600; border-left: 2px solid var(--ig-teal); }

/* Click-to-sort column headers (initSortableTables() in app.js) — applied
   generically to every .data-table with a single, colspan-free header row. */
.data-table thead th.sortable-col { cursor: pointer; user-select: none; }
.data-table thead th.sortable-col:hover { background: #00bda0; }
.data-table thead th.sortable-col .sort-indicator { font-size: 10px; margin-left: 2px; }

/* Frozen first column — the row label stays put while the rest of a wide
   table scrolls horizontally underneath it. Doesn't set its own background;
   the existing thead/tbody rules above (teal header, striped/hover rows)
   already cover it since they match the same cells. */
.data-table th.sticky-col, .data-table td.sticky-col {
  position: sticky; left: 0; z-index: 1;
  box-shadow: 1px 0 0 var(--ig-border);
}
.data-table thead th.sticky-col { z-index: 3; }

/* Second frozen column (Lucelle's Date + Metric pair) — offset by the first
   column's own min-width so it sits immediately to the right of it. */
.data-table th.sticky-col-2, .data-table td.sticky-col-2 {
  position: sticky; left: 100px; z-index: 1;
  box-shadow: 1px 0 0 var(--ig-border);
}
.data-table thead th.sticky-col-2 { z-index: 3; }

/* Third frozen column (e.g. Campaign Manager / Team Leader / Agent tree
   columns) — offset by the first two columns' combined min-width. Callers
   with non-default column widths should override `left` inline (see
   kerus/hourly_cm_tl_agent.html) rather than relying on this 200px default. */
.data-table th.sticky-col-3, .data-table td.sticky-col-3 {
  position: sticky; left: 200px; z-index: 1;
  box-shadow: 1px 0 0 var(--ig-border);
}
.data-table thead th.sticky-col-3 { z-index: 3; }

/* Fourth frozen column (e.g. CCM Manager / CM Manager / Team Leader / Agent
   4-level tree columns) — offset by the first three columns' combined
   min-width. Callers with non-default column widths should override `left`
   inline, same convention as sticky-col-3. */
.data-table th.sticky-col-4, .data-table td.sticky-col-4 {
  position: sticky; left: 300px; z-index: 1;
  box-shadow: 1px 0 0 var(--ig-border);
}
.data-table thead th.sticky-col-4 { z-index: 3; }

.data-table tfoot td { position: sticky; bottom: 0; background: #f5f7fa; font-weight: 600;
  color: var(--ig-navy); border-top: 2px solid var(--ig-teal); padding: 5px 8px; }

.table-search {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 6px 2px; font-size: 12px; color: var(--ig-slate);
}
.table-search input {
  border: 1px solid var(--ig-teal); border-radius: 4px; padding: 5px 9px;
  font: inherit; font-size: 12px; width: 220px; max-width: 100%;
}
.table-search input:focus { outline: none; box-shadow: 0 0 0 2px rgba(0,210,169,0.18); }
/* When a table's search box sits directly under its section title, lift it onto
   the title's own row (title left, search right) instead of adding a tall, mostly
   empty band between the heading and the table — the "too much spacing" between a
   visual's description and the visual itself. Only applies when a .section-title
   is the immediate previous sibling, so a standalone table's search box is
   untouched. */
.section-title + .table-search {
  margin-top: -32px;
  padding-top: 0;
  min-height: 26px;
}


.edc-group-label {
  background: var(--ig-navy); color: var(--ig-off-white);
  font-weight: 600; padding: 6px 10px; font-size: 12.5px;
  letter-spacing: 0.02em;
}

/* ---- Conditional formatting ---- */
.fmt-pct-1 { background: #f8696b; }
.fmt-pct-2 { background: #fcaa7b; }
.fmt-pct-3 { background: #ffe684; }
.fmt-pct-4 { background: #b8d97a; }
.fmt-pct-5 { background: #63be7b; }

/* ---- Loader ---- */
#page-loader {
  position: fixed; top: 0; left: 0; height: 3px; width: 0%;
  background: var(--ig-teal); z-index: 100; transition: width .2s ease;
  opacity: 0;
}
#page-loader.visible { opacity: 1; width: 70%; }
.busy-text { font-style: italic; color: var(--ig-slate); font-size: 12px; }

/* ---- Login page ---- */
.login-wrap {
  display: flex; align-items: center; justify-content: center; height: 100vh;
  background: var(--ig-off-white);
}
.login-card {
  background: var(--ig-white); border: 2px solid var(--ig-teal); border-radius: 10px;
  box-shadow: 0 4px 24px rgba(22,42,60,0.10); max-width: 380px; overflow: hidden; text-align: center;
}
.login-header {
  background: var(--ig-navy); padding: 26px 24px;
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.login-hex { width: 32px; height: 32px; color: var(--ig-white); flex: 0 0 auto; }
.login-wordmark { color: var(--ig-white); font-weight: 700; font-size: 19px; letter-spacing: 0.02em; }
.login-wordmark-cx { color: var(--ig-teal); }
.login-body { padding: 30px 36px 8px; }
.login-title { font-size: 19px; font-weight: 700; color: var(--ig-navy); margin: 0 0 8px; }
.login-sub { font-size: 13px; color: var(--ig-slate); margin: 0 0 22px; }
.login-btn {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--ig-navy); color: var(--ig-white);
  font-weight: 600; font-size: 14px; padding: 11px 20px; border-radius: 6px; text-decoration: none;
}
.login-btn:hover { background: var(--ig-navy-deep); }
.login-ms-logo { width: 18px; height: 18px; flex: 0 0 auto; }
.login-denied { color: var(--ig-red); font-size: 13px; margin: 14px 0 0; }
.login-footer-hint {
  background: var(--ig-off-white); color: var(--ig-slate); font-size: 11.5px; line-height: 1.5;
  padding: 16px 30px 24px; border-top: 1px solid var(--ig-border); margin-top: 22px;
}

/* ---- Generic per-control busy spinner — every button/dropdown app-wide,
   wired centrally in app.js (htmx:beforeRequest/afterRequest + submit).
   Positioned via JS (fixed, next to whichever control triggered the
   request), not inserted into document flow. ---- */
.inline-spinner {
  position: fixed; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid rgba(22,42,60,0.15); border-top-color: var(--ig-teal);
  animation: ask-spin 0.7s linear infinite; z-index: 300; pointer-events: none;
}

/* ---- Ask page: full-page-post spinner (Cortex round trips can take ~1min) ---- */
.ask-spinner-overlay {
  display: none; position: fixed; inset: 0; z-index: 200;
  background: rgba(22,42,60,0.55); backdrop-filter: blur(1px);
  flex-direction: column; align-items: center; justify-content: center; gap: 16px;
  color: var(--ig-white); text-align: center; padding: 20px;
}
.ask-spinner-overlay.visible { display: flex; }
.ask-spinner {
  width: 42px; height: 42px; border-radius: 50%;
  border: 4px solid rgba(255,255,255,0.25); border-top-color: var(--ig-teal);
  animation: ask-spin 0.8s linear infinite;
}
@keyframes ask-spin { to { transform: rotate(360deg); } }

/* ============================================================
   Uconnect Payment Report additions (merged in from its own
   standalone app). Everything above is Collections' own CSS.
   ============================================================ */

/* Destructive action — used by /uconnect/reconciliation's Ignore button.
   Collections had no destructive-action button before this merge. */
.btn-reject {
  font: 500 13px/1 inherit; padding: 7px 16px;
  background: var(--ig-white); color: var(--ig-red);
  border: 1px solid var(--ig-red); border-radius: 4px; cursor: pointer;
}
.btn-reject:hover { background: rgba(192, 57, 43, 0.10); }
.btn-reject:active { transform: translateY(1px); }

/* Workflow-state pills — used by /uconnect/security's Active/Inactive column. */
.status-pill { display: inline-block; padding: 3px 10px; font-size: 12px; font-weight: 600;
  border-radius: 99px; letter-spacing: 0.02em; white-space: nowrap; }
.status-approved { background: rgba(46,204,113,0.18); color: #1a6b3a; }
.status-rejected { background: rgba(231,76,60,0.18);  color: #922b1f; }

/* Busy indicator inside a split-table card while its HTMX partial loads. */
.split-loading {
  font-style: italic;
  color: var(--ig-slate);
  font-size: 12px;
  padding: 12px;
}

/* ============================================================
   Policy Search / Create Users additions (merged in from the
   standalone "Data & AI Reporting App").
   ============================================================ */

.summary-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.summary-header h2 { margin: 0; font-size: 18px; color: var(--ig-navy); }

.table-section { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
.table-toolbar { display: flex; align-items: center; justify-content: space-between; }
.table-toolbar h3 { margin: 0; font-size: 14px; color: var(--ig-navy); }

/* Power-BI-style single-level drill: one breadcrumb trail + a drill-up
   button, replacing the whole table body with the next/previous level
   rather than expanding a nested row underneath it (see sales3m's
   leader_view.html / provider_mom.html). */
.drill-breadcrumb { font-size: 13px; color: var(--ig-slate); }
.drill-breadcrumb .crumb-link { cursor: pointer; color: var(--ig-teal); }
.drill-breadcrumb .crumb-link:hover { text-decoration: underline; }
.drill-breadcrumb .crumb-link.current { cursor: default; color: var(--ig-navy); font-weight: 600; text-decoration: none; }
.drill-breadcrumb .crumb-sep { margin: 0 4px; color: var(--ig-border); }
tr.drill-row { cursor: pointer; font-weight: 600; }
tr.drill-row:hover { background: rgba(0, 210, 169, 0.06); }
tr.leaf-row { cursor: pointer; }
tr.leaf-row:hover { background: rgba(0, 82, 204, 0.06); }
tr.leaf-row .leaf-toggle { cursor: pointer; color: var(--ig-teal); font-size: 12px; }

/* Power BI's own visual-header icon buttons: drill up / click-to-drill-down
   toggle / next level. Small square icon buttons, not text links. */
.drill-icons { display: flex; gap: 2px; }
.drill-icon-btn { width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--ig-border); background: var(--ig-white); border-radius: 4px; cursor: pointer;
  font-size: 14px; line-height: 1; color: var(--ig-slate); padding: 0; }
.drill-icon-btn:hover:not(:disabled) { border-color: var(--ig-teal); color: var(--ig-teal); }
.drill-icon-btn:disabled { opacity: 0.35; cursor: default; }
.drill-icon-btn.active { background: var(--ig-teal); border-color: var(--ig-teal); color: var(--ig-white); }

.search-form { display: flex; align-items: end; gap: 12px; }
.search-form label,
.user-form label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ig-slate); display: block; margin-bottom: 6px; }
.user-form { display: flex; flex-direction: column; gap: 12px; }
.form-row { display: flex; align-items: end; gap: 12px; }

.search-busy { font-style: italic; color: var(--ig-slate); font-size: 13px; opacity: 0; transition: opacity .15s ease; }
.search-busy.htmx-request { opacity: 1; }

.pagination { display: flex; align-items: center; justify-content: center; gap: 16px; padding: 10px 0; flex: 0 0 auto; }
.pagination-status { font-size: 13px; color: var(--ig-slate); }
.btn-reload.disabled { color: var(--ig-slate); border-color: var(--ig-border); cursor: default; pointer-events: none; }

.data-freshness { color: var(--ig-teal); }
.empty-state { color: var(--ig-slate); font-style: italic; padding: 12px 4px; }

/* ============================================================
   CX / Vetting Allocation additions (merged in from its own
   standalone app, "Silver Surfer Vetting Allocation").
   ============================================================ */

.row-between { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.page-title { margin: 0; font-size: 17px; color: var(--ig-navy); }
.section-title { margin: 12px 0 6px; font-size: 13.5px; color: var(--ig-navy); }
.hint { font-size: 11.5px; color: var(--ig-slate); }
.muted { color: var(--ig-slate); }
.warn-tag {
  display: inline-block; margin-left: 6px; padding: 1px 7px; font-size: 10.5px; font-weight: 600;
  border-radius: 99px; background: rgba(211,51,51,0.12); color: #b42318; letter-spacing: 0.02em;
}
.inline { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Extra status-pill tones beyond approved/rejected — allocation & vetting workflow states. */
.status-progress { background: rgba(0,210,169,0.16); color: #0a6b57; }
.status-declined  { background: rgba(231,76,60,0.18); color: #922b1f; }
.status-pending   { background: rgba(232,197,71,0.22); color: #6c5500; }
.status-neutral   { background: rgba(100,116,139,0.14); color: var(--ig-slate); }

/* ---------------------------------------------------------------------------
   Report UX (2026-08): freeze the filter bar and let each table scroll INSIDE
   itself with a frozen header, instead of scrolling the whole page. .data-table
   thead is already `position: sticky` (above), so bounding the .table-scroll
   height is what actually freezes the header. Scoped to `scroll-page` report
   dashboards; `fixed-viewport` pages already scroll their table body internally
   and pin their filters via flex, so they're intentionally left untouched.
--------------------------------------------------------------------------- */
body.scroll-page .filters,
body.scroll-page .filters-vertical {
  position: sticky;
  top: 0;
  z-index: 30;
}
/* A vertical rail is often the TALLEST element in .filters-layout — its report
   body is frequently capped (table-scroll 70vh) or laid out side-by-side, so
   it's shorter than a long filter list. A sticky flex item only holds while its
   flex container is taller than the item; when the rail IS the tallest child
   there's no "stick room" and it scrolls away with the page (the reported bug).
   Cap it to the visible scroll area so the body column is the taller one (restoring
   stick room) and let a long list scroll inside the pinned rail. --rail-max-h is
   set in base.html from the scroll area's live height (falls back to a viewport
   estimate); align-self stops the rail stretching to the container height on any
   report whose layout wrapper doesn't already set align-items:flex-start. */
body.scroll-page .filters-vertical {
  align-self: flex-start;
  max-height: var(--rail-max-h, calc(100vh - 160px));
  overflow-y: auto;
}
body.scroll-page .table-scroll { max-height: 70vh; }

/* ---------------------------------------------------------------------------
   Report header zone (2026-08). The report NAME + filter bar are pinned
   together as one opaque strip flush under the app header, so the name stays
   visible while the body scrolls and NO row can bleed into the gap above the
   filters. The gap was app-main's 18px top padding: on scroll-page we drop it
   so the pinned strip sits flush against the (114px) app header. Templates opt
   in by wrapping their title + filters in <div class="report-head">.
--------------------------------------------------------------------------- */
body.scroll-page .app-main { padding-top: 0; }
body.scroll-page .report-head {
  position: sticky;
  top: 0;
  z-index: 35;                    /* above content (thead z:2), below app header (z:50) */
  background: var(--ig-off-white);
  padding: 10px 0 8px;
  margin-bottom: 2px;
}
/* The strip's last line is usually a muted subtitle <p>, whose UA bottom margin
   (~1em) opens a gap between the pinned title and the filters/body below it. On
   vertical-rail pages that pushed the whole .filters-layout down noticeably.
   Drop it so the filters sit snug under the title on every report page. */
body.scroll-page .report-head > :last-child { margin-bottom: 0; }
/* Inside a pinned report-head the filters ride along with it — don't also make
   them individually sticky (that double-sticks and reintroduces a seam). */
body.scroll-page .report-head .filters,
body.scroll-page .report-head .filters-vertical { position: static; top: auto; }

/* Vertical filter-rail pages (Attendance, Keru): when a .report-head precedes
   the .filters-layout, the sticky left rail must stick BELOW the pinned title,
   not behind it. --report-head-h is set by base.html to the report-head's live
   height, so the rail clears it exactly regardless of the title's height. */
body.scroll-page .report-head ~ .filters-layout .filters-vertical { top: var(--report-head-h, 0px); }

/* ---------------------------------------------------------------------------
   Searchable multi-select dropdown (templates/_multiselect.html + the handlers
   in static/app.js). Ported from the CIP app so both look the same; replaces
   the old native `<select multiple>` + "Ctrl/Cmd-click" filters. Trigger reads
   like a native select; the panel is absolutely positioned and only IT scrolls.
--------------------------------------------------------------------------- */
.ms-field { display: flex; flex-direction: column; gap: 4px; position: relative; }
.filters .ms-field { min-width: 210px; }
.ms-field .filter-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ig-slate); font-weight: 500; }

.dropdown { position: relative; }
.dropdown-trigger {
  font: inherit; font-size: 13px; width: 100%;
  padding: 6px 10px; border: 1px solid var(--ig-teal); border-radius: 4px;
  background: var(--ig-white); cursor: pointer;
  display: flex; align-items: center; gap: 8px; text-align: left;
}
.dropdown-trigger:hover { border-color: var(--ig-navy); }
.dropdown.is-open .dropdown-trigger { box-shadow: 0 0 0 2px rgba(0,210,169,0.18); }
.dropdown-summary { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ig-navy); }
.dropdown-caret { color: var(--ig-slate); font-size: 11px; flex-shrink: 0; }

.dropdown-panel {
  display: none; position: absolute; top: calc(100% + 4px); left: 0;
  min-width: 100%; max-width: 420px; width: max-content;
  background: var(--ig-white); border: 1px solid var(--ig-border); border-radius: 4px;
  box-shadow: 0 6px 20px rgba(22,42,60,0.16);
  padding: 8px; z-index: 40;            /* above sticky theads (z:2) + filters (z:30) */
}
.dropdown.is-open .dropdown-panel { display: block; }
.dropdown-panel-header { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
.dropdown-panel-header .filter-actions { align-self: flex-end; }
.filter-search { font: inherit; font-size: 13px; padding: 5px 8px;
  border: 1px solid var(--ig-teal); border-radius: 3px; background: var(--ig-white); width: 100%; }
.filter-search:focus { outline: none; box-shadow: 0 0 0 2px rgba(0,210,169,0.18); }
.filter-actions { display: inline-flex; gap: 4px; }
.filter-actions button { font: inherit; font-size: 11px; padding: 2px 8px;
  border: 1px solid var(--ig-border); background: var(--ig-off-white); color: var(--ig-slate);
  border-radius: 3px; cursor: pointer; }
.filter-actions button:hover { background: var(--ig-white); border-color: var(--ig-teal);
  color: var(--ig-navy); }

.checkbox-list { border: 1px solid var(--ig-border); background: var(--ig-white);
  border-radius: 3px; max-height: 240px; overflow-y: auto; padding: 4px 0; }
/* .filters-vertical label {display:flex;flex-direction:column;text-transform:uppercase}
   has higher specificity than .check-item alone and was overriding it whenever a
   multiselect sits inside a report filter bar, stacking the checkbox above the
   (now uppercase) text instead of beside it — force row layout back explicitly. */
.checkbox-list .check-item,
.check-item { display: flex; flex-direction: row; align-items: center; gap: 8px; padding: 3px 10px;
  font-size: 13px; text-transform: none; cursor: pointer; user-select: none; }
.check-item:hover { background: #eef5fb; }
.check-item input { margin: 0; width: auto; flex: 0 0 auto; cursor: pointer; accent-color: var(--ig-teal); }
.check-item span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.check-item.search-hidden { display: none; }   /* hidden by the search box */

/* ---------------------------------------------------------------------------
   Data-freshness pill (bottom right) — ported from CIP so both apps match.
   Markup in base.html, live "x ago" + stale state in app.js. Reports read
   30-minute Snowflake snapshots, so this tells the reader how old the numbers
   are instead of leaving them to assume "now".
--------------------------------------------------------------------------- */
.data-freshness {
  position: fixed; right: 12px; bottom: 10px; z-index: 60;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; line-height: 1; color: var(--ig-slate, #53606b);
  background: rgba(255, 255, 255, .92);
  border: 1px solid var(--ig-border, #dfe1e5); border-radius: 14px;
  padding: 4px 10px; box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
}
.data-freshness .df-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  background: var(--ig-teal, #00d2a9);
}
.data-freshness.is-stale .df-dot { background: #e0a106; }   /* amber once overdue */
.data-freshness .df-ago { color: var(--ig-slate-2, #7a8390); }
@media (max-width: 480px) {
  .data-freshness { font-size: 10.5px; padding: 3px 8px; right: 8px; bottom: 8px; }
}

/* ===========================================================================
   INTERNAL AUDIT — app-specific additions
   ---------------------------------------------------------------------------
   Everything above this line is the shared Data & AI Reporting App stylesheet,
   copied verbatim so the two apps stay visually identical. Add app-specific
   rules HERE, below the line, and never edit above it — that keeps a future
   re-sync with the reference stylesheet a copy-and-reapply rather than a merge.
   =========================================================================== */

.app-main { padding: 12px 16px 24px; display: flex; flex-direction: column; gap: 12px; }
.page-title { font-size: 19px; font-weight: 700; color: var(--ig-navy); margin: 0; }
.page-sub   { font-size: 11.5px; color: var(--ig-slate); margin: 2px 0 0;
              text-transform: uppercase; letter-spacing: 0.05em; }

/* Filter bar: the shared .filters styles labels directly, so these wrap the
   same shape for <label class="filter-field"> without restating them. */
.filter-field  { display: flex; flex-direction: column; gap: 3px; }
.filter-narrow input { width: 76px; }
.filter-check  { flex-direction: row !important; align-items: center; gap: 6px;
                 text-transform: none !important; letter-spacing: 0 !important;
                 font-size: 11.5px !important; }
.filter-check input { width: auto; }

.btn-primary { background: var(--ig-teal); color: var(--ig-navy); border: none;
               border-radius: 4px; padding: 7px 16px; font: inherit; font-weight: 600;
               cursor: pointer; }
.btn-primary:hover { background: #00bda0; }

/* KPI row — 5 tiles, not the shared sheet's 6-column grid. */
.kpi-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.kpi-card { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px;
            border-left: 3px solid var(--ig-border); }
.kpi-foot { font-size: 10px; color: var(--ig-slate); margin-top: 2px; }
.kpi-good { border-left-color: var(--ig-green); }
.kpi-warn { border-left-color: #e8a33d; }
.kpi-bad  { border-left-color: var(--ig-red); }
.kpi-bad .kpi-value { color: var(--ig-red); }

.card { padding: 12px 14px; }
.card-title { font-size: 13.5px; font-weight: 700; color: var(--ig-navy);
              margin: 0 0 10px; display: flex; align-items: baseline; gap: 8px; }
.card-count { font-size: 11px; font-weight: 500; color: var(--ig-slate); }
.card-note  { font-size: 12px; color: var(--ig-slate); margin: 0 0 10px; max-width: 80ch; }
.empty-state { font-size: 12.5px; color: var(--ig-slate); margin: 4px 0; }

/* Caveat panel — the "read this before believing the numbers" block. Amber
   rather than red: these are interpretation warnings, not failures. */
.card-caveat { border-left: 3px solid #e8a33d; background: #fffdf7; }
.caveat { margin: 0 0 14px; }
.caveat:last-child { margin-bottom: 0; }
.caveat p { font-size: 12.5px; color: #3f4854; margin: 6px 0 8px; max-width: 90ch; line-height: 1.5; }
.caveat-tag { display: inline-block; font-size: 9.5px; font-weight: 700;
              text-transform: uppercase; letter-spacing: 0.06em;
              background: var(--ig-navy); color: var(--ig-white);
              padding: 2px 7px; border-radius: 3px; }
.caveat-tag-amber { background: #b9791c; }

.card-error { border-left: 3px solid var(--ig-red); background: #fdf6f5; }
.error-detail { font-size: 12.5px; color: #6b2119; margin: 0; max-width: 90ch;
                line-height: 1.55; white-space: pre-wrap; }

/* An inference we have not had signed off. Deliberately conspicuous. */
.unconfirmed-mark { display: inline-block; margin-left: 4px; width: 13px; height: 13px;
                    line-height: 13px; text-align: center; border-radius: 50%;
                    background: #b9791c; color: #fff; font-size: 9px; font-weight: 700;
                    cursor: help; vertical-align: middle; }

.rule-list { margin: 8px 0 0; padding-left: 18px; }
.rule-list li { font-size: 12px; color: #3f4854; margin-bottom: 7px; line-height: 1.45; }
.rule-list code { background: #eef1f4; padding: 1px 5px; border-radius: 3px;
                  font-size: 11px; color: var(--ig-navy); }
.rule-list em { color: var(--ig-slate); font-size: 11px; }
.rule-note { display: block; font-size: 11px; color: var(--ig-slate);
             margin-top: 2px; line-height: 1.45; max-width: 90ch; }

/* Coverage trend — a bar drawn behind the number, so the shape of the filing
   lag is readable at a glance without pulling in a charting library. */
.trend-table { width: auto; min-width: 460px; }
.cov-bar { display: inline-block; height: 8px; width: var(--pct); max-width: 90px;
           background: linear-gradient(90deg, var(--ig-teal), #7fd9c6);
           border-radius: 2px; margin-right: 6px; vertical-align: middle; }

/* Per-document tick/cross columns. */
.data-table thead th.num, .data-table thead th.doc-col { text-align: right; }
.doc-col   { font-size: 10.5px; max-width: 92px; white-space: normal !important;
             line-height: 1.25; text-align: center !important; }
.doc-cell  { text-align: center !important; font-weight: 700; }
.doc-yes   { color: var(--ig-green); }
.doc-no    { color: var(--ig-red); }
.missing-count { font-weight: 700; color: var(--ig-navy); }
.employee-cell { font-variant-numeric: tabular-nums; }

/* Overview page */
.welcome-wrap { display: flex; flex-direction: column; gap: 12px; }
.welcome-lede { font-size: 13px; color: #3f4854; margin: 0; max-width: 85ch; line-height: 1.55; }
.exception-tile { display: flex; align-items: center; gap: 12px; text-decoration: none;
                  border: 1px solid var(--ig-border); border-radius: 6px;
                  padding: 12px 14px; transition: border-color .12s, background .12s; }
.exception-tile:hover { border-color: var(--ig-teal); background: #f5fdfb; }
.exception-no { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
                background: var(--ig-teal); color: var(--ig-navy);
                font-weight: 700; font-size: 13px;
                display: flex; align-items: center; justify-content: center; }
.exception-body { display: flex; flex-direction: column; gap: 2px; }
.exception-name { font-size: 13.5px; font-weight: 600; color: var(--ig-navy); }
.exception-meta { font-size: 11px; color: var(--ig-slate); }
.planned-table { font-size: 11.5px; }
.planned-table td { white-space: normal; }
.limitation-list { margin: 0; padding-left: 18px; }
.limitation-list li { font-size: 12.5px; color: #3f4854; margin-bottom: 7px;
                      line-height: 1.5; max-width: 90ch; }

/* Sidebar entries for reports that do not exist yet — visible so the shape of
   the programme is obvious, but plainly not clickable. */
.sidebar-link-pending { display: block; padding: 6px 24px; font-size: 11.5px;
                        color: rgba(237,239,242,0.40); line-height: 1.4;
                        cursor: default; }

/* Rule viability bands — whether a rule's underlying document type is captured
   in Sage often enough for a per-employee conclusion to mean anything. */
.band { display: inline-block; font-size: 9.5px; font-weight: 700; text-transform: uppercase;
        letter-spacing: 0.05em; padding: 2px 7px; border-radius: 3px; }
.band-viable   { background: #dff6ee; color: #10715a; }
.band-marginal { background: #fdf0da; color: #8a5a12; }
.band-unusable { background: #fbe3e0; color: #8f2c20; }
.cov-pct { color: var(--ig-slate); font-size: 11px; }

/* Access / security page */
.flash { padding: 10px 14px; font-size: 12.5px; border-left: 3px solid var(--ig-border); }
.flash-ok  { border-left-color: var(--ig-green); background: #f4fbf6; color: #1d6b38; }
.flash-err { border-left-color: var(--ig-red);   background: #fdf6f5; color: #6b2119; }
.caveat-body { font-size: 12.5px; color: #3f4854; margin: 6px 0 8px; max-width: 90ch; line-height: 1.55; }
.inline-form { display: inline; }
.btn-danger { background: var(--ig-white); color: var(--ig-red); border: 1px solid var(--ig-red);
              border-radius: 4px; padding: 2px 10px; font: inherit; font-size: 11px;
              font-weight: 600; cursor: pointer; }
.btn-danger:hover { background: var(--ig-red); color: var(--ig-white); }
.data-table tbody tr.row-inactive td { opacity: 0.55; }
.filters select { border: 1px solid var(--ig-teal); border-radius: 4px; padding: 5px 9px; font: inherit; }

/* No-access page */
.noaccess-wrap { display: flex; justify-content: center; padding: 40px 16px; }
.noaccess-card { max-width: 640px; }
.noaccess-title { font-size: 17px; font-weight: 700; color: var(--ig-navy); margin: 0 0 12px; }
.noaccess-body  { font-size: 13px; color: #3f4854; line-height: 1.6; margin: 0 0 12px; }
.noaccess-foot  { font-size: 11.5px; color: var(--ig-slate); margin: 18px 0 0;
                  padding-top: 12px; border-top: 1px solid var(--ig-border); }

/* Inline flags on a table row - population and data-quality markers that must
   not be mistaken for compliance findings. */
.flag { display: inline-block; margin-left: 5px; font-size: 9px; font-weight: 700;
        text-transform: uppercase; letter-spacing: 0.04em; padding: 1px 5px;
        border-radius: 3px; vertical-align: middle; cursor: help; white-space: nowrap; }
.flag-transfer { background: #e6eefc; color: #26457f; }
.flag-badcode  { background: #fbe3e0; color: #8f2c20; }

/* Trend table: was min-width 460px inside a full-width card, which left a large
   empty area to its right on a wide screen. Let it use the space it needs and
   no more, and keep the numeric columns from crowding the coverage bar. */
.trend-table { width: 100%; max-width: 640px; min-width: 0; }
.trend-table td, .trend-table th { padding-left: 10px; padding-right: 10px; }
.trend-table td.num, .trend-table th.num { white-space: nowrap; }
.cov-bar { max-width: 72px; }

/* The exceptions table is wide (9 document columns plus dates). Bound the
   scroll area so the page does not grow unusably tall, and keep the employee
   column readable while the rest scrolls under it. */
.table-scroll { max-height: 70vh; }
.data-table td.employee-cell { min-width: 210px; white-space: nowrap; }

/* ---------------------------------------------------------------------------
   Analysis row. The caveat panel and the per-requirement table both hold
   naturally narrow content (prose capped at ~90ch for readability, a 5-column
   table), so stacking them full-width left most of a wide monitor empty. Side
   by side on a wide screen, stacked below 1200px where two columns would
   squeeze both.
   --------------------------------------------------------------------------- */
.analysis-grid { display: grid; gap: 12px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1200px) {
  .analysis-grid { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); }
}
.analysis-grid > .card { margin: 0; min-width: 0; }
.card-requirements .data-table { width: 100%; }
.trend-table { max-width: 100%; }
.caveat p, .caveat-body, .rule-note, .limitation-list li { max-width: none; }

/* ---------------------------------------------------------------------------
   Filter bar: Apply belongs ON the filter row, at the same height as the
   inputs. It was being pushed onto a line of its own by the wrapping checkbox
   label, which left it floating under the first field looking unrelated to the
   controls it applies.
   --------------------------------------------------------------------------- */
.filters { align-items: flex-end; row-gap: 8px; }
.filters input, .filters select, .filters .btn-primary,
.filters .dropdown-trigger {
  height: 30px; box-sizing: border-box; line-height: 1;
}
.filters .btn-primary { padding: 0 20px; align-self: flex-end; }

.filter-actions {
  display: flex; align-items: center; gap: 14px;
  margin-left: auto;              /* push to the right edge of the bar */
  align-self: flex-end;
}
.filter-actions .filter-check {
  display: flex; flex-direction: row; align-items: center; gap: 6px;
  font-size: 11.5px; text-transform: none; letter-spacing: 0;
  color: var(--ig-slate); white-space: nowrap;
}
.filter-actions .filter-check input { height: auto; width: auto; }

/* ---------------------------------------------------------------------------
   Exceptions table: 9 document columns plus 3 dates makes it very wide, and
   the free-text columns were taking far more room than their content needs.
   Cap them and ellipsis the overflow (the full value stays in the title
   attribute), and let the date columns shrink to their fixed-width content.
   --------------------------------------------------------------------------- */
.data-table td, .data-table th { padding-left: 7px; padding-right: 7px; }
.data-table td.cell-clip {
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.data-table td.cell-date, .data-table th.cell-date { width: 1%; white-space: nowrap; }
.data-table td.employee-cell { min-width: 0; max-width: 260px;
                               overflow: hidden; text-overflow: ellipsis; }
.doc-col { max-width: 62px; font-size: 10px; }
.rules-table td { white-space: normal; vertical-align: top; }
.rules-table td:first-child { min-width: 220px; }
.rule-cond { display: block; font-size: 11px; color: var(--ig-slate); }
.rule-cond-not { color: var(--ig-red); }
.sidebar-link-sub { padding-left: 38px; font-size: 11.5px; opacity: 0.8; }

/* Column widths, measured rather than guessed: at 898px of scroller the table
   came out 1692px, with Employee 218, Job title 190, Division 165 and a
   "Joined group" HEADER 148px wide - wider than the date under it. Capping the
   free-text columns and shortening those headers takes roughly 220px out.
   A 20-column table still scrolls horizontally, which is legitimate; it should
   just not waste width doing it. */
.data-table td.cell-clip { max-width: 140px; }
.data-table td.employee-cell { max-width: 175px; }
.data-table th.cell-date { width: 1%; }
/* The "Joined" column stayed 148px after shortening its header, because the
   transfer badge sits beside the date on one nowrap line. Let this one cell
   wrap so the badge drops underneath: the column narrows to the date, and only
   transfer rows get taller. The badge stays a readable word rather than being
   abbreviated into something an auditor has to decode. */
.data-table td.cell-date-flag { white-space: normal; }
.data-table td.cell-date-flag .flag { margin-left: 0; margin-top: 2px; }

/* ---------------------------------------------------------------------------
   The page has TWO searches, on purpose, and they must not be confusable:

     "Search (affects export)"  filter bar, server-side, re-runs the query and
                                is what the .xlsx download reflects.
     "Filter on screen"         this control, client-side, instant, narrows the
                                rows already loaded and reaches nothing else.

   The second is styled deliberately unlike a filter-bar field - plain, inline,
   with its caveat printed next to it rather than hidden in a tooltip - so it
   does not read as another query control.
   --------------------------------------------------------------------------- */
.rowfilter { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             margin: 0 0 8px; padding: 7px 10px; background: #f4f6f8;
             border: 1px solid var(--ig-border); border-radius: 5px; }
.rowfilter-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em;
                   color: var(--ig-slate); font-weight: 600; }
.rowfilter input { height: 27px; box-sizing: border-box; min-width: 230px;
                   border: 1px solid var(--ig-border); border-radius: 4px;
                   padding: 4px 9px; font: inherit; background: var(--ig-white); }
.rowfilter input:focus { outline: none; border-color: var(--ig-teal);
                         box-shadow: 0 0 0 2px rgba(0,210,169,0.16); }
.rowfilter-count { font-size: 11.5px; color: var(--ig-navy); font-weight: 600;
                   font-variant-numeric: tabular-nums; white-space: nowrap; }
.rowfilter-count-none { color: var(--ig-red); }
.rowfilter-note { font-size: 11px; color: var(--ig-slate); margin-left: auto;
                  max-width: 52ch; line-height: 1.35; }
.rowfilter-note strong { color: #8a5a12; }
