/* Minimal, accessible defaults. Designed for one-pager dashboards. */

/* APK brand palette
 * - Primary red from the APK logo (~#E2231A) — used for headings, links, accent rings, CTAs.
 * - Slate gray (the logo's arrow tone) carried by the neutral text/border surfaces below.
 * - Orange (--warning) is retained ONLY as a semantic warning color (validation chips,
 *   partial-status icons); it no longer competes with brand since brand is now red.
 * - Light surfaces with soft slate borders. */
:root {
  --bg: #f5f7fb;
  --bg-elev: #ffffff;
  --bg-elev-2: #eef2f8;
  --border: #d7dde6;
  --text: #1c2541;
  --text-dim: #5a6a85;
  --primary: #e2231a;
  --primary-dark: #b81c13;
  /* APK logo arrow gray — used for header titles (app + page titles). */
  --brand-gray: #58595b;
  --warning: #e87722;
  --warning-dark: #c45f12;
  --danger: #c0392b;
  --ok: #2e8e5e;
  --shadow: 0 4px 18px rgba(28, 37, 65, 0.08);
  /* Shared height anchors the sticky app-header, sidebar top offset, and table thead top. */
  --app-header-height: 60px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
}

/* ---------- Full-width app header (logo + brand + user avatar) ---------- */

.app-header {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--app-header-height);
  background: var(--bg-elev);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1.25rem;
  box-shadow: 0 1px 0 rgba(28, 37, 65, 0.03);
}

.app-header-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.app-header-logo {
  height: 28px;
  width: auto;
  object-fit: contain;
}

.app-header-title {
  font-weight: 700;
  color: var(--brand-gray);
  font-size: 1.4rem;
  letter-spacing: -0.01em;
}

/* ---------- App shell + sidebar (below the header) ---------- */

.app-shell {
  display: flex;
  align-items: stretch;
  min-height: calc(100vh - var(--app-header-height));
}

.main-area {
  flex: 1;
  min-width: 0;       /* lets the table-wrap horizontal scroll work inside the flex item */
  display: flex;
  flex-direction: column;
}

/* main below the section title bar fills the remaining vertical space so the
 * Applications embed iframe can stretch to fit. The Entities page's <main> has
 * its own padding/max-width applied later; this just gives it the flex slot. */
.main-area > main { flex: 1; min-height: 0; }

.section-title-bar {
  padding: 1rem 2rem;
  background: var(--bg-elev);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* Standard table-utility icons (Filters, Columns) parked at the right of the title bar. */
.section-title-actions {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.section-title-bar h1 {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--brand-gray);
  letter-spacing: -0.005em;
}

.sidebar {
  width: 232px;
  flex-shrink: 0;
  background: var(--bg-elev);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: var(--app-header-height);
  height: calc(100vh - var(--app-header-height));
  transition: width 0.18s ease;
  z-index: 5;
}

.sidebar.collapsed { width: 68px; }

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.75rem 0.55rem;
  flex: 1;
  overflow-y: auto;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.7rem;
  border-radius: 6px;
  color: var(--text);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  transition: background-color 0.1s ease;
}
.nav-item:hover { background: var(--bg-elev-2); }
.nav-item.active {
  background: rgba(226, 35, 26, 0.1);
  color: var(--primary);
}
.nav-item.active .nav-icon { color: var(--primary); }

.nav-icon {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-dim);
}
.nav-icon svg { width: 100%; height: 100%; }

.sidebar.collapsed .nav-label { display: none; }
.sidebar.collapsed .nav-item  { justify-content: center; padding: 0.6rem; }

/* ---- Saved queries (dynamic Query Builder nav section) ---- */
.sidebar-saved { display: flex; flex-direction: column; gap: 0.15rem; }
.sidebar-saved-label {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-dim); font-weight: 700; padding: 0.6rem 0.7rem 0.25rem;
}
/* A section label can be a link (e.g. Forms → the tile overview page). */
a.sidebar-saved-label { text-decoration: none; display: block; }
a.sidebar-saved-label:hover,
a.sidebar-saved-label.active { color: var(--primary); }
.nav-item-saved .nav-label {
  flex: 1; overflow: hidden; text-overflow: ellipsis; font-weight: 500;
}
.nav-saved-delete {
  flex-shrink: 0; border: none; background: transparent; cursor: pointer;
  color: var(--text-dim); font-size: 0.8rem; line-height: 1; border-radius: 4px;
  width: 20px; height: 20px; display: none; align-items: center; justify-content: center;
}
.nav-item-saved:hover .nav-saved-delete { display: inline-flex; }
/* "New Query" reads as a subtle add action, less prominent than the real sections. */
.nav-item-new { color: var(--text-dim); font-weight: 400; font-size: 0.85rem; }
.nav-item-new:hover { color: var(--text); }
.nav-saved-delete:hover { background: var(--danger); color: #fff; }
.sidebar.collapsed .sidebar-saved-label { display: none; }
.sidebar.collapsed .nav-saved-delete { display: none !important; }

.sidebar-toggle {
  margin: 0.5rem;
  align-self: flex-end;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-dim);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.sidebar-toggle svg { width: 16px; height: 16px; transition: transform 0.18s ease; }
.sidebar-toggle:hover {
  background: var(--bg-elev-2);
  border-color: var(--border);
  color: var(--text);
}
.sidebar.collapsed .sidebar-toggle { align-self: center; }
.sidebar.collapsed .sidebar-toggle svg { transform: rotate(180deg); }

/* Application tile grid (Applications page) — one card per app. */
.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  gap: 1.25rem;
}

.app-tile {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.35rem 1.5rem;
  min-height: 92px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.12s ease, box-shadow 0.12s ease, transform 0.05s ease;
}
.app-tile:hover {
  border-color: var(--primary);
  box-shadow: var(--shadow);
}
.app-tile:active { transform: translateY(1px); }

.app-tile-icon {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: rgba(226, 35, 26, 0.1);
  color: var(--primary);
}
.app-tile-icon svg { width: 22px; height: 22px; }

.app-tile-body {
  flex: 1;
  min-width: 0;
}

.app-tile-name {
  font-weight: 600;
  font-size: 0.98rem;
  color: var(--text);
}

.app-tile-host {
  font-size: 0.82rem;
  color: var(--text-dim);
  margin-top: 0.2rem;
  line-height: 1.4;
  white-space: normal;       /* let the description wrap so it's fully visible */
}

.app-tile-arrow {
  color: var(--text-dim);
  font-size: 1rem;
  flex-shrink: 0;
}
.app-tile:hover .app-tile-arrow { color: var(--primary); }

/* ---------- Embedded app view (Applications → click a tile) ----------
 * The embed takes the full main slot: section-title bar is hidden via JS,
 * <main>'s padding is zeroed, the iframe fills 100%. A small floating circular
 * back button is overlaid in the top-left corner to return to the tile grid. */

