/* ============================================================================
   Framer shared components - used by BOTH the admin portal and the main app.
   Everything here was previously duplicated across base.html, index.html,
   history.html, requirements.html and the three error pages.

   Loads after Bootstrap, so component-scoped --bs-* overrides and plain
   declarations both win on source order. No !important anywhere.
   ============================================================================ */

/* ---- Cards -----------------------------------------------------------------
   Bootstrap declares --bs-card-* INSIDE .card, so these must live on the
   selector rather than :root.                                               */
.card {
  --bs-card-bg: var(--surface-raised);
  --bs-card-color: var(--text-primary);
  --bs-card-border-color: var(--border-subtle);
  --bs-card-cap-bg: var(--surface-sunken);
  --bs-card-cap-color: var(--text-primary);
  --bs-card-border-radius: var(--radius-lg);
  --bs-card-inner-border-radius: calc(var(--radius-lg) - 1px);
  box-shadow: var(--shadow-md);
}
.card-header { font-weight: 600; padding: .875rem 1.25rem; }
.card-body   { padding: 1.25rem; }

/* ---- Tables ---------------------------------------------------------------- */
.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--text-primary);
  --bs-table-border-color: var(--border-subtle);
  --bs-table-striped-bg: var(--surface-row-alt);
  --bs-table-striped-color: var(--text-primary);
  --bs-table-hover-bg: var(--brand-wash);
  --bs-table-hover-color: var(--text-primary);
}
.table thead th {
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-weight: 600;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  border-bottom: 2px solid var(--border-subtle);
  padding: .875rem 1rem;
}
.table tbody td { padding: .875rem 1rem; vertical-align: middle; }

/* Sticky header for long test/list tables (was an inline style). */
.table-sticky thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-raised);
}
/* Alternating row shade that inverts correctly in light mode
   (was a hardcoded rgba(255,255,255,.03)). */
.row-alt { background: var(--surface-row-alt); }

/* ---- Modals ---------------------------------------------------------------- */
.modal {
  --bs-modal-bg: var(--surface-overlay);
  --bs-modal-color: var(--text-primary);
  --bs-modal-border-color: var(--border-default);
  --bs-modal-header-border-color: var(--border-subtle);
  --bs-modal-footer-border-color: var(--border-subtle);
  --bs-modal-border-radius: var(--radius-lg);
}
.modal-title { font-weight: 600; }
.modal-header, .modal-footer {
  background: var(--surface-sunken);
  padding: 1rem 1.25rem;
}

