/* ============================================================================
   CROMULTY DESIGN SYSTEM — Fase A: capa de tokens (PRD-087)
   ----------------------------------------------------------------------------
   Se carga DESPUÉS de Bootstrap, dashboard.css y del <style> inline del chrome,
   así que sus :root ganan la cascada. NO redefine selectores de componentes en
   esta fase (eso llega en B/C): sólo (1) declara la capa semántica que hoy
   falta, (2) realiasa los tokens legacy ya usados por el CSS existente hacia la
   marca, y (3) remapea las variables nativas --bs-* de Bootstrap 5.3.

   Los valores dark quedan definidos pero inertes hasta que la Fase F ponga
   data-theme="dark" en <html>. Declararlos ahora no cambia nada visible.
   ============================================================================ */

:root {
  /* ── Marca — escala derivada del navy actual #2A4B8C ───────────────────── */
  --brand-50:#EEF2FA;  --brand-100:#DCE4F4; --brand-200:#B8C8E8;
  --brand-300:#8CA5D6; --brand-400:#5C7CBF; --brand-500:#2A4B8C;
  --brand-600:#24417A; --brand-700:#1E3A6E; --brand-800:#16294E;
  --brand-900:#0F1E3D; --brand-950:#0A1429;

  /* ── Acento — sólo CTA primario, estado activo y focus ring ────────────── */
  --accent:#FF6B00; --accent-hover:#E05F00; --accent-tint:#FFF1E6; --accent-ink:#B24B00;

  /* ── Semánticos ────────────────────────────────────────────────────────── */
  --ok:#12B76A;   --ok-tint:#E7F8F0;   --ok-ink:#05603A;
  --warn:#F79009; --warn-tint:#FEF4E6; --warn-ink:#B54708;
  --bad:#F04438;  --bad-tint:#FEECEB;  --bad-ink:#B42318;
  --info:#2E90FA; --info-tint:#E8F2FE; --info-ink:#175CD3;

  /* ── Capa semántica que hoy NO existe (surface / text / border) ────────── */
  --surface-0:#FFFFFF; --surface-1:#F7F8FA; --surface-2:#EFF1F5; --surface-3:#E7EAF0;
  --text-1:#101828; --text-2:#475467; --text-3:#8A94A6; --text-inv:#FFFFFF;
  --border:#E4E7EC; --border-strong:#D0D5DD;

  /* ── Chrome de navegación (lo consumirá la Fase B) ─────────────────────── */
  --nav-bg:#0F1E3D; --nav-bg-2:#16294E; --nav-text:#A9B6CE; --nav-text-hi:#FFFFFF;
  --nav-hover:rgba(255,255,255,.06); --nav-active:rgba(255,107,0,.14); --nav-border:rgba(255,255,255,.08);

  /* ── Forma / profundidad — estética "border-first" ─────────────────────── */
  --r-sm:6px; --r:8px; --r-md:10px; --r-lg:14px; --r-xl:20px; --r-full:999px;
  --sh-1:0 1px 2px rgba(16,24,40,.04);
  --sh-2:0 1px 3px rgba(16,24,40,.06), 0 1px 2px rgba(16,24,40,.04);
  --sh-3:0 8px 24px -6px rgba(16,24,40,.10), 0 2px 6px rgba(16,24,40,.04);
  --sh-pop:0 16px 40px -12px rgba(16,24,40,.22);
  --ring:0 0 0 3px rgba(255,107,0,.32);

  /* ── Espaciado 4/8 ─────────────────────────────────────────────────────── */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s8:32px; --s10:40px; --s12:48px;

  /* ── Tipografía ────────────────────────────────────────────────────────── */
  --font:'Inter','Open Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --font-logo:'Montserrat',var(--font);
  --font-mono:ui-monospace,SFMono-Regular,'SF Mono',Menlo,Consolas,monospace;

  /* ── Realias de tokens LEGACY ya usados por dashboard.css y el <style>
        inline (mismo navy/naranja, así que no hay salto brusco: sólo
        consolida el origen de verdad y propaga la tipografía nueva). ──────── */
  --color-primary:var(--brand-500);
  --color-primary-hover:var(--brand-700);
  --color-primary-light:var(--brand-50);
  --color-accent:var(--accent);
  --color-accent-hover:var(--accent-hover);
  --primary-color:var(--brand-500);
  --primary-dark:var(--brand-700);
  --font-family:var(--font);
  --font-family-heading:var(--font-logo);

  /* ── Remapeo de las variables nativas de Bootstrap 5.3 ─────────────────── */
  --bs-body-font-family:var(--font);
  --bs-primary:var(--brand-500);
  --bs-primary-rgb:42,75,140;
  --bs-link-color:var(--brand-600);
  --bs-link-color-rgb:36,65,122;
  --bs-link-hover-color:var(--brand-700);
  --bs-border-color:var(--border);
  --bs-border-radius:var(--r);
  --bs-border-radius-sm:var(--r-sm);
  --bs-border-radius-lg:var(--r-md);
  --bs-focus-ring-color:rgba(255,107,0,.32);
  --bs-focus-ring-width:3px;
}

