/* ═══════════════════════════════════════════════════════════════════════════
   COMPONENTS — the UI kit.

   Loaded last so it wins over the legacy custom.css at equal specificity.

   Bootstrap variants are restyled by reassigning Bootstrap's own per-component
   custom properties (--bs-btn-bg, --bs-btn-hover-bg, …) rather than by
   overriding declarations. That keeps Bootstrap's internal state logic —
   :disabled, .active, .show, focus rings — working instead of fighting it, and
   needs no !important anywhere in this file.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ BUTTONS ══════════════════════════════════════════════════════════════ */

.btn {
  --bs-btn-padding-y: 0.4375rem;
  --bs-btn-padding-x: 0.875rem;
  --bs-btn-font-size: var(--fs-ui);
  --bs-btn-font-weight: var(--fw-semibold);
  --bs-btn-line-height: 1.35;
  --bs-btn-border-width: 1px;
  --bs-btn-border-radius: var(--radius-md);
  --bs-btn-focus-box-shadow: var(--ring-focus);
  --bs-btn-disabled-opacity: 0.45;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
  letter-spacing: var(--ls-normal);
  white-space: nowrap;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out),
              transform var(--dur-instant) var(--ease-out);
}

/* Tactile press. Kept tiny — a big scale reads as a toy. */
.btn:active:not(:disabled):not(.disabled) {
  transform: translateY(0.5px) scale(0.995);
}

.btn > i {
  font-size: 1.05em;
  line-height: 1;
}

.btn-sm {
  --bs-btn-padding-y: 0.25rem;
  --bs-btn-padding-x: 0.625rem;
  --bs-btn-font-size: var(--fs-sm);
  --bs-btn-border-radius: var(--radius-sm);
}

.btn-lg {
  --bs-btn-padding-y: 0.625rem;
  --bs-btn-padding-x: 1.25rem;
  --bs-btn-font-size: var(--fs-md);
  --bs-btn-border-radius: var(--radius-lg);
}

/* ─── Variants ──────────────────────────────────────────────────────────── */

.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-color: var(--text-on-brand);
  --bs-btn-hover-bg: var(--brand-hover);
  --bs-btn-hover-border-color: var(--brand-hover);
  --bs-btn-hover-color: var(--text-on-brand);
  --bs-btn-active-bg: var(--brand-active);
  --bs-btn-active-border-color: var(--brand-active);
  --bs-btn-active-color: var(--text-on-brand);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
  --bs-btn-disabled-color: var(--text-on-brand);
  box-shadow: var(--highlight-top-strong);
}

/* Secondary = a quiet filled surface, not a grey slab */
.btn-secondary {
  --bs-btn-bg: var(--surface-4);
  --bs-btn-border-color: var(--border-default);
  --bs-btn-color: var(--text-primary);
  --bs-btn-hover-bg: var(--surface-5);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--text-primary);
  --bs-btn-active-bg: var(--surface-5);
  --bs-btn-active-border-color: var(--border-strong);
  --bs-btn-active-color: var(--text-primary);
  --bs-btn-disabled-bg: var(--surface-3);
  --bs-btn-disabled-border-color: var(--border-subtle);
  --bs-btn-disabled-color: var(--text-disabled);
}

.btn-success {
  --bs-btn-bg: var(--status-success);
  --bs-btn-border-color: var(--status-success);
  --bs-btn-color: var(--text-on-brand);
  --bs-btn-hover-bg: var(--brand-hover);
  --bs-btn-hover-border-color: var(--brand-hover);
  --bs-btn-hover-color: var(--text-on-brand);
  --bs-btn-active-bg: var(--brand-active);
  --bs-btn-active-border-color: var(--brand-active);
  --bs-btn-active-color: var(--text-on-brand);
}

.btn-danger {
  --bs-btn-bg: var(--status-danger);
  --bs-btn-border-color: var(--status-danger);
  --bs-btn-color: var(--bd-white);
  --bs-btn-hover-bg: var(--bd-red-400);
  --bs-btn-hover-border-color: var(--bd-red-400);
  --bs-btn-hover-color: var(--bd-white);
  --bs-btn-active-bg: var(--bd-red-600);
  --bs-btn-active-border-color: var(--bd-red-600);
  --bs-btn-focus-box-shadow: var(--ring-danger);
}

/* Amber = caution. The legacy theme painted this dark red (#9f0000), which
   read as destructive; every current use is a confirm-gated bulk action. */
.btn-warning {
  --bs-btn-bg: var(--status-warning);
  --bs-btn-border-color: var(--status-warning);
  --bs-btn-color: var(--text-on-accent);
  --bs-btn-hover-bg: var(--accent-hover);
  --bs-btn-hover-border-color: var(--accent-hover);
  --bs-btn-hover-color: var(--text-on-accent);
  --bs-btn-active-bg: var(--bd-amber-600);
  --bs-btn-active-border-color: var(--bd-amber-600);
  --bs-btn-active-color: var(--text-on-accent);
}

.btn-info {
  --bs-btn-bg: var(--status-info);
  --bs-btn-border-color: var(--status-info);
  --bs-btn-color: var(--bd-teal-900);
  --bs-btn-hover-bg: var(--bd-teal-400);
  --bs-btn-hover-border-color: var(--bd-teal-400);
  --bs-btn-hover-color: var(--bd-teal-900);
  --bs-btn-active-bg: var(--bd-teal-600);
  --bs-btn-active-border-color: var(--bd-teal-600);
}

.btn-light {
  --bs-btn-bg: var(--bd-neutral-100);
  --bs-btn-border-color: var(--bd-neutral-100);
  --bs-btn-color: var(--text-inverse);
  --bs-btn-hover-bg: var(--bd-white);
  --bs-btn-hover-border-color: var(--bd-white);
  --bs-btn-hover-color: var(--text-inverse);
}

.btn-dark {
  --bs-btn-bg: var(--surface-1);
  --bs-btn-border-color: var(--border-default);
  --bs-btn-color: var(--text-primary);
  --bs-btn-hover-bg: var(--surface-2);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--text-primary);
}

/* ─── Outline variants ──────────────────────────────────────────────────── */

.btn-outline-primary {
  --bs-btn-color: var(--brand);
  --bs-btn-border-color: var(--border-brand);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--brand-subtle);
  --bs-btn-hover-border-color: var(--brand);
  --bs-btn-hover-color: var(--brand-hover);
  --bs-btn-active-bg: var(--brand-subtle-hi);
  --bs-btn-active-border-color: var(--brand);
  --bs-btn-active-color: var(--brand-hover);
}