main:has(.app-embed) { padding: 0; max-width: none; }

.app-embed {
  position: relative;            /* positioning context for the floating back button */
  display: flex;
  flex-direction: column;
  /* Flex:1 inherited from .main-area > main; the calc() is a defensive fallback
   * for browsers that don't propagate the flex height to <main>. */
  min-height: calc(100vh - var(--app-header-height));
  flex: 1;
  background: var(--bg);
}

.app-embed-frame {
  flex: 1;
  width: 100%;
  border: 0;
  background: #fff;
  min-height: calc(100vh - var(--app-header-height));
}

/* Floating back button — circular, brand-tinted, with a soft shadow so it
 * reads clearly on top of whatever the embedded app happens to render. */
.embed-back-btn {
  position: absolute;
  top: 0.85rem;
  left: 0.85rem;
  z-index: 5;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  box-shadow: 0 2px 8px rgba(28, 37, 65, 0.12);
  color: var(--text);
  text-decoration: none;
  transition: background-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease, transform 0.05s ease;
}
.embed-back-btn:hover {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
  box-shadow: 0 3px 10px rgba(226, 35, 26, 0.3);
}
.embed-back-btn:active { transform: scale(0.96); }
.embed-back-btn svg { width: 18px; height: 18px; }

/* Modern avatar + dropdown account menu (replaces the old "Signed in as ..." line). */
.user-menu {
  position: relative;
  flex-shrink: 0;
}

button.user-avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
  color: #fff;
  font-weight: 600;
  font-size: 0.95rem;
  border: 1px solid rgba(255, 255, 255, 0.08);
  padding: 0;
  cursor: pointer;
  transition: box-shadow 0.15s ease, transform 0.05s ease;
}

button.user-avatar:hover:not(:disabled) {
  box-shadow: 0 0 0 3px rgba(226, 35, 26, 0.18);
  border-color: rgba(255, 255, 255, 0.18);
}

button.user-avatar:active:not(:disabled) {
  transform: scale(0.97);
}

button.user-avatar:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(226, 35, 26, 0.35);
}

.user-initials {
  line-height: 1;
  letter-spacing: 0.02em;
}

.user-dropdown {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 240px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  overflow: hidden;
  z-index: 20;
}

.user-dropdown-header {
  padding: 0.85rem 1rem 0.75rem;
}

.user-dropdown-name {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-dropdown-email {
  color: var(--text-dim);
  font-size: 0.82rem;
  margin-top: 0.15rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-dropdown-divider {
  height: 1px;
  background: var(--border);
}

.user-dropdown-item {
  display: block;
  padding: 0.65rem 1rem;
  color: var(--text);
  text-decoration: none;
  font-size: 0.9rem;
}

.user-dropdown-item:hover {
  background: var(--bg-elev-2);
}

main {
  /* Fit the main-area flex slot (which already accounts for the sidebar width)
   * and cap at 1800px on huge displays. Using % instead of vw is essential —
   * vw doesn't know about the sidebar and would overflow the main-area. */
  max-width: min(100%, 1800px);
  margin: 0;
  padding: 1.5rem 2rem 2rem;
}

.actions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin-bottom: 2rem;
}

button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.35rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elev);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: transform 0.05s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

button .label {
  font-weight: 600;
  font-size: 1.05rem;
}

button .hint {
  font-size: 0.8rem;
  color: var(--text-dim);
}

button:hover:not(:disabled) {
  border-color: var(--primary);
  box-shadow: var(--shadow);
}

button:active:not(:disabled) {
  transform: translateY(1px);
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

button.primary  { border-color: rgba(226, 35, 26, 0.35); }
button.warning  { border-color: rgba(232, 119, 34, 0.4); }
button.danger   { border-color: rgba(192, 57, 43, 0.4); }
button.primary:hover:not(:disabled)  { border-color: var(--primary); }
button.warning:hover:not(:disabled)  { border-color: var(--warning); }
button.danger:hover:not(:disabled)   { border-color: var(--danger); }

.status {
  padding: 1rem 1.25rem;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: 6px;
  margin-bottom: 1.5rem;
}

.status p {
  margin: 0;
}

/* ---------- Inline progress strip (lives in the toolbar row between filter + buttons) ---------- */

.progress-inline {
  /* flex:1 so it fills the slack between toolbar-left (filter) and toolbar-right (CTAs).
   * min-width:0 lets the bar shrink with the toolbar instead of forcing a wrap on
   * tight viewports; the bar stays visible because flex-grow:1 always claims any
   * remaining space. */
  flex: 1;
  min-width: 0;
  max-width: 560px;
  margin: 0 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.82rem;
  align-self: center;
}

.progress-text {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  color: var(--text);
}

.progress-label    { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.progress-meta     { display: inline-flex; gap: 0.55rem; flex-shrink: 0; color: var(--text-dim); }
.progress-counter  { font-variant-numeric: tabular-nums; }
.progress-timer    { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.78rem; }

.progress-track {
  position: relative;
  height: 5px;
  border-radius: 3px;
  background: var(--bg-elev-2);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 3px;
  width: 0%;
  transition: width 0.25s ease;
}

/* Indeterminate variant — bouncing partial fill while we wait for the first
 * poll cycle to report real stagesCompleted/Total numbers. */
.progress-fill.indeterminate {
  width: 35%;
  transition: none;
  animation: progress-indeterminate 1.4s ease-in-out infinite;
}

@keyframes progress-indeterminate {
  0%   { transform: translateX(-100%); }
  50%  { transform: translateX(180%); }
  100% { transform: translateX(-100%); }
}

/* ---------- Completion toast (bottom-right) ---------- */

.toast {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  padding: 0.7rem 1rem;
  border-radius: 8px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  color: var(--text);
  font-size: 0.88rem;
  font-weight: 500;
  box-shadow: 0 4px 18px rgba(28, 37, 65, 0.16);
  z-index: 100;
  animation: toast-in 0.18s ease-out;
}
.toast-ok    { border-left-color: var(--ok); }
.toast-error { border-left-color: var(--danger); }

@keyframes toast-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

.result {
  padding: 1.5rem 2rem;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.result h2 {
  margin: 0 0 1rem;
  font-size: 1.15rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.5rem;
}

#report h1 { font-size: 1.3rem; margin-top: 1.5rem; }
#report h2 { font-size: 1.15rem; margin-top: 1.5rem; border: 0; padding: 0; }
#report h3 { font-size: 1rem; margin-top: 1.25rem; color: var(--text); }

#report table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.75rem 0 1.5rem;
  font-size: 0.9rem;
}

#report th, #report td {
  text-align: left;
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

#report th {
  background: var(--bg-elev-2);
  font-weight: 600;
  color: var(--text);
}

#report tr:hover td { background: rgba(28, 37, 65, 0.03); }

#report code {
  background: var(--bg-elev-2);
  padding: 0.1rem 0.4rem;
  border-radius: 3px;
  font-size: 0.85em;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

#report a { color: var(--primary); }

#report blockquote, #report em { color: var(--text-dim); }

.error {
  padding: 1.5rem;
  background: rgba(192, 57, 43, 0.08);
  border: 1px solid var(--danger);
  border-radius: 8px;
  margin-top: 1.5rem;
}

.error h2 {
  margin: 0 0 0.75rem;
  color: var(--danger);
}

.error pre {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 0.85rem;
  color: var(--text-dim);
  margin: 0;
}

/* ---------- Phase B: hierarchy dashboard ---------- */

/* Toolbar stays on a single row even when the CTAs widen (e.g.
 * "Refresh N selected" / "Update N selected"). flex-shrink:0 on the
 * right group keeps the buttons inline; the left group is allowed to
 * shrink so the filter input absorbs any squeeze. */
.toolbar {
  display: flex;
  flex-wrap: nowrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: nowrap;     /* filter input + BRYTER toggle stay on the same row */
  min-width: 0;          /* lets the filter input shrink instead of forcing a wrap */
  flex-shrink: 1;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: nowrap;
  flex-shrink: 0;        /* keep all four CTAs on the same line as the filter */
}

.freshness-text {
  color: var(--text-dim);
  font-size: 0.85rem;
}

/* Toolbar CTA buttons — solid APK red for the primary write action,
 * lighter red tint for the secondary read action. */
button.cta {
  font-size: 0.88rem;
  font-weight: 600;
  padding: 0.45rem 0.95rem;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  line-height: 1;
  transition: background-color 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}

button.cta-primary {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}
button.cta-primary:hover:not(:disabled) {
  background: var(--primary-dark);
  border-color: var(--primary-dark);
}
button.cta-primary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(226, 35, 26, 0.3);
}