/* ── Modo oscuro — inerte hasta que la Fase F ponga data-theme="dark" ────── */
:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-0:#12161F; --surface-1:#0B0E14; --surface-2:#1A2029; --surface-3:#222A36;
  --text-1:#E6EAF2; --text-2:#9AA5B8; --text-3:#6C7789; --text-inv:#0B0E14;
  --border:#1F2733; --border-strong:#2C3745;
  --nav-bg:#0E131C; --nav-bg-2:#0B0F17; --nav-text:#8B97AB; --nav-text-hi:#F2F5FA;
  --nav-hover:rgba(255,255,255,.05); --nav-active:rgba(255,107,0,.16); --nav-border:#1F2733;
  --brand-50:#111A2C; --brand-100:#16233C; --brand-200:#1D2F52;
  --accent-tint:#2A1A0C; --accent-ink:#FFB77A;
  --ok-tint:#0D2119;  --ok-ink:#5BE0A0;
  --warn-tint:#241A0B; --warn-ink:#FDBE6A;
  --bad-tint:#2A1414;  --bad-ink:#FF9A92;
  --info-tint:#0E1D30; --info-ink:#84BDFF;
  --sh-1:none; --sh-2:0 1px 2px rgba(0,0,0,.4); --sh-3:0 8px 24px -6px rgba(0,0,0,.55);
  --sh-pop:0 16px 40px -12px rgba(0,0,0,.7);

  /* Re-alias the legacy grayscale that dashboard.css and inline views paint with,
     so surfaces, text and borders written as color-gray or color-white tokens
     also invert under dark. Bootstrap components are handled by data-bs-theme. */
  --color-white: var(--surface-0);
  --color-gray-50:  var(--surface-1);
  --color-gray-100: var(--surface-2);
  --color-gray-200: var(--border);
  --color-gray-300: var(--border-strong);
  --color-gray-400: var(--text-3);
  --color-gray-500: var(--text-3);
  --color-gray-600: var(--text-2);
  --color-gray-700: var(--text-2);
  --color-gray-800: var(--text-1);
  --color-gray-900: var(--text-1);

  /* Legacy semantic *-light tints used by dashboard.css alerts/badges → dark. */
  --color-primary-light: var(--brand-100);
  --color-success-light: var(--ok-tint);
  --color-warning-light: var(--warn-tint);
  --color-danger-light:  var(--bad-tint);
  --color-info-light:    var(--info-tint);

  /* Links/primary text must be a LIGHT blue on dark (brand-50..200 are dark
     tints in this theme; 300+ stay light). Backgrounds keep navy --bs-primary. */
  --bs-link-color: var(--brand-300);
  --bs-link-color-rgb: 140,165,214;
  --bs-link-hover-color: var(--brand-200);
}

/* ── FASE F QA — contraste en modo oscuro ───────────────────────────────────
   Corrige los ofensores detectados por el auditor WCAG: azul de marca ilegible
   para texto/enlaces/tabs, y el menú del org-switcher que no oscurecía. */