.btn-outline-secondary,
.btn-outline-light,
.btn-outline-dark {
  --bs-btn-color: var(--text-secondary);
  --bs-btn-border-color: var(--border-default);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--surface-hover);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-hover-color: var(--text-primary);
  --bs-btn-active-bg: var(--surface-active);
  --bs-btn-active-border-color: var(--border-strong);
  --bs-btn-active-color: var(--text-primary);
}

.btn-outline-danger {
  --bs-btn-color: var(--bd-red-400);
  --bs-btn-border-color: rgba(229, 72, 77, 0.42);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--status-danger-subtle);
  --bs-btn-hover-border-color: var(--status-danger);
  --bs-btn-hover-color: var(--bd-red-300);
  --bs-btn-focus-box-shadow: var(--ring-danger);
}

.btn-outline-warning {
  --bs-btn-color: var(--bd-amber-400);
  --bs-btn-border-color: rgba(248, 166, 47, 0.42);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--status-warning-subtle);
  --bs-btn-hover-border-color: var(--status-warning);
  --bs-btn-hover-color: var(--bd-amber-300);
}

.btn-outline-success {
  --bs-btn-color: var(--bd-green-400);
  --bs-btn-border-color: var(--border-brand);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--status-success-subtle);
  --bs-btn-hover-border-color: var(--status-success);
  --bs-btn-hover-color: var(--bd-green-300);
}

.btn-outline-info {
  --bs-btn-color: var(--bd-teal-400);
  --bs-btn-border-color: rgba(79, 195, 195, 0.42);
  --bs-btn-bg: transparent;
  --bs-btn-hover-bg: var(--status-info-subtle);
  --bs-btn-hover-border-color: var(--status-info);
  --bs-btn-hover-color: var(--bd-teal-300);
}

.btn-link {
  --bs-btn-color: var(--brand);
  --bs-btn-hover-color: var(--brand-hover);
  --bs-btn-font-weight: var(--fw-medium);
  text-decoration: none;
}

.btn-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ─── Ghost: toolbar/table-row actions with no chrome until hovered ─────── */

.btn-ghost {
  --bs-btn-color: var(--text-tertiary);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-bg: var(--surface-hover);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-hover-color: var(--text-primary);
  --bs-btn-active-bg: var(--surface-active);
  --bs-btn-active-border-color: transparent;
  --bs-btn-active-color: var(--text-primary);
}

.btn-ghost-danger {
  --bs-btn-color: var(--text-tertiary);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-bg: var(--status-danger-subtle);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-hover-color: var(--bd-red-400);
}

/* ─── Icon-only ─────────────────────────────────────────────────────────── */

.btn-icon {
  --bs-btn-padding-x: 0;
  --bs-btn-padding-y: 0;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
}

.btn-icon.btn-sm { width: 28px; height: 28px; }
.btn-icon.btn-lg { width: 42px; height: 42px; }

/* ─── Loading state ─────────────────────────────────────────────────────── */

.btn.is-loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}

.btn.is-loading > * {
  visibility: hidden;
}

.btn.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1em;
  height: 1em;
  margin: -0.5em 0 0 -0.5em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-full);
  color: var(--bs-btn-color);
  animation: btn-spin 0.55s linear infinite;
  visibility: visible;
}

@keyframes btn-spin {
  to { transform: rotate(360deg); }
}

/* ─── Button group ──────────────────────────────────────────────────────── */

.btn-group > .btn {
  --bs-btn-border-radius: var(--radius-md);
}

.btn-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}


/* ═══ SEGMENTED CONTROL ════════════════════════════════════════════════════
   For view switches (grid/table, date ranges). Reads as one object rather
   than a row of separate buttons. */