button.cta-secondary {
  background: #fbe0de;       /* soft tint of --primary */
  color: var(--primary-dark);
  border-color: #f4c7c3;
}
button.cta-secondary:hover:not(:disabled) {
  background: #f4c7c3;
  border-color: #eeb0aa;
}
button.cta-secondary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(226, 35, 26, 0.25);
}

/* Tertiary CTA: outlined-only, icon-only. Used for utility toolbar buttons
 * (Schedule, Columns) that share the row with the primary Refresh/Update
 * actions. Square shape sized to roughly match the labeled CTAs' overall
 * height so the toolbar reads as one consistent row of controls. */
button.cta-ghost {
  background: transparent;
  color: var(--text-dim);
  border-color: var(--border);
  /* Override .cta's wider padding for a compact square icon button. */
  padding: 0;
  width: 32px;
  height: 32px;
  justify-content: center;
}
button.cta-ghost:hover:not(:disabled) {
  background: var(--bg-elev-2);
  border-color: var(--primary);
  color: var(--primary);
}
button.cta-ghost:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(226, 35, 26, 0.2);
}
/* Toggled-on state (e.g. the Filters toggle while the filter row is showing). */
button.cta-ghost[aria-pressed="true"] {
  background: var(--bg-elev-2);
  border-color: var(--primary);
  color: var(--primary);
}
button.cta-ghost svg { width: 16px; height: 16px; display: block; }

/* Split button: a primary action with an attached secondary segment (e.g. a
 * schedule clock), joined into one control so the segment clearly belongs to the
 * action. The two .cta children share an edge; only the outer corners round. */
.cta-split { display: inline-flex; }
.cta-split > .cta { border-radius: 0; }
.cta-split > .cta:first-child {
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}
.cta-split > .cta:last-child {
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}
/* Hairline divider between segments (light-on-red, matches the primary fill). */
.cta-split > .cta + .cta { border-left-color: rgba(255, 255, 255, 0.4); }
.cta-split-side { padding: 0.45rem 0.6rem; }
.cta-split-side svg { width: 16px; height: 16px; display: block; }

button.cta:disabled { opacity: 0.55; cursor: not-allowed; }

.filter input {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 0.4rem 0.7rem;
  font: inherit;
  width: 240px;
  min-width: 0;
  max-width: 100%;       /* lets the input shrink when the toolbar tightens */
}

.filter input:focus { outline: none; border-color: var(--primary); }

/* "Show only BRYTER records" audit toggle. Sits inline with the filter
 * input in .toolbar-left. The count suffix appears only when the toggle is
 * off and the BRYTER-eligible subset differs from the full KLEA set.
 *
 * flex-shrink:0 + white-space:nowrap so the toggle never wraps or clips
 * its label — the filter input absorbs the squeeze instead. */
.bryter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
  flex-shrink: 0;
  white-space: nowrap;
}
.bryter-toggle input { margin: 0; cursor: pointer; }
.bryter-toggle-count {
  font-size: 0.78rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.meta-banner {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.85rem;
  color: var(--text-dim);
  margin-bottom: 1rem;
}

.meta-totals {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  flex: 1;
  min-width: 0;
}

.meta-banner .freshness-text {
  /* Pushed to the far right of the ribbon. flex-shrink:0 so long totals don't squeeze it out. */
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
}

.meta-banner strong { color: var(--text); }
.meta-banner .dot   { color: var(--border); }

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
}