:root[data-theme="dark"] .text-primary { color: var(--brand-300) !important; }
:root[data-theme="dark"] .nav-tabs .nav-link.active { color: var(--text-1); border-bottom-color: var(--accent); }
:root[data-theme="dark"] .btn-outline-primary {
  --bs-btn-color: var(--brand-300); --bs-btn-border-color: var(--brand-400);
  --bs-btn-hover-bg: var(--brand-300); --bs-btn-hover-border-color: var(--brand-300); --bs-btn-hover-color: #0B0E14;
}
/* Warning button: dark ink reads far better than white on amber. */
:root[data-theme="dark"] .btn-warning { --bs-btn-color:#0B0E14; --bs-btn-hover-color:#0B0E14; color:#0B0E14; }

/* Org switcher: a dark dropdown with light text (was forced light in main.php). */
:root[data-theme="dark"] .org-switcher-menu { background: var(--surface-1); border-color: var(--border); }
:root[data-theme="dark"] .org-switcher-menu .dropdown-header { color: var(--text-3); }
:root[data-theme="dark"] .org-switcher-menu .dropdown-item,
:root[data-theme="dark"] .org-switcher-menu .dropdown-item .text-truncate,
:root[data-theme="dark"] .org-switcher-menu .dropdown-item span { color: var(--text-1) !important; }
:root[data-theme="dark"] .org-switcher-menu .dropdown-item:hover,
:root[data-theme="dark"] .org-switcher-menu .dropdown-item:focus { color: var(--text-1) !important; background-color: var(--surface-2) !important; }
:root[data-theme="dark"] .org-switcher-menu .dropdown-item.active,
:root[data-theme="dark"] .org-switcher-menu .dropdown-item:active { color:#fff !important; background-color: var(--brand-500) !important; }
:root[data-theme="dark"] .org-switcher-menu .dropdown-divider { border-color: var(--border); }

/* Bootstrap's .bg-white/.bg-light never invert with data-bs-theme, so any card
   or strip painted with them stays glaringly light in dark. Map them to dark
   surfaces (93 bg-light + 31 bg-white call sites across the app). */
:root[data-theme="dark"] .bg-white { background-color: var(--surface-0) !important; }
:root[data-theme="dark"] .bg-light { background-color: var(--surface-2) !important; }
/* .text-dark is a fixed utility (near-black) — on now-dark surfaces it turns
   invisible. Common on `.badge.bg-light .text-dark` (domain/type/variant pills). */
/* .text-dark inverts to light in dark EXCEPT on amber/cyan badge fills (which
   stay light, so their ink must stay dark). This covers bg-light badges and
   stray .text-dark on now-dark surfaces, without breaking warning/info badges. */
:root[data-theme="dark"] .text-dark:not(.bg-warning):not(.bg-info) { color: var(--text-1) !important; }
:root[data-theme="dark"] .badge.bg-light { color: var(--text-1) !important; }

/* ── Base mínima de Fase A: tipografía del cuerpo + foco visible consistente
      + numerales tabulares. Nada de esto altera el layout. ───────────────── */
body {
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--r-sm);
}

.num, .tabular-nums { font-variant-numeric: tabular-nums; }

::selection { background: var(--accent); color: #fff; }

/* ── Componentes base compartidos por TODOS los layouts (app + auth) ─────────
      El botón primario adopta el acento (decisión del prototipo aprobada). Se
      define aquí — no en el <style> del chrome — para que el CTA sea idéntico
      en el login, donde auth.php no carga ese <style>. Cubre tanto las
      --bs-btn-* (app, vía Bootstrap) como background directo (auth, vía
      dashboard.css). ──────────────────────────────────────────────────────── */
.btn-primary {
  --bs-btn-bg: var(--accent); --bs-btn-border-color: var(--accent);
  --bs-btn-hover-bg: var(--accent-hover); --bs-btn-hover-border-color: var(--accent-hover);
  --bs-btn-active-bg: var(--accent-hover); --bs-btn-active-border-color: var(--accent-hover);
  --bs-btn-disabled-bg: var(--accent); --bs-btn-disabled-border-color: var(--accent);
  background-color: var(--accent); border-color: var(--accent); color: #fff;
}
.btn-primary:hover, .btn-primary:focus, .btn-primary:active {
  background-color: var(--accent-hover); border-color: var(--accent-hover); color: #fff;
}

/* ============================================================================
   FASE C — componentes compartidos (tablas, pestañas, formularios)
   Se restilan vía CSS global con tokens en lugar de editar cada parcial de
   partials/tables/, para no tocar markup ni los ganchos js- y data- de los que
   depende data-table.js. Sólo propiedades visuales sobre selectores estándar.
   ============================================================================ */

/* ── Tablas ──────────────────────────────────────────────────────────────── */
.table { color: var(--text-2); vertical-align: middle; --bs-table-bg: transparent; }
.table > :not(caption) > * > * { border-bottom-color: var(--border); background-color: transparent; }
.table > thead th,
.table > thead td,
.table-light > :not(caption) > * > * {
  font-weight: 600; color: var(--text-2);
  background: var(--surface-1); border-bottom: 1px solid var(--border);
}
.table > tbody > tr:last-child > * { border-bottom: 0; }
.table-hover > tbody > tr:hover > * { background: var(--surface-1); color: var(--text-1); }

/* ── Pestañas (nav-tabs → subrayado con acento) ─────────────────────────── */
.nav-tabs { border-bottom: 1px solid var(--border); gap: 2px; }
.nav-tabs .nav-link {
  border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; border-radius: 0;
  color: var(--text-2); font-weight: 550; padding: .5rem .85rem;
}
.nav-tabs .nav-link:hover { border-color: transparent; border-bottom-color: var(--border-strong); color: var(--text-1); background: transparent; }
.nav-tabs .nav-link.active {
  color: var(--brand-600); background: transparent; font-weight: 650;
  border-color: transparent; border-bottom-color: var(--accent);
}

/* ── Formularios ────────────────────────────────────────────────────────── */
.form-control, .form-select {
  border-color: var(--border); border-radius: var(--r);
  color: var(--text-1); background-color: var(--surface-0);
}
.form-control:hover, .form-select:hover { border-color: var(--border-strong); }
.form-control:focus, .form-select:focus { border-color: var(--accent); box-shadow: var(--ring); }
.form-control::placeholder { color: var(--text-3); }
.input-group-text { background: var(--surface-1); border-color: var(--border); color: var(--text-3); }

/* ── Badges: light-coloured fills (amber/cyan) need dark ink in BOTH themes;
      white-on-amber/cyan is illegible (measured 1.3–2.0 contrast). ────────── */
/* Solid amber/cyan fills always need dark ink (white-on-amber measured ~1.4). */
.badge.bg-warning, .badge.badge-paused { color:#111 !important; }
.badge.bg-info:not(.bg-opacity-10):not(.text-info) { color:#08233f !important; }
/* Subtle/opacity variants keep their own text-* class, made legible per theme. */
.badge.text-warning, .badge.text-warning-emphasis { color: var(--warn-ink) !important; }
.badge.text-info, .badge.text-info-emphasis,
.badge.bg-info.bg-opacity-10, .badge.bg-warning.bg-opacity-10 { color: var(--info-ink) !important; }
.badge.bg-warning.bg-opacity-10 { color: var(--warn-ink) !important; }

/* Active/selected table rows use light -bg-subtle fills that don't invert. */
:root[data-theme="dark"] .table-primary,
:root[data-theme="dark"] .table-active,
:root[data-theme="dark"] .table-secondary { --bs-table-bg: var(--surface-2); --bs-table-color: var(--text-1); color: var(--text-1); }

/* ============================================================================
   FASE F QA — AAA: subir contrastes borderline (2.2–2.9) a ≥3.0
   ============================================================================ */
.badge-running, .badge.bg-success:not(.text-dark) { background-color:#0a8f52 !important; }
:root[data-theme="dark"] .wizard-step-indicator.active .step-label { color: var(--brand-300) !important; }
.wizard-step-indicator .step-label { color: var(--text-2); }
:root[data-theme="dark"] .btn-outline-secondary { --bs-btn-color: var(--text-1); --bs-btn-hover-color: #fff; }
:root[data-theme="dark"] .btn-outline-primary { --bs-btn-color: var(--brand-300); }
.alert-warning { --bs-alert-color: var(--warn-ink); }
.cw-stat-value { color: var(--cw-text, var(--text-1)); }
/* White initials over generated fills — a soft dark outline keeps them legible. */
.user-avatar-monogram, .org-logo, .badge.rounded-pill { text-shadow: 0 1px 2px rgba(0,0,0,.45); }

/* Bootstrap alerts sometimes keep the light -text-emphasis on a dark fill. */
:root[data-theme="dark"] .alert-warning { color: var(--warn-ink) !important; --bs-alert-color: var(--warn-ink); }
:root[data-theme="dark"] .alert-danger  { color: var(--bad-ink) !important;  --bs-alert-color: var(--bad-ink); }
:root[data-theme="dark"] .alert-success { color: var(--ok-ink) !important;   --bs-alert-color: var(--ok-ink); }
:root[data-theme="dark"] .alert-info    { color: var(--info-ink) !important; --bs-alert-color: var(--info-ink); }

/* ============================================================================
   PALETTE DISCIPLINE (PRD-087) — match the approved prototype
   Names/links inside data tables read as TEXT (not bright blue links); the
   accent (orange) stays reserved for CTA / active / focus, never decorative.
   ============================================================================ */
.table a:not(.btn), table.tbl a:not(.btn), .data-table a:not(.btn),
.page-group-card a:not(.btn), .folder-row a:not(.btn) { color: var(--text-1); text-decoration: none; }
.table a:not(.btn):hover, table.tbl a:not(.btn):hover, .data-table a:not(.btn):hover,
.page-group-card a:not(.btn):hover, .folder-row a:not(.btn):hover { color: var(--accent); }
/* Monospace slugs/paths stay muted, not blue. */
.table a.mono, .table code a, .data-table .mono a { color: var(--text-3); }

/* ============================================================================
   PRD-087 DASHBOARD — KPI cards, running-tests panel, top pages, activity feed.
   Border-first, tabular numerics, semantic tints only. Dark mode is automatic:
   every colour resolves through a token that already inverts under data-theme.
   ============================================================================ */
.tnum { font-variant-numeric: tabular-nums; }
.hint { font-size: .8rem; color: var(--text-3); }

/* ── KPI cards ───────────────────────────────────────────────────────────── */
.kpi-card {
  background: var(--surface-0); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 14px 16px; height: 100%;
  display: grid; gap: 9px; box-shadow: var(--sh-1);
}
.kpi-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.kpi-card-label { font-size: .78rem; font-weight: 550; color: var(--text-2); letter-spacing: .005em; }
.kpi-card-ic { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; flex: 0 0 auto; font-size: .95rem; }
.kpi-ic-brand  { background: var(--brand-50);   color: var(--brand-600); }
.kpi-ic-ok     { background: var(--ok-tint);    color: var(--ok-ink); }
.kpi-ic-accent { background: var(--accent-tint); color: var(--accent-ink); }
.kpi-ic-info   { background: var(--info-tint);  color: var(--info-ink); }
.kpi-card-value { font-size: 1.7rem; font-weight: 650; letter-spacing: -.03em; line-height: 1.1; color: var(--text-1); font-variant-numeric: tabular-nums; }
.kpi-card-delta { font-size: .74rem; color: var(--text-3); display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.kpi-delta-up   { color: var(--ok-ink);  font-weight: 600; }
.kpi-delta-down { color: var(--bad-ink); font-weight: 600; }
.kpi-delta-flat { color: var(--text-3); font-weight: 550; }

/* ── Running tests panel ─────────────────────────────────────────────────── */
.dash-run-card .run-list { display: grid; gap: 12px; align-content: start; }
.run-item { display: grid; gap: 7px; }
.run-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.run-name { font-size: .82rem; font-weight: 600; color: var(--text-1); text-decoration: none; max-width: 62%; }
.run-name:hover { color: var(--accent); }
.run-badge { display: inline-flex; align-items: center; gap: 5px; font-size: .68rem; font-weight: 600; padding: 3px 8px; border-radius: var(--r-full); white-space: nowrap; }
.run-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .85; }
.run-ok   { background: var(--ok-tint);   color: var(--ok-ink); }
.run-info { background: var(--info-tint); color: var(--info-ink); }
.run-warn { background: var(--warn-tint); color: var(--warn-ink); }
.run-bar { height: 7px; border-radius: var(--r-full); background: var(--surface-2); overflow: hidden; }
.run-bar i { display: block; height: 100%; border-radius: var(--r-full); }
.run-bar-winner  i { background: var(--ok); }
.run-bar-running i { background: var(--info); }
.run-bar-nodata  i { background: var(--warn); opacity: .7; }
.run-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: .72rem; color: var(--text-3); }
.run-uplift.up   { color: var(--ok-ink); font-weight: 600; }
.run-uplift.down { color: var(--bad-ink); font-weight: 600; }
.run-sep { height: 1px; background: var(--border); }
.run-note { font-size: .74rem; color: var(--text-2); background: var(--surface-1); border-top: 1px solid var(--border); }

/* ── Top performing pages ────────────────────────────────────────────────── */
.top-pages { font-size: .84rem; }
.top-pages thead th { font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-3); font-weight: 600; border-bottom: 1px solid var(--border); }
.top-pages td { vertical-align: middle; color: var(--text-1); }
.top-page-name { max-width: 260px; }
.site-tag { display: inline-block; font-size: .72rem; padding: 2px 8px; border-radius: var(--r-full); background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border); }
.rate-badge { font-size: .74rem; font-weight: 600; padding: 3px 9px; border-radius: var(--r-full); }
.rate-ok      { background: var(--ok-tint);   color: var(--ok-ink); }
.rate-info    { background: var(--info-tint); color: var(--info-ink); }
.rate-neutral { background: var(--surface-2); color: var(--text-2); }
.rate-warn    { background: var(--warn-tint); color: var(--warn-ink); }

/* ── Recent activity timeline ────────────────────────────────────────────── */
.dash-timeline { display: grid; gap: 16px; }
.tl-item { display: flex; gap: 11px; align-items: flex-start; }
.tl-ic { width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center; flex: 0 0 auto; font-size: .78rem; margin-top: 1px; }
.tl-brand   { background: var(--brand-50);    color: var(--brand-600); }
.tl-ok      { background: var(--ok-tint);     color: var(--ok-ink); }
.tl-accent  { background: var(--accent-tint); color: var(--accent-ink); }
.tl-info    { background: var(--info-tint);   color: var(--info-ink); }
.tl-warn    { background: var(--warn-tint);   color: var(--warn-ink); }
.tl-danger  { background: var(--bad-tint);    color: var(--bad-ink); }
.tl-neutral { background: var(--surface-2);   color: var(--text-2); }
.tl-body { min-width: 0; }
.tl-text { font-size: .82rem; color: var(--text-2); line-height: 1.45; }
.tl-text b { color: var(--text-1); font-weight: 600; }
.tl-time { font-size: .72rem; color: var(--text-3); margin-top: 2px; }

/* ── Status pill (PRD-087 list pattern) — dot + text on a soft tint, replacing
      solid Bootstrap bg-* badges for STATUS ONLY (counters/chips keep bg-*).
      Theme-aware via tokens. Used by /pages tree, /tests list, etc. ─────────── */
.status-pill { display: inline-flex; align-items: center; gap: 6px; font-size: .72rem; font-weight: 600; padding: 3px 9px; border-radius: var(--r-full); white-space: nowrap; line-height: 1.35; }
.status-pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .85; flex: 0 0 auto; }
.st-ok      { background: var(--ok-tint);    color: var(--ok-ink); }
.st-warn    { background: var(--warn-tint);  color: var(--warn-ink); }
.st-info    { background: var(--info-tint);  color: var(--info-ink); }
.st-bad     { background: var(--bad-tint);   color: var(--bad-ink); }
.st-brand   { background: var(--brand-50);   color: var(--brand-600); }
.st-neutral { background: var(--surface-2);  color: var(--text-2); }

/* ── Ghost icon-action buttons (PRD-087 list pattern) — replace the rainbow of
      solid btn-success/warning/danger squares in table action cells. Neutral at
      rest; the DESTRUCTIVE variant only tints on hover. ─────────────────────── */
.btn-icon-ghost { background: transparent; border: 1px solid var(--border); color: var(--text-2); }
.btn-icon-ghost:hover, .btn-icon-ghost:focus { background: var(--surface-2); border-color: var(--border-strong); color: var(--text-1); }
.btn-icon-ghost.danger:hover, .btn-icon-ghost.danger:focus { background: var(--bad-tint); border-color: var(--bad); color: var(--bad-ink); }

/* ── Label chip — user label colour survives only as a small dot; the chip body
      stays neutral so arbitrary hues never shout in the table. ──────────────── */
.label-chip { display: inline-flex; align-items: center; gap: 6px; font-size: .72rem; font-weight: 550; padding: 2px 9px; border-radius: var(--r-full); background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border); text-decoration: none; white-space: nowrap; }
.label-chip:hover { color: var(--text-1); border-color: var(--border-strong); }
.label-chip .lc-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }

/* ── /pages merged name cell (PRD-087) — site + slug under the page name ──── */
.page-name-wrap { min-width: 0; }
.page-addr { display: block; margin-top: 2px; font-size: .74rem; line-height: 1.4; }
.page-addr-slug { font-size: .72rem; color: var(--text-3); background: none; padding: 0; }

/* ── Site "At a glance" sidebar (PRD-087) ────────────────────────────────── */
.glance-list { display: grid; gap: 10px; }
.glance-row { display: flex; align-items: center; justify-content: space-between; font-size: .84rem; color: var(--text-2); }
.glance-row b { color: var(--text-1); font-weight: 650; }
.glance-sep { height: 1px; background: var(--border); margin: 2px 0; }

/* ============================================================================
   PRD-087 FASE E — responsive dirigido
   ============================================================================ */
/* dashboard.css pins .top-bar to a fixed height (+sticky). When the actions
   row wraps on small screens the box can't grow and the content overlaps
   whatever follows (seen on /stats over the alert banner). Height follows
   content; sticky stays desktop-only. */
.top-bar { height: auto; min-height: 0; }
@media (max-width: 767px) {
    .top-bar { position: static; }
    /* action clusters inside the top-bar wrap instead of clipping */
    .top-bar > .d-flex { flex-wrap: wrap; row-gap: .5rem; }
    /* Segmented metric toggles (dashboard/tests charts) don't fit 5-up on a
       phone — let the group wrap instead of clipping. */
    .btn-group[aria-label="Chart metric"] { flex-wrap: wrap; }
    .btn-group[aria-label="Chart metric"] .btn { border-radius: var(--r-sm) !important; }
}