.segmented {
  display: inline-flex;
  padding: 2px;
  background: var(--surface-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.segmented__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  text-decoration: none;
  background: none;
  border: 0;
  border-radius: calc(var(--radius-md) - 3px);
  transition: var(--transition-colors);
}

.segmented__item:hover {
  color: var(--text-secondary);
}

.segmented__item.is-active {
  color: var(--text-primary);
  background: var(--surface-5);
  box-shadow: var(--shadow-xs), var(--highlight-top);
}


/* ═══ FORM CONTROLS ════════════════════════════════════════════════════════ */

.form-label {
  margin-bottom: var(--space-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
}

.form-label--required::after {
  content: "*";
  margin-left: 2px;
  color: var(--status-danger);
}

.form-control,
.form-select {
  --bs-border-radius: var(--radius-md);
  padding: 0.4375rem 0.75rem;
  font-size: var(--fs-ui);
  line-height: 1.4;
  color: var(--text-primary);
  background-color: var(--surface-3);
  border: 1px solid var(--border-default);
  box-shadow: none;
  transition: border-color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

.form-control:hover:not(:disabled):not(:focus),
.form-select:hover:not(:disabled):not(:focus) {
  border-color: var(--border-strong);
}

.form-control:focus,
.form-select:focus {
  color: var(--text-primary);
  background-color: var(--surface-3);
  border-color: var(--border-focus);
  box-shadow: var(--ring-focus);
}

.form-control::placeholder {
  color: var(--text-muted);
}

.form-control:disabled,
.form-select:disabled {
  color: var(--text-disabled);
  background-color: var(--surface-2);
  border-color: var(--border-subtle);
}

.form-control-sm,
.form-select-sm {
  padding: 0.25rem 0.5rem;
  font-size: var(--fs-sm);
  --bs-border-radius: var(--radius-sm);
}

.form-control-lg,
.form-select-lg {
  padding: 0.625rem 1rem;
  font-size: var(--fs-md);
  --bs-border-radius: var(--radius-lg);
}

/* Native select needs a light caret on a dark field */
.form-select {
  padding-right: 2.25rem;
  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='%237fabb7' 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: 14px 11px;
}

/* The dropdown list itself is OS-rendered; only bg/color are honoured */
.form-select option,
.form-control option {
  color: var(--text-primary);
  background-color: var(--surface-4);
}

.form-text {
  margin-top: var(--space-1);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

textarea.form-control {
  min-height: 5rem;
  line-height: var(--lh-normal);
}

/* ─── Checkbox / radio ──────────────────────────────────────────────────── */

.form-check {
  min-height: auto;
  margin-bottom: var(--space-2);
  padding-left: 1.65em;
}

.form-check-input {
  width: 1.05em;
  height: 1.05em;
  margin-top: 0.2em;
  margin-left: -1.65em;
  background-color: var(--surface-3);
  border: 1px solid var(--border-strong);
  transition: var(--transition-colors);
}

.form-check-input:hover:not(:disabled) {
  border-color: var(--border-brand);
}

.form-check-input:checked {
  background-color: var(--brand);
  border-color: var(--brand);
}

.form-check-input:focus {
  border-color: var(--border-focus);
  box-shadow: var(--ring-focus);
}

.form-check-input[type="checkbox"] {
  border-radius: var(--radius-xs);
}

.form-check-label {
  font-size: var(--fs-ui);
  color: var(--text-secondary);
  cursor: pointer;
}

.form-switch {
  padding-left: 2.5em;
}

.form-switch .form-check-input {
  width: 2em;
  height: 1.1em;
  margin-left: -2.5em;
  border-radius: var(--radius-full);
}

/* ─── Input group ───────────────────────────────────────────────────────── */

.input-group-text {
  padding: 0.4375rem 0.75rem;
  font-size: var(--fs-ui);
  color: var(--text-muted);
  background-color: var(--surface-4);
  border: 1px solid var(--border-default);
}

/* ─── Validation ────────────────────────────────────────────────────────── */

.form-control.is-invalid,
.form-select.is-invalid,
.was-validated .form-control:invalid,
.was-validated .form-select:invalid {
  border-color: var(--status-danger);
  background-image: none;
}

.form-control.is-invalid:focus,
.was-validated .form-control:invalid:focus {
  border-color: var(--status-danger);
  box-shadow: var(--ring-danger);
}

.form-control.is-valid,
.was-validated .form-control:valid {
  border-color: var(--status-success);
  background-image: none;
}

.invalid-feedback {
  font-size: var(--fs-xs);
  color: var(--bd-red-400);
}

.valid-feedback {
  font-size: var(--fs-xs);
  color: var(--bd-green-400);
}

/* ─── Field grid ────────────────────────────────────────────────────────── */

.field-grid {
  display: grid;
  gap: var(--space-4) var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}

.field-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.field-grid__full { grid-column: 1 / -1; }


/* ═══ SELECT2 ══════════════════════════════════════════════════════════════
   Select2 renders into a detached container at the end of <body>, so it never
   inherits page context and has to be themed on its own. The legacy rules
   styled it for a light theme (white field, #212529 text), which is why the
   marketplace filters rendered as bright boxes on a dark page. */

.select2-container {
  width: 100% !important;
}

.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
  min-height: 36px;
  height: auto;
  padding: 0;
  color: var(--text-primary);
  background-color: var(--surface-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

.select2-container--default .select2-selection--single:hover,
.select2-container--default .select2-selection--multiple:hover {
  border-color: var(--border-strong);
}

.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--multiple {
  border-color: var(--border-focus);
  box-shadow: var(--ring-focus);
}

.select2-container--default .select2-selection--single .select2-selection__rendered {
  padding: 0 2rem 0 0.75rem;
  font-size: var(--fs-ui);
  line-height: 34px;
  color: var(--text-primary);
}

.select2-container--default .select2-selection--single .select2-selection__placeholder {
  color: var(--text-muted);
}

.select2-container--default .select2-selection--single .select2-selection__arrow {
  top: 0;
  right: 0.5rem;
  height: 34px;
}

.select2-container--default .select2-selection--single .select2-selection__arrow b {
  border-color: var(--text-muted) transparent transparent;
}

.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
  border-color: transparent transparent var(--text-muted);
}

.select2-container--default .select2-selection--single .select2-selection__clear {
  margin-right: var(--space-2);
  color: var(--text-muted);
  font-weight: var(--fw-regular);
}

.select2-container--default .select2-selection--single .select2-selection__clear:hover {
  color: var(--bd-red-400);
}

/* Multi-select tokens */
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
  padding: 3px 5px;
  margin: 0;
}

.select2-container--default .select2-selection--multiple .select2-selection__choice {
  margin: 3px 4px 3px 0;
  padding: 1px 7px;
  font-size: var(--fs-xs);
  color: var(--bd-green-200);
  background-color: var(--brand-subtle-hi);
  border: 1px solid var(--border-brand);
  border-radius: var(--radius-sm);
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
  margin-right: 4px;
  color: var(--bd-green-300);
  border: 0;
  background: none;
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
  color: var(--bd-white);
  background: none;
}

.select2-container--default .select2-search--inline .select2-search__field {
  margin-top: 5px;
  font-family: var(--font-sans);
  font-size: var(--fs-ui);
  color: var(--text-primary);
}

/* Dropdown panel */
.select2-dropdown {
  color: var(--text-secondary);
  background-color: var(--surface-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}

.select2-container--default .select2-search--dropdown {
  padding: var(--space-2);
  background: var(--surface-4);
  border-bottom: 1px solid var(--border-subtle);
}

.select2-container--default .select2-search--dropdown .select2-search__field {
  padding: 0.3rem 0.5rem;
  font-size: var(--fs-ui);
  color: var(--text-primary);
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  outline: none;
}

.select2-container--default .select2-search--dropdown .select2-search__field:focus {
  border-color: var(--border-focus);
  box-shadow: var(--ring-focus);
}

.select2-results {
  color: var(--text-secondary);
}

.select2-results__options {
  max-height: 260px;
  padding: var(--space-1);
}

.select2-container--default .select2-results__option {
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-ui);
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
}

.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted {
  color: var(--text-primary);
  background-color: var(--surface-hover);
}

.select2-container--default .select2-results__option[aria-selected="true"],
.select2-container--default .select2-results__option--selected {
  color: var(--brand);
  background-color: var(--surface-selected);
  font-weight: var(--fw-medium);
}

.select2-container--default .select2-results__option[aria-disabled="true"] {
  color: var(--text-disabled);
}

.select2-container--default .select2-results__group {
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
}


/* ═══ PANEL / CARD ═════════════════════════════════════════════════════════ */

.panel {
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm), var(--highlight-top);
}

.panel__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

.panel__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
}

.panel__title > i {
  color: var(--text-muted);
  font-size: 0.95em;
}

.panel__subtitle {
  margin: 2px 0 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.panel__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.panel__body {
  padding: var(--space-5);
}

.panel__body--flush {
  padding: 0;
}

.panel__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--border-subtle);
}

/* Bootstrap .card is used on ~40 pages; align it to the panel treatment so
   both read identically while pages are migrated one at a time. */