/* Zoom/pan viewport (QBViewport) — shared with the query builder. */
.qb-vp { position: relative; overflow: hidden; border: 1px solid var(--border);
  border-radius: 8px; background: #fff; touch-action: none; }
.qb-vp-stage { transform-origin: 0 0; width: max-content; cursor: grab; }
.qb-vp-grabbing .qb-vp-stage { cursor: grabbing; user-select: none; }
.qb-vp-bar { position: absolute; top: 6px; right: 6px; z-index: 2; display: flex;
  align-items: center; gap: 2px; background: rgba(255,255,255,0.92);
  border: 1px solid var(--border); border-radius: 6px; padding: 2px; }
.qb-vp-btn { border: none; background: transparent; cursor: pointer; width: 24px; height: 22px;
  border-radius: 4px; font-size: 14px; line-height: 1; color: var(--text);
  display: inline-flex; align-items: center; justify-content: center; }
.qb-vp-btn:hover { background: var(--bg-elev-2); }
.qb-vp-pct { font-size: 11px; color: var(--text-dim); min-width: 36px; text-align: center;
  font-variant-numeric: tabular-nums; }

table.hierarchy {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
  /* fixed layout makes the <colgroup> widths authoritative — required for column resizing. */
  table-layout: fixed;
}

table.hierarchy th,
table.hierarchy td {
  text-align: left;
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  /* truncate long values with an ellipsis rather than wrapping (resize the column if you need more). */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

table.hierarchy thead th {
  background: var(--bg-elev-2);
  font-weight: 600;
  /* `position: relative` is needed so the absolutely-positioned .col-resizer handle
   * has the th as its positioning context. We intentionally do NOT use position:sticky
   * here — .table-wrap's `overflow-x: auto` makes it a scroll container for both
   * axes per spec, which would constrain the sticky thead in a way that breaks
   * the page-level vertical scroll experience. */
  position: relative;
  z-index: 1;
}

table.hierarchy .col-check     { padding-left: 0.6rem; padding-right: 0; text-align: center; }
table.hierarchy .col-check input { cursor: pointer; margin: 0; vertical-align: middle; }
table.hierarchy .col-name      { font-weight: 500; }
table.hierarchy .col-id        { font-family: ui-monospace, "SF Mono", Menlo, monospace; color: var(--text-dim); }
table.hierarchy .col-num       { text-align: right; font-variant-numeric: tabular-nums; }
table.hierarchy .col-status        { text-align: center; }
table.hierarchy .col-status-rollup { text-align: center; }

/* Pin the Actions column to the right of the horizontally-scrollable .table-wrap
 * so the per-row buttons remain visible regardless of scroll position. Grey tint
 * (var(--bg-elev-2)) keeps it visually distinct from the scrolling content.
 *
 * NB: we paint the left edge via box-shadow (not border-left). border-collapse:
 * collapse on the table makes cell borders unreliable when combined with
 * position: sticky — they vanish at scrollLeft=0 in WebKit/Blink because the
 * border is owned by the table grid, not the sticky cell. The inset shadow is
 * painted by the cell itself, so it's always visible. */
table.hierarchy th.col-actions,
table.hierarchy td.col-actions {
  text-align: center;
  position: sticky;
  right: 0;
  background: var(--bg-elev-2);
  box-shadow:
    inset 2px 0 0 0 #aab4c6,                      /* solid 2px left "border" */
    -6px 0 8px -6px rgba(28, 37, 65, 0.18);       /* soft drop shadow for separation */
  z-index: 1;
}
table.hierarchy thead th.col-actions {
  z-index: 3;  /* above sticky body cells (z:1) and sticky thead (z:1) */
}
/* Keep the pinned cell grey on row hover / expand so it doesn't lose its "pinned" look. */
tr.row-company:hover td.col-actions,
tr.row-company.expanded td.col-actions {
  background: var(--bg-elev-2);
}

/* Drag-to-resize handle that sits on the right edge of each th. */
.col-resizer {
  position: absolute;
  top: 0;
  right: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
  z-index: 2;
}
.col-resizer:hover { background: var(--primary); opacity: 0.4; }
body.col-resizing { cursor: col-resize; user-select: none; }
body.col-resizing .col-resizer { background: var(--primary); opacity: 0.6; }

table.directors th.col-status,
table.directors td.col-status      { text-align: center; white-space: nowrap; padding-left: 1rem; padding-right: 1rem; }
/* Director-row Actions column: width-matched to the parent's 110px so its left
 * edge sits at the same x as the parent's pinned Actions column, with the same
 * grey tint + 2px slate left border + soft outer shadow for visual continuity.
 * Without an explicit width, the auto-layout sub-table would size this column
 * to its content (~80px) and the borders wouldn't line up. */
table.directors th.col-actions,
table.directors td.col-actions {
  width: 110px;
  min-width: 110px;
  text-align: center;
  white-space: nowrap;
  background: var(--bg-elev-2);
  box-shadow:
    inset 2px 0 0 0 #aab4c6,
    -6px 0 8px -6px rgba(28, 37, 65, 0.18);
}

.rollup-count {
  margin-left: 0.35rem;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.85em;
  color: var(--text-dim);
}

.validation-error {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  background: rgba(232, 119, 34, 0.1);
  border: 1px solid rgba(232, 119, 34, 0.35);
  color: var(--warning);
  font-size: 0.78rem;
  font-weight: 500;
  cursor: help;
}

tr.row-company { cursor: pointer; }
tr.row-company:hover td { background: rgba(28, 37, 65, 0.03); }
tr.row-company.expanded td { background: rgba(226, 35, 26, 0.05); }

/* Non-BRYTER audit row. Muted text + faded background so users don't
 * read the empty BRYTER/CPAI columns as a sync failure. No expand cursor —
 * these rows have no directors detail row to open. */
tr.row-non-bryter { cursor: default; }
tr.row-non-bryter td {
  color: var(--text-dim);
  background: rgba(28, 37, 65, 0.015);
}
tr.row-non-bryter:hover td { background: rgba(28, 37, 65, 0.04); }
tr.row-non-bryter td.col-name { font-weight: 400; }   /* override .col-name's font-weight: 500 */

/* "Is BRYTER?" column values — green for TRUE so the rare anomaly
 * (FALSE-flagged company that's actually in BRYTER) reads as routine, not
 * alarming; gray for FALSE so it sits visually with the muted row. */
td.is-bryter-true  { color: var(--ok);       font-weight: 600; }
td.is-bryter-false { color: var(--text-dim); }

tr.row-detail .detail-cell {
  background: var(--bg);
  /* Left padding clears the L-shaped tree connector + lines the sub-table up
   * roughly with the Company name column above. Right padding is 0 so the
   * sub-table's right edge aligns flush with the parent table's right edge,
   * keeping the director-row Actions column border lined up with the parent's. */
  padding: 0.6rem 0 1rem 3.5rem;
  position: relative;          /* positioning context for the L connector */
  /* the parent rule sets nowrap+ellipsis on every td — undo it for the nested table's container. */
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/* L-shaped tree connector visually anchors the directors sub-table to the
 * company row above it: a thin line drops out of the parent row and curves
 * right into the directors table. Pure CSS, no extra DOM. */
tr.row-detail .detail-cell::before {
  content: "";
  position: absolute;
  left: 1.65rem;
  top: 0;
  width: 1.1rem;
  height: 1.3rem;
  border-left:   2px solid #a4b1c4;
  border-bottom: 2px solid #a4b1c4;
  border-bottom-left-radius: 6px;
  pointer-events: none;
}

table.directors th,
table.directors td {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;      /* fixed-layout columns truncate overflow cleanly */
}

/* Column widths for the directors sub-table live in the per-row <colgroup>
 * (see renderDirectorsRow in app.js). Fixed layout enforces them, with the
 * spacer column absorbing whatever horizontal slack is left so the Actions
 * column lines up with the parent table's pinned Actions border. The spacer
 * cells get no special treatment — they inherit the row bg + border-bottom
 * from the generic td rule, reading as an empty cell within the row. */

table.directors {
  /* Full-width so the Actions column can be pushed to the right via the
   * spacer column, lining up with the parent table's pinned Actions border.
   * NB: no right border — the parent table's Actions column has its own
   * left-edge inset shadow at the same x, and a 1px right border here would
   * push the directors' Actions cell 1px inward, visibly misaligning the
   * two vertical separators. */
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 0.85rem;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-right: 0;
  border-radius: 4px 0 0 4px;
}

table.directors th,
table.directors td {
  padding: 0.45rem 0.6rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

table.directors thead th {
  background: var(--bg-elev-2);
  font-weight: 600;
  color: var(--text-dim);
}

table.directors tr:last-child td { border-bottom: 0; }

.status-icon {
  font-size: 1.05rem;
  line-height: 1;
  cursor: help;
}

.status-icon.ok       { color: var(--ok); }
.status-icon.missing  { color: var(--danger); }
.status-icon.partial  { color: var(--warning); }
.status-icon.pending  { color: var(--text-dim); }
.status-icon.warning  { color: var(--warning); }

.muted { color: var(--text-dim); font-size: 0.78rem; }

/* Per-row check (↻) + sync (↑) buttons.
 * Both icons share the brand blue so they read as the row-level analogs of
 * the global "Refresh all" / "Update all" CTAs in the toolbar. The .warning
 * class is kept for semantic grouping (sync is a write action) but uses the
 * same blue palette per design. */
button.row-btn {
  display: inline-block;
  flex-direction: row;
  padding: 0.15rem 0.4rem;
  margin: 0 0.1rem;
  font-size: 0.95rem;
  line-height: 1;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--primary);
  cursor: pointer;
  min-width: 0;
  text-align: center;
}
button.row-btn:hover:not(:disabled) {
  border-color: var(--primary);
  background: rgba(226, 35, 26, 0.1);
  color: var(--primary-dark);
}
button.row-btn.warning { color: var(--primary); }
button.row-btn.warning:hover:not(:disabled) {
  border-color: var(--primary);
  background: rgba(226, 35, 26, 0.1);
  color: var(--primary-dark);
}
button.row-btn:disabled { opacity: 0.5; cursor: wait; }
button.row-btn.error {
  border-color: var(--danger);
  color: var(--danger);
}

/* Per-row loading state: replaces the action buttons in the Actions cell
 * while a check/sync call is in flight. Stacked compact layout fits the
 * 110px cell width. */
.row-loading {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.3rem;
  padding: 0.1rem 0.4rem;
}
.row-loading-label {
  font-size: 0.78rem;
  color: var(--primary);
  font-weight: 500;
  text-align: center;
}
.row-loading-bar {
  position: relative;
  height: 3px;
  border-radius: 2px;
  background: var(--bg-elev);
  overflow: hidden;
}
.row-loading-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 40%;
  background: var(--primary);
  border-radius: 2px;
  animation: progress-indeterminate 1.2s ease-in-out infinite;
}

.legend {
  text-align: center;
  margin-top: 1.5rem;
  font-size: 0.8rem;
  color: var(--text-dim);
}

/* ---------- Column-settings modal ----------
 * Modal pattern: full-viewport dimmed backdrop + centered panel.
 * Body gets `.modal-open` while open to prevent background scroll.
 * Save/Cancel semantics — see app.js openColsModal/closeColsModal. */

body.modal-open { overflow: hidden; }

/* :not([hidden]) is required: `display: flex` on a bare `.modal-overlay` rule
 * would override the user-agent `[hidden] { display: none }` (author rules win
 * at equal specificity), and the modal would never hide. */
.modal-overlay:not([hidden]) {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(28, 37, 65, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.modal {
  background: var(--bg-elev);
  border-radius: 10px;
  box-shadow: 0 24px 48px rgba(28, 37, 65, 0.25);
  width: min(720px, 100%);
  max-height: calc(100vh - 3rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1.25rem;
  border-bottom: 1px solid var(--border);
}
.modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
  color: var(--text);
  font-weight: 600;
}
.modal-close {
  background: transparent;
  border: 0;
  color: var(--text-dim);
  font-size: 1.1rem;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  line-height: 1;
}
.modal-close:hover { background: var(--bg-elev-2); color: var(--text); }

.modal-body {
  padding: 1rem 1.25rem;
  overflow-y: auto;
  flex: 1;
}

.modal-hint {
  margin: 0 0 0.85rem;
  font-size: 0.83rem;
  color: var(--text-dim);
}

.cols-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}
@media (max-width: 640px) {
  .cols-grid { grid-template-columns: 1fr; }
}

.cols-section h3 {
  margin: 0 0 0.5rem;
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

.cols-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
}

.cols-list-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-elev);
  cursor: grab;
  user-select: none;
}
.cols-list-item:last-child { border-bottom: 0; }
.cols-list-item:active     { cursor: grabbing; }
.cols-list-item.dragging   { opacity: 0.5; }
/* Insertion indicator while dragging (drop inserts before this row). */
.cols-list-item.drop-target { box-shadow: inset 0 2px 0 0 var(--primary); }

.cols-handle {
  color: var(--text-dim);
  font-size: 0.9rem;
  line-height: 1;
  letter-spacing: -0.15em;     /* tighter '⋮⋮' so it reads as a single grip */
  width: 14px;
  text-align: center;
  cursor: grab;
}

.cols-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1;
  cursor: pointer;
  font-size: 0.88rem;
  color: var(--text);
}
.cols-toggle input[type=checkbox] {
  cursor: pointer;
  margin: 0;
}
.cols-label { line-height: 1.2; }

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.85rem 1.25rem;
  border-top: 1px solid var(--border);
  background: var(--bg-elev-2);
}
.modal-actions {
  display: flex;
  gap: 0.5rem;
}