/* ============================================================================
   PRD-087 FASE E.2 — responsive QA squad fixes (systemic layer)
   ============================================================================ */

/* 1. Page headers: every view opens with .d-flex.justify-content-between
      (title col + action cluster). Below 768px the cluster must wrap UNDER the
      title instead of crushing it to a sliver / forcing body-level H-scroll
      (found on /pages 331px void, /tests 66px title, /glossary CTA off-screen). */
@media (max-width: 767.98px) {
    .main-content > .d-flex.justify-content-between,
    .main-content form > .d-flex.justify-content-between,
    .card-header.d-flex { flex-wrap: wrap; row-gap: .6rem; }
    .main-content > .d-flex.justify-content-between > div:first-child { flex: 1 1 100%; min-width: 0; }
}

/* 2. The legacy sticky .top-bar fights the mobile topbar in the 768-991 band
      (H1 slides under it when scrolling) — static wherever the mobile chrome exists. */
@media (max-width: 991.98px) {
    .top-bar { position: static; }
}

/* 3. Scroll affordance for every .table-responsive: pure-CSS scroll shadows
      (background-attachment: local trick — the fade only shows while there is
      content hidden on that side). Bootstrap .table cells are transparent, so
      the shadows read through. Kills the "clipped mid-digit / hidden columns
      with zero affordance" class found on 10+ routes. */