.card {
  --bs-card-border-radius: var(--radius-lg);
  --bs-card-inner-border-radius: calc(var(--radius-lg) - 1px);
  --bs-card-spacer-y: var(--space-4);
  --bs-card-spacer-x: var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-sm), var(--highlight-top);
  transition: border-color var(--dur-normal) var(--ease-out),
              box-shadow var(--dur-normal) var(--ease-out),
              transform var(--dur-normal) var(--ease-out);
}

.card-header,
.card-footer {
  background: transparent;
  border-color: var(--border-subtle);
}

.card-title {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
}

.card-text {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* Interactive cards signal that the whole surface is a target */
.card--link,
.card[data-href],
a.card {
  cursor: pointer;
  text-decoration: none;
}

.card--link:hover,
.card[data-href]:hover,
a.card:hover {
  border-color: var(--border-brand);
  box-shadow: var(--shadow-lg), var(--highlight-top);
  transform: translateY(-2px);
}


/* ═══ STAT TILE ════════════════════════════════════════════════════════════ */

.stat-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  margin-bottom: var(--space-6);
}

.stat {
  position: relative;
  padding: var(--space-4);
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--highlight-top);
  transition: border-color var(--dur-normal) var(--ease-out);
}

.stat:hover {
  border-color: var(--border-default);
}

.stat__label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--text-muted);
}

.stat__value {
  margin-top: var(--space-2);
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.stat__meta {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.stat__delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

.stat__delta--up   { color: var(--bd-green-400); }
.stat__delta--down { color: var(--bd-red-400); }
.stat__delta--flat { color: var(--text-muted); }

/* Accent rule keyed to the metric's role */
.stat__accent {
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--brand);
}

.stat--info    .stat__accent { background: var(--status-info); }
.stat--warning .stat__accent { background: var(--status-warning); }
.stat--danger  .stat__accent { background: var(--status-danger); }
.stat--neutral .stat__accent { background: var(--bd-neutral-500); }


/* ═══ DATA TABLE ═══════════════════════════════════════════════════════════
   The dense-table pattern that carries the management pages. Wrap in
   .table-wrap for horizontal overflow without the page body scrolling. */

.table-wrap {
  width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm), var(--highlight-top);
}

.table-wrap--flush {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.data-table {
  width: 100%;
  margin: 0;
  font-size: var(--fs-sm);
  border-collapse: separate;
  border-spacing: 0;
}

.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
  background: var(--surface-3);
  border-bottom: 1px solid var(--border-default);
}

.data-table thead th:first-child { border-top-left-radius: calc(var(--radius-lg) - 1px); }
.data-table thead th:last-child  { border-top-right-radius: calc(var(--radius-lg) - 1px); }

/* Sortable header */
.data-table th.is-sortable {
  cursor: pointer;
  user-select: none;
  transition: color var(--dur-fast) var(--ease-out);
}

.data-table th.is-sortable:hover {
  color: var(--text-secondary);
}

.data-table th.is-sortable::after {
  content: "\F282"; /* bi-chevron-expand */
  display: inline-block;
  margin-left: var(--space-2);
  font-family: "bootstrap-icons";
  font-size: 0.85em;
  font-weight: normal;
  opacity: 0.35;
  vertical-align: -1px;
}

.data-table th.is-sorted-asc::after {
  content: "\F286"; /* bi-chevron-up */
  opacity: 1;
  color: var(--brand);
}

.data-table th.is-sorted-desc::after {
  content: "\F282";
  content: "\F229"; /* bi-chevron-down */
  opacity: 1;
  color: var(--brand);
}

.data-table tbody td {
  padding: var(--space-3) var(--space-4);
  color: var(--text-secondary);
  vertical-align: middle;
  border-bottom: 1px solid var(--border-subtle);
}

.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.data-table tbody tr {
  transition: background-color var(--dur-fast) var(--ease-out);
}

.data-table tbody tr:hover {
  background: var(--surface-hover);
}

.data-table tbody tr.is-selected {
  background: var(--surface-selected);
}

/* Density variants */
.data-table--compact tbody td,
.data-table--compact thead th {
  padding: var(--space-2) var(--space-3);
}

.data-table--relaxed tbody td {
  padding: var(--space-4);
}

/* Column helpers */
.data-table .col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.data-table .col-actions {
  width: 1%;
  text-align: right;
  white-space: nowrap;
}

.data-table .col-check {
  width: 1%;
  padding-right: 0;
}

.data-table .col-thumb {
  width: 1%;
  padding-right: 0;
}

/* Row actions stay hidden until the row is hovered or focused within,
   which keeps a dense table calm without hiding the affordance from
   keyboard users. */