/* Link-styled CTA — used for the modal's "Reset to defaults" action so it
 * reads as a tertiary control beside the primary Save / secondary Cancel. */
button.cta-link {
  background: transparent;
  border-color: transparent;
  color: var(--text-dim);
  padding: 0.45rem 0.5rem;
}
button.cta-link:hover:not(:disabled) {
  color: var(--primary);
  text-decoration: underline;
}

/* ---------- Schedule modal ----------
 * Reuses the generic .modal-overlay / .modal scaffolding. Only the
 * form-specific bits (enabled toggle, day-of-week chip group, status
 * footer) need bespoke rules. */

.sched-row {
  margin: 0 0 1rem;
  display: block;
}
.sched-row:last-of-type { margin-bottom: 0; }

.sched-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
}
.sched-toggle input { margin: 0; cursor: pointer; }

.sched-days {
  border: 0;
  padding: 0;
  margin: 0 0 1rem;
}
.sched-days legend {
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  margin-bottom: 0.4rem;
  padding: 0;
}
.sched-days {
  display: block;
}
.sched-days > label {
  /* Each day renders as a pill: clicking the label toggles the hidden checkbox. */
  display: inline-block;
  margin: 0 0.35rem 0.35rem 0;
  cursor: pointer;
  user-select: none;
}
.sched-days > label input[type=checkbox] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.sched-days > label span {
  display: inline-block;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  font-size: 0.85rem;
  color: var(--text-dim);
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.sched-days > label:hover span {
  border-color: var(--primary);
  color: var(--primary);
}
.sched-days > label input:checked + span {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.sched-days > label input:focus-visible + span {
  box-shadow: 0 0 0 3px rgba(226, 35, 26, 0.25);
}

.sched-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.85rem;
}
.sched-grid label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}
.sched-grid input[type=time],
.sched-grid select {
  font: inherit;
  font-size: 0.9rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text);
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-elev);
}
.sched-grid input[type=time]:focus,
.sched-grid select:focus {
  outline: none;
  border-color: var(--primary);
}

