/* =============================================================
   AdminKit · catchy + minimal
   Loaded after bootstrap.min.css on every page.
   ============================================================= */

/* ------------------------------------------------------------- */
/* 0. Fonts · Inter (18pt optical-size — designed for UI text)   */
/*    8 TTF files in public/fonts/inter/ wired below — Regular   */
/*    / Medium / SemiBold / Bold with matching italics.          */
/* ------------------------------------------------------------- */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-Regular.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-Italic.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-Medium.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-MediumItalic.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-SemiBold.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-SemiBoldItalic.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-Bold.ttf') format('truetype');
}
@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/inter/Inter_18pt-BoldItalic.ttf') format('truetype');
}

/* ------------------------------------------------------------- */
/* 1. Tokens                                                     */
/* ------------------------------------------------------------- */
:root {
  --brand: #4f46e5;
  --brand-2: #7c3aed;
  --brand-soft: rgba(79, 70, 229, .12);
  --brand-ring: rgba(79, 70, 229, .18);
  --brand-press: #4338ca;

  --bg: #f6f7fb;
  --surface: #ffffff;
  --surface-alt: #fafbfc;
  --text: #0f172a;
  --muted: #64748b;
  --muted-soft: #94a3b8;

  --border: #e2e8f0;
  --border-soft: #f1f5f9;
  --hover-row: #f8fafc;

  --sidebar-bg: #0f172a;
  --sidebar-fg: #cbd5e1;

  --code-bg: #0f172a;
  --code-fg: #e2e8f0;

  --radius: .55rem;
  --radius-lg: .9rem;

  --ease: cubic-bezier(.4, 0, .2, 1);
  --t-fast: .12s;
  --t-base: .18s;

  --ring: 0 0 0 3px var(--brand-ring);
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, .04);
  --shadow: 0 4px 14px rgba(15, 23, 42, .06);
  --shadow-lg: 0 20px 50px rgba(15, 23, 42, .12);

  --bs-font-sans-serif: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', Arial, sans-serif;
  --bs-font-monospace: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --bs-body-font-family: var(--bs-font-sans-serif);
}

/* ------------------------------------------------------------- */
/* 2. Base                                                       */
/* ------------------------------------------------------------- */
* { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
html, body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', Arial, sans-serif;
  font-feature-settings: 'ss01', 'ss02', 'ss03', 'kern';
  text-rendering: optimizeLegibility;
  letter-spacing: -.005em;
}
body {
  background: var(--bg);
  color: var(--text);
}

a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-press); }
code { color: inherit; background: transparent; padding: 0; font-size: .9em; }

::selection { background: var(--brand-soft); color: var(--text); }

