/* ─── Modern UI polish — applied to every renderPage()-served page ─────────
 *
 * Targets the common class names already in use across the app:
 *   .topbar / .brand / .nav-tab           — top navigation
 *   .it-subnav / .it-sub-tab              — IT sub-nav strip
 *   .card / .sum-card / .mini-card /      — KPI / summary cards
 *   .res-card / .eng-stat /
 *   .hd-chart-card                         — chart panels on dashboards
 *   .btn / .btn-ghost / .icon-btn /        — buttons
 *   .qa-btn / .preset / .preset-btn
 *   .status-badge / .status-pill /
 *   .alert-count / .it-sub-badge           — badges
 *   .modal-overlay / .modal                — modals
 *
 * Goals: subtle depth (gradients + soft shadows), refined hover/active
 * states, smoother transitions, animated badges. Accessibility kept (focus
 * outlines preserved, color contrast maintained).
 *
 * Light + dark themes both supported via the existing CSS variables. Uses
 * rgba() over color-mix() for broader browser compatibility.
 */

/* ── Topbar polish ───────────────────────────────────────────────────────── */
/* ===== Design-system foundation (consolidated) ===== */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap');

/* Theme variables — single source of truth. This file loads AFTER each page's
   inline <style>, so these identical values are a no-op on legacy pages but
   let converted pages drop their inline :root. The tenant accent set at
   runtime by nav-init.js still wins (inline style on <html>). */
:root{--bg:#0d1117;--surface:#161b22;--border:#21262d;--text:#c9d1d9;--muted:#8b949e;--accent:#58a6ff;--green:#3fb950;--red:#f85149;--orange:#e3b341;--head:#0d1117}
[data-theme="light"]{--bg:#f6f8fa;--surface:#fff;--border:#d0d7de;--text:#24292f;--muted:#57606a;--accent:#0969da;--green:#1a7f37;--red:#cf222e;--orange:#9a6700;--head:#f6f8fa}

/* Shared components not previously centralised — values match the canonical
   inline copies used across pages (zero-variation per audit). */
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin-bottom:18px}
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:14px 18px}
.kpi .label{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);font-weight:600;margin-bottom:6px}
.kpi .value{font-size:24px;font-weight:700;font-family:'IBM Plex Mono',monospace}
.kpi.bad .value{color:var(--red)}.kpi.warn .value{color:var(--orange)}.kpi.good .value{color:var(--green)}
.pill{display:inline-block;padding:1px 8px;border-radius:10px;font-size:10.5px;border:1px solid var(--border)}
.pill.bad{color:var(--red);border-color:var(--red)}.pill.warn{color:var(--orange);border-color:var(--orange)}.pill.ok{color:var(--green);border-color:var(--green)}
.empty{padding:50px;text-align:center;color:var(--muted)}
.form-grid{display:grid;grid-template-columns:140px 1fr;gap:10px 14px;align-items:center;margin-top:8px}
.form-grid label{font-size:12px;color:var(--muted);text-align:right}
/* Toggle-style modal (the .modal-bg pattern used by ~46 pages). Width is left
   to the page (varies 600–880px) so wider modals aren't shrunk. */
.modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.7);display:none;align-items:center;justify-content:center;z-index:1000;padding:16px}
.modal-bg.on{display:flex}
.modal-card{background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:22px;max-width:100%;max-height:90vh;overflow:auto}
.toast{position:fixed;bottom:16px;right:16px;background:var(--surface);color:var(--text);border:1px solid var(--border);padding:12px 16px;border-radius:6px;box-shadow:0 6px 20px rgba(0,0,0,.35);z-index:10000}

/* ── PAGE-LEVEL BASE STYLES (added 2026-07-02 to fix employees.html stripped
   inline styles). Applies globally, so 74+ pages that stopped defining these
   inline during the UI foundation refactor get consistent baseline styling.
   Later polish rules (line 228+) override background where needed. ────── */