.sched-status {
  margin: 0;
  padding: 0.6rem 0.85rem;
  border-radius: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  font-size: 0.83rem;
  color: var(--text-dim);
  line-height: 1.4;
}

/* ---------- Login page ----------
 * Standalone /login.html (no sidebar / app shell). Centered card with the
 * brand + email/password form + secondary "Sign in with AAD" link. */

body.login-body {
  background: var(--bg);
  min-height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;          /* vertical center; was flex-start */
  justify-content: center;
}

.login-shell {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 2rem 1.5rem;         /* equal top/bottom; was 5vh top + 2rem bottom */
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.75rem;
  box-shadow: var(--shadow);
}

.login-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}
.login-logo { height: 30px; width: auto; object-fit: contain; }
.login-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--brand-gray);
  letter-spacing: -0.005em;
}

.login-heading {
  margin: 0 0 0.85rem;
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--text);
}

.login-form { display: flex; flex-direction: column; gap: 0.85rem; }
.login-field { display: flex; flex-direction: column; gap: 0.3rem; }
.login-field span {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.login-field input {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 0.55rem 0.7rem;
  font: inherit;
  font-size: 0.95rem;
}
.login-field input:focus { outline: none; border-color: var(--primary); }

.login-error {
  color: var(--danger);
  background: rgba(192, 57, 43, 0.08);
  border: 1px solid rgba(192, 57, 43, 0.25);
  padding: 0.5rem 0.7rem;
  border-radius: 6px;
  font-size: 0.85rem;
}

.login-submit { width: 100%; justify-content: center; margin-top: 0.3rem; }

.login-divider {
  margin: 1.25rem 0 1rem;
  text-align: center;
  position: relative;
  color: var(--text-dim);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.login-divider::before,
.login-divider::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 40%;
  height: 1px;
  background: var(--border);
}
.login-divider::before { left: 0; }
.login-divider::after  { right: 0; }
.login-divider span { background: var(--bg-elev); padding: 0 0.6rem; position: relative; }

.login-aad { width: 100%; justify-content: center; text-decoration: none; }

/* ---------- Admin: Manage users ---------- */

.admin-main {
  padding: 1.5rem 2rem 2rem;
  max-width: 1200px;
  width: 100%;
}

.admin-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.admin-hint {
  margin: 0;
  font-size: 0.88rem;
  color: var(--text-dim);
  flex: 1;
  min-width: 240px;
}
.admin-hint strong { color: var(--text); }

.admin-table-wrap {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.admin-table th,
.admin-table td {
  text-align: left;
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--border);
}
.admin-table thead th {
  background: var(--bg-elev-2);
  font-weight: 600;
  color: var(--text-dim);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.admin-table tbody tr:last-child td { border-bottom: 0; }

.admin-empty {
  text-align: center;
  color: var(--text-dim);
  padding: 1.5rem;
}

.admin-actions {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.admin-pill {
  display: inline-block;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.admin-pill-ok   { background: rgba(46, 142, 94, 0.12);  color: var(--ok); }
.admin-pill-warn { background: rgba(232, 119, 34, 0.12); color: var(--warning-dark); }

/* Compact CTA variant for table actions. */
button.cta-sm { padding: 0.32rem 0.7rem; font-size: 0.82rem; }

/* Danger CTA — used for destructive admin actions (Delete user). */
button.cta-danger {
  background: var(--bg-elev);
  color: var(--danger);
  border-color: rgba(192, 57, 43, 0.35);
}
button.cta-danger:hover:not(:disabled) {
  background: rgba(192, 57, 43, 0.08);
  border-color: var(--danger);
}

/* Sign-out / Back-to-dashboard row under the change-password form.
 * Change-password is a standalone card with no sidebar, so without this
 * row a user who forgets their current password has no way out. */
.login-secondary {
  margin: 1.1rem 0 0;
  font-size: 0.85rem;
  display: flex;
  justify-content: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.login-secondary a {
  color: var(--text-dim);
  text-decoration: none;
}
.login-secondary a:hover { color: var(--text); text-decoration: underline; }

/* Login fineprint — used on /login.html, /change-password.html for the
 * "minimum 10 chars" hint under the form fields. */
.login-fineprint,
.login-hint {
  margin: 0;
  font-size: 0.8rem;
  color: var(--text-dim);
  line-height: 1.4;
}
.login-hint {
  padding: 0.6rem 0.8rem;
  background: rgba(232, 119, 34, 0.08);
  border: 1px solid rgba(232, 119, 34, 0.25);
  border-radius: 6px;
  margin-bottom: 0.85rem;
  color: var(--warning-dark);
  font-size: 0.85rem;
}

/* Temp-password modal: one-shot reveal with copy button. */
.temp-pw-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.4rem 0 0.6rem;
}
.temp-pw-value {
  flex: 1;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 1rem;
  padding: 0.55rem 0.7rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  user-select: all;
  word-break: break-all;
}

/* ---------- APK Qooling↔BRYTER console (page-specific) ---------- */

.login-subtitle {
  margin: 0.25rem 0 0;
  color: var(--text-dim);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
}

/* ---------- Qooling console: pivot matrix ---------- */

/* Flex row: the matrix (#pivot) takes the remaining width and scrolls horizontally
 * inside its own .table-wrap; the record pane (.pivot-drawer) sits inline beside it
 * so the full matrix stays reachable while the pane is open. */
.pivot-wrap {
  margin-top: 0.5rem;
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}
#pivot { flex: 1 1 auto; min-width: 0; }   /* min-width:0 lets .table-wrap shrink + scroll */

.pivot-placeholder {
  color: var(--text-dim);
  font-size: 0.9rem;
  font-style: italic;
}
.pivot-error {
  color: var(--danger);
  font-size: 0.9rem;
  padding: 0.75rem 1rem;
  background: rgba(192, 57, 43, 0.08);
  border: 1px solid rgba(192, 57, 43, 0.25);
  border-radius: 6px;
}

table.pivot {
  border-collapse: collapse;
  font-size: 0.85rem;
  background: var(--bg-elev);
  /* Fill the panel when no detail pane is open: width:100% stretches the columns
   * to span #pivot, and still scrolls horizontally inside .table-wrap when the
   * columns' min-content exceeds it. */
  width: 100%;
}
/* Detail pane open → let the matrix size to its columns (natural width) and scroll
 * inside the narrowed #pivot, rather than cramming columns into the leftover space. */
.pivot-wrap:has(.pivot-drawer:not([hidden])) table.pivot { width: auto; }

table.pivot th,
table.pivot td {
  border: 1px solid var(--border);
  padding: 0.4rem 0.6rem;
  vertical-align: top;
}

/* Header cells */
table.pivot thead th {
  background: var(--bg-elev-2);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  text-align: center;
  position: sticky;
  top: 0;
  z-index: 2;
}
table.pivot thead .pivot-type {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--primary);
}
table.pivot thead .pivot-col-week,
table.pivot thead .pivot-col-undated { font-weight: 500; color: var(--text-dim); }

/* Clickable (expandable/collapsible) header + row-label cells */
table.pivot .is-toggle,
table.pivot .pivot-row-label[data-row-key] { cursor: pointer; user-select: none; }
table.pivot .is-toggle:hover,
table.pivot .pivot-row-label[data-row-key]:hover { background: rgba(226, 35, 26, 0.08); }

.pivot-toggle {
  display: inline-block;
  width: 0.9em;
  margin-right: 0.25rem;
  color: var(--text-dim);
  font-size: 0.8em;
}
.pivot-warn { color: var(--warning); cursor: help; }

/* Row-label column (sticky left) */
table.pivot .pivot-corner,
table.pivot .pivot-row-label {
  text-align: left;
  position: sticky;
  left: 0;
  background: var(--bg-elev-2);
  white-space: nowrap;
  z-index: 1;
}
table.pivot .pivot-corner {
  z-index: 3;          /* above both sticky thead and sticky row-labels */
  vertical-align: bottom;
}

/* Corner cell hosts the global column-level selector above the row-header label. */
.pivot-level {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}
.pivot-level-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  font-weight: 600;
}
.pivot-level-select {
  font: inherit;
  font-size: 0.82rem;
  color: var(--text);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.2rem 0.4rem;
  cursor: pointer;
}
.pivot-level-select:focus { outline: none; border-color: var(--primary); }
.pivot-corner-label { font-weight: 700; color: var(--text); }

table.pivot tbody .pivot-row-label { background: var(--bg-elev); font-weight: 600; }

/* Count cells */
table.pivot .pivot-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
/* A count > 0 is a clickable drill into the side pane. */
table.pivot .pivot-num.is-clickable {
  cursor: pointer;
  color: var(--primary);
  font-weight: 600;
}
table.pivot .pivot-num.is-clickable:hover { background: rgba(226, 35, 26, 0.1); }

table.pivot tr.pivot-total th,
table.pivot tr.pivot-total td {
  background: var(--bg-elev-2);
  font-weight: 700;
  color: var(--text);
}

/* Crosshair / intersection highlight (driven by pivot.js). The row guide lights the row
 * from the BU label up to the cell, the column guide from the leaf header down to the
 * cell, forming an L that points at the intersection. Hover = transient (xh-*), selected
 * = persistent + stronger (xs-*). Element-qualified (th/td) and placed after the sticky
 * row-label / header / total-row backgrounds so the guide wins on ties. */
table.pivot tr th.pivot-xh-row, table.pivot tr td.pivot-xh-row,
table.pivot tr th.pivot-xh-col, table.pivot tr td.pivot-xh-col { background: rgba(226, 35, 26, 0.05); }
table.pivot tr th.pivot-xh-cell, table.pivot tr td.pivot-xh-cell { background: rgba(226, 35, 26, 0.1); }

table.pivot tr th.pivot-xs-row, table.pivot tr td.pivot-xs-row,
table.pivot tr th.pivot-xs-col, table.pivot tr td.pivot-xs-col { background: rgba(226, 35, 26, 0.08); }
table.pivot tr th.pivot-xs-cell, table.pivot tr td.pivot-xs-cell {
  background: rgba(226, 35, 26, 0.16);
  outline: 2px solid var(--primary);
  outline-offset: -2px;
}

.pivot-empty {
  text-align: center;
  color: var(--text-dim);
  font-style: italic;
  padding: 1.25rem;
}

/* ---------- Record side pane (drawer) ---------- */

/* :not([hidden]) is required: a bare `.pivot-drawer { display: flex }` would
 * override the user-agent `[hidden] { display: none }` (author rules win at equal
 * specificity), so the drawer could never be hidden. Same pattern as .modal-overlay.
 * Inline (in-flow) flex column beside the matrix; sticky so it stays in view while the
 * page scrolls, with its body scrolling internally past max-height. */
.pivot-drawer:not([hidden]) {
  flex: 0 0 380px;
  align-self: flex-start;
  position: sticky;
  top: calc(var(--app-header-height) + 1rem);
  max-height: calc(100vh - var(--app-header-height) - 2rem);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;   /* clip the head's background to the rounded corners */
  box-shadow: 0 4px 16px rgba(28, 37, 65, 0.1);
  display: flex;
  flex-direction: column;
}

.pivot-drawer-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-elev-2);
}
.pivot-drawer-title { font-weight: 700; color: var(--text); font-size: 1rem; }
.pivot-drawer-sub { color: var(--text-dim); font-size: 0.82rem; margin-top: 0.15rem; }