.data-table .row-actions {
  display: inline-flex;
  gap: var(--space-1);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.data-table tbody tr:hover .row-actions,
.data-table tbody tr:focus-within .row-actions,
.data-table tbody tr.is-selected .row-actions {
  opacity: 1;
}

@media (hover: none) {
  .data-table .row-actions { opacity: 1; }
}

/* Primary cell: thumbnail + title + sub-line */
.cell-primary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.cell-thumb {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  overflow: hidden;
  background: var(--surface-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.cell-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cell-body {
  min-width: 0;
}

.cell-title {
  display: block;
  overflow: hidden;
  font-size: var(--fs-ui);
  font-weight: var(--fw-medium);
  color: var(--text-primary);
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;
}

a.cell-title:hover {
  color: var(--brand);
}

.cell-sub {
  display: block;
  overflow: hidden;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Bootstrap .table alignment for pages not yet migrated */
.table {
  --bs-table-bg: transparent;
  font-size: var(--fs-sm);
}

.table > :not(caption) > * > * {
  padding: var(--space-3) var(--space-4);
  background-color: transparent;
  box-shadow: none;
}

.table > thead {
  color: var(--text-muted);
}

.table > thead th {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  border-bottom-color: var(--border-default);
}


/* ═══ STATUS PILL ══════════════════════════════════════════════════════════ */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.15em 0.6em;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  line-height: 1.5;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: var(--radius-full);
}

.pill--dot::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: currentColor;
  flex-shrink: 0;
}

.pill--success { color: var(--bd-green-300);  background: var(--status-success-subtle); border-color: rgba(100, 200, 93, 0.28); }
.pill--warning { color: var(--bd-amber-300);  background: var(--status-warning-subtle); border-color: rgba(248, 166, 47, 0.28); }
.pill--danger  { color: var(--bd-red-300);    background: var(--status-danger-subtle);  border-color: rgba(229, 72, 77, 0.28); }
.pill--info    { color: var(--bd-teal-300);   background: var(--status-info-subtle);    border-color: rgba(79, 195, 195, 0.28); }
.pill--neutral { color: var(--text-tertiary); background: var(--status-neutral-subtle); border-color: var(--border-default); }
.pill--brand   { color: var(--bd-green-200);  background: var(--brand-subtle-hi);       border-color: var(--border-brand); }
.pill--accent  { color: var(--bd-amber-200);  background: var(--accent-subtle);         border-color: rgba(248, 166, 47, 0.35); }

.pill--solid {
  color: var(--text-on-brand);
  background: var(--brand);
  border-color: var(--brand);
}

.pill-sm {
  padding: 0.05em 0.45em;
  font-size: var(--fs-3xs);
}

/* Bootstrap badges follow the pill treatment */
.badge {
  --bs-badge-border-radius: var(--radius-sm);
  --bs-badge-font-weight: var(--fw-semibold);
  --bs-badge-font-size: var(--fs-xs);
  --bs-badge-padding-x: 0.55em;
  --bs-badge-padding-y: 0.3em;
  letter-spacing: var(--ls-normal);
}

.badge.bg-primary { color: var(--text-on-brand); background-color: var(--brand) !important; }
.badge.bg-success { color: var(--bd-green-200); background-color: var(--status-success-subtle) !important; border: 1px solid rgba(100, 200, 93, 0.28); }
.badge.bg-danger  { color: var(--bd-red-300);   background-color: var(--status-danger-subtle) !important;  border: 1px solid rgba(229, 72, 77, 0.28); }
.badge.bg-warning { color: var(--bd-amber-200); background-color: var(--status-warning-subtle) !important; border: 1px solid rgba(248, 166, 47, 0.28); }
.badge.bg-info    { color: var(--bd-teal-300);  background-color: var(--status-info-subtle) !important;    border: 1px solid rgba(79, 195, 195, 0.28); }
.badge.bg-secondary { color: var(--text-tertiary); background-color: var(--status-neutral-subtle) !important; border: 1px solid var(--border-default); }

/* `.badge bg-warning text-dark` is a standard Bootstrap pairing: the stock
   bg-warning is bright yellow, so it needs dark text. These badges are now dark
   translucent tints, which makes `.text-dark` (a `#212529 !important` utility)
   produce dark-on-dark — measured 1.40:1 on the classifieds type badge.
   Re-asserting the variant colour is safer than hunting every template, since
   the pairing appears across admin, classifieds and clutch pages and would
   otherwise creep back in. */
.badge.bg-warning.text-dark { color: var(--bd-amber-200) !important; }
.badge.bg-info.text-dark    { color: var(--bd-teal-300) !important; }
.badge.bg-success.text-dark { color: var(--bd-green-200) !important; }
.badge.bg-primary.text-dark { color: var(--text-on-brand) !important; }


/* ═══ AVATAR ═══════════════════════════════════════════════════════════════ */

.avatar {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  overflow: hidden;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  color: var(--text-on-brand);
  text-transform: uppercase;
  background: linear-gradient(135deg, var(--bd-green-400), var(--bd-green-600));
  border-radius: var(--radius-full);
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-sm { width: 24px; height: 24px; font-size: var(--fs-3xs); }
.avatar-lg { width: 44px; height: 44px; font-size: var(--fs-ui); }
.avatar-xl { width: 72px; height: 72px; font-size: var(--fs-lg); }

.avatar--square { border-radius: var(--radius-md); }

.avatar-stack {
  display: flex;
}

.avatar-stack > .avatar {
  margin-left: -8px;
  border: 2px solid var(--surface-2);
}

.avatar-stack > .avatar:first-child {
  margin-left: 0;
}


/* ═══ TABS ═════════════════════════════════════════════════════════════════ */

.tabs {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--border-subtle);
}

.tabs::-webkit-scrollbar { display: none; }

.tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-ui);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  background: none;
  border: 0;
  transition: var(--transition-colors);
}

.tab:hover {
  color: var(--text-secondary);
}

.tab.is-active {
  color: var(--text-primary);
}

.tab.is-active::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px 0;
  height: 2px;
  background: var(--brand);
  border-radius: var(--radius-full) var(--radius-full) 0 0;
}

.tab__count {
  padding: 0 0.35em;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  color: var(--text-muted);
  background: var(--surface-4);
  border-radius: var(--radius-full);
  font-variant-numeric: tabular-nums;
}

.tab.is-active .tab__count {
  color: var(--brand);
  background: var(--brand-subtle-hi);
}

/* Bootstrap nav-tabs follow the same treatment */
.nav-tabs {
  border-bottom-color: var(--border-subtle);
}

.nav-tabs .nav-link {
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-ui);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  transition: var(--transition-colors);
}

.nav-tabs .nav-link:hover {
  color: var(--text-secondary);
  border-color: transparent;
}

.nav-tabs .nav-link.active {
  color: var(--text-primary);
  background: none;
  border-bottom-color: var(--brand);
}


/* ═══ FILTER BAR / CHIPS ═══════════════════════════════════════════════════ */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}

.filter-bar__group {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.filter-bar__spacer {
  flex: 1;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.2rem 0.5rem 0.2rem 0.65rem;
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--bd-green-200);
  background: var(--brand-subtle);
  border: 1px solid var(--border-brand);
  border-radius: var(--radius-full);
}

.chip__remove {
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  font-size: 0.7rem;
  color: var(--bd-green-300);
  background: none;
  border: 0;
  border-radius: var(--radius-full);
  transition: var(--transition-colors);
}

.chip__remove:hover {
  color: var(--bd-white);
  background: rgba(255, 255, 255, 0.12);
}

.chip--neutral {
  color: var(--text-secondary);
  background: var(--surface-4);
  border-color: var(--border-default);
}


/* ═══ EMPTY STATE ══════════════════════════════════════════════════════════ */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-12) var(--space-6);
  text-align: center;
}

.empty__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: var(--space-4);
  font-size: 1.5rem;
  color: var(--text-muted);
  background: var(--surface-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
}

.empty__title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  color: var(--text-primary);
}

.empty__text {
  max-width: 42ch;
  margin: 0 0 var(--space-5);
  font-size: var(--fs-ui);
  color: var(--text-muted);
}

.empty__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
}

.empty--compact {
  padding: var(--space-8) var(--space-4);
}

.empty--compact .empty__icon {
  width: 40px;
  height: 40px;
  font-size: 1.15rem;
  border-radius: var(--radius-lg);
}