.btn{padding:6px 14px;border:none;border-radius:6px;font-size:12px;cursor:pointer;font-family:inherit;background:var(--accent);color:#fff;line-height:1.4}
.btn-ghost{background:transparent;color:var(--muted);border:1px solid var(--border)}
.btn-danger{background:var(--red);color:#fff}
.btn-sm{padding:3px 10px;font-size:11px}
.btn-primary{background:var(--accent);color:#fff}
input,select,textarea{font:inherit;color:var(--text);background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:7px 10px;box-sizing:border-box}
textarea{min-height:80px}
input[type="checkbox"],input[type="radio"]{width:auto;padding:0;background:transparent}
input[type="file"]{padding:4px 6px;background:var(--surface);font-size:11px}
button{cursor:pointer;font-family:inherit;font-size:12px}
label{color:var(--text);font-size:12px}
.search-input{background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-family:inherit;font-size:12px}
select.filter,.filter{background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-family:inherit;font-size:12px;cursor:pointer}
.form-group{margin-bottom:10px;display:flex;flex-direction:column;gap:4px}
.form-group label{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.4px;font-weight:600}
.controls{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:12px}

/* ── Tables: full-width by default (canonical from admin-announcements et al) ─── */
table{width:100%;border-collapse:collapse;font-size:12.5px}
td{padding:8px 12px;border-bottom:1px solid var(--border);vertical-align:middle}
tbody tr:hover{background:rgba(88,166,255,.04)}

/* ── Search input + filter dropdowns should be natural-width, not 100% ────── */
.controls .search-input{min-width:280px;flex:1;max-width:400px}
.controls .filter,.controls select.filter{min-width:140px;width:auto}



/* Responsive / mobile — applies to EVERY page (this file overrides inline),
   so dense tables get horizontal scroll, KPIs go 2-up, modals near full-width,
   and touch targets grow. Fixes the field-staff phone experience globally. */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
@media (max-width:760px){
  .section{padding:12px 10px}
  .card table, .section > table, .table-wrap > table{display:block;overflow-x:auto;white-space:nowrap}
  .kpi-grid{grid-template-columns:1fr 1fr !important}
  .btn, .icon-btn{min-height:36px}
  .modal-card, .modal-overlay .modal, .modal{width:96vw !important;max-width:96vw}
  .filters{flex-wrap:wrap}
}

/* ── Topbar polish ── */
.topbar {
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 130%);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 0 6px 14px -10px rgba(0, 0, 0, 0.18);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Force single-row flex layout. !important on every property because
     some pre-existing pages have their own .topbar block whose CSS is
     loaded AFTER this file in the cascade (per-page <style> blocks come
     after the auto-injected <link>). Without !important the per-page
     block wins source-order, but it doesn't set flex-wrap, so the
     default browser flex behavior allows wrapping on overflow. */
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap !important;
  align-items: center !important;
  gap: 12px;
  /* Internal horizontal scroll keeps the document body from getting a
     scrollbar. We hide the visible scrollbar UI below — content stays
     reachable by mouse-wheel/swipe but no ugly grey strip appears under
     the topbar. */
  overflow-x: auto;
  overflow-y: visible;
}
/* Hide the horizontal-scroll affordance entirely — when the topbar
   overflows we let it overflow silently rather than show a permanent
   scrollbar strip (which was creating a visible dark bar under the
   topbar even when content fit). Children stay reachable via the
   :focus scroll behavior or arrow-key tabbing. */
.topbar { scrollbar-width: none; }
.topbar::-webkit-scrollbar { display: none; }
.brand {
  letter-spacing: -0.3px;
  text-shadow: 0 0 14px rgba(88, 166, 255, 0.18);
  transition: filter 0.2s ease;
}
.brand:hover { filter: brightness(1.15); }

/* Nav icons — small visual anchors before each label */
.nav-icon {
  display: inline-block;
  margin-right: 6px;
  font-size: 0.95em;
  opacity: 0.7;
  transition: opacity 0.15s ease, transform 0.15s ease;
  vertical-align: middle;
}
.nav-tab:hover .nav-icon,
.nav-tab.active .nav-icon,
.it-sub-tab:hover .nav-icon,
.it-sub-tab.active .nav-icon {
  opacity: 1;
  transform: scale(1.05);
}

/* Nav tabs — animated underline + better hover */
.nav-tab {
  position: relative;
  transition: color 0.15s ease;
}
.nav-tab::after {
  content: '';
  position: absolute;
  bottom: 0; left: 50%; right: 50%;
  height: 2px;
  background: var(--accent);
  transition: left 0.2s ease, right 0.2s ease, opacity 0.2s ease;
  opacity: 0;
}
.nav-tab:hover::after,
.nav-tab.active::after { left: 8px; right: 8px; opacity: 1; }
.nav-tab:hover { color: var(--text); }

/* ── IT sub-nav ──────────────────────────────────────────────────────────── */
.it-subnav {
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%) !important;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 4px 10px -8px rgba(0, 0, 0, 0.18);
}
.it-subnav .it-sub-tab {
  position: relative;
  transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
.it-subnav .it-sub-tab:hover { transform: translateY(-1px); }

/* ── Badges — subtle pulse so the eye catches new alerts ─────────────────── */
.alert-count,
.it-sub-badge,
#helpdesk-badge {
  background: linear-gradient(135deg, #f85149 0%, #d73a3a 100%) !important;
  box-shadow: 0 0 0 0 rgba(248, 81, 73, 0.55);
  animation: badge-pulse 2.4s ease-in-out infinite;
  font-variant-numeric: tabular-nums;
}
@keyframes badge-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(248, 81, 73, 0.5); }
  50%      { box-shadow: 0 0 0 5px rgba(248, 81, 73, 0); }
}