/* Focus ring (uniform) */
*:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }
.top-nav *:focus-visible { outline-color: #fff; }
.btn:focus-visible { outline: 0; box-shadow: var(--ring); }

/* Skip link */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 8px;
  background: var(--brand);
  color: #fff;
  padding: .5rem 1rem;
  border-radius: var(--radius);
  z-index: 9999;
  font-weight: 600;
}
.skip-link:focus { left: 8px; outline: 2px solid #fff; outline-offset: 2px; color: #fff; }

/* ------------------------------------------------------------- */
/* 3. Layout · top navbar                                        */
/* ------------------------------------------------------------- */
.top-nav {
  background: var(--sidebar-bg);
  box-shadow: 0 1px 0 rgba(15, 23, 42, .06);
  padding: .55rem 1rem;
}
.top-nav .navbar-brand {
  color: #fff;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -.01em;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}
.top-nav .navbar-brand:hover,
.top-nav .navbar-brand:focus { color: #fff; }

/* Breathing room between top-level nav items (Dashboard / Apps / Bugs /     */
/* Admin / user-chip). Bootstrap's .navbar-nav has 0 gap by default, so     */
/* the menus run flush against each other and look cramped on desktop.     */
@media (min-width: 992px) {
  .top-nav .navbar-nav { gap: 1.75rem; }
  .top-nav .nav-item   { padding: .35rem 0; }
}
@media (max-width: 991.98px) {
  /* Collapsed (mobile) — vertical stack, smaller gap is enough.           */
  .top-nav .navbar-nav { gap: .5rem; }
  .top-nav .nav-item   { padding: .3rem 0; }
}

.top-nav .nav-link {
  color: var(--sidebar-fg);
  border-radius: var(--radius);
  padding: .55rem 1.25rem;
  font-size: .9rem;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.top-nav .nav-link i { font-size: 0.9rem; opacity: 1; line-height: 1; }
.top-nav .nav-link:hover,
.top-nav .nav-link:focus { background: rgba(255, 255, 255, .06); color: #fff; }
.top-nav .nav-link:hover i { opacity: 1; }
/* Active menu — only the text colour changes (white instead of muted grey).
   No background pill, no glow shadow. Slight font-weight bump keeps the
   active item readable without the box treatment. */
.top-nav .nav-link.active {
  background: transparent;
  color: #fff;
  font-weight: 600;
  box-shadow: none;
}
.top-nav .nav-link.active i { opacity: 1; }

.top-nav .dropdown-menu {
  border: 0;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: .35rem;
  min-width: 14rem;
  margin-top: .35rem;
}
.top-nav .dropdown-item {
  border-radius: calc(var(--radius) - 2px);
  padding: .5rem .7rem;
  font-size: .9rem;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
}
.top-nav .dropdown-item i { color: var(--muted); width: 1rem; text-align: center; }
.top-nav .dropdown-item:hover,
.top-nav .dropdown-item:focus { background: var(--brand-soft); color: var(--brand-press); }
.top-nav .dropdown-item:hover i,
.top-nav .dropdown-item:focus i { color: var(--brand-press); }
.top-nav .dropdown-item.active,
.top-nav .dropdown-item:active { background: transparent; color: var(--text); font-weight: 600; }

.top-nav .navbar-toggler {
  padding: .35rem .55rem;
  border: 1px solid rgba(255, 255, 255, .15);
}
.top-nav .navbar-toggler:focus { box-shadow: 0 0 0 .15rem rgba(255, 255, 255, .2); }
.top-nav .navbar-toggler-icon {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23ffffff' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

.top-nav .user-chip { background: rgba(255, 255, 255, .05); }
.top-nav .user-chip .badge { font-size: .65rem; padding: .2em .5em; }

/* Brand logo size tokens — replace inline style="max-height:Npx" in views. */
.brand-logo    { max-height: 28px; width: auto; }
.brand-logo-md { max-height: 36px; width: auto; }

/* Table cell width utilities — used for "label : value" tables on detail pages. */
.col-label      { width: 140px; min-width: 140px; }
.col-label-sm   { width: 5rem;  min-width: 5rem;  }

/* Code/log preview pane — fixed-height scroll box for tail output. */
.log-tail { max-height: 340px; overflow: auto; }

/* Audit/activity "When" column — fixed width to keep timestamps tidy. */
.col-when { width: 7rem; min-width: 7rem; }

.content { padding: 1.5rem; min-height: calc(100vh - 56px - 60px); }

/* ------------------------------------------------------------- */
/* 4. Cards                                                      */
/* ------------------------------------------------------------- */
.card {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: none;
  transition: box-shadow var(--t-base) var(--ease), transform var(--t-base) var(--ease), border-color var(--t-base) var(--ease);
}
.card-header { background: transparent; border-bottom: 1px solid var(--border-soft); padding: .9rem 1.1rem; font-weight: 600; }
.card-footer { background: transparent; border-top: 1px solid var(--border-soft); padding: .9rem 1.1rem; }

/* Dashboard KPI card — coloured-soft background that matches its icon hue. */
/* Hover gives a noticeable lift + colour-matched glow + icon pop.         */
.stat-card {
  display: block;
  height: 100%;
  padding: 1.1rem 1.15rem;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  background: var(--surface);
  position: relative;
  overflow: hidden;
  transition:
    transform .25s var(--ease),
    box-shadow .25s var(--ease),
    border-color .25s var(--ease),
    background-color .25s var(--ease);
}
/* Decorative diagonal sheen on the card — invisible at rest, slides across */
/* on hover. Pure CSS, no JS.                                              */
.stat-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, transparent 30%, rgba(255, 255, 255, .35) 50%, transparent 70%);
  transform: translateX(-100%);
  transition: transform .6s var(--ease);
  pointer-events: none;
}
a.stat-card { color: inherit; text-decoration: none; }
a.stat-card:hover,
a.stat-card:focus-visible {
  transform: translateY(-1px);
  color: inherit;
}
/* Sheen sweep disabled for the minor-hover treatment — too flashy for the  */
/* light-gray look.                                                         */

/* All stat-card variants share a soft light-gray background — calm,       */
/* neutral, so the data does the talking.                                  */
.stat-card-primary,
.stat-card-warning,
.stat-card-danger,
.stat-card-success,
.stat-card-info {
  background: linear-gradient(135deg, #e2e8f0 0%, #f1f5f9 100%);
  border-color: var(--border-soft);
  color: var(--text);
}

/* Stat icon on the light surface — keep the existing solid colour set on  */
/* the <span> via bg-primary / bg-warning utilities; just ensure the glyph */
/* stays readable.                                                         */

/* Hover: minor — barely-there bg shift + small neutral shadow.            */
a.stat-card-primary:hover, a.stat-card-warning:hover,
a.stat-card-danger:hover,  a.stat-card-success:hover,
a.stat-card-info:hover {
  background: linear-gradient(135deg, #cbd5e1 0%, #e2e8f0 100%);
  border-color: var(--border);
  box-shadow: var(--shadow-sm);
  color: var(--text);
}

a.stat-card:active { transform: translateY(0); transition-duration: .08s; }

/* Dark mode — keep the same brand gradient (already reads well on dark).  */
body.dark-mode .stat-card::after {
  background: linear-gradient(120deg, transparent 30%, rgba(255, 255, 255, .08) 50%, transparent 70%);
}

.stat-icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
  position: relative;
  z-index: 1;
}
a.stat-card:hover .stat-icon {
  transform: scale(1.03);
}
.stat-icon-md { width: 40px; height: 40px; }
.stat-icon-sm { width: 36px; height: 36px; font-size: .9rem; }

/* Make sure the number/label text stay above the sliding sheen pseudo-el. */
.stat-card > * { position: relative; z-index: 1; }

/* Status / severity pills on bug rows — slightly smaller than .badge default. */
.badge-status { font-size: .72rem; padding: .3em .6em; }

/* AI-assist side panel — distinguishes itself from regular cards with a   */
/* dashed border and soft surface so users notice it is AI-generated UI.    */
.ai-panel {
  background: var(--surface-alt);
  border: 1px dashed var(--border);
  border-radius: var(--radius-lg);
  padding: 1rem;
}
.ai-btn {
  background: linear-gradient(135deg, var(--brand-2), var(--brand));
  border: 0;
  color: #fff;
  font-weight: 500;
}
.ai-btn:hover,
.ai-btn:focus { color: #fff; opacity: .95; box-shadow: 0 4px 12px rgba(124, 58, 237, .25); }
.ai-btn:active { color: #fff; opacity: 1; }

/* Attachment thumbnail square — used on bug view + apps form icon preview. */
.attachment-thumb {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-alt);
}

/* Gujarati script textareas — distinct font so the user can tell the EN    */
/* and GU summary fields apart visually.                                     */
textarea.gujarati { font-family: 'Noto Sans Gujarati', 'Inter', sans-serif; }
.gujarati { font-family: 'Noto Sans Gujarati', 'Inter', sans-serif; }

/* Preserve newlines + wrap — used by bug raw description / steps / summary */
/* fields when rendering free-text the user typed in a textarea.            */
.text-prewrap { white-space: pre-wrap; word-wrap: break-word; }

/* Bug attachment thumbnail grid cell — fixed-width caption under the thumb */
.attachment-cell { width: 120px; }
.attachment-cell .attachment-name { font-size: .8rem; max-width: 120px; }
.attachment-cell .attachment-size { font-size: .7rem; color: var(--muted); }

/* App icon thumbnail — fixed 36×36 square used in the apps list rows. */
.app-icon-sm { width: 36px; height: 36px; object-fit: cover; }

/* Thin progress bar — used inline in tables and on the SLA sidebar card. */
.progress-thin { height: .45rem; }

/* Bug-view timeline — single item is a left-border line + content gutter. */
.timeline-item {
  border-left: 2px solid var(--border-soft);
  padding-left: 1rem;
  margin-bottom: 1rem;
}
.timeline-item:last-child { margin-bottom: 0; }
.timeline-item .timeline-meta { font-size: .8rem; color: var(--muted); }

/* ------------------------------------------------------------- */
/* 5. Buttons                                                    */
/* ------------------------------------------------------------- */
.btn {
  --bs-btn-padding-y: .5rem;
  --bs-btn-padding-x: .9rem;
  --bs-btn-font-size: .9rem;
  --bs-btn-font-weight: 500;
  --bs-btn-border-radius: var(--radius);
  /* Bootstrap 5.0.2 does NOT consume --bs-btn-* vars (those are 5.3+ only), so
     apply them explicitly here. Every variant (.btn-sm, .btn-icon, …) then only
     overrides the vars and this base rule makes them take effect. */
  padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x);
  font-size: var(--bs-btn-font-size);
  font-weight: var(--bs-btn-font-weight);
  border-radius: var(--bs-btn-border-radius);
  letter-spacing: -.005em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease),
              transform .06s var(--ease);
}
.btn:active { transform: translateY(0.5px); }
.btn i { line-height: 1; }

/* Smaller variant — overrides the vars; the base .btn rule applies them. */
.btn-sm { --bs-btn-padding-y: .45rem; --bs-btn-padding-x: 1rem; --bs-btn-font-size: .85rem; --bs-btn-border-radius: .4rem; }

.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-press);
  --bs-btn-hover-border-color: var(--brand-press);
  --bs-btn-active-bg: var(--brand-press);
  --bs-btn-active-border-color: var(--brand-press);
  --bs-btn-disabled-bg: #c7d2fe;
  --bs-btn-disabled-border-color: #c7d2fe;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 1px 2px rgba(79, 70, 229, .25);
}
.btn-primary:hover { box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 4px 10px rgba(79, 70, 229, .3); }

.btn-light {
  --bs-btn-bg: #f1f5f9;
  --bs-btn-border-color: #f1f5f9;
  --bs-btn-color: var(--text);
  --bs-btn-hover-bg: #e2e8f0;
  --bs-btn-hover-border-color: #e2e8f0;
  --bs-btn-hover-color: var(--text);
  --bs-btn-active-bg: #cbd5e1;
}

.btn-outline-secondary {
  --bs-btn-color: var(--text);
  --bs-btn-border-color: #cbd5e1;
  --bs-btn-hover-bg: var(--brand-soft);
  --bs-btn-hover-border-color: var(--brand);
  --bs-btn-hover-color: var(--brand-press);
  --bs-btn-focus-shadow-rgb: 79, 70, 229;
  --bs-btn-active-bg: var(--brand-soft);
  --bs-btn-active-border-color: var(--brand);
  --bs-btn-active-color: var(--brand-press);
}
.btn-outline-secondary:focus-visible,
.btn-outline-secondary.focus {
  border-color: var(--brand);
  box-shadow: var(--ring);
  color: var(--brand-press);
}
.btn-outline-primary {
  --bs-btn-color: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand);
  --bs-btn-hover-border-color: var(--brand);
}
.btn-outline-danger {
  --bs-btn-color: #dc2626;
  --bs-btn-border-color: #fecaca;
  --bs-btn-hover-bg: #dc2626;
  --bs-btn-hover-border-color: #dc2626;
}

/* Solid tone-colored buttons: brand-consistent palette + inset highlight
   + colored ambient shadow that intensifies on hover. Matches the
   .btn-primary treatment so all tones feel like one family. */
.btn-danger {
  --bs-btn-bg: #dc2626;
  --bs-btn-border-color: #dc2626;
  --bs-btn-hover-bg: #b91c1c;
  --bs-btn-hover-border-color: #b91c1c;
  --bs-btn-active-bg: #b91c1c;
  --bs-btn-disabled-bg: #fca5a5;
  --bs-btn-disabled-border-color: #fca5a5;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 1px 2px rgba(220, 38, 38, .25);
}
.btn-danger:hover { box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 4px 10px rgba(220, 38, 38, .3); }

.btn-warning {
  --bs-btn-bg: #f59e0b;
  --bs-btn-border-color: #f59e0b;
  --bs-btn-color: #fff;
  --bs-btn-hover-bg: #d97706;
  --bs-btn-hover-border-color: #d97706;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #d97706;
  --bs-btn-active-color: #fff;
  --bs-btn-disabled-bg: #fde68a;
  --bs-btn-disabled-border-color: #fde68a;
  --bs-btn-disabled-color: #fff;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 1px 2px rgba(245, 158, 11, .25);
}
.btn-warning:hover { box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 4px 10px rgba(245, 158, 11, .3); }

.btn-success {
  --bs-btn-bg: #16a34a;
  --bs-btn-border-color: #16a34a;
  --bs-btn-hover-bg: #15803d;
  --bs-btn-hover-border-color: #15803d;
  --bs-btn-active-bg: #15803d;
  --bs-btn-disabled-bg: #86efac;
  --bs-btn-disabled-border-color: #86efac;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 1px 2px rgba(22, 163, 74, .25);
}
.btn-success:hover { box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 4px 10px rgba(22, 163, 74, .3); }

.btn-info {
  --bs-btn-bg: #0284c7;
  --bs-btn-border-color: #0284c7;
  --bs-btn-color: #fff;
  --bs-btn-hover-bg: #0369a1;
  --bs-btn-hover-border-color: #0369a1;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #0369a1;
  --bs-btn-active-color: #fff;
  --bs-btn-disabled-bg: #7dd3fc;
  --bs-btn-disabled-border-color: #7dd3fc;
  --bs-btn-disabled-color: #fff;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 1px 2px rgba(2, 132, 199, .25);
}
.btn-info:hover { box-shadow: 0 1px 0 rgba(255, 255, 255, .12) inset, 0 4px 10px rgba(2, 132, 199, .3); }

/* Outline-warning to round out the outline family alongside primary/danger */
.btn-outline-warning {
  --bs-btn-color: #d97706;
  --bs-btn-border-color: #fde68a;
  --bs-btn-hover-bg: #f59e0b;
  --bs-btn-hover-border-color: #f59e0b;
  --bs-btn-hover-color: #fff;
}
.btn-outline-info {
  --bs-btn-color: #0284c7;
  --bs-btn-border-color: #bae6fd;
  --bs-btn-hover-bg: #0284c7;
  --bs-btn-hover-border-color: #0284c7;
  --bs-btn-hover-color: #fff;
}
.btn-outline-success {
  --bs-btn-color: #16a34a;
  --bs-btn-border-color: #bbf7d0;
  --bs-btn-hover-bg: #16a34a;
  --bs-btn-hover-border-color: #16a34a;
  --bs-btn-hover-color: #fff;
}

/* Square icon-only button — no text label, clean centered glyph. */
.btn-icon {
  --bs-btn-padding-x: 0;
  --bs-btn-padding-y: 0;
  width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.btn-icon.btn-sm { width: 2rem; height: 2rem; font-size: .85rem; }
.btn-icon i.bi { line-height: 1; }

.btn-group .btn { border-radius: 0; }
.btn-group > .btn:first-child { border-top-left-radius: var(--bs-btn-border-radius); border-bottom-left-radius: var(--bs-btn-border-radius); }
.btn-group > .btn:last-child { border-top-right-radius: var(--bs-btn-border-radius); border-bottom-right-radius: var(--bs-btn-border-radius); }

/* Equal-width group — every button in the group takes the same width */
.btn-group-equal { display: inline-flex; }
.btn-group-equal > .btn { flex: 1 1 0; min-width: 100px; }

/* Icon-only buttons */
.btn > i.bi:only-child { display: inline-flex; align-items: center; justify-content: center; }

/* ------------------------------------------------------------- */
/* 6. Forms                                                      */
/* ------------------------------------------------------------- */
.form-label {
  font-size: .82rem;
  font-weight: 500;
  color: var(--text);
  margin-bottom: .35rem;
}

.form-text { font-size: .78rem; color: var(--muted); margin-top: .35rem; }

.form-control,
.form-select {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .5rem .85rem;
  font-size: .9rem;
  line-height: 1.5;
  color: var(--text);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
  box-shadow: none;
}
.form-control::placeholder { color: var(--muted-soft); }
.form-control:hover,
.form-select:hover { border-color: #cbd5e1; }
.form-control:focus,
.form-select:focus {
  border-color: var(--brand);
  box-shadow: var(--ring);
  outline: none;
}
.form-control:disabled,
.form-select:disabled,
.form-control[readonly] {
  background-color: var(--surface-alt);
  color: var(--muted);
  cursor: not-allowed;
  border-color: var(--border-soft);
}

.form-control-sm, .form-select-sm { padding: .45rem .75rem; font-size: .85rem; border-radius: .4rem; }

textarea.form-control { padding: .65rem .85rem; resize: vertical; min-height: 6rem; }

.form-control.is-invalid,
.form-select.is-invalid {
  border-color: #dc2626;
  background-image: none;
  padding-right: .85rem;
}
.form-control.is-invalid:focus,
.form-select.is-invalid:focus { box-shadow: 0 0 0 3px rgba(220, 38, 38, .18); }
.invalid-feedback { font-size: .78rem; color: #dc2626; }

.form-control.is-valid,
.form-select.is-valid { border-color: #16a34a; background-image: none; padding-right: .85rem; }
.form-control.is-valid:focus { box-shadow: 0 0 0 3px rgba(22, 163, 74, .18); }
.valid-feedback { font-size: .78rem; color: #16a34a; }

/* Selects — custom caret + native option tint */
.form-select {
  /* default chevron */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2364748b' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
  background-position: right .85rem center;
  background-size: 12px;
  padding-right: 2.5rem;
  /* tints the OS-native option highlight in Chrome / Edge / Safari */
  accent-color: var(--brand);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}
.form-select:hover { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%234f46e5' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round' d='M2 4l4 4 4-4'/%3E%3C/svg%3E"); }
.form-select:focus { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%234f46e5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2 4l4 4 4-4'/%3E%3C/svg%3E"); }
.form-select[multiple],
.form-select[size]:not([size="1"]) {
  background-image: none;
  padding-right: .85rem;
  cursor: default;
}

/* Native <option> — limited but honoured by most browsers */
.form-select option,
.form-select optgroup {
  font-family: inherit;
  font-size: .9rem;
  background-color: var(--surface);
  color: var(--text);
  padding: .5rem .75rem;
}
.form-select option:hover { background-color: var(--surface-alt); }
.form-select option:checked,
.form-select option:focus,
.form-select option[selected] {
  background: linear-gradient(0deg, var(--brand-soft), var(--brand-soft)), var(--surface);
  background-color: var(--brand-soft);
  color: var(--brand-press);
  font-weight: 500;
}
.form-select option:disabled { color: var(--muted-soft); }
.form-select optgroup {
  font-weight: 600;
  color: var(--muted);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.form-select-sm { background-position: right .65rem center; background-size: 10px; padding-right: 2rem; }

/* Color & date inputs keep native look but match height */
input[type="color"].form-control { padding: .25rem; width: 3rem; cursor: pointer; }
input[type="file"].form-control { padding: .35rem .55rem; }
input[type="file"].form-control::file-selector-button {
  background: var(--surface-alt);
  border: 0;
  border-right: 1px solid var(--border);
  color: var(--text);
  font-weight: 500;
  margin: -.35rem .85rem -.35rem -.55rem;
  padding: .55rem .85rem;
  border-radius: 0;
}

/* Number inputs — hide the chunky native spinner arrows for a cleaner
   admin look. Users can still type freely; arrow keys still increment. */
input[type="number"].form-control { -moz-appearance: textfield; }
input[type="number"].form-control::-webkit-outer-spin-button,
input[type="number"].form-control::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Search inputs — restyle the native clear (X) so it matches the
   muted-soft palette instead of the OS-default heavy gray. */
input[type="search"].form-control::-webkit-search-cancel-button {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  margin-left: .3rem;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%2394a3b8' d='M11.5 4.5L4.5 11.5M4.5 4.5L11.5 11.5' stroke='%2394a3b8' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / contain;
  cursor: pointer;
  opacity: .7;
  transition: opacity var(--t-fast) var(--ease);
}
input[type="search"].form-control::-webkit-search-cancel-button:hover { opacity: 1; }

/* Date / time inputs — make the native calendar/clock indicator subtle
   in rest, lift on hover (Chromium/Edge only — Firefox/Safari ignore). */
input[type="date"].form-control::-webkit-calendar-picker-indicator,
input[type="time"].form-control::-webkit-calendar-picker-indicator,
input[type="datetime-local"].form-control::-webkit-calendar-picker-indicator,
input[type="month"].form-control::-webkit-calendar-picker-indicator,
input[type="week"].form-control::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: .55;
  transition: opacity var(--t-fast) var(--ease);
  filter: invert(0); /* light-mode default; flipped under body.dark-mode in §17 */
}
input[type="date"].form-control:hover::-webkit-calendar-picker-indicator,
input[type="time"].form-control:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"].form-control:hover::-webkit-calendar-picker-indicator { opacity: .95; }

/* Input groups — feel like one unit */
.input-group { position: relative; }
.input-group-text {
  background-color: var(--surface);
  border-color: var(--border);
  color: var(--muted);
  font-size: .85rem;
}
.input-group:focus-within > .form-control,
.input-group:focus-within > .form-select,
.input-group:focus-within > .input-group-text,
.input-group:focus-within > .btn { border-color: var(--brand); }
.input-group:focus-within { box-shadow: var(--ring); border-radius: var(--radius); }
.input-group:focus-within > .form-control:focus,
.input-group:focus-within > .form-select:focus { box-shadow: none; }

/* Checkboxes & radios */
.form-check-input {
  border: 1.5px solid #cbd5e1;
  width: 1.1em;
  height: 1.1em;
  margin-top: .2em;
  transition: background-color var(--t-fast), border-color var(--t-fast), box-shadow var(--t-fast);
}
.form-check-input:hover { border-color: var(--brand); }
.form-check-input:checked {
  background-color: var(--brand);
  border-color: var(--brand);
}
.form-check-input:focus { box-shadow: var(--ring); border-color: var(--brand); }
.form-check-input[type="radio"]:checked { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='2' fill='%23fff'/%3E%3C/svg%3E"); }
.form-check-label { font-size: .9rem; color: var(--text); cursor: pointer; }

/* Only inside .form-check do we pull the input left into the label gutter */
.form-check { padding-left: 1.7em; min-height: 1.4rem; }
.form-check .form-check-input { margin-left: -1.7em; }

/* ------------------------------------------------------------- */
/* 7. Tables                                                     */
/* ------------------------------------------------------------- */
.table {
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--border-soft);
  --bs-table-hover-bg: var(--hover-row);
  margin-bottom: 0;
  color: var(--text);
  font-size: .9rem;
}
.table > :not(caption) > * > * {
  padding: 1rem 1.25rem;
  border-bottom-width: 1px;
  vertical-align: middle;
}
.table thead th {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-alt) !important;
  border-bottom: 1px solid var(--border) !important;
  border-top: 0 !important;
  padding-top: .85rem;
  padding-bottom: .85rem;
  white-space: nowrap;
}
.table > tbody > tr {
  transition: background var(--t-fast) var(--ease);
  line-height: 1.55;
}
.table > tbody > tr > * { font-size: inherit; }
/* Every text node inside a cell — sub-labels, links, codes, divs — picks up
   the cell font-size. Hierarchy comes from color (.text-secondary) and
   weight (.fw-semibold), not size. */
.table > tbody > tr > * .small,
.table > tbody > tr > * small,
.table > tbody > tr > * .fs-6,
.table > tbody > tr > * div,
.table > tbody > tr > * a,
.table > tbody > tr > * span:not(.badge):not(.method):not(.stat-icon):not(.file-icon):not(.user-avatar-circle) {
  font-size: inherit;
}
.table > tbody > tr > * code { font-size: inherit; }

.table tbody tr:hover { background: var(--hover-row); }
.table tbody tr:last-child > td { border-bottom: 0; }
.table.thead-light thead th,
.table .bg-light { background: var(--surface-alt) !important; }
.table th, .table td { border-color: var(--border-soft); }

/* Density variants */
.table-sm { font-size: .82rem; }
.table-sm > :not(caption) > * > * { padding: .65rem .85rem; }

/* table-responsive — keep card corners rounded */
.card > .table-responsive,
.card > .table-responsive > .table { border-radius: inherit; }
.card > .table-responsive { overflow: hidden auto; }
.table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-responsive::-webkit-scrollbar { height: 8px; }
.table-responsive::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }

/* Tighter horizontal padding on small screens so 5+ columns don't get   */
/* clipped on a 360-px viewport.                                          */
@media (max-width: 575.98px) {
  .table > :not(caption) > * > * { padding: .75rem .85rem; }
  .table thead th { padding-top: .65rem; padding-bottom: .65rem; }
  .table { font-size: .82rem; }
}

/* DataTables controls — top length/search bar + bottom info/pagination. */
.dataTables_wrapper {
  padding: 0;
}
.dataTables_wrapper .row:first-child,
.dataTables_wrapper .row:last-child {
  padding: .85rem 1.25rem;
  margin: 0;
  align-items: center;
}
.dataTables_wrapper .row:first-child { border-bottom: 1px solid var(--border-soft); }
.dataTables_wrapper .row:last-child  { border-top:    1px solid var(--border-soft); }
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info { font-size: .82rem; color: var(--muted); }
.dataTables_wrapper .dataTables_length label,
.dataTables_wrapper .dataTables_filter label { margin-bottom: 0; display: inline-flex; align-items: center; gap: .5rem; }
.dataTables_wrapper .dataTables_length select { width: auto; padding: .3rem 1.85rem .3rem .6rem; }
.dataTables_wrapper .dataTables_filter input { width: 14rem; max-width: 100%; }
@media (max-width: 575.98px) {
  .dataTables_wrapper .row:first-child > div,
  .dataTables_wrapper .row:last-child  > div { text-align: left !important; padding-bottom: .35rem; }
  .dataTables_wrapper .dataTables_filter input { width: 100%; }
}

/* Pagination — Bootstrap default look + tighter spacing on table footers.
   Page items render as squares (min-width = height) so single-digit pages and
   the « ‹ › » chevrons all sit in equal-sized boxes. Multi-digit pages widen
   horizontally as needed but keep the same height. */
.pagination { margin-bottom: 0; gap: .4rem; }
.page-link {
  border-radius: var(--radius);
  border-color: var(--border);
  color: var(--text);
  min-width: 2.25rem;
  height: 2.25rem;
  padding: 0 .5rem;
  font-size: .85rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.page-link:hover { background: var(--surface-alt); color: var(--brand-press); border-color: var(--border); }
.page-item.active .page-link { background: var(--brand); border-color: var(--brand); color: #fff; }
.page-link .bi { font-size: 1em; line-height: 1; }

/* ------------------------------------------------------------- */
/* 7b. Charts & sparklines                                       */
/* Wrappers that give a Chart.js canvas explicit height so        */
/* `responsive: true, maintainAspectRatio: false` works.          */
/* ------------------------------------------------------------- */
.chart-wrap    { position: relative; height: 240px; }
.chart-wrap-sm { position: relative; height: 180px; }
.chart-wrap-lg { position: relative; height: 340px; }
@media (max-width: 575.98px) {
  .chart-wrap    { height: 200px; }
  .chart-wrap-lg { height: 260px; }
}

/* Inline CSS-only mini bar chart (e.g. 7-day request volume on
   endpoint detail page). Bars set their own height inline. */
.spark {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 60px;
  width: 100%;
}
.spark > span,
.spark > div {
  flex: 1 1 0;
  min-width: 2px;
  background: var(--brand);
  opacity: .8;
  border-radius: 2px;
  transition: opacity var(--t-fast) var(--ease);
}
.spark > span:hover,
.spark > div:hover { opacity: 1; }

/* ------------------------------------------------------------- */
/* 8. Badges                                                     */
/* ------------------------------------------------------------- */
.badge {
  font-weight: 600;
  letter-spacing: .01em;
  border-radius: .375rem;
  padding: .3em .55em;
  font-size: .72rem;
  line-height: 1.2;
  vertical-align: middle;
}

/* DEV / PROD mode badge — letter-spaced for that "STATUS" feel.
   Size inherits from base .badge (0.72rem); add `.badge-mode` for the spacing. */
.badge-mode { letter-spacing: .05em; }

.bg-success-subtle { background-color: #dcfce7 !important; }
.bg-warning-subtle { background-color: #fef3c7 !important; }
.bg-danger-subtle  { background-color: #fee2e2 !important; }
.bg-info-subtle    { background-color: #dbeafe !important; }
.bg-primary-subtle { background-color: #ede9fe !important; }
.bg-secondary-subtle { background-color: #f1f5f9 !important; }

/* Solid colored dot — used for state indicators (health probe OK/fail,
   live activity). Combine with bg-X (success/danger/etc.) for color. */
.badge-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 50%;
  vertical-align: middle;
  flex-shrink: 0;
}

/* ------------------------------------------------------------- */
/* 9. Nav · tabs · pills                                          */
/* ------------------------------------------------------------- */
.nav-tabs {
  --bs-nav-tabs-border-color: var(--border);
  --bs-nav-tabs-border-radius: 0;
  border-bottom-width: 1px;
}
.nav-tabs .nav-link {
  color: var(--muted);
  font-weight: 500;
  font-size: .9rem;
  border: 0;
  padding: .65rem .9rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: transparent;
}
.nav-tabs .nav-link:hover { color: var(--text); border-bottom-color: var(--border); background: transparent; }
.nav-tabs .nav-link.active { color: var(--brand); border-bottom-color: var(--brand); background: transparent; }

.nav-pills {
  --bs-nav-pills-border-radius: var(--radius);
  --bs-nav-pills-link-active-bg: var(--brand);
  gap: 4px;
}
.nav-pills .nav-link { color: var(--text); font-weight: 500; font-size: .9rem; padding: .5rem .8rem; }
.nav-pills .nav-link:hover { background: var(--surface-alt); color: var(--text); }
.nav-pills .nav-link.active { color: #fff; }
/* Panel tab pills (grant editors, modules, effective): active tab keeps the
   normal text colour — only a soft tint + weight marks it, no white-on-fill. */
.panel-tabs .nav-link { color: var(--text); }
.panel-tabs .nav-link.active { background: var(--brand-soft); color: var(--text); font-weight: 600; }

/* ------------------------------------------------------------- */
/* 10. Modal · offcanvas · toast                                  */
/* ------------------------------------------------------------- */
.modal-content { border: 0; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.modal-header { border-bottom-color: var(--border-soft); padding: 1.1rem 1.25rem; }
.modal-footer { border-top-color: var(--border-soft); padding: 1rem 1.25rem; gap: .35rem; }
.modal-title { font-size: 1.05rem; font-weight: 600; }
.modal-backdrop.show { opacity: .55; }

.offcanvas { border: 0 !important; }
.offcanvas-header { border-bottom: 1px solid var(--border-soft); }

.toast { border-radius: var(--radius); box-shadow: var(--shadow); }

/* ------------------------------------------------------------- */
/* 11. Alerts                                                    */
/* Admin-Bootstrap pattern: leading icon at top-left of each      */
/* alert, body content flows with extra left padding. Absolute    */
/* positioning so it works for simple text AND structured alerts  */
/* (alert-heading, <pre>, multi-line content).                    */
/* ------------------------------------------------------------- */
.alert {
  border: 0;
  border-radius: var(--radius);
  padding: .85rem 1rem .85rem 2.65rem;
  font-size: .9rem;
  position: relative;
}
.alert::before {
  position: absolute;
  left: 1rem;
  top: .95rem;
  font-family: 'bootstrap-icons' !important;
  font-style: normal;
  font-weight: normal;
  font-size: 1.05rem;
  line-height: 1;
  display: inline-block;
}
.alert-info    { background: #eff6ff; color: #1e3a8a; }
.alert-warning { background: #fffbeb; color: #78350f; }
.alert-danger  { background: #fef2f2; color: #991b1b; }
.alert-success { background: #f0fdf4; color: #166534; }
.alert-light   { background: var(--surface-alt); color: var(--text); }

.alert-info::before    { content: '\f430'; } /* bi-info-circle-fill */
.alert-warning::before { content: '\f33a'; } /* bi-exclamation-triangle-fill */
.alert-danger::before  { content: '\f622'; } /* bi-x-circle-fill */
.alert-success::before { content: '\f26a'; } /* bi-check-circle-fill */
.alert-light::before   { content: '\f431'; } /* bi-info-circle (outlined for muted look) */

/* The custom .alert padding above sets right padding to 1rem, which clobbers
   Bootstrap's .alert-dismissible padding-right:3rem — so the absolute close
   button overlaps long text. Re-reserve room on the right for the X button. */
.alert-dismissible { padding-right: 2.75rem; }
.alert-dismissible .btn-close { padding: .9rem 1rem; }

/* Opt-out of the leading ::before marker for a specific alert (pass
   'icon' => false to the alert partial). Drops the icon + its reserved gap. */
.alert.alert-no-icon { padding-left: 1rem; }
.alert.alert-no-icon::before { content: none; }

/* ------------------------------------------------------------- */
/* 12. Common utilities                                          */
/* ------------------------------------------------------------- */
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .85rem; }

/* Micro text — sub-meta lines beneath primary content (slug under name,
   actor · time under action label, timestamps, secondary tier labels). */
.text-micro { font-size: .72rem; }

/* Flexbox child that needs to truncate — Bootstrap has no utility for this.
   Pair with .text-truncate on a descendant to clamp text inside a flex row. */
.min-w-0 { min-width: 0; }

/* In-card section subhead — smaller, less-prominent than .section-title.
   Used inside framework widgets, server panels, etc. for secondary groupings. */
.subhead {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  font-weight: 600;
}

/* Mini section header used inside form cards (Admin-Bootstrap input.html). */
.section-title {
  font-size: .75rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 1rem;
}

/* Reset uppercase + letter-spacing inherited from a parent (.section-title
   etc.) for an inline span. Used on SdkAuth info "(secret)" sub-label. */
.normal-case {
  text-transform: none;
  letter-spacing: 0;
}

/* ----- JS-hook classes (no styling — markers for app.js / inline JS) -----
   .dash-live           — dashboard live in-flight cells (poller updates text)
   .ep-live             — Endpoints index live in-flight cells (same poller)
   .repo-copy-label     — Gradle-user form copy-button label span (swaps to "Copied")
   These intentionally have no CSS rule. JS toggles their visibility via
   .d-none / textContent updates. Don't add styling — that's their contract.
   --------------------------------------------------------------------- */

.snippet {
  background: var(--code-bg);
  color: var(--code-fg);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .82rem;
  line-height: 1.6;
  position: relative;
  overflow: auto;
}
.snippet .copy { position: absolute; top: .5rem; right: .5rem; }

/* Transparent <pre> for command-output dumps (no bg, no padding) —
   used in dummy_data result alerts. */
.pre-output {
  white-space: pre-wrap;
  font-size: .78rem;
  max-height: 420px;
  overflow: auto;
  background: transparent;
  border: 0;
  padding: 0;
}

/* Inline-detail <pre> for audit JSON / context blobs — subtle bg, padded,
   sits inside a card row. */
.pre-details {
  white-space: pre-wrap;
  max-width: 100%;
  background: var(--surface-alt);
  padding: .5rem;
  border-radius: .35rem;
}

.meta-row {
  padding: .85rem 0;
  border-bottom: 1px solid var(--border-soft);
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 1rem;
}
.meta-row:last-child { border-bottom: 0; }
.meta-row .label { color: var(--muted); font-size: .85rem; }
@media (max-width: 767.98px) { .meta-row { grid-template-columns: 1fr; gap: .25rem; } }

/* Initials circle — used by the topbar user dropdown (trigger + menu header) */
.user-avatar-circle {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: -.02em;
  flex-shrink: 0;
}
.user-avatar-circle.user-avatar-lg {
  width: 44px;
  height: 44px;
  font-size: 1rem;
}

/* HTTP method tags */
.method {
  font-weight: 700;
  font-size: .7rem;
  letter-spacing: .04em;
  padding: .25rem .55rem;
  border-radius: 4px;
  display: inline-block;
}
.m-get   { background: #dcfce7; color: #166534; }
.m-post  { background: #dbeafe; color: #1e40af; }
.m-put   { background: #fef3c7; color: #92400e; }
.m-patch { background: #ede9fe; color: #5b21b6; }
.m-del, .m-delete { background: #fee2e2; color: #991b1b; }
.m-head  { background: #ede9fe; color: #5b21b6; }

/* File icon — used on Repository artifact detail header. */
.file-icon { width: 40px; height: 40px; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; }
.file-icon-lg { width: 64px; height: 64px; border-radius: 14px; font-size: 1.6rem; display: inline-flex; align-items: center; justify-content: center; }

/* ------------------------------------------------------------- */
/* 13. Auth / error chrome                                       */
/* ------------------------------------------------------------- */
.auth-bg {
  min-height: 100vh;
  background:
    radial-gradient(circle at 20% 10%, rgba(255, 255, 255, .12) 0, transparent 30%),
    radial-gradient(circle at 80% 80%, rgba(255, 255, 255, .08) 0, transparent 40%),
    linear-gradient(135deg, var(--brand) 0%, var(--brand-2) 100%);
  display: flex; align-items: center; justify-content: center;
  padding: 2rem 1rem;
}
.auth-bg-soft {
  min-height: 100vh;
  background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  padding: 2rem 1rem;
}
.auth-card {
  max-width: 460px;
  width: 100%;
  border: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.error-code {
  font-size: clamp(5rem, 18vw, 11rem);
  font-weight: 800;
  line-height: 1;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.error-code.error-500 {
  background: linear-gradient(135deg, #dc2626, #f59e0b);
  -webkit-background-clip: text; background-clip: text;
}

/* ------------------------------------------------------------- */
/* 14. Responsive                                                */
/* ------------------------------------------------------------- */
@media (max-width: 991.98px) {
  .content { padding: 1rem; }

  /* Collapsed nav becomes a dark panel below the brand bar.            */
  .top-nav .navbar-collapse {
    background: var(--sidebar-bg);
    margin-top: .55rem;
    padding: .5rem;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }
  .top-nav .navbar-nav .nav-link { padding: .55rem .75rem; }
  .top-nav .nav-item.dropdown .dropdown-menu {
    /* Inline dropdowns inside the collapsed menu — flat, no shadow.    */
    border: 0;
    background: rgba(255, 255, 255, .04);
    box-shadow: none;
    padding: .25rem .25rem .25rem 1.4rem;
    margin: .15rem 0 .35rem;
  }
  .top-nav .dropdown-item { color: var(--sidebar-fg); }
  .top-nav .dropdown-item i { color: var(--sidebar-fg); }
  .top-nav .dropdown-item:hover,
  .top-nav .dropdown-item:focus { background: rgba(255, 255, 255, .08); color: #fff; }
  .top-nav .dropdown-item:hover i,
  .top-nav .dropdown-item:focus i { color: #fff; }
  .top-nav .user-chip { background: transparent; }
}
@media (max-width: 575.98px) {
  .content { padding: .85rem .75rem; }
  .meta-row { padding-top: 1rem; padding-bottom: 1rem; }
  /* Smaller hero on small screens                                     */
  h4.fw-bold, h5.fw-bold { font-size: 1.1rem; }
}

/* ------------------------------------------------------------- */
/* 15. Motion · print                                             */
/* ------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

@media print {
  .top-nav, .btn, .pagination, .form-control, .form-select { display: none !important; }
  .content { padding: 0; }
  .card { box-shadow: none; border: 1px solid var(--border) !important; break-inside: avoid; }
  a[href]::after { content: " (" attr(href) ")"; font-size: .8em; color: #444; }
}

/* ------------------------------------------------------------- */
/* 16. Scrollbars                                                */
/* Thin styled scrollbars applied globally (Webkit + Firefox).    */
/* Per-component rules in §3 (.sidebar) and §7 (.table-responsive)*/
/* keep their tighter widths via higher selector specificity.     */
/* ------------------------------------------------------------- */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--muted-soft) transparent;
}
*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background-color: var(--muted-soft);
  border-radius: 8px;
  /* 2px transparent border creates a visual gutter so the thumb
     doesn't touch the track edges — looks more refined. */
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
  background-color: var(--muted);
}
*::-webkit-scrollbar-corner {
  background: transparent;
}

/* ------------------------------------------------------------- */
/* 17. Dark mode                                                 */
/* Activated by `<html data-bs-theme="dark">` + `body.dark-mode`.*/
/* The data-bs-theme attribute auto-darkens Bootstrap's own      */
/* tokens (dropdowns, modals, tables, btn-close, etc.). The      */
/* `body.dark-mode` rules below override our custom design tokens*/
/* and the few hardcoded utility colors that don't go through BS.*/
/* ------------------------------------------------------------- */
body.dark-mode {
  --bg: #0b1220;
  --surface: #131c2c;
  --surface-alt: #1a2336;
  --text: #e2e8f0;
  --muted: #94a3b8;
  --muted-soft: #64748b;

  --border: #1f2a3d;
  --border-soft: #1a2336;
  --hover-row: #1a2336;

  /* sidebar — keep it dark but slightly lighter than bg so it has presence */
  --sidebar-bg: #0a0f1c;
  --sidebar-fg: #cbd5e1;

  --code-bg: #050b18;
  --code-fg: #e2e8f0;

  --brand-soft: rgba(129, 140, 248, .18);
  --brand-ring: rgba(129, 140, 248, .35);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
  --shadow:    0 4px 14px rgba(0, 0, 0, .45);
  --shadow-lg: 0 20px 50px rgba(0, 0, 0, .55);
}

/* Top nav — keep dark across themes (already dark in light mode);            */
/* nothing to override here, but ensure dropdown items inherit dark surface.  */
body.dark-mode .top-nav .dropdown-menu { background: var(--surface); }
body.dark-mode .top-nav .dropdown-item { color: var(--text); }
body.dark-mode .top-nav .dropdown-item i { color: var(--muted); }
body.dark-mode .top-nav .dropdown-item:hover { background: var(--brand-soft); color: var(--text); }

/* Cards / inputs pick up via tokens, but the explicit white/light bgs need help. */
body.dark-mode .card { background: var(--surface); }
body.dark-mode .card-header,
body.dark-mode .card-footer { border-color: var(--border-soft); background: transparent; }

body.dark-mode .form-control,
body.dark-mode .form-select {
  background-color: var(--surface);
  border-color: var(--border);
  color: var(--text);
}
body.dark-mode .form-control::placeholder { color: var(--muted-soft); }
body.dark-mode .form-control:hover,
body.dark-mode .form-select:hover { border-color: #334155; }
body.dark-mode .form-control:disabled,
body.dark-mode .form-control[readonly],
body.dark-mode .form-select:disabled { background-color: var(--surface-alt); color: var(--muted); }
body.dark-mode .input-group-text {
  background-color: var(--surface-alt);
  border-color: var(--border);
  color: var(--muted);
}
body.dark-mode input[type="file"].form-control::file-selector-button {
  background: var(--surface-alt);
  border-right-color: var(--border);
  color: var(--text);
}

/* Select chevron — recolor for dark contrast */
body.dark-mode .form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2394a3b8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
}

/* Checkboxes — bump the unchecked border so they read on dark */
body.dark-mode .form-check-input { border-color: #475569; }

/* btn-light → dark-tinted neutral */
body.dark-mode .btn-light {
  --bs-btn-bg: var(--surface-alt);
  --bs-btn-border-color: var(--surface-alt);
  --bs-btn-color: var(--text);
  --bs-btn-hover-bg: #233048;
  --bs-btn-hover-border-color: #233048;
  --bs-btn-hover-color: var(--text);
  --bs-btn-active-bg: #2c3a55;
}
body.dark-mode .btn-outline-secondary {
  --bs-btn-color: var(--text);
  --bs-btn-border-color: #334155;
}
body.dark-mode .btn-primary { --bs-btn-disabled-bg: #3730a3; --bs-btn-disabled-border-color: #3730a3; }
body.dark-mode .btn-outline-danger { --bs-btn-border-color: rgba(220, 38, 38, .45); }

/* Table — header/border tokens flow through, but bg-light cells need help */
body.dark-mode .table thead.bg-light,
body.dark-mode .table thead th.bg-light,
body.dark-mode .table .bg-light { background-color: var(--surface-alt) !important; }
body.dark-mode .table-responsive::-webkit-scrollbar-thumb { background: #334155; }

/* Subtle badge backgrounds — re-derive with dark palette */
body.dark-mode .bg-success-subtle   { background-color: rgba(34, 197, 94, .15) !important; }
body.dark-mode .bg-warning-subtle   { background-color: rgba(234, 179, 8, .15) !important; }
body.dark-mode .bg-danger-subtle    { background-color: rgba(239, 68, 68, .15) !important; }
body.dark-mode .bg-info-subtle      { background-color: rgba(59, 130, 246, .18) !important; }
body.dark-mode .bg-primary-subtle   { background-color: rgba(129, 140, 248, .18) !important; }
body.dark-mode .bg-secondary-subtle { background-color: rgba(148, 163, 184, .15) !important; }
body.dark-mode .bg-light-subtle     { background-color: var(--surface-alt) !important; }

/* Text-X colors on dark — slightly lighter so subtle bg+text combos stay readable */
body.dark-mode .text-success { color: #4ade80 !important; }
body.dark-mode .text-warning { color: #fbbf24 !important; }
body.dark-mode .text-danger  { color: #f87171 !important; }
body.dark-mode .text-info    { color: #60a5fa !important; }
body.dark-mode .text-primary { color: #a5b4fc !important; }
body.dark-mode .text-secondary { color: var(--muted) !important; }

/* Bare bg-light utility (used for code blocks, table thead, etc.) */
body.dark-mode .bg-light { background-color: var(--surface-alt) !important; }

/* Alerts — re-derive with dark, muted backgrounds */
body.dark-mode .alert-info    { background: rgba(59, 130, 246, .12); color: #93c5fd; }
body.dark-mode .alert-warning { background: rgba(234, 179, 8, .12);  color: #fcd34d; }
body.dark-mode .alert-danger  { background: rgba(239, 68, 68, .12);  color: #fca5a5; }
body.dark-mode .alert-success { background: rgba(34, 197, 94, .12);  color: #86efac; }
body.dark-mode .alert-light   { background: var(--surface-alt); color: var(--text); }

/* HTTP method tags + reason tags */
body.dark-mode .m-get   { background: rgba(34, 197, 94, .18); color: #86efac; }
body.dark-mode .m-post  { background: rgba(59, 130, 246, .18); color: #93c5fd; }
body.dark-mode .m-put   { background: rgba(234, 179, 8, .18); color: #fcd34d; }
body.dark-mode .m-patch,
body.dark-mode .m-head  { background: rgba(167, 139, 250, .18); color: #c4b5fd; }
body.dark-mode .m-del,
body.dark-mode .m-delete { background: rgba(239, 68, 68, .18); color: #fca5a5; }

/* Confirm-modal modal & dropdowns — BS5 auto-handles via data-bs-theme,
   but the dropdown shadow needs to read on dark backgrounds */
body.dark-mode .dropdown-menu { box-shadow: var(--shadow); }
body.dark-mode .modal-content { box-shadow: var(--shadow-lg); }

/* Code element on dark — lift contrast */
body.dark-mode code { color: #fca5a5; }

/* Auth-bg-soft (used by 404 page when on dark) — flip to dark surface */
body.dark-mode .auth-bg-soft { background: var(--bg); }


/* Progress bars stay visible on dark surface */
body.dark-mode .progress { background-color: var(--surface-alt); }

/* Pagination — BS5 handles dark via data-bs-theme; just nudge active */
body.dark-mode .page-link { background-color: var(--surface); border-color: var(--border); color: var(--text); }
body.dark-mode .page-link:hover { background-color: var(--surface-alt); color: var(--text); }
body.dark-mode .page-item.active .page-link { background-color: var(--brand); border-color: var(--brand); color: #fff; }
body.dark-mode .page-item.disabled .page-link { background-color: var(--surface); color: var(--muted-soft); }

/* Global scrollbars in dark mode — darker thumb on dark page bg */
body.dark-mode { scrollbar-color: #334155 transparent; }
body.dark-mode *::-webkit-scrollbar-thumb { background-color: #334155; }
body.dark-mode *::-webkit-scrollbar-thumb:hover { background-color: #475569; }

/* Native date/time picker icons render as black SVG by default — flip to
   white on dark backgrounds so they stay visible. */
body.dark-mode input[type="date"].form-control::-webkit-calendar-picker-indicator,
body.dark-mode input[type="time"].form-control::-webkit-calendar-picker-indicator,
body.dark-mode input[type="datetime-local"].form-control::-webkit-calendar-picker-indicator,
body.dark-mode input[type="month"].form-control::-webkit-calendar-picker-indicator,
body.dark-mode input[type="week"].form-control::-webkit-calendar-picker-indicator {
  filter: invert(1) brightness(.85);
}

/* Search clear-X in dark mode — slate-400 instead of muted-soft */
body.dark-mode input[type="search"].form-control::-webkit-search-cancel-button {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%2394a3b8' d='M11.5 4.5L4.5 11.5M4.5 4.5L11.5 11.5' stroke='%23cbd5e1' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------- */
/* 18. Toast stack                                                */
/* Lightweight, CSP-friendly feedback for small "Copied" /        */
/* "Saved" confirmations — replaces window.alert().               */
/* Injected by app.js into <body> on first window.toast() call.   */
/* ------------------------------------------------------------- */
.toast-stack {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1080;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  pointer-events: none;
}
.toast-item {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .55rem .9rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  font-size: .85rem;
  font-weight: 500;
  min-width: 12rem;
  max-width: 22rem;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--t-base) var(--ease), transform var(--t-base) var(--ease);
  pointer-events: auto;
}
.toast-item.show { opacity: 1; transform: translateY(0); }
.toast-item i { font-size: 1rem; line-height: 1; flex-shrink: 0; }
.toast-primary i { color: var(--brand); }
.toast-success i { color: #16a34a; }
.toast-warning i { color: #f59e0b; }
.toast-danger  i { color: #dc2626; }
body.dark-mode .toast-item { background: var(--surface); color: var(--text); border-color: var(--border); }

/* Play · Tom Select combobox → Bootstrap .form-select parity (downloads / reviews). */
.ts-wrapper.single .ts-control {
    min-height: calc(1.5em + 1rem + 2px);
    padding: 0.5rem 2.25rem 0.5rem 0.85rem;
    font-size: 0.9rem;
    font-weight: 400;
    line-height: 1.5;
    color: var(--bs-body-color, #212529);
    background-color: var(--bs-body-bg, #fff);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 16px 12px;
    border: var(--bs-border-width, 1px) solid var(--bs-border-color, #dee2e6);
    border-radius: var(--bs-border-radius, 0.375rem);
    box-shadow: none;
}
.ts-wrapper.single .ts-control:after { display: none !important; }
.ts-wrapper.single.input-active .ts-control { background: var(--bs-body-bg, #fff); }
.ts-wrapper.focus .ts-control,
.ts-wrapper .ts-control:focus-within {
    border-color: #86b7fe;
    box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
    outline: 0;
}
.ts-wrapper.disabled .ts-control { background-color: var(--bs-secondary-bg, #e9ecef); }
.ts-dropdown {
    margin-top: 0.125rem;
    padding: 0.25rem 0;
    font-size: 0.9rem;
    color: var(--bs-body-color, #212529);
    background-color: var(--bs-body-bg, #fff);
    border: var(--bs-border-width, 1px) solid var(--bs-border-color, #dee2e6);
    border-radius: var(--bs-border-radius, 0.375rem);
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.ts-dropdown .ts-dropdown-content { padding: 0; }
.ts-dropdown .option {
    padding: 0.60rem 0.75rem !important;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--bs-body-color, #212529);
}
.ts-dropdown .option > div { padding: 0 !important; }
.ts-dropdown .option img { width: 18px; height: 18px; }
.ts-dropdown .option:hover,
.ts-dropdown .option.active { background-color: var(--bs-tertiary-bg, #f8f9fa); color: var(--bs-body-color, #212529); }
.ts-dropdown .option.selected { background-color: var(--bs-secondary-bg, #e9ecef); }
.ts-dropdown .no-results,
.ts-dropdown .optgroup-header { padding: 0.375rem 0.75rem; color: var(--bs-secondary-color, #6c757d); }