.pivot-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.pivot-drawer-empty { color: var(--text-dim); font-style: italic; }

/* One record per card */
.pivot-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.7rem 0.85rem;
  background: var(--bg);
}
.pivot-card-head {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--primary);
  margin-bottom: 0.4rem;
}

/* Formatted record object (key/value list), used inside each card */
.pivot-detail-object {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  white-space: normal;
}
.pdo-line { display: flex; gap: 0.75rem; justify-content: space-between; }
.pdo-k { color: var(--text-dim); font-size: 0.78rem; }
.pdo-v { color: var(--text); font-size: 0.8rem; font-weight: 500; text-align: right; word-break: break-word; }

/* ---------- Profit Centers: records table ---------- */

/* Capped-height scroll container — the IntersectionObserver sentinel lives at
 * the bottom and triggers render-on-scroll as it nears the viewport. */
.pc-scroll {
  max-height: calc(100vh - var(--app-header-height) - 220px);
  min-height: 240px;
  overflow: auto;
  position: relative;
}

table.records-table {
  border-collapse: collapse;
  font-size: 0.85rem;
  background: var(--bg-elev);
  /* fixed layout makes the <colgroup> widths authoritative — required for resizing.
   * The explicit total width is set in JS (= sum of column widths) so each column is
   * exactly its col width and cell values truncate; the container scrolls horizontally. */
  table-layout: fixed;
}

table.records-table th,
table.records-table td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

table.records-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg-elev-2);
  font-weight: 600;
  color: var(--text);
}