/* ═══ SKELETON ═════════════════════════════════════════════════════════════ */

.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--surface-3);
  border-radius: var(--radius-sm);
  /* Never let a skeleton read as content */
  color: transparent;
  user-select: none;
  pointer-events: none;
}

.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    transparent,
    rgba(255, 255, 255, 0.055),
    transparent);
  transform: translateX(-100%);
  animation: skeleton-sweep 1.4s var(--ease-in-out) infinite;
}

@keyframes skeleton-sweep {
  to { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}

.skeleton-text {
  height: 0.7em;
  margin: 0.3em 0;
  border-radius: var(--radius-full);
}

.skeleton-text--sm { width: 35%; }
.skeleton-text--md { width: 60%; }
.skeleton-text--lg { width: 85%; }

.skeleton-circle {
  border-radius: var(--radius-full);
}

.skeleton-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}


/* ═══ TOASTS ═══════════════════════════════════════════════════════════════ */

.toast-stack {
  position: fixed;
  top: calc(var(--topbar-h) + var(--space-3));
  right: var(--space-4);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(380px, calc(100vw - var(--space-8)));
  pointer-events: none;
}

.toast-stack > * {
  pointer-events: auto;
}

.toast-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-ui);
  color: var(--text-secondary);
  background: var(--surface-4);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--bd-neutral-500);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xl);
  animation: toast-in var(--dur-normal) var(--ease-spring);
}

.toast-item.is-leaving {
  animation: toast-out var(--dur-fast) var(--ease-in) forwards;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateX(16px) scale(0.97); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}

@keyframes toast-out {
  to { opacity: 0; transform: translateX(16px); }
}

.toast-item__icon {
  flex-shrink: 0;
  margin-top: 1px;
  font-size: 1.05rem;
}

.toast-item__body {
  flex: 1;
  min-width: 0;
}

.toast-item__title {
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
}

.toast-item__text {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.toast-item__close {
  flex-shrink: 0;
  padding: 0;
  font-size: 0.85rem;
  color: var(--text-muted);
  background: none;
  border: 0;
  transition: color var(--dur-fast) var(--ease-out);
}

.toast-item__close:hover {
  color: var(--text-primary);
}

.toast-item--success { border-left-color: var(--status-success); }
.toast-item--success .toast-item__icon { color: var(--status-success); }
.toast-item--danger  { border-left-color: var(--status-danger); }
.toast-item--danger  .toast-item__icon { color: var(--status-danger); }
.toast-item--warning { border-left-color: var(--status-warning); }
.toast-item--warning .toast-item__icon { color: var(--status-warning); }
.toast-item--info    { border-left-color: var(--status-info); }
.toast-item--info    .toast-item__icon { color: var(--status-info); }


/* ═══ ALERTS ═══════════════════════════════════════════════════════════════ */

.alert {
  --bs-alert-border-radius: var(--radius-md);
  --bs-alert-padding-y: var(--space-3);
  --bs-alert-padding-x: var(--space-4);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--fs-ui);
  border-width: 1px;
  border-left-width: 3px;
}

.alert > i:first-child {
  flex-shrink: 0;
  margin-top: 2px;
  font-size: 1.05rem;
}

.alert-success { --bs-alert-color: var(--bd-green-200); --bs-alert-bg: var(--status-success-subtle); --bs-alert-border-color: rgba(100, 200, 93, 0.3); border-left-color: var(--status-success); }
.alert-danger  { --bs-alert-color: var(--bd-red-300);   --bs-alert-bg: var(--status-danger-subtle);  --bs-alert-border-color: rgba(229, 72, 77, 0.3);  border-left-color: var(--status-danger); }
.alert-warning { --bs-alert-color: var(--bd-amber-200); --bs-alert-bg: var(--status-warning-subtle); --bs-alert-border-color: rgba(248, 166, 47, 0.3); border-left-color: var(--status-warning); }
.alert-info    { --bs-alert-color: var(--bd-teal-300);  --bs-alert-bg: var(--status-info-subtle);    --bs-alert-border-color: rgba(79, 195, 195, 0.3); border-left-color: var(--status-info); }
.alert-primary { --bs-alert-color: var(--bd-green-200); --bs-alert-bg: var(--brand-subtle);          --bs-alert-border-color: var(--border-brand);     border-left-color: var(--brand); }
.alert-secondary,
.alert-light,
.alert-dark    { --bs-alert-color: var(--text-secondary); --bs-alert-bg: var(--surface-3); --bs-alert-border-color: var(--border-default); border-left-color: var(--bd-neutral-500); }

.alert-dismissible {
  padding-right: var(--space-10);
}

/* Close button.
   Ships its own light glyph rather than inverting Bootstrap's dark one.
   `filter: invert(1)` — the usual dark-theme trick — was actively wrong here:
   custom.css already supplied a WHITE svg, so inverting it produced a black X
   on a dark modal, i.e. an invisible close button on every dialog. Owning the
   image outright removes the ordering dependency entirely. */
.btn-close {
  width: 1.5em;
  height: 1.5em;
  padding: 0.25em;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23dceaee'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e") center / 1em auto no-repeat;
  filter: none;
  opacity: 0.55;
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
}

.btn-close:hover {
  opacity: 1;
  background-color: var(--surface-hover);
}

.btn-close:focus-visible {
  opacity: 1;
  outline: 2px solid var(--border-focus);
  outline-offset: 1px;
  box-shadow: none;
}


/* ═══ DROPDOWN ═════════════════════════════════════════════════════════════ */

.dropdown-menu {
  --bs-dropdown-padding-y: var(--space-1);
  --bs-dropdown-item-padding-y: var(--space-2);
  --bs-dropdown-item-padding-x: var(--space-3);
  --bs-dropdown-font-size: var(--fs-ui);
  --bs-dropdown-min-width: 11rem;
  box-shadow: var(--shadow-xl), var(--highlight-top);
  animation: dropdown-in var(--dur-fast) var(--ease-out);
}

@keyframes dropdown-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 1px var(--space-1);
  width: auto;
  border-radius: var(--radius-sm);
  transition: var(--transition-colors);
}

.dropdown-item > i {
  width: 16px;
  font-size: 0.95em;
  text-align: center;
  color: var(--text-muted);
}

.dropdown-item:hover > i,
.dropdown-item.active > i {
  color: inherit;
}

.dropdown-item--danger {
  color: var(--bd-red-400);
}

.dropdown-item--danger:hover {
  color: var(--bd-red-300);
  background: var(--status-danger-subtle);
}

.dropdown-header {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
}