.table-responsive {
    background:
        linear-gradient(to right, var(--surface-0) 30%, transparent) left/48px 100% no-repeat local,
        linear-gradient(to left, var(--surface-0) 30%, transparent) right/48px 100% no-repeat local,
        radial-gradient(farthest-side at 0 50%, rgba(16,24,40,.28), transparent) left/16px 100% no-repeat scroll,
        radial-gradient(farthest-side at 100% 50%, rgba(16,24,40,.28), transparent) right/16px 100% no-repeat scroll;
}
:root[data-theme="dark"] .table-responsive {
    background:
        linear-gradient(to right, var(--surface-0) 30%, transparent) left/48px 100% no-repeat local,
        linear-gradient(to left, var(--surface-0) 30%, transparent) right/48px 100% no-repeat local,
        radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.55), transparent) left/16px 100% no-repeat scroll,
        radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.55), transparent) right/16px 100% no-repeat scroll;
}
/* numbers must never sit flush against the cut edge */
.table-responsive th:last-child, .table-responsive td:last-child { padding-right: 1rem; }

/* 4. Touch targets on phones: action icons and small buttons reach a usable
      hit area without changing the desktop density. */
@media (max-width: 767.98px) {
    .btn-sm, .btn-icon-ghost { min-height: 38px; }
    .btn-icon-ghost { min-width: 40px; }
    .sidebar-toggle { width: 42px; height: 42px; }
    .mobile-topbar { min-height: 58px; }
}