/* pc-sortable needs relative positioning for the resize handle; sticky on the
 * header row is applied above. */
th.pc-sortable { cursor: pointer; user-select: none; }

/* Drag-to-resize handle on the right edge of each header cell (reuses .col-resizer
 * base rules defined for the hierarchy table). */
table.records-table .col-resizer {
  position: absolute;
  top: 0;
  right: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
  z-index: 3;
}
table.records-table .col-resizer:hover { background: var(--primary); opacity: 0.4; }
th.pc-sortable:hover { background: rgba(226, 35, 26, 0.08); }
.pc-sort { color: var(--primary); font-size: 0.85em; }

/* Maps icon on the MapBox-geocoded address column headers (left of the label). */
.pc-col-icon { color: var(--primary); margin-right: 0.3rem; }
.pc-col-icon svg { width: 14px; height: 14px; vertical-align: -2px; }

/* Per-column filter row (second sticky header row, toggled by the Filters button) */
tr.pc-filter-row th {
  top: 2.1rem;                 /* sits just under the header-label row */
  background: var(--bg-elev);
  padding: 0.3rem 0.5rem;
  vertical-align: top;
}
/* Stacked operator select + value input so it fits a narrow column. */
.pc-filter-cell {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.pc-filter-op {
  font: inherit;
  font-size: 0.75rem;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.15rem 0.3rem;
  cursor: pointer;
}
.pc-filter-op:focus { outline: none; border-color: var(--primary); }
.pc-col-filter {
  width: 100%;
  min-width: 0;                /* let the filter input shrink with a narrowed column */
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 4px;
  padding: 0.25rem 0.45rem;
  font: inherit;
  font-size: 0.8rem;
}
.pc-col-filter:focus { outline: none; border-color: var(--primary); }

table.records-table tbody tr:hover td { background: rgba(226, 35, 26, 0.05); }

.pc-state {
  margin: 0;
  padding: 1rem 0.75rem;
  color: var(--text-dim);
  font-size: 0.9rem;
  font-style: italic;
}
#pc-sentinel { height: 1px; }

/* ---------- Business Units: card grid ----------
 * One card per business unit; inside, people grouped under each role as "Name (email)". */

.bu-cards {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

/* Each BU is an always-open card; only its Complaints/Damages/Safety items collapse. */
.bu-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.bu-card-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.85rem;
  background: var(--bg-elev-2);
  border-bottom: 1px solid var(--border);
}
.bu-card-name {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bu-chip {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.02rem 0.45rem;
  font-size: 0.72rem;
  color: var(--text-dim);
  white-space: nowrap;
}
.bu-chip b { color: var(--text); font-weight: 600; }

/* Collapsible source item (Roles / Complaints / Damages / Safety). */
.bu-srcd { border-top: 1px solid var(--border); }
.bu-card-body > .bu-srcd:first-child { border-top: 0; }
.bu-srcd-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3rem 0.5rem;
  padding: 0.5rem 0;
  cursor: pointer;
  list-style: none;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text);
}
.bu-srcd-head::-webkit-details-marker { display: none; }
.bu-srcd-head:hover .bu-srcd-title { color: var(--primary); }
.bu-caret {
  flex: none;
  width: 0; height: 0;
  border-left: 5px solid var(--text-dim);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.15s ease;
}
details.bu-srcd[open] > .bu-srcd-head .bu-caret { transform: rotate(90deg); }
.bu-srcd-body { padding-bottom: 0.5rem; }

.bu-count {
  flex: none;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.02rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-dim);
}

/* Expandable body: stacked source blocks (Roles, Complaints, Damages, Safety). */
.bu-card-body { padding: 0.6rem 0.85rem 0.85rem; }

.bu-src { padding: 0.5rem 0; }
.bu-src + .bu-src { border-top: 1px solid var(--border); }
.bu-src-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3rem 0.5rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.45rem;
}
.bu-subsrc { margin-top: 0.55rem; }
.bu-subsrc-head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 0.3rem;
}

/* The four roles laid out as columns within the Roles block. */
.bu-roles-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.85rem 1.25rem;
}
@media (max-width: 900px) { .bu-roles-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .bu-roles-grid { grid-template-columns: 1fr; } }

/* Embedded record list (Complaints / Damages / Safety rows). */
.bu-table-wrap { max-height: 22rem; overflow: auto; }
table.bu-table {
  border-collapse: collapse;
  font-size: 0.8rem;
  background: var(--bg-elev);
  width: auto;
}
table.bu-table th, table.bu-table td {
  border: 1px solid var(--border);
  padding: 0.3rem 0.5rem;
  text-align: left;
  white-space: nowrap;
  vertical-align: top;
}
table.bu-table thead th {
  position: sticky;
  top: 0;
  background: var(--bg-elev-2);
  font-weight: 600;
  z-index: 1;
}

.bu-role-block { min-width: 0; }
.bu-role-title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  margin-bottom: 0.25rem;
}
.bu-role-title .bu-count { text-transform: none; letter-spacing: 0; }

.bu-role-title {
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.2rem;
}

.bu-people { list-style: none; margin: 0; padding: 0; }
.bu-people li {
  font-size: 0.85rem;
  color: var(--text);
  padding: 0.12rem 0;
  line-height: 1.35;
}
.bu-person-email { color: var(--text-dim); }
.bu-empty { margin: 0.12rem 0; color: var(--text-dim); font-size: 0.85rem; }

/* ---- Data View tree (window.QBViews.treeHtml): parent → sub-sections → table ----
   Shared by the query builder (query-builder.html) and the read-only dashboard
   (custom-view.html). Nested <details> with the default marker hidden + our own caret. */
.qb-tree { display: flex; flex-direction: column; }
.qb-tree-node { border-radius: 6px; }
.qb-tree-node > summary { list-style: none; cursor: pointer; }
.qb-tree-node > summary::-webkit-details-marker { display: none; }
.qb-tree-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.3rem;
  border-bottom: 1px solid var(--border); }
.qb-tree-node[open] > summary > .qb-tree-row { border-bottom-color: transparent; }
.qb-tree-caret { width: 16px; flex-shrink: 0; display: inline-flex; justify-content: center;
  color: var(--text-dim); transition: transform 0.12s ease; }
.qb-tree-node[open] > summary .qb-tree-caret { transform: rotate(90deg); }
.qb-tree-label { flex: 1; min-width: 0; font-size: 0.88rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qb-tree-count { font-size: 0.78rem; font-weight: 700; color: var(--text-dim);
  background: var(--bg-elev-2); border-radius: 999px; padding: 0.02rem 0.45rem; }
/* Children/tables indent under the row, with a guide line. */
.qb-tree-body { margin-left: 0.8rem; padding-left: 0.6rem; border-left: 2px solid var(--border); }
.qb-tree-body .table-wrap { margin: 0.4rem 0; }