/* ═══ MODAL ════════════════════════════════════════════════════════════════ */

.modal-content {
  --bs-modal-border-radius: var(--radius-xl);
  --bs-modal-padding: var(--space-5);
  --bs-modal-header-padding: var(--space-4) var(--space-5);
  background: var(--surface-3);
  border: 1px solid var(--border-default);
  box-shadow: var(--shadow-2xl), var(--highlight-top-strong);
}

.modal-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
}

.modal-header,
.modal-footer {
  border-color: var(--border-subtle);
}

.modal-footer {
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
}

.modal-backdrop {
  --bs-backdrop-bg: var(--bd-neutral-990);
  --bs-backdrop-opacity: 0.7;
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}


/* ═══ PAGINATION ═══════════════════════════════════════════════════════════ */

.pagination {
  --bs-pagination-padding-y: 0.3rem;
  --bs-pagination-padding-x: 0.7rem;
  --bs-pagination-font-size: var(--fs-sm);
  --bs-pagination-border-radius: var(--radius-md);
  gap: var(--space-1);
  align-items: center;
}

.page-link {
  min-width: 34px;
  font-weight: var(--fw-medium);
  text-align: center;
  border-radius: var(--radius-md);
  transition: var(--transition-colors);
}

.page-item.active .page-link {
  font-weight: var(--fw-bold);
  box-shadow: var(--highlight-top-strong);
}

/* Long paginators need an ellipsis, not 40 numbers */
.pagination__gap {
  padding: 0 var(--space-1);
  color: var(--text-muted);
  user-select: none;
}


/* ═══ PROGRESS ═════════════════════════════════════════════════════════════ */

.progress,
.progress-stacked {
  background: var(--surface-4);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.progress-bar {
  background: var(--brand);
  transition: width var(--dur-slow) var(--ease-out);
}

.progress-bar-striped {
  background-image: linear-gradient(45deg,
    rgba(255, 255, 255, 0.13) 25%, transparent 25%,
    transparent 50%, rgba(255, 255, 255, 0.13) 50%,
    rgba(255, 255, 255, 0.13) 75%, transparent 75%, transparent);
}


/* ═══ KEY-VALUE LIST ═══════════════════════════════════════════════════════
   Detail pages (animal, breeder, plant, order) are mostly attribute lists;
   this makes them scannable instead of a wall of paragraphs. */

.kv {
  display: grid;
  grid-template-columns: minmax(7rem, auto) 1fr;
  gap: var(--space-3) var(--space-5);
  margin: 0;
  font-size: var(--fs-ui);
}

.kv__key {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  padding-top: 1px;
}

.kv__val {
  margin: 0;
  color: var(--text-primary);
  min-width: 0;
  overflow-wrap: break-word;
}

.kv__val--empty {
  color: var(--text-muted);
  font-style: italic;
}

/* Stacked on narrow screens — a 2-col grid at 360px produces 4-char columns */
@media (max-width: 575.98px) {
  .kv {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }

  .kv__val {
    margin-bottom: var(--space-3);
  }
}

/* Inline meta row: "· Female · Ball Python · Cape Town" */
.meta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.meta-row > * {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}

.meta-row > * + *::before {
  content: "·";
  margin-right: 0.35em;
  color: var(--text-muted);
}


/* ═══ LISTING CARD ═════════════════════════════════════════════════════════
   The marketplace grid unit — animals, plants, products, auctions. */

.listing-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr));
}

.listing {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm), var(--highlight-top);
  text-decoration: none;
  transition: border-color var(--dur-normal) var(--ease-out),
              box-shadow var(--dur-normal) var(--ease-out),
              transform var(--dur-normal) var(--ease-out);
}

.listing:hover {
  border-color: var(--border-brand);
  box-shadow: var(--shadow-lg), var(--highlight-top);
  transform: translateY(-3px);
}

.listing__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--surface-3);
}

.listing__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slower) var(--ease-out);
}

.listing:hover .listing__media img {
  transform: scale(1.045);
}

/* Scrim so overlaid text stays legible on any photo */
.listing__media::after {
  content: "";
  position: absolute;
  inset: 40% 0 0;
  background: linear-gradient(to top, rgba(6, 15, 19, 0.82), transparent);
  pointer-events: none;
}

.listing__badges {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* Status pills over photography need their own backdrop. The translucent
   .pill--* fills are tuned for flat surfaces and vanish over a busy image —
   a green-on-substrate "For sale" was effectively unreadable. Same glass
   treatment as .listing__price, which reads cleanly over any photo. */
.listing__badges .pill {
  padding: 0.15em 0.55em;
  font-size: var(--fs-2xs);
  background: var(--surface-glass);
  border-color: var(--border-default);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.listing__badges .pill--success {
  color: var(--bd-green-300);
  border-color: var(--border-brand);
}

.listing__badges .pill--neutral {
  color: var(--text-secondary);
}

.listing__price {
  position: absolute;
  right: var(--space-2);
  bottom: var(--space-2);
  z-index: 2;
  padding: 0.15rem 0.5rem;
  font-family: var(--font-display);
  font-size: var(--fs-ui);
  font-weight: var(--fw-bold);
  color: var(--text-primary);
  background: var(--surface-glass);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-variant-numeric: tabular-nums;
}

.listing__fav {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  font-size: 0.9rem;
  color: var(--text-primary);
  background: var(--surface-glass);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: var(--transition-colors);
}

.listing__fav:hover,
.listing__fav.is-active {
  color: var(--bd-red-400);
  border-color: rgba(229, 72, 77, 0.5);
}

/* Stand-in when a record has no image (breeders without a logo). Fills the same
   aspect box as a photo so the grid stays on a single baseline. */
.listing__fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  height: 100%;
  padding: var(--space-4);
  text-align: center;
  background: linear-gradient(135deg, var(--surface-3), var(--surface-5));
}

.listing__fallback > i {
  font-size: 2rem;
  color: var(--text-muted);
}

.listing__fallback > span {
  font-family: var(--font-display);
  font-size: var(--fs-ui);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  color: var(--text-secondary);
  /* long breeder names must not push the fallback taller than the photo box */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.listing__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4) var(--space-4);
}

/* Inline tag row (breeder types). Capped in markup at 3 + overflow count so a
   breeder with eight types cannot blow the card height out. */
.listing__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: var(--space-1) 0;
}


/* ─── .listing--doc — media-less variant ─────────────────────────────────────
   For records with no imagery (care sheets). The photo-led card gave every one
   of these an identical gradient block, so a third of each card was decoration.
   Horizontal instead: icon left, content right, and a denser grid because the
   cards are now much shorter. */