/* ---- Dropdowns -------------------------------------------------------------- */
.dropdown-menu {
  --bs-dropdown-bg: var(--surface-overlay);
  --bs-dropdown-color: var(--text-primary);
  --bs-dropdown-border-color: var(--border-subtle);
  --bs-dropdown-link-color: var(--text-primary);
  --bs-dropdown-link-hover-bg: var(--surface-hover);
  --bs-dropdown-link-hover-color: var(--text-primary);
  --bs-dropdown-link-active-bg: var(--brand-solid);
  --bs-dropdown-link-active-color: var(--brand-contrast);
  --bs-dropdown-divider-bg: var(--border-subtle);
  --bs-dropdown-border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

/* ---- List groups, tabs, accordions ------------------------------------------ */
.list-group {
  --bs-list-group-bg: var(--surface-raised);
  --bs-list-group-color: var(--text-primary);
  --bs-list-group-border-color: var(--border-subtle);
  --bs-list-group-action-hover-bg: var(--surface-hover);
  --bs-list-group-action-hover-color: var(--text-primary);
}
.nav-tabs {
  --bs-nav-tabs-border-color: var(--border-subtle);
  --bs-nav-tabs-link-hover-border-color: var(--border-default);
  --bs-nav-tabs-link-active-bg: var(--surface-raised);
  --bs-nav-tabs-link-active-color: var(--text-primary);
  --bs-nav-tabs-link-active-border-color: var(--border-subtle);
}
.accordion {
  --bs-accordion-bg: var(--surface-raised);
  --bs-accordion-color: var(--text-primary);
  --bs-accordion-border-color: var(--border-subtle);
  --bs-accordion-btn-bg: var(--surface-sunken);
  --bs-accordion-btn-color: var(--text-primary);
  --bs-accordion-active-bg: var(--brand-subtle);
  --bs-accordion-active-color: var(--brand);
}

/* ---- Forms ------------------------------------------------------------------
   Bootstrap hardcodes `background-color: var(--bs-body-bg)` on .form-control.
   We want sunken inputs against raised cards, so these are plain rules.      */
.form-control, .form-select, .input-group-text {
  background-color: var(--surface-sunken);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: .6rem .875rem;
  transition: border-color .2s, box-shadow .2s;
}
.form-control:focus, .form-select:focus {
  background-color: var(--surface-sunken);
  color: var(--text-primary);
  border-color: var(--brand-solid);
  box-shadow: var(--focus-ring);
}
.form-control::placeholder { color: var(--text-muted); opacity: 1; }
.input-group-text { color: var(--text-muted); }
.form-label { font-weight: 500; margin-bottom: .5rem; font-size: .9rem; }
.form-text  { font-size: .8rem; margin-top: .4rem; }
.form-check-input {
  background-color: var(--surface-sunken);
  border-color: var(--border-default);
}
.form-check-input:checked {
  background-color: var(--brand-solid);
  border-color: var(--brand-solid);
}
.form-check-input:focus { box-shadow: var(--focus-ring); }

.form-section {
  border-bottom: 1px solid var(--border-subtle);
  padding-bottom: 1.5rem;
  margin-bottom: 1.5rem;
}
.form-section:last-child { border-bottom: none; padding-bottom: 0; margin-bottom: 0; }
.form-section-title { font-weight: 600; margin-bottom: 1rem; color: var(--text-primary); }

/* ---- Buttons ---------------------------------------------------------------- */
.btn {
  font-weight: 500;
  border-radius: var(--radius-md);
  padding: .5rem 1rem;
  transition: all .2s;
}
.btn-primary {
  background: linear-gradient(135deg, var(--brand-solid), var(--brand-solid-hi));
  border: none;
  color: var(--brand-contrast);
  box-shadow: 0 2px 4px color-mix(in srgb, var(--brand-solid) 30%, transparent);
}
.btn-primary:hover, .btn-primary:focus {
  background: linear-gradient(135deg, var(--brand-solid-hi), var(--iris-700));
  color: var(--brand-contrast);
  box-shadow: var(--shadow-brand);
  transform: translateY(-1px);
}
.btn-success { background: linear-gradient(135deg, var(--status-pass), #059669); border: none; color: #fff; }
.btn-danger  { background: linear-gradient(135deg, var(--status-fail), #dc2626); border: none; color: #fff; }
.btn-outline-primary { border-color: var(--brand-solid); color: var(--brand); }
.btn-outline-primary:hover {
  background-color: var(--brand-solid);
  border-color: var(--brand-solid);
  color: var(--brand-contrast);
}
.btn-outline-secondary { border-color: var(--border-default); color: var(--text-secondary); }
.btn-outline-secondary:hover {
  background-color: var(--surface-hover);
  border-color: var(--border-strong);
  color: var(--text-primary);
}

/* ---- Alerts -----------------------------------------------------------------
   Bootstrap's own .alert-* now resolve correctly because tokens.css supplies
   --bs-*-bg-subtle / -text-emphasis / -border-subtle. All that is left is the
   left-rule flourish the old stylesheet added.                              */
.alert {
  border-width: 0 0 0 4px;
  border-radius: var(--radius-lg);
  backdrop-filter: blur(10px);
}
.alert-success { border-left-color: var(--status-pass); }
.alert-danger  { border-left-color: var(--status-fail); }
.alert-warning { border-left-color: var(--status-warn); }
.alert-info    { border-left-color: var(--status-info); }

/* ---- Badges -----------------------------------------------------------------
   Bootstrap's .bg-* utility is itself !important, but it only sets
   background-color via rgba(var(--bs-*-rgb), var(--bs-bg-opacity)) - and
   --bs-bg-opacity is an ordinary custom property we can simply set. So a
   tinted badge needs no !important.

   Scoping to `.badge.bg-*` also fixes a latent bug: the old rules recoloured
   EVERY .bg-secondary / .bg-dark element on the page, not just badges.     */
.badge {
  font-weight: 500;
  padding: .4em .7em;
  border-radius: var(--radius-sm);
}
.badge.bg-success   { --bs-bg-opacity: .16; color: var(--status-pass-strong); }
.badge.bg-danger    { --bs-bg-opacity: .16; color: var(--status-fail-strong); }
.badge.bg-warning   { --bs-bg-opacity: .16; color: var(--status-warn-strong); }
.badge.bg-info      { --bs-bg-opacity: .16; color: var(--status-info-strong); }
/* Tints from --bs-secondary-rgb, which tokens.css pins per theme for
   .text-secondary legibility. The resulting tint stays readable in both
   modes (measured), so this keeps the no-!important approach. */
.badge.bg-secondary { --bs-bg-opacity: .22; color: var(--status-skip-strong); }
.badge.bg-purple    { background-color: var(--brand-subtle); color: var(--brand); }

/* ---- Status text ------------------------------------------------------------ */
.status-pass  { color: var(--status-pass-strong); font-weight: 600; }
.status-pass::before  { content: "\2713  "; }
.status-fail  { color: var(--status-fail-strong); font-weight: 600; }
.status-fail::before  { content: "\2717  "; }
.status-error { color: var(--status-warn-strong); font-weight: 600; }
.status-error::before { content: "\26A0  "; }
.status-other { color: var(--text-secondary); font-weight: 600; }

/* ---- Stat cards -------------------------------------------------------------- */
.stat-card {
  border: none;
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: var(--shadow-md);
  transition: transform .2s, box-shadow .2s;
}
.stat-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.stat-card .stat-icon {
  width: 50px; height: 50px;
  border-radius: var(--radius-lg);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem;
}
.stat-card .stat-value { font-size: 2rem; font-weight: 700; }
.stat-card .stat-label {
  font-size: .75rem;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.stat-value--pass { color: var(--status-pass-strong); }
.stat-value--fail { color: var(--status-fail-strong); }

/* ---- Code blocks -------------------------------------------------------------
   Replaces eleven <pre> elements that each copy-pasted the palette into an
   inline style attribute.                                                    */
.code-block {
  background: var(--surface-sunken);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: .85rem;
  line-height: 1.6;
  padding: 1rem;
  overflow-x: auto;
  max-height: 60vh;
}
.code-block--wrap { white-space: pre-wrap; word-wrap: break-word; max-height: none; }

.surface-sunken { background: var(--surface-sunken); }

/* One-time plaintext API key reveal. */
.key-display {
  background: var(--surface-sunken);
  padding: 1rem;
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  word-break: break-all;
  border: 1px solid var(--border-subtle);
  color: var(--brand);
  font-size: .95rem;
}
.small-mono { font-family: var(--font-mono); font-size: .8rem; color: var(--brand); }

/* ---- Python syntax highlighting ----------------------------------------------
   Emitted by highlightPython() in index.html, which used to inject raw hex
   into inline style attributes.                                             */
.tok-comment   { color: var(--syntax-comment); font-style: italic; }
.tok-keyword   { color: var(--syntax-keyword); }
.tok-string    { color: var(--syntax-string); }
.tok-number    { color: var(--syntax-number); }
.tok-decorator { color: var(--syntax-decorator); }
.tok-fn        { color: var(--syntax-function); }

/* ---- Live log panel ----------------------------------------------------------- */
.log-panel {
  max-height: 70vh;
  overflow-y: auto;
  font-family: var(--font-mono);
  font-size: .82rem;
  background: var(--surface-sunken);
  color: var(--text-primary);
  padding: 1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}
.log-entry { padding: 4px 0; border-bottom: 1px solid var(--log-rule); }
.log-entry:last-child { border-bottom: none; }
.log-timestamp     { color: var(--log-timestamp); margin-right: 10px; }
.log-level-debug   { color: var(--log-debug); }
.log-level-info    { color: var(--log-info); }
.log-level-warning { color: var(--log-warning); }
.log-level-error   { color: var(--log-error); }
.log-test          { color: var(--log-test); }
.log-site          { color: var(--log-site); }
.log-message       { color: var(--text-primary); }

/* ---- Run status pills ---------------------------------------------------------- */
.run-status {
  padding: .5rem 1rem;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: .875rem;
}
.run-status-running  { background: var(--status-warn-subtle); color: var(--status-warn-strong); border: 1px solid var(--status-warn); }
.run-status-complete { background: var(--status-pass-subtle); color: var(--status-pass-strong); border: 1px solid var(--status-pass); }
.run-status-error    { background: var(--status-fail-subtle); color: var(--status-fail-strong); border: 1px solid var(--status-fail); }

/* ---- Header nav links (shared by both shells) ------------------------------------ */
.nav-link-custom {
  color: var(--text-secondary);
  text-decoration: none;
  padding: .5rem .75rem;
  border-radius: var(--radius-sm);
  transition: all .2s;
  font-size: .9rem;
}
.nav-link-custom:hover {
  color: var(--text-primary);
  background: var(--brand-wash);
  text-decoration: none;
}
.nav-link-custom.active { color: var(--brand); background: var(--brand-subtle); }

/* ---- Theme toggle ---------------------------------------------------------------- */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  line-height: 1;
}
.theme-toggle:hover { border-color: var(--border-subtle); }
.theme-toggle__label { font-size: .85rem; }
.theme-toggle-float { position: fixed; top: 1rem; right: 1rem; z-index: 1050; }

.avatar-sm { width: 24px; height: 24px; border-radius: 50%; }

/* ---- YAML editor textarea --------------------------------------------------------- */
.yaml-editor {
  font-family: var(--font-mono);
  font-size: .875rem;
  line-height: 1.6;
  min-height: 500px;
  resize: vertical;
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  color: var(--text-primary);
}

/* ---- Error pages (401 / 403 / 404) ------------------------------------------------- */
.error-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  text-align: center;
}
.error-container { max-width: 560px; padding: 2rem; }
.cat-image { max-width: 220px; margin-bottom: 1.5rem; border-radius: var(--radius-lg); }
.error-code {
  font-size: 4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--brand);
  letter-spacing: -.03em;
}
.error-title { font-size: 1.5rem; font-weight: 600; margin: .5rem 0 1rem; color: var(--text-primary); }
.error-message { color: var(--text-secondary); margin-bottom: 1.5rem; }
.error-icon { font-size: 3.5rem; color: var(--brand); display: block; margin-bottom: .5rem; }

.error-detail {
  margin-top: 2rem;
  padding: 1.25rem;
  text-align: left;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}
.error-detail h6 { font-weight: 600; margin-bottom: .75rem; }
.role-badge { font-size: .8rem; vertical-align: baseline; }
.role-list { list-style: none; padding: 0; margin: 0; }
.role-list li { display: flex; align-items: center; gap: .6rem; padding: .35rem 0; }
.role-viewer { color: var(--status-pass); }
.role-runner { color: var(--status-info); }
.role-admin  { color: var(--status-warn); }