/* 5. Chips never wrap into circular blobs (found on '1 lang' tags). */
.site-tag { white-space: nowrap; }

/* 6. /pages tree on mobile: keep checkbox + name sticky so rows keep context
      while the metrics scroll; the shadows above signal the rest. */
@media (max-width: 575.98px) {
    #pagesTable th:nth-child(1), #pagesTable td:nth-child(1) { position: sticky; left: 0; background: var(--surface-0); z-index: 2; }
    #pagesTable th:nth-child(2), #pagesTable td:nth-child(2) { position: sticky; left: 36px; background: var(--surface-0); z-index: 2; }
    #pagesTable tr.folder-row td { position: sticky; left: 0; background: var(--surface-1); z-index: 1; }
}

/* 7. Dashboard Top pages on phones: drop the SITE column so Visits/Conv./Rate
      fit without scroll (agents measured the chip sliced at the edge). */
@media (max-width: 575.98px) {
    .top-pages th:nth-child(2), .top-pages td:nth-child(2) { display: none; }
    .top-page-name { max-width: 160px; }
}
/* 8. /sites/{id}: the 8 tabs scroll horizontally on mobile instead of wrapping
      into a baseline-less 3-row chip cloud. */
@media (max-width: 767.98px) {
    .site-tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .site-tabs::-webkit-scrollbar { display: none; }
    .site-tabs .nav-link { white-space: nowrap; }
}
/* 9. Pagination clusters breathe on phones (both /stats footers jammed at 0px). */
@media (max-width: 575.98px) {
    .table-responsive + .d-flex, .card .d-flex.justify-content-between.align-items-center.px-3 { flex-wrap: wrap; row-gap: .5rem; }
}

/* 10. Insight cards: a LEFT accent stripe, not a 4px frame (Bootstrap .border-4
       widens every side of an already-bordered card). */
.insight-stripe { border-left: 4px solid var(--border) !important; }
.insight-stripe.stripe-info    { border-left-color: var(--info) !important; }
.insight-stripe.stripe-success { border-left-color: var(--ok) !important; }
.insight-stripe.stripe-warning { border-left-color: var(--warn) !important; }
.insight-stripe.stripe-danger  { border-left-color: var(--bad) !important; }

/* 11. Asset library: contain rendering cost of huge grids; thumbs never
       upscale into blur. */