.listing-grid--doc {
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
}

/* Wider tracks for text-heavy reference cards (.morph-card), which carry
   descriptions, inheritance notes and chip rows rather than a photo. */
.listing-grid--wide {
  grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr));
}

.listing--doc {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
}

.listing--doc:hover {
  transform: none;              /* no lift — these sit in a dense list */
  border-color: var(--border-brand);
}

.listing__doc-icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  font-size: 1.15rem;
  color: var(--brand);
  background: var(--brand-subtle);
  border: 1px solid var(--border-brand);
  border-radius: var(--radius-md);
}

.listing--doc .listing__body {
  padding: 0;
  gap: 2px;
}

.listing--doc .listing__title {
  font-size: var(--fs-ui);
}

.listing--doc .listing__footer {
  padding-top: var(--space-2);
}

.listing__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--fs-ui);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
  /* Two-line clamp keeps every card in the row the same height */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.listing__sub {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.listing__footer {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}


/* ═══ SECTION HEADER (public listing pages) ════════════════════════════════
   Deliberately mirrors .page-header so the public marketplace and the signed-in
   workspace read as one product. It replaces a centred, inline-block heading
   with a 50px green underline rule — a marketing-page pattern that made every
   public page look like a different site from the member pages.

   Kept as .section-header rather than renamed: 13 templates use it, and the
   class name is accurate. Callers only need `text-center` removed. */

.section-header {
  margin-bottom: var(--space-6);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

.section-header h1,
.section-header h2,
.section-header .section-title {
  display: block;
  margin: 0;
  padding: 0;
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
  text-align: left;
  text-transform: none;
  background: none;
}

/* Neutralise the legacy underline rule in case a stale cached stylesheet
   still carries it. */
.section-header h1::after,
.section-header h2::after {
  content: none;
}

.section-subtitle {
  margin: var(--space-2) 0 0;
  max-width: var(--prose-max);
  font-size: var(--fs-ui);
  color: var(--text-muted);
  text-align: left;
}

/* Actions sitting alongside a section header (share, view switch) */
.section-header--split {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-4);
}

.section-header--split > :first-child {
  flex: 1 1 20rem;
  min-width: 0;
}

.overline {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--brand);
}

/* Carousel slide caption title. Was an <h3>; demoted to a div for document
   order, so it needs its heading appearance restored explicitly. */
.carousel-caption__title {
  margin-bottom: var(--space-2);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--text-primary);
}


/* ═══ DIVIDER WITH LABEL ═══════════════════════════════════════════════════ */

.divider-label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-6) 0;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
}

.divider-label::before,
.divider-label::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}


/* ═══ SCROLL REVEAL ════════════════════════════════════════════════════════
   Opt-in via [data-reveal]; app.js adds .is-revealed. Guarded so content is
   visible even if JS never runs — the no-JS state must not be blank. */

@media (prefers-reduced-motion: no-preference) {
  html.js [data-reveal] {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
  }

  html.js [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
  }
}


/* ═══ POINTER TARGET SIZE ══════════════════════════════════════════════════
   WCAG 2.2 SC 2.5.8 (AA) wants pointer targets of at least 24x24 CSS px. The
   footer nav links measured 21px tall and the footer brand link 19px.

   Scoped deliberately: the exemption for links inline in a sentence is real, so
   this must not blanket every <a>. These are list-based navigation, which the
   exemption does not cover. */

/* Carousel indicators are 14x14 dots. Enlarging the dot would change the design,
   so the hit area is extended with a transparent pseudo-element instead: the
   indicator still *looks* 14px but is 24x24 to a finger or pointer. */
.carousel-indicators [data-bs-target] {
  position: relative;
}

.carousel-indicators [data-bs-target]::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 24px;
  height: 24px;
  transform: translate(-50%, -50%);
}

/* Standalone link controls — "View all" beside a section heading, forum
   category/thread links, and similar. These are navigation, not inline prose,
   so SC 2.5.8's 24px minimum applies. */
.hp-view-all,
.hp-section-head__actions a,
/* A link that is the entire content of a heading is a card/section title link —
   navigation, not prose. Covers the forum category and thread lists. */
h1 > a:only-child,
h2 > a:only-child,
h3 > a:only-child,
h4 > a:only-child,
h5 > a:only-child,
h6 > a:only-child,
/* Contact rows: an icon plus a single mailto/tel/website link. The link carries
   the whole meaning of the row, so it is a target in its own right. */
.contact-item > a,
.card-body p.small > a,
li > a.text-decoration-none,
.footer-links a,
.site-footer nav a,
/* A link that is the whole content of a list item is navigation, not an inline
   prose link, so SC 2.5.8's 24px minimum applies to it. Anchored on
   `:only-child` deliberately: a link sitting inside a sentence has text siblings
   and so is excluded, which is exactly the exemption the SC grants. Catches the
   terms-of-service contents list and the forum category/thread lists. */
li > a:only-child {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/* Logo link: inline boxes collapse to the line-height regardless of the image
   inside, so this needs a block-level display to inherit the image's height. */
.footer-brand__link {
  display: inline-block;
  min-height: 24px;
}

/* ═══ UTILITIES ════════════════════════════════════════════════════════════ */

.u-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.u-clamp-2,
.u-clamp-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.u-clamp-2 { -webkit-line-clamp: 2; }
.u-clamp-3 { -webkit-line-clamp: 3; }

.u-num { font-variant-numeric: tabular-nums; }
.u-mono { font-family: var(--font-mono); }

.u-muted    { color: var(--text-muted); }
.u-tertiary { color: var(--text-tertiary); }
.u-primary  { color: var(--text-primary); }
.u-brand    { color: var(--brand); }
.u-accent   { color: var(--accent); }
.u-danger   { color: var(--bd-red-400); }

.u-stack   { display: flex; flex-direction: column; }
.u-row     { display: flex; align-items: center; }
.u-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.u-wrap    { flex-wrap: wrap; }
.u-gap-1 { gap: var(--space-1); }
.u-gap-2 { gap: var(--space-2); }
.u-gap-3 { gap: var(--space-3); }
.u-gap-4 { gap: var(--space-4); }
.u-gap-5 { gap: var(--space-5); }
.u-gap-6 { gap: var(--space-6); }

/* Bootstrap's .text-muted resolves to a near-black on dark surfaces */
.text-muted {
  color: var(--text-muted) !important;
}