/* ── Cards — depth + lift on hover ───────────────────────────────────────── */
.card,
.sum-card,
.mini-card,
.res-card,
.eng-stat,
.hd-chart-card {
  position: relative;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.018) 0%, transparent 60%);
}
[data-theme="light"] .card,
[data-theme="light"] .sum-card,
[data-theme="light"] .mini-card,
[data-theme="light"] .res-card,
[data-theme="light"] .eng-stat,
[data-theme="light"] .hd-chart-card {
  background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.012) 0%, transparent 60%);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}

/* Hoverable cards: lift + glow */
.card:hover,
.sum-card-clickable:hover,
.mini-card:hover,
.res-card:hover {
  transform: translateY(-2px);
  border-color: var(--accent) !important;
  box-shadow: 0 8px 18px -8px rgba(88, 166, 255, 0.28),
              0 2px 4px rgba(0, 0, 0, 0.08);
}

/* Cursor for any clickable summary/KPI card. Defined globally so per-page
   CSS doesn't have to repeat it; pages just add the .sum-card-clickable
   class (or use <a class="card">) to opt-in. */
.sum-card-clickable, a.card, a.res-card { cursor: pointer; }

/* Cards with semantic color — get a tinted top accent strip */
.card.green   { box-shadow: inset 3px 0 0 rgba(63, 185, 80, 0.65); }
.card.red     { box-shadow: inset 3px 0 0 rgba(248, 81, 73, 0.7); }
.card.orange  { box-shadow: inset 3px 0 0 rgba(227, 179, 65, 0.7); }
.card.muted   { box-shadow: inset 3px 0 0 rgba(139, 148, 158, 0.45); }
.mini-card.green   { box-shadow: inset 3px 0 0 rgba(63, 185, 80, 0.65); }
.mini-card.red     { box-shadow: inset 3px 0 0 rgba(248, 81, 73, 0.7); }
.mini-card.orange  { box-shadow: inset 3px 0 0 rgba(227, 179, 65, 0.7); }
.mini-card.muted   { box-shadow: inset 3px 0 0 rgba(139, 148, 158, 0.45); }
.eng-stat.green    { box-shadow: inset 3px 0 0 rgba(63, 185, 80, 0.65); }
.eng-stat.red      { box-shadow: inset 3px 0 0 rgba(248, 81, 73, 0.7); }
.eng-stat.orange   { box-shadow: inset 3px 0 0 rgba(227, 179, 65, 0.7); }