.asset-card { content-visibility: auto; contain-intrinsic-size: 220px 180px; }
.asset-card img { object-fit: contain; }

/* 12. Translation group headers wrap on phones instead of crushing titles
       into one-word-per-line slivers. */
@media (max-width: 767.98px) {
    .domain-group > .d-flex, .page-group-header { flex-wrap: wrap; row-gap: .4rem; }
    .page-group-header .text-truncate { min-width: 180px; }
}

/* ============================================================================
   PRD-087 E.3 — owner mobile polish round
   ============================================================================ */

/* (1) Page-title block breathes before the controls row on phones. */
@media (max-width: 767.98px) {
    .top-bar { row-gap: .8rem; }
    .top-bar > div:first-child { padding-bottom: .3rem; }
}

/* (2) Status tabs (All/Published/Drafts/…) stay on ONE line and scroll
       sideways instead of wrapping — same idiom as the site-detail tabs. */
@media (max-width: 767.98px) {
    .nav-tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .nav-tabs::-webkit-scrollbar { display: none; }
    .nav-tabs .nav-link { white-space: nowrap; }
}

/* (3) Stat/KPI numerals scale down on phones — 18,772 shouldn't shout. */
@media (max-width: 575.98px) {
    .stat-card .stat-value { font-size: 1.3rem; }
    .stat-card .stat-label { font-size: .72rem; }
    .stat-card .stat-sub { font-size: .68rem; }
    .kpi-card-value { font-size: 1.4rem; }
}

/* (5) Breadcrumbs: quiet, small, senior. On phones they disappear — the
       mobile topbar already names the page (profile showed the title 3x). */
.breadcrumb { font-size: .78rem; margin-bottom: .6rem; }
.breadcrumb .breadcrumb-item a { color: var(--text-3); text-decoration: none; }
.breadcrumb .breadcrumb-item a:hover { color: var(--text-1); }
.breadcrumb .breadcrumb-item.active { color: var(--text-2); }
.breadcrumb .breadcrumb-item + .breadcrumb-item::before { color: var(--text-3); }
@media (max-width: 767.98px) {
    nav[aria-label="breadcrumb"] { display: none; }
}

/* PRD-087 E.3b — owner follow-ups */
/* Language chips hold one line and scroll sideways on phones. */
@media (max-width: 767.98px) {
    .lang-filter-row { flex-wrap: nowrap !important; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px; }
    .lang-filter-row::-webkit-scrollbar { display: none; }
    .lang-filter-row .btn, .lang-filter-row > span { white-space: nowrap; flex: 0 0 auto; }
}
/* The header controls row was glued to the top-bar's bottom edge. */
@media (max-width: 767.98px) {
    .top-bar { padding-bottom: .85rem; }
}

/* ── App footer (PRD-087) — brand linked to the agency site, quiet links ── */
.app-footer {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
    margin-top: 2.5rem; padding: 1.1rem 0 .35rem; border-top: 1px solid var(--border);
    font-size: .8rem; color: var(--text-3);
}
.app-footer-brand a { text-decoration: none; }
.app-footer-brand strong { color: var(--text-2); font-weight: 700; }
.app-footer-brand .brand-accent { color: var(--accent); }
.app-footer-brand a:hover strong { color: var(--text-1); }
.app-footer-product { color: var(--text-3); letter-spacing: .08em; font-size: .72rem; margin-left: .3rem; }
.app-footer-links { display: flex; gap: 1.1rem; }
.app-footer-links a { color: var(--text-3); text-decoration: none; }
.app-footer-links a:hover { color: var(--text-1); }
@media (max-width: 575.98px) { .app-footer { justify-content: center; text-align: center; } }

/* PRD-087 E.3c — manual mobile QA follow-ups */
/* Action headers (page editor: Re-upload / Create ads / Preview / View live /
   Export / Save) wrap on phones instead of running off-screen. Covers the
   bordered editor header and any page-level between-row plus their inner
   action clusters. */
@media (max-width: 767.98px) {
    .main-content .d-flex.justify-content-between.border-bottom { flex-wrap: wrap; row-gap: .6rem; }
    .main-content > .d-flex.justify-content-between > .d-flex,
    .main-content .d-flex.justify-content-between.border-bottom > .d-flex { flex-wrap: wrap; row-gap: .5rem; min-width: 0; }
}

/* ── PJAX loading state (PRD-088) — the region dims briefly while the fresh
      content arrives; no layout shift, no spinner circus. ──────────────────── */
.main-content.pjax-loading { opacity: .55; pointer-events: none; transition: opacity .12s ease .08s; cursor: progress; }