.card .num,
.sum-num,
.mini-card .num,
.res-total,
.eng-stat .num {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.5px;
  font-feature-settings: 'tnum' 1;
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  background: linear-gradient(135deg, var(--accent) 0%, #4690d8 100%);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1),
              inset 0 1px 0 rgba(255, 255, 255, 0.15);
  transition: transform 0.1s ease, box-shadow 0.18s ease, opacity 0.15s ease;
  font-weight: 600;
}
.btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 6px 14px -4px rgba(88, 166, 255, 0.4),
              inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-ghost {
  background: transparent !important;
  box-shadow: none;
  font-weight: 500;
}
.btn-ghost:hover:not(:disabled) {
  background: rgba(88, 166, 255, 0.1) !important;
  border-color: var(--accent);
  color: var(--text);
  transform: none;
}

.btn-danger {
  background: linear-gradient(135deg, #f85149 0%, #c43b35 100%);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
.btn-danger:hover:not(:disabled) {
  box-shadow: 0 6px 14px -4px rgba(248, 81, 73, 0.45);
}
.btn-green {
  background: linear-gradient(135deg, #3fb950 0%, #2e8e3a 100%);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.btn-green:hover:not(:disabled) {
  box-shadow: 0 6px 14px -4px rgba(63, 185, 80, 0.4);
}

.icon-btn {
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.icon-btn:hover:not(:disabled) {
  background: rgba(88, 166, 255, 0.07);
  border-color: var(--accent);
  color: var(--text);
}

/* ── Filter chips / preset buttons ───────────────────────────────────────── */
.qa-btn,
.preset,
.preset-btn {
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.qa-btn.active,
.preset.active,
.preset-btn.active {
  background: linear-gradient(135deg, var(--accent) 0%, #4690d8 100%) !important;
  border-color: var(--accent) !important;
  color: #fff !important;
  box-shadow: 0 2px 6px -2px rgba(88, 166, 255, 0.45);
}

.filter-row label.on {
  background: linear-gradient(135deg, rgba(88, 166, 255, 0.18) 0%, rgba(88, 166, 255, 0.08) 100%) !important;
  border-color: var(--accent) !important;
  color: var(--text) !important;
  font-weight: 600;
}

/* ── Status / priority pills — subtle gradient ───────────────────────────── */
.status-badge,
.status-pill,
.sla-pill,
.spec-pill,
.role-pill,
.action-pill {
  font-feature-settings: 'tnum' 1;
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, transparent 100%);
  letter-spacing: 0.5px;
}

/* ── Tables ──────────────────────────────────────────────────────────────── */
thead th {
  background-image: linear-gradient(180deg, var(--head) 0%, var(--bg) 110%) !important;
  color: var(--text) !important;                   /* explicit — dark theme readable */
  font-weight: 700 !important;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  white-space: nowrap;
}
tbody tr {
  transition: background 0.1s ease;
}

/* Sticky-thead bug guard — when a list page contains its table in a
   scrollable wrap (overflow:auto / overflow-y:auto), the sticky thead
   must pin to the wrap's top edge (top:0), NOT to the page topbar
   height. Pages that incorrectly set top:44px would overlap with the
   IT sub-nav. Forcing top:0 here is safe because: (a) thead sticky is
   relative to its scrolling ancestor, so 0 means "top of wrap"; (b)
   pages that DO scroll the page (no inner wrap) have non-sticky thead
   anyway. */
[class*="-wrap"] > table > thead > tr > th[style*="sticky"],
[class*="-wrap"] > table thead th {
  /* No-op; the actual top: enforcement lives on the per-page selectors
     where applicable. This block kept as a hook for future defense. */
}

/* ── Modals — .modal-overlay + itShared.openModal('.show') pattern ─────── */
/* Positioning + hide/show. Without these, the div renders inline in the
   document flow (see 2026-07-02 employees.html bug — modal docked at
   bottom of page). itShared.openModal adds .show; itShared.closeModal
   removes it. */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  background: rgba(0, 0, 0, 0.6);
  overflow-y: auto;
}
.modal-overlay.show { display: flex; }
.modal-overlay .modal {
  background: var(--surface, #161b22) !important;
  color: var(--text, #c9d1d9) !important;
  border: 1px solid var(--border, #21262d);
  border-radius: 8px;
  padding: 20px;
  max-width: 640px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
}
/* Form elements inside modals inherit browser defaults (white/black) unless
   we style them. Match the dark theme + border. */
.modal-overlay .modal h1,
.modal-overlay .modal h2,
.modal-overlay .modal h3,
.modal-overlay .modal h4,
.modal-overlay .modal label,
.modal-overlay .modal p,
.modal-overlay .modal span,
.modal-overlay .modal div {
  color: var(--text, #c9d1d9);
}
.modal-overlay .modal input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="reset"]),
.modal-overlay .modal select,
.modal-overlay .modal textarea {
  background: var(--bg, #0d1117) !important;
  color: var(--text, #c9d1d9) !important;
  border: 1px solid var(--border, #21262d) !important;
  border-radius: 4px;
  padding: 6px 10px;
  font-family: inherit;
  font-size: 13px;
  width: 100%;
  box-sizing: border-box;
  margin: 3px 0 8px;
}
.modal-overlay .modal input[type="file"] {
  color: var(--text, #c9d1d9);
  font-size: 12px;
}
.modal-overlay .modal label {
  display: block;
  font-size: 12px;
  color: var(--muted, #8b949e);
  margin-top: 6px;
  font-weight: 500;
}
/* ── Sticky header + action bar inside modals ────────────────────────────
   Keeps Cancel/Save always visible without scrolling on tall forms
   (employees, tenants, branches, etc). Also stickies the h3 title so
   the operator knows what modal they're in while scrolling. Negative
   margins let the sticky bars bleed to the modal edges cleanly. */
.modal-overlay .modal h1,
.modal-overlay .modal h2,
.modal-overlay .modal h3 {
  position: sticky;
  top: -20px;                     /* offset for modal padding */
  z-index: 5;
  background: var(--surface, #161b22);
  margin: -20px -20px 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border, #21262d);
  font-size: 15px;
}
.modal-overlay .modal .form-actions,
.modal-overlay .modal .modal-actions,
.modal-overlay .modal .modal-footer {
  position: sticky;
  bottom: -20px;                  /* offset for modal padding */
  z-index: 5;
  background: var(--surface, #161b22);
  margin: 12px -20px -20px;
  padding: 12px 20px;
  border-top: 1px solid var(--border, #21262d);
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  flex-wrap: wrap;
}
.modal {
  box-shadow: 0 20px 50px -10px rgba(0, 0, 0, 0.5),
              0 0 0 1px rgba(255, 255, 255, 0.04) inset;
}

/* ── Inputs / selects — focus glow ───────────────────────────────────────── */
input:focus, select:focus, textarea:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.15);
}

/* ── Sub-nav badge animation ─────────────────────────────────────────────── */
.it-sub-badge {
  animation: badge-pulse 2.4s ease-in-out infinite;
}

/* Reduce motion preference — respect it */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    transition-duration: 0.001s !important;
  }
}

/* ── Mobile + tablet responsiveness pass ─────────────────────────────────
 * Touch-friendly tap targets, single-column page layouts on narrow viewports,
 * tables → cards stacked, modals full-width. Targets phones (<= 640px)
 * with a softer tablet break at <= 980px.
 * --------------------------------------------------------------------- */

@media (max-width: 980px) {
  /* Topbar — keep nav clickable but compress padding. */
  .topbar { gap: 8px !important; padding: 0 10px !important; }
  .nav-tab { padding: 12px 5px !important; font-size: 11px !important; }
  .it-subnav { overflow-x: auto !important; padding: 0 8px !important; gap: 4px !important; }
  .it-sub-tab { padding: 6px 8px !important; font-size: 11px !important; }
  /* Page wrappers stop demanding 24px side padding. */
  .wrap, .page-wrap { padding: 12px 10px !important; }
  /* Stat strips become single-column-friendly. */
  .kpis, .stat-grid { grid-template-columns: repeat(2, 1fr) !important; }
}

@media (max-width: 640px) {
  body { font-size: 12px; }
  /* Big enough buttons for touch. */
  .btn { padding: 8px 12px !important; min-height: 36px; }
  .btn-sm { padding: 6px 10px !important; min-height: 30px; }
  /* Section heads stack their action row below the heading. */
  .section-head { flex-direction: column !important; align-items: flex-start !important; }
  .section-head .actions { width: 100%; display: flex; flex-wrap: wrap; gap: 6px; }
  /* Stat KPIs stack 1-per-row for max readability. */
  .kpis { grid-template-columns: 1fr !important; gap: 6px !important; }
  /* Modals: full viewport on phones, no surrounding padding. */
  .modal-backdrop, .modal-bg { padding: 0 !important; }
  .modal { max-width: 100% !important; max-height: 100vh !important; border-radius: 0 !important; }
  /* Drawer becomes full width. */
  .drawer { width: 100% !important; min-width: 100% !important; }
  /* Wide HTML tables — let them scroll horizontally instead of breaking layout. */
  table.dh, table.ssid-table, table.log, table { display: block; overflow-x: auto; white-space: nowrap; }
  /* Inputs / selects fill the width by default. */
  input[type="text"], input[type="number"], input[type="email"], input[type="password"], select, textarea {
    width: 100%; box-sizing: border-box;
  }
  /* Topbar brand label can shrink. */
  .brand { font-size: 12px !important; }
  /* Sub-nav badges visible but tighter. */
  .nav-icon { display: none; }
  /* Card grids → one column. */
  .ap-grid, .grid, .ctl-card { grid-template-columns: 1fr !important; }
  .ctl-card { flex-direction: column !important; align-items: stretch !important; }
}

/* Always-on tweaks (any viewport) */
.btn, .nav-tab, .chip { touch-action: manipulation; }   /* avoid double-tap zoom on iOS */

/* ══════════════════════════════════════════════════════════════════════════
 * Polish layer (added 2026-07-06) — visual upgrades that cascade to every
 * page importing this stylesheet, without needing per-page edits. All rules
 * use progressive enhancement (pseudo-elements, hover, gradients) so pages
 * that already customized these classes keep their look; pages that didn't
 * inherit a subtle lift, top-stripe, and gradient pill treatment.
 * ══════════════════════════════════════════════════════════════════════════ */

/* KPI cards — accent top-stripe + hover-lift.
   ::before is a scoped enhancement — no existing page uses it. */
body .kpi{position:relative;overflow:hidden;transition:transform .12s ease,box-shadow .12s ease}
body .kpi::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--kpi-color,var(--accent));opacity:.85;pointer-events:none}
body .kpi.good::before,body .kpi.up::before{background:var(--green)}
body .kpi.warn::before{background:var(--orange)}
body .kpi.bad::before,body .kpi.down::before{background:var(--red)}
body .kpi.info::before{background:var(--accent)}
body .kpi.total::before,body .kpi.count::before{background:#a371f7}
body .kpi:hover{transform:translateY(-1px);box-shadow:0 4px 12px rgba(0,0,0,.15)}

/* Cards — gentle shadow-lift on hover */
body .card{transition:box-shadow .12s ease,border-color .12s ease}
body .card:hover{box-shadow:0 4px 12px rgba(0,0,0,.1)}

/* Gradient pills — upgrade existing status classes.
   Uses text-shadow so the white text stays legible on the darker gradient. */
body .pill.ok,body .pill.up,body .pill.on{background:linear-gradient(180deg,#3fb950,#238636);color:#fff;border-color:#238636;font-weight:600;text-shadow:0 1px 0 rgba(0,0,0,.15)}
body .pill.bad,body .pill.down,body .pill.crit{background:linear-gradient(180deg,#f85149,#c02c26);color:#fff;border-color:#c02c26;font-weight:600;text-shadow:0 1px 0 rgba(0,0,0,.15)}
body .pill.warn{background:linear-gradient(180deg,#f2cc60,#d4a72c);color:#0d1117;border-color:#bf8700;font-weight:600}

/* Buttons — brighter hover + press-down animation. Doesn't change base look. */
body .btn:not(:disabled):hover{filter:brightness(1.1)}
body .btn:not(:disabled):active{transform:translateY(1px)}
body .btn:disabled{opacity:.45;cursor:not-allowed}
body .btn-ghost:not(:disabled):hover{background:var(--bg);border-color:var(--accent);color:var(--accent);filter:none}

/* Primary button — replace the flat accent background with a subtle gradient
   AND keep the same colour intent so existing pages don't feel different. */
body .btn-primary{background:linear-gradient(180deg,#4692ff 0%,#2f7dee 60%,#1e6bd6 100%);border:1px solid #1e6bd6;box-shadow:0 1px 2px rgba(0,0,0,.15),inset 0 1px 0 rgba(255,255,255,.15);font-weight:600;color:#fff}
body .btn-primary:not(:disabled):hover{background:linear-gradient(180deg,#5aa0ff 0%,#3d89f5 60%,#2679df 100%);box-shadow:0 2px 8px rgba(56,139,253,.4);filter:none}

/* Danger button — same gradient treatment */
body .btn-danger{background:linear-gradient(180deg,#f85149 0%,#c02c26 100%);border:1px solid #c02c26;box-shadow:0 1px 2px rgba(0,0,0,.15),inset 0 1px 0 rgba(255,255,255,.15);font-weight:600;color:#fff}
body .btn-danger:not(:disabled):hover{background:linear-gradient(180deg,#ff6259 0%,#d13530 100%);box-shadow:0 2px 6px rgba(248,81,73,.35);filter:none}

/* Tables — row hover accent + first/last row rounding */
body table tbody tr{transition:background .1s}
body table tbody tr:hover td{background:rgba(88,166,255,.06)}

/* Sticky topbar drop-shadow when scrolled — subtle depth cue */
body .topbar{box-shadow:0 1px 3px rgba(0,0,0,.08)}

/* Focus rings — accessible + consistent across inputs and selects */
body input:focus-visible,body select:focus-visible,body textarea:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(56,139,253,.15)}

/* ── Global skeleton loading (2026-07-06) ─────────────────────────────
 * Pages that fetch async data can show a skeleton while the network
 * round-trip is in flight — cheaper than a full-page spinner and hints
 * at the shape of what's coming. Two building blocks:
 *
 *   .skeleton              — a single shimmering placeholder block.
 *                            Set width/height via inline style or a
 *                            utility class. Uses the CSS variables so
 *                            it works in light AND dark themes.
 *   .skeleton-table > tr   — full skeleton row for tabular loading.
 *                            Drop N of these into a <tbody> and remove
 *                            them once real rows arrive.
 *
 * The shimmer respects prefers-reduced-motion — users with that
 * setting see a static bar instead of a moving gradient.
 */
@keyframes it-skeleton-shimmer {
  0%   { background-position: -400px 0; }
  100% { background-position: 400px 0; }
}
.skeleton {
  display: inline-block;
  background: linear-gradient(90deg,
    rgba(255,255,255,0.04) 0%,
    rgba(255,255,255,0.10) 50%,
    rgba(255,255,255,0.04) 100%);
  background-size: 800px 100%;
  animation: it-skeleton-shimmer 1.6s linear infinite;
  border-radius: 4px;
  min-height: 12px;
  min-width: 40px;
  color: transparent !important;
  user-select: none;
  pointer-events: none;
}
.skeleton.skeleton-line { display: block; height: 12px; margin: 6px 0; }
.skeleton.skeleton-title { height: 18px; width: 40%; margin-bottom: 10px; }
.skeleton.skeleton-avatar { width: 32px; height: 32px; border-radius: 50%; }
.skeleton.skeleton-block { display: block; width: 100%; height: 80px; }
.skeleton-table td { padding: 8px 12px; }
.skeleton-table td .skeleton { display: block; height: 12px; width: 90%; }
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; background: rgba(255,255,255,0.06); }
}

