/* === Coming Soon Banner === */
.coming-soon-banner {
  position: relative; /* Scrolls with page — not sticky */
  background: linear-gradient(135deg, var(--accent-dark) 0%, var(--accent) 40%, var(--accent-light) 100%);
  color: var(--lavender-100);
  padding: var(--space-6) var(--space-8);
  overflow: hidden;
}
.coming-soon-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 400px 200px at 80% 50%, rgba(var(--accent-light-rgb), 0.25), transparent 60%);
  pointer-events: none;
}
.coming-soon-banner__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 1200px;
  margin: 0 auto;
  gap: var(--space-6);
  flex-wrap: wrap;
}
.coming-soon-banner__left {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.coming-soon-banner__badge {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  background: rgba(var(--accent-light-rgb), 0.25);
  border: 1px solid rgba(var(--accent-light-rgb), 0.4);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--lavender-200);
}
.coming-soon-banner__countdown {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.coming-soon-banner__countdown-unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 52px;
}
.coming-soon-banner__countdown-value {
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--on-primary);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.coming-soon-banner__countdown-label {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(var(--white-rgb), 0.6);
  margin-top: 2px;
}
.coming-soon-banner__countdown-sep {
  font-size: var(--text-xl);
  font-weight: 300;
  color: rgba(var(--white-rgb), 0.35);
  align-self: flex-start;
  margin-top: 2px;
}
body.bento-theme .coming-soon-banner__countdown-label { color: rgba(var(--warm-amber-rgb), 0.5); }
body.bento-theme .coming-soon-banner__countdown-sep { color: rgba(var(--warm-amber-rgb), 0.3); }
.coming-soon-banner__sub {
  font-size: var(--text-base);
  color: rgba(var(--white-rgb), 0.7);
  font-weight: 400;
}
.coming-soon-banner__cta-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: rgba(var(--white-rgb), 0.85);
  white-space: nowrap;
}
.coming-soon-banner__right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.coming-soon-banner--geo-blocked .coming-soon-banner__countdown,
.coming-soon-banner--geo-blocked .coming-soon-banner__right {
  display: none;
}
.coming-soon-banner__email {
  padding: var(--space-3) var(--space-4);
  border: 1px solid rgba(var(--white-rgb), 0.25);
  border-radius: var(--radius-sm);
  background: rgba(var(--white-rgb), 0.1);
  color: var(--on-primary);
  font-size: var(--text-base);
  width: 260px;
  backdrop-filter: blur(4px);
  transition: border-color var(--duration-fast);
}
.coming-soon-banner__email::placeholder { color: rgba(var(--white-rgb), 0.5); }
.coming-soon-banner__email:focus { border-color: rgba(var(--accent-light-rgb), 0.7); outline: none; }
.coming-soon-banner__email.error { border-color: var(--status-danger); animation: shake 0.3s; }
.coming-soon-banner__btn {
  padding: var(--space-3) var(--space-5);
  background: var(--accent-light);
  color: white;
  border: none;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--duration-fast);
}
.coming-soon-banner__btn:hover { background: var(--accent); }
.coming-soon-banner__btn:disabled { opacity: var(--btn-disabled-opacity); cursor: not-allowed; }
.coming-soon-banner__confirm {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--green-300);
}
/* Bento theme — warm tones */
body.bento-theme .coming-soon-banner {
  /* UI Unity W1 — dégradé d'origine restauré (4fdb8603) : espresso→acajou→ambre-900.
   * Le mapping --accent-* de juin rendait orange-jaune (ΔE 25.5). */
  background: linear-gradient(135deg, var(--bento-espresso) 0%, var(--bento-mahogany) 40%, var(--accent3) 100%);
  color: var(--ct-load-badge-text);
}
/* ATSIQ Sage & Forest — jungle greens (accent-dark → accent → accent-light) */
body.atsiq-theme .coming-soon-banner {
  background: linear-gradient(135deg, var(--accent-dark) 0%, var(--accent) 40%, var(--accent-light) 100%);
  color: var(--text-inverse);
}
/* Light theme — preserve contrast on light background.
   2026-05-15: the default banner gradient is dark indigo intended for
   dark theme; without this override, light-theme users get white text
   on (still) dark indigo, which is fine, but the visual was inconsistent
   with the rest of the light theme. Switch to softer indigo gradient
   that fits the lavender/light palette. */
body.light-theme .coming-soon-banner {
  background: linear-gradient(135deg, var(--lavender-200) 0%, var(--data-indigo) 40%, var(--accent-light) 100%);
  color: var(--text);
}
body.light-theme .coming-soon-banner__badge {
  background: rgba(var(--accent-rgb), 0.15);
  color: var(--text);
}
/* Restore the ORIGINAL gold #fbbf24 (rgb 251,191,36) for the bento banner accents.
   PITFALL: --severity-medium-rgb is 251,191,36 in :root but is OVERRIDDEN to 180,83,9
   (#b45309 orange) in body.bento-theme (variables.css) — tokenizing the original
   literal rgba(251,191,36,…) to it (commit b8ac7b09) silently turned the badge / glow /
   email pill ORANGE in bento. --amber-rgb is 251,191,36 and is NOT overridden in bento,
   so it keeps the token AND matches the pre-tokenization gold. Do NOT re-point these at
   --severity-medium-rgb. */
body.bento-theme .coming-soon-banner::before {
  background: radial-gradient(ellipse 400px 200px at 80% 50%, rgba(var(--amber-rgb), 0.2), transparent 60%);
}
body.bento-theme .coming-soon-banner__badge {
  background: rgba(var(--amber-rgb), 0.2);
  border-color: rgba(var(--amber-rgb), 0.4);
  color: var(--warm-amber-light);
}
body.bento-theme .coming-soon-banner__email {
  border-color: rgba(var(--amber-rgb), 0.3);
  background: rgba(var(--amber-rgb), 0.15);
  color: var(--ct-load-badge-text);
}
body.bento-theme .coming-soon-banner__email::placeholder { color: rgba(var(--accent-gold-deep-rgb, 69, 26, 3), 0.5); }
body.bento-theme .coming-soon-banner__email:focus { border-color: rgba(var(--amber-rgb), 0.6); }
body.bento-theme .coming-soon-banner__sub { color: rgba(var(--warm-amber-rgb), 0.6); }
body.bento-theme .coming-soon-banner__cta-label { color: rgba(var(--warm-amber-rgb), 0.8); }
body.bento-theme .coming-soon-banner__btn { background: var(--accent3); }
body.bento-theme .coming-soon-banner__btn:hover { background: var(--warning-text); }
/* ATSIQ Sage & Forest — badge / glow / sub-texts / button */
body.atsiq-theme .coming-soon-banner::before {
  background: radial-gradient(ellipse 400px 200px at 80% 50%, rgba(var(--accent2-rgb), 0.22), transparent 60%);
}
body.atsiq-theme .coming-soon-banner__badge {
  background: rgba(var(--accent2-rgb), 0.22);
  border-color: rgba(var(--accent2-rgb), 0.45);
  color: var(--accent2-light);
}
body.atsiq-theme .coming-soon-banner__countdown-label { color: rgba(var(--accent2-rgb), 0.55); }
body.atsiq-theme .coming-soon-banner__countdown-sep   { color: rgba(var(--accent2-rgb), 0.35); }
body.atsiq-theme .coming-soon-banner__email {
  border-color: rgba(var(--accent2-rgb), 0.35);
  background: rgba(var(--accent2-rgb), 0.15);
  color: var(--text-inverse);
}
/* W3b: pas de var fidèle pour rgba(122,154,131,0.55) atsiq placeholder (ΔE min >10) — token --atsiq-input-placeholder à définir dans atsiq-theme.css (W5+) */
body.atsiq-theme .coming-soon-banner__email::placeholder { color: var(--atsiq-input-placeholder, rgba(122,154,131, 0.55)); }
body.atsiq-theme .coming-soon-banner__email:focus { border-color: rgba(var(--accent2-rgb), 0.65); }
body.atsiq-theme .coming-soon-banner__sub        { color: rgba(var(--accent2-rgb), 0.75); }
body.atsiq-theme .coming-soon-banner__cta-label  { color: rgba(var(--accent2-rgb), 0.90); }
body.atsiq-theme .coming-soon-banner__btn        { background: var(--accent-light); }
body.atsiq-theme .coming-soon-banner__btn:hover  { background: var(--accent); }
/* Sub-landing banner (inside hero sections) */
.coming-soon-banner--sub {
  margin-bottom: var(--space-4);
  border-radius: var(--radius-sm);
  position: relative;
  z-index: 5;
}
/* Hide pre-launch banners for authenticated users. body.is-authed is
   added by auth.js refreshMe() success + by the cookie pre-check in
   index.html:222 (prevents flicker on page load). Decoupled from
   .coming-soon-overlay (registration modal overlay) which lives inside
   #paneRegister and is untouched by this rule. */
body.is-authed #comingSoonBanner,
body.is-authed .coming-soon-banner--sub { display: none !important; }
body.modal-open { overflow: hidden; }
/* Mobile */
@media (max-width: 768px) {
  .coming-soon-banner { padding: var(--space-5) var(--space-4); }
  .coming-soon-banner__inner { flex-direction: column; text-align: center; gap: var(--space-3); }
  .coming-soon-banner__left { flex-direction: column; align-items: center; gap: var(--space-2); }
  .coming-soon-banner__countdown-value { font-size: var(--text-lg); }
  .coming-soon-banner__countdown-unit { min-width: 40px; }
  .coming-soon-banner__countdown-label { font-size: var(--text-2xs); }
  .coming-soon-banner__right { width: 100%; flex-wrap: wrap; justify-content: center; gap: var(--space-2); }
  .coming-soon-banner__cta-label { width: 100%; text-align: center; margin-bottom: var(--space-1); }
  .coming-soon-banner__email { width: 100%; min-width: 0; flex: none; }
  .coming-soon-banner__btn { width: 100%; }
}

/* === Demo Coming Soon Overlay === */
/* Registration gate — Coming Soon overlay on register pane */
.coming-soon-overlay {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: linear-gradient(145deg, rgba(var(--slate-dark-rgb), 0.88), rgba(var(--black-rgb), 0.72));
  border: 1px solid rgba(var(--white-rgb), 0.12);
  box-shadow: var(--shadow);
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  backdrop-filter: blur(18px) saturate(1.15);
  border-radius: var(--radius);
  padding: var(--space-6);
  text-align: center;
  animation: cjsFadeIn 0.3s var(--ease-decel);
}
.coming-soon-overlay__icon { font-size: 48px; /* hero scale — hors échelle */ margin-bottom: var(--space-3); }
.coming-soon-overlay__title { font-size: var(--text-xl); font-weight: 700; color: var(--text); margin-bottom: var(--space-2); }
.coming-soon-overlay__desc { font-size: var(--text-sm); color: var(--muted); margin-bottom: var(--space-4); line-height: 1.5; }
.coming-soon-overlay__notify-label { font-size: var(--text-sm); color: var(--muted); margin-bottom: var(--space-2); }
.coming-soon-overlay__notify-row { display: flex; flex-wrap: wrap; gap: var(--space-2); width: 100%; max-width: min(100%, 420px); }
.coming-soon-overlay__email { flex: 1 1 180px; min-width: 0; padding: var(--space-2) var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-glass-strong); color: var(--text); font-size: var(--text-sm); }
.coming-soon-overlay__email::placeholder { color: var(--text-soft); }
.coming-soon-overlay__btn { padding: var(--space-2) var(--space-3); background: var(--primary); color: var(--on-primary); border: none; border-radius: var(--radius-sm); font-weight: 600; cursor: pointer; white-space: nowrap; }
.coming-soon-overlay__notify-row .btn { flex: 0 1 auto; white-space: normal; }
.coming-soon-overlay__confirm { color: var(--status-ok); font-size: var(--text-sm); margin-top: var(--space-2); }
.coming-soon-overlay__sep { width: 60%; height: 1px; background: var(--border); margin: var(--space-4) 0; }
.coming-soon-overlay__hint { font-size: var(--text-sm); color: var(--muted); }
.coming-soon-overlay__hint a, .coming-soon-overlay__hint button { color: var(--primary); background: none; border: none; cursor: pointer; font-weight: 600; text-decoration: underline; font-size: inherit; }
.coming-soon-pane { position: relative; }
.coming-soon-overlay__confirmed { color: var(--status-ok); font-weight: 600; font-size: var(--text-base); padding: var(--space-3) var(--space-4); background: rgba(var(--status-ok-rgb,34,197,94),0.1); border-radius: var(--radius-sm); }
.coming-soon-overlay__email.error { border-color: var(--status-danger); animation: comingSoonShake 0.3s; }
body.light-theme .coming-soon-overlay,
body.bento-theme .coming-soon-overlay {
  background: linear-gradient(145deg, rgba(var(--paper-rgb), 0.96), rgba(var(--warm-cream-rgb), 0.90));
  border-color: rgba(var(--accent-rgb), 0.24);
  box-shadow: 0 22px 48px rgba(var(--slate-dark-rgb), 0.16), inset 0 1px 0 rgba(var(--white-rgb), 0.60);
}
body.light-theme .coming-soon-overlay__email,
body.bento-theme .coming-soon-overlay__email {
  background: rgba(var(--white-rgb), 0.78);
  border-color: rgba(var(--status-muted-rgb), 0.22);
}
body.atsiq-theme .coming-soon-overlay {
  background: linear-gradient(145deg, rgba(var(--accent-dark-rgb), 0.94), rgba(var(--accent-rgb), 0.88));
  border-color: rgba(var(--accent2-rgb), 0.42);
  box-shadow: 0 24px 56px rgba(var(--text-rgb), 0.24), inset 0 1px 0 rgba(var(--text-inverse-rgb), 0.16);
}
body.atsiq-theme .coming-soon-overlay__title,
body.atsiq-theme .coming-soon-overlay__confirmed {
  color: var(--text-inverse);
}
body.atsiq-theme .coming-soon-overlay__desc,
body.atsiq-theme .coming-soon-overlay__notify-label,
body.atsiq-theme .coming-soon-overlay__hint {
  color: rgba(var(--text-inverse-rgb), 0.84);
}
body.atsiq-theme .coming-soon-overlay__sep {
  background: rgba(var(--accent2-rgb), 0.38);
}
body.atsiq-theme .coming-soon-overlay__email {
  background: rgba(var(--paper-rgb), 0.94);
  border-color: rgba(var(--accent2-rgb), 0.55);
  color: var(--text);
}
body.atsiq-theme .coming-soon-overlay__email::placeholder {
  color: rgba(var(--text-rgb), 0.48);
}

body.atsiq-theme .coming-soon-overlay .btn.btn--outline {
  border-color: rgba(var(--accent2-rgb), 0.62);
  color: var(--text-inverse);
  background: rgba(var(--text-inverse-rgb), 0.08);
}

body.atsiq-theme .coming-soon-overlay .btn.btn--outline:hover {
  background: rgba(var(--accent2-rgb), 0.18);
}
@keyframes comingSoonShake { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-4px)} 75%{transform:translateX(4px)} }
/* Ultra-small viewport (≤380px iPhone SE / Galaxy A01) — reduce overlay
   padding so the 320px notify-row + 12px gap fits without horizontal
   overflow. 2026-05-15 audit. */
@media (max-width: 380px) {
  .coming-soon-overlay { padding: var(--space-4) var(--space-3); }
  .coming-soon-overlay__icon { font-size: var(--text-4xl); margin-bottom: var(--space-2); }
}

@media (max-width: 640px) {
  .coming-soon-overlay__notify-row {
    flex-direction: column;
    max-width: 100%;
  }

  .coming-soon-overlay__notify-row .btn,
  .coming-soon-overlay__email {
    width: 100%;
  }
  /* §11 mobile (2026-07-16) — in this column direction the base `flex: 1 1 180px`
     turns 180px of flex-BASIS into HEIGHT: the ATSIQ "Coming soon" email input
     rendered ~180px tall. Reset the basis so the input keeps its natural height. */
  .coming-soon-overlay__email {
    flex: 0 0 auto;
  }
}
/* Registration closed state */
.registration-closed-notice { background: rgba(var(--status-warn-rgb), 0.15); border: 1px solid rgba(var(--status-warn-rgb), 0.30); color: var(--status-warn); padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); margin-bottom: var(--space-4); text-align: center; font-size: var(--text-sm); font-weight: 600; }
/* L2 T2.8 : !important justifié, guerre d'ORDRE (pas de spécificité) — cette
   règle précède la base .btn (~L2900+) dans le fichier ; à spécificité égale
   (0,1,0) la base .btn plus tardive gagnerait le cursor/opacity sans lui. */
.btn-registration-closed { opacity: 0.6 !important; cursor: not-allowed !important; }

.demo-coming-soon-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--black-rgb), 0.7);
  backdrop-filter: blur(8px);
  animation: dcs-fadein 0.3s ease-out;
}
@keyframes dcs-fadein { from { opacity: 0; } to { opacity: 1; } }
.demo-coming-soon-card {
  text-align: center;
  padding: var(--space-9) var(--space-8);
  max-width: 480px;
  animation: dcs-scalein 0.4s var(--ease-spring, cubic-bezier(0.34,1.56,0.64,1));
}
@keyframes dcs-scalein { from { transform: scale(0.8); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.demo-coming-soon-card h2 {
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--on-primary);
  margin: var(--space-5) 0 var(--space-3);
}
.demo-coming-soon-card p {
  font-size: var(--text-md);
  color: rgba(var(--white-rgb), 0.7);
  line-height: 1.6;
  margin: 0 0 var(--space-6);
}
.demo-coming-soon-play {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent, #6366f1) 0%, var(--accent2, #8b5cf6) 100%);
  color: var(--on-primary);
  animation: dcs-pulse 2s ease-in-out infinite;
  box-shadow: 0 0 40px rgba(var(--accent-rgb),0.4), 0 0 80px rgba(var(--accent-rgb),0.2);
}
@keyframes dcs-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 40px rgba(var(--accent-rgb),0.4), 0 0 80px rgba(var(--accent-rgb),0.2); }
  50% { transform: scale(1.08); box-shadow: 0 0 60px rgba(var(--accent-rgb),0.5), 0 0 120px rgba(var(--accent-rgb),0.3); }
}
.demo-coming-soon-play::before,
.demo-coming-soon-play::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  border: 2px solid rgba(var(--primary-rgb), 0.3);
  animation: dcs-ring 2.5s ease-out infinite;
}
.demo-coming-soon-play::before { inset: -15px; animation-delay: 0s; }
.demo-coming-soon-play::after { inset: -30px; animation-delay: 0.5s; }
@keyframes dcs-ring {
  0% { transform: scale(0.8); opacity: 1; }
  100% { transform: scale(1.4); opacity: 0; }
}
.demo-coming-soon-play svg { position: relative; z-index: 1; margin-left: 4px; }
/* Bento theme */
body.bento-theme .demo-coming-soon-play {
  /* W3b: pas de var fidèle (ΔE min = 16.9 vs --accent-light) — gradient marque bento ; candidat W5+ --bento-play-gradient */
  background: linear-gradient(135deg, #92400e 0%, #d97706 100%);
  box-shadow: 0 0 40px rgba(var(--amber-dark-rgb), 0.4), 0 0 80px rgba(var(--amber-dark-rgb), 0.2);
}
body.bento-theme .demo-coming-soon-play::before,
body.bento-theme .demo-coming-soon-play::after {
  border-color: rgba(var(--amber-dark-rgb), 0.3);
}
@keyframes dcs-pulse-bento {
  0%, 100% { transform: scale(1); box-shadow: 0 0 40px rgba(var(--amber-dark-rgb), 0.4); }
  50% { transform: scale(1.08); box-shadow: 0 0 60px rgba(var(--amber-dark-rgb), 0.5); }
}
body.bento-theme .demo-coming-soon-play { animation-name: dcs-pulse-bento; }

/* === Cards === */
.card {
  position: relative;
  background: linear-gradient(170deg, rgba(var(--white-rgb),0.07) 0%, rgba(var(--white-rgb),0.03) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(var(--white-rgb),0.05);
  overflow: hidden;
  margin-top: 18px;
  padding: var(--space-6);
  transition: border-color var(--duration-base) var(--ease-default), box-shadow var(--duration-base) var(--ease-default), transform var(--duration-slow) var(--ease-default);
}

.card:hover {
  border-color: var(--border-accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover, 0 8px 24px rgba(var(--black-rgb), 0.1)),
              inset 0 1px 0 rgba(var(--white-rgb), 0.06);
}
/* No hover lift on touch devices (including iPad which reports hover:hover) */
@media (hover: none), (pointer: coarse) {
  .card:hover {
    transform: none;
    box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(var(--white-rgb), 0.05);
  }
}
/* Active feedback on touch instead of hover lift */
@media (pointer: coarse) {
  .card:active {
    transform: scale(0.99);
    transition-duration: 0.1s;
  }
}
/* Phase 11.8 — explicit prefers-reduced-motion guard on .card hover lift.
   Required by WCAG 2.3.3 (Animation from Interactions). */
@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
  .card:hover {
    transform: none;
    box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(var(--white-rgb), 0.05);
  }
  .card:active { transform: none; }
}

/* Elevated card variant */
.card--elevated {
  box-shadow: var(--shadow), inset 0 1px 0 rgba(var(--white-rgb),0.05);
}

/* ── CANON CONTENEURS (UI Unity W4) ──────────────────────────────────────── */

/* Flat card — no shadow, solid background (for nested / low-elevation contexts) */
.card--flat {
  box-shadow: none;
  background: var(--card);
}

/* Compact card — reduced padding for dense layouts */
.card--compact {
  padding: var(--space-4);
}

/* Stat / KPI card — balanced padding + constrained KPI number typography */
.card--stat {
  padding: var(--space-5) var(--space-4);
}
.card--stat .card__kpi {
  font-size: var(--text-3xl);
  font-family: var(--font-mono);
  font-weight: 700;
}

/* ── ERROR STATE (UI Unity W4.2) ─────────────────────────────────────────── */

/* Canonical error-state component — centred container with icon + message + retry */
.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-7);
  gap: var(--space-4);
}
.error-state__icon {
  font-size: var(--text-3xl);
  line-height: 1;
  opacity: 0.8;
}
.error-state__msg {
  font-size: var(--text-base);
  color: var(--muted);
  max-width: 36ch;
}

/* ─────────────────────────────────────────────────────────────────────────── */

/* Links inside cards — accessible, themed, clear distinction from text */
.card a:not(.btn):not(.empty-state__cta) {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--duration-fast);
}
.card a:not(.btn):not(.empty-state__cta):hover {
  text-decoration: underline;
  color: var(--accent2, var(--accent));
}

.cardHead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: none;
  position: relative;
}
.cardHead::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, rgba(var(--primary-rgb), 0.15), rgba(var(--primary-rgb), 0.05));
  pointer-events: none;
}

/* ═══ CANON TYPO (UI Unity W2 — source unique, ne pas overrider par pane) ═══
 * page 24/750 → section 18/700 → sous-section 16/600 → label 14/600 → desc 13 muted
 * Réf: docs/audits/ui-unity-review.md § CANON PROPOSÉ (validé 2026-06-11). */
.h1, .pageTitle { font-size: var(--text-2xl); font-weight: 750; line-height: 1.2; letter-spacing: -0.04em; }
.h2 { font-size: var(--text-lg); font-weight: 700; line-height: 1.3; letter-spacing: -0.04em; }
.h3 { font-size: var(--text-md); font-weight: 600; line-height: 1.35; }
.h4 { font-size: var(--text-base); font-weight: 600; line-height: 1.4; }
.sub { margin-top: 6px; font-size: var(--text-sm); color: var(--muted); }

/* Titre de CARTE/SECTION (≠ titre de page) : 18/700. Un cardHead qui titre un
 * pane entier porte .pageTitle sur son .h1 (survey W2.1). */
.cardHead .h1:not(.pageTitle) { font-size: var(--text-lg); font-weight: 700; }

/* === Card Tabs === */
.cardTabs {
  display: flex;
  gap: 2px;
  margin-bottom: var(--space-4);
  background: rgba(var(--white-rgb),0.04);
  border-radius: var(--radius-sm);
  padding: 3px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.cardTab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 10px 20px;
  background: rgba(var(--white-rgb), 0.02);
  border: 1px solid transparent;
  color: var(--muted);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  border-radius: var(--radius-8);
  transition: all var(--duration-base);
  flex: 1;
  justify-content: center;
}

.cardTab:hover {
  color: var(--text);
  background: rgba(var(--white-rgb),0.05);
}

.cardTab.active {
  color: var(--text-inverse);
  background: var(--accent);
  box-shadow: 0 2px 8px rgba(var(--accent-rgb), 0.25);
}

.tabBadge {
  background: rgba(var(--white-rgb),0.12);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 700;
}

.cardTab.active .tabBadge {
  background: rgba(var(--white-rgb),0.25);
  color: var(--text-inverse);
}

.cardTabContent {
  position: relative;
}

.tabPane {
  display: block;
}
.tabPane.hidden {
  display: none;
}
/* Sub-pane and tabPane entrance — triggered when hidden class is removed.
   Uses MutationObserver-free approach: the .hidden removal itself triggers the animation
   because the element goes from display:none → display:block, resetting the animation.
   VQA-C60 — fill-mode 'backwards' (not 'both'): 'both' kept the from-state
   (opacity 0) applied whenever the animation was cancelled or never completed
   (observed stuck at playState 'running' / opacity 0 on async-mounted toolbox
   panes, cand #50). 'backwards' is visually identical in the nominal case
   (the 'to' keyframe equals the natural style) but never pins the element
   invisible after the animation should have ended. Async-mounting consumers
   (candidate-conferences.js / candidate-homelab.js) also force-finish a stuck
   run after render. */
.tabPane:not(.hidden) {
  animation: tabPaneIn var(--duration-base) ease backwards;
}
@keyframes tabPaneIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .tabPane.tab-entering { animation: none; }
}

@media (max-width: 480px) {
  .cardTab { padding: var(--space-2) var(--space-3); font-size: var(--text-sm); }
}

/* Mobile: reduce card padding for better space usage */
@media (max-width: 600px) {
  .card {
    padding: 14px;
    margin-left: 0;
    margin-right: 0;
    border-radius: var(--radius-sm);
  }
  .cardHead {
    flex-direction: column;
    gap: 10px;
  }
  .cardHead .actions {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
}

/* Skills extraction indicator */
.skillsBadge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  border: 1px solid rgba(var(--status-ok-rgb), 0.3);
  font-size: var(--text-xs);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  background: rgba(var(--status-ok-rgb), 0.15);
  color: var(--accent2);
}

.skillsBadge.pending {
  background: rgba(var(--status-warn-rgb), 0.15);
  color: var(--status-warn);
}

.skillsBadge--locked {
  background: rgba(var(--muted-rgb, 128, 128, 128), 0.1);
  border-color: rgba(var(--muted-rgb, 128, 128, 128), 0.2);
  color: var(--muted);
  cursor: help;
  transition: all var(--duration-base) var(--ease-default);
}

/* Badge transition: locked → unlocked (spring overshoot) */
.skillsBadge.flow-reveal {
  animation: skillsBadgeUnlock 0.4s var(--ease-spring) both;
}
@keyframes skillsBadgeUnlock {
  from { opacity: 0; transform: scale(0.8); }
  to { opacity: 1; transform: scale(1); }
}

/* === Layout Helpers === */
.grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
@media (max-width: 900px) {
  .grid2 { grid-template-columns: 1fr; }
}
/* === Help Button (contextual help) === */
.btn--help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  min-width: 28px;
  min-height: 28px;
  border-radius: 50%;
  background: rgba(var(--primary-rgb), 0.15);
  /* da-11 (re-gate, WCAG 1.4.3) — le « ? » était peint avec l'accent NATIF comme couleur de
     TEXTE : en Obsidian l'accent natif sur le voile d'accent à 15 % ne fait que ~3,4:1, relevé
     sur 66 captures. --accent-text est la variante « accent lisible » du thème (déclarée une
     fois par thème dans variables.css / atsiq-theme.css) : --accent-light en Obsidian —
     mesuré 6,50:1 sur --bg1 et 5,86:1 sur --card —, l'accent natif sur les fonds clairs.
     (Valeurs citées par TOKEN et non en littéral : la règle css-hex-color du lint premium
     interdit tout hexadécimal dans cette feuille, commentaires compris.) */
  color: var(--accent-text, var(--accent));
  border: 1px solid rgba(var(--primary-rgb), 0.3);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  margin-left: var(--space-2);
  vertical-align: middle;
  transition: all var(--duration-base) var(--ease-default);
  position: relative;
  z-index: var(--z-decoration);
  /* Ensure button is easily tappable on mobile */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.btn--help:hover,
.btn--help:focus {
  background: rgba(var(--primary-rgb), 0.3);
  outline: none;
  box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.4);
}

/* Scale transforms only on devices with real hover (not touch) */
@media (hover: hover) {
  .btn--help:hover,
  .btn--help:focus-visible {
    transform: scale(1.1);
  }
  .btn--help:active {
    transform: scale(0.95);
  }
}

.helpContent {
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text);
}

.helpContent strong {
  color: var(--accent);
}

.field {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: var(--space-2);
}
.field > label {
  min-width: 80px;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-secondary);
}
.field input,
.field textarea,
.field select {
  flex: 1;
  min-width: 0;
}

/* Vertical field — label above, input full width */
.fieldStack {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: var(--space-2);
  position: relative;
}
.fieldStack > label {
  min-width: auto;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--muted);
}
.fieldStack input,
.fieldStack textarea,
.fieldStack select {
  width: 100%;
}

/* Checkbox + label horizontal */
.checkboxField {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
  padding: 10px 0;
}
.checkboxField input[type="checkbox"] {
  margin-top: 3px;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  accent-color: var(--primary);
}
@media (pointer: coarse) {
  .checkboxField input[type="checkbox"] {
    width: 24px;
    height: 24px;
  }
}
.checkboxField .checkboxText {
  font-size: var(--text-sm);
  line-height: 1.5;
}
.checkboxField .checkboxText a {
  color: var(--accent);
  text-decoration: underline;
}

/* Opt-out AI-scoring INFORMATION notice (doctrine §1) — mirror of the agency panel's
   .ctaap__consent-notice. NON-interactive Art.13-14 info callout (NOT a checkbox): soft
   surface, left accent hairline + ⓘ marker, muted tone → reads as "you are informed".
   Tokens only (DS: --accent, --muted, --card2, --space-*, --text-*, --radius-sm). */
.aiConsentNotice {
  display: block;
  position: relative;
  margin: 0;
  padding: var(--space-3) var(--space-3) var(--space-3) calc(var(--space-6) + var(--space-2));
  background: var(--card2);
  border-radius: var(--radius-sm);
  border-left: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--muted);
  font-size: var(--text-xs);
  line-height: 1.55;
}
.aiConsentNotice::before {
  content: "ⓘ";
  position: absolute;
  left: var(--space-3);
  top: var(--space-3);
  color: var(--accent);
  font-size: var(--text-md);
  line-height: 1.3;
}

/* Standardized form action buttons */
.formActions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: var(--space-4);
}
.formActions .btn { flex: 1; min-width: 0; }
.formActions .btn.btn--primary { flex: 2; min-width: 0; }
@media (max-width: 480px) {
  .formActions {
    flex-direction: column;
  }
  .formActions .btn,
  .formActions .btn.btn--primary {
    flex: none;
    width: 100%;
  }
}

/* Credits badge — standardized cost display */
.creditsBadge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--muted);
  margin-top: var(--space-3);
}
.creditsBadge strong { color: var(--accent); }

/* Credit cost indicator on action buttons (via data attribute + CSS ::after) */
[data-credit-cost]::after {
  content: " (" attr(data-credit-cost) " credits)";
  color: var(--warning-text);
  font-weight: 600;
  font-size: 0.85em;
}
/* Hide credit indicator when cost is empty (already paid) */
[data-credit-cost=""]::after { content: none; }

/* Step header — centered title for wizard steps */
.stepHeader {
  text-align: center;
  margin-bottom: var(--space-4);
}
.stepHeader .stepTitle {
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--fg);
}
.stepHeader .stepSub {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: var(--space-1);
}
.input {
  width: 100%;
}
.form-group {
  margin-bottom: 14px;
}
.form-group > label {
  display: block;
  margin-bottom: 6px;
  font-weight: 500;
  color: var(--muted);
  font-size: var(--text-sm);
}
.form-group input,
.form-group textarea,
.form-group select {
  width: 100%;
}

/* Form sections for better modal organization */
.formSection {
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.formSection:last-of-type {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.formSectionTitle {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.formSectionTitle::before {
  content: "";
  width: 3px;
  height: 16px;
  background: var(--accent);
  border-radius: var(--radius-2);
}

/* 2-column form grid */
.formGrid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.formGrid2 .field {
  margin-top: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.formGrid2 .field label {
  min-width: auto;
  font-size: var(--text-sm);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 6px;
}

.formGrid2 .field input,
.formGrid2 .field select,
.formGrid2 .field textarea {
  width: 100%;
}

/* Full-width field inside grid */
.formGrid2 .field.fullWidth {
  grid-column: 1 / -1;
}

/* Required indicator */
.field .required {
  color: var(--danger-text);
  font-weight: 500;
}
/* Required inputs — subtle left accent when empty (placeholder visible) */
.field input[required]:placeholder-shown,
.field select[required]:invalid,
.field textarea[required]:placeholder-shown {
  border-left: 3px solid rgba(var(--accent-rgb), 0.3);
}

/* Responsive: stack on mobile */
@media (max-width: 600px) {
  .formGrid2 {
    grid-template-columns: 1fr;
  }
}

.uploadRow {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: 10px;
}

/* Transcription Preset Selector (Alpha 13) */
.preset-selector {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
  flex-wrap: wrap;
}

.preset-card {
  flex: 1;
  min-width: 140px;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--duration-base) var(--ease-default);
}

.preset-card:hover {
  background: var(--card2);
  border-color: rgba(var(--accent-rgb), 0.3);
}

.preset-card.selected {
  background: rgba(var(--accent-rgb), 0.15);
  border-color: var(--accent);
  box-shadow: 0 0 20px rgba(var(--accent-rgb), 0.15);
}

.preset-icon {
  font-size: var(--text-2xl);
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--btn);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.preset-card.selected .preset-icon {
  background: rgba(var(--accent-rgb), 0.3);
}

.preset-info {
  flex: 1;
  min-width: 0;
}

.preset-name {
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--text);
}

.preset-card.selected .preset-name {
  color: var(--accent-light);
}

.preset-card:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.preset-card:focus:not(:focus-visible) {
  outline: none;
}

.preset-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.preset-desc {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 2px;
}

@media (max-width: 600px) {
  .preset-selector {
    flex-direction: column;
  }
  .preset-card {
    min-width: 100%;
  }
}

.hint {
  color: var(--muted);
  font-size: var(--text-sm);
  margin-top: var(--space-2);
}

/* Form Controls and Buttons are defined at the end of this file */

/* === Actions Bar === */
.actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}
.actions input[type="search"],
.actions input[type="text"] {
  width: 280px;
  max-width: 55vw;
}
.actions select { width: 120px; }

@media (max-width: 480px) {
  .actions {
    justify-content: stretch;
  }
  .actions input[type="search"],
  .actions input[type="text"] {
    width: 100%;
    max-width: 100%;
  }
  .actions select {
    width: 100%;
    min-width: 0 !important;
  }
}

/* === Table === */
.tableWrap {
  padding: 10px 0;
  margin-top: 14px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}

/* Table styles are defined at the end of this file */

.chk { width: 40px; }
.chk input { width: 18px; height: 18px; }
.right { text-align: right; }
.cellTruncate {
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cellNowrap { white-space: nowrap; }
.cellActions {
  white-space: nowrap;
  text-align: right;
}
.cellActions .btn + .btn {
  margin-left: 6px;
}

/* Badges are defined at the end of this file */

/* === Modals === */
.modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  z-index: var(--z-modal);
  overflow: hidden; /* Prevent spring overshoot from causing horizontal scrollbar */
}
.modal::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(var(--black-rgb),0.80);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  pointer-events: none;
}
.modal > * { position: relative; z-index: var(--z-decoration); }

/* Modal stacking (Plan job-intake-stepper P0) — pushed modals via
   window.pushModal() get a data-stack-level attribute that escalates their
   z-index. Non-topmost modals (data-stack-top absent) become inert so the
   user can only interact with the topmost modal, while lower modals remain
   visually present in the background. */
.modal[data-stack-level="0"] { z-index: var(--z-modal-stack-0); }
.modal[data-stack-level="1"] { z-index: var(--z-modal-stack-1); }
.modal[data-stack-level="2"] { z-index: var(--z-modal-stack-2); }
.modal[data-stack-level]:not([data-stack-top="1"]) {
  pointer-events: none;
}
.modal[data-stack-suspended="1"] {
  pointer-events: none;
}
.modal[data-stack-level]:not([data-stack-top="1"]) .modalCard {
  /* Slight desaturation + scale-down to signal "inactive in background" without
     hiding the parent modal entirely. The user keeps spatial context. */
  filter: brightness(0.85) saturate(0.92);
  transform: scale(0.98);
  transition: filter var(--duration-base) var(--ease-default),
              transform var(--duration-base) var(--ease-default);
}
.modal[data-stack-level][data-stack-top="1"] .modalCard {
  filter: none;
  transform: scale(1);
  transition: filter var(--duration-base) var(--ease-default),
              transform var(--duration-base) var(--ease-default);
}
/* Stacked modals' backdrops compose : level 0 backdrop is the strongest
   (full app obscured), level 1+ backdrops are progressively lighter so the
   user sees through to the parent modal. */
.modal[data-stack-level="1"]::before {
  background: rgba(var(--black-rgb), 0.45);
}
.modal[data-stack-level="2"]::before {
  background: rgba(var(--black-rgb), 0.35);
}

/* Premium entry/exit animations for pushed modals — slide-up + fade.
   wizardStepIn already exists in effects.css; we apply it to .modalCard
   when the parent .modal has a stack level (i.e. was pushed via pushModal).
   Legacy .modal opens without animation (unchanged). */
.modal[data-stack-level] .modalCard {
  animation: wizardStepIn var(--duration-slow) var(--ease-decel) both;
}
@media (prefers-reduced-motion: reduce) {
  .modal[data-stack-level] .modalCard,
  .modal[data-stack-level]:not([data-stack-top="1"]) .modalCard,
  .modal[data-stack-level][data-stack-top="1"] .modalCard {
    animation: none !important;
    transition: none !important;
    filter: none !important;
    transform: none !important;
  }
}

/* === Modal skeleton (dynamiques core-utils) — source unique L2 T2.11 ===
   Relocalisé VERBATIM depuis ui-primitives.css (aucun renommage — .modalActions
   reste sous contrat test_fullview_e2e.py:95). Système kebab-case (.modal-overlay/
   .modal-card/.modal-box, consommé par core-utils.js showModal()/confirmDialog())
   distinct de la famille statique camelCase ci-dessous (.modalCard/.modalActions) —
   coexistence assumée, l'unification des recettes est du L5. */
.modal-overlay--dynamic { z-index: var(--z-modal); }

/* Modal primitive — base overlay + box. RELOCATED here from recruiter-phase3.css.
   The centering (position:fixed + flex) previously lived ONLY in the recruiter-gated
   stylesheet, so showModal()/confirmWithdrawalRight()/confirmDialog-style overlays
   rendered as a static block in normal flow for non-recruiter roles (candidate, coach,
   admin) — dropping the box to the bottom of the page, off-screen. ui-primitives.css is
   loaded for all authenticated roles, so the modal now centers for everyone. */
.modal-overlay {
  position: fixed; inset: 0; z-index: var(--z-modal-backdrop);
  background: rgba(var(--black-rgb), 0.5);
  display: flex; align-items: center; justify-content: center;
}
.modal-card, .modal-box {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: var(--space-4);
  max-width: 460px; width: 90%; max-height: 80vh; overflow-y: auto;
  box-shadow: var(--shadow);
  /* Scale-in entrance animation */
  animation: modalScaleIn var(--duration-base) ease-out forwards;
}
@keyframes modalScaleIn {
  from { transform: scale(0.95) translateY(8px); opacity: 0; }
  to   { transform: scale(1) translateY(0); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .modal-card, .modal-box { animation: none; }
}
body.light-theme .modal-card, body.light-theme .modal-box,
body.bento-theme .modal-card, body.bento-theme .modal-box,
body.atsiq-theme .modal-card, body.atsiq-theme .modal-box {
  background: rgba(var(--white-rgb), 0.95); box-shadow: var(--shadow);
}

.modalCard {
  position: relative;
  width: min(560px, 96vw);
  max-height: 90vh;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 0;
  background: var(--bg-popup) !important;
  border: 1px solid rgba(var(--white-rgb), 0.10);
  box-shadow: 0 25px 60px rgba(var(--black-rgb), 0.5), inset 0 1px 0 rgba(var(--white-rgb), 0.06);
  border-radius: var(--radius);
  padding: 24px 28px;
  /* Modal entrance animation — spring easing for premium feel */
  transform: scale(0.96) translateY(12px);
  opacity: 0;
  transition: transform var(--duration-base) var(--ease-spring), opacity var(--duration-slow) var(--ease-decel);
}
.modal:not(.hidden) .modalCard {
  transform: scale(1) translateY(0);
  opacity: 1;
}
/* Modal content stagger — header first, then body, then actions */
.modal:not(.hidden) .modalHead {
  animation: modalContentIn var(--duration-slow) var(--ease-decel) 0.05s both;
}
.modal:not(.hidden) .modalBody {
  animation: modalContentIn var(--duration-slow) var(--ease-decel) 0.12s both;
}
.modal:not(.hidden) .modalActions {
  animation: modalContentIn var(--duration-slow) var(--ease-decel) 0.2s both;
}
@keyframes modalContentIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Default modal close button — top-right, consistent across all modals lacking
   their own flex .modalHead chrome (.modalHeader/.modal-header/.modalBox
   consumers — position:relative context from `.modal > *` above). */
.modalHeader .btn--icon, .modal-header .btn--icon, .modalBox .btn--icon { position: absolute; top: var(--space-3); right: var(--space-3); background: none; border: none; color: var(--muted); font-size: var(--text-xl); cursor: pointer; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background var(--duration-fast); z-index: 1; }
.modalHeader .btn--icon:hover, .modal-header .btn--icon:hover, .modalBox .btn--icon:hover { background: var(--bg-tertiary); color: var(--fg); }
.modalHeader .btn--icon:focus-visible, .modal-header .btn--icon:focus-visible, .modalBox .btn--icon:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.modalCard { position: relative; } /* Ensure absolute positioning context for .modalHeader/.modal-header/.modalBox close buttons */
/* Mobile: faster, no spring overshoot + 44px touch target (WCAG 2.5.5 AA) */
@media (max-width: 768px) {
  .modalCard {
    transition: transform var(--duration-slow) var(--ease-decel), opacity var(--duration-base) var(--ease-decel);
  }
  .modalHeader .btn--icon, .modal-header .btn--icon, .modalBox .btn--icon { width: 44px; height: 44px; }
}
/* Modal sizing classes — 2026-05-13 user feedback : les modals étaient
 * inutilement étroits. Un modal sur-couche peut prendre l'espace dispo
 * sans gêner. Bumped : compact 480→520, medium 650→760, wide 920→1240.
 * (Specific modals override e.g. .jobIntake-with-preview = 1480.) */
.modalCard.compact { width: min(520px, 96vw); }
.modalCard.medium  { width: min(760px, 96vw); }
.modalCard.wide    { width: min(1240px, 96vw); }

/* Full-page modal for major tools */
.modalCard.fullPage {
  width: min(1100px, 96vw);
  max-height: 95vh;
  max-height: 95dvh;
  padding: 28px 36px;
}
.modalCard.fullPage .modalHead {
  padding-bottom: var(--space-5);
  margin-bottom: var(--space-6);
}
/* .modalCard.fullPage .modalHead .h1 : hérite du canon .h1 24px (UI Unity W2.5) */

/* Section cards inside fullPage modals */
.toolSection {
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-4);
  transition: border-color var(--duration-base);
}
.toolSection:hover {
  border-left-color: var(--accent-light);
}
.toolSectionHeader {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: var(--space-4);
}
.toolSectionIcon {
  font-size: var(--text-2xl);
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--accent-rgb), 0.1);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.toolSectionHeader h3 {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--fg);
  margin: 0;
  line-height: 1.3;
}
.toolSectionHeader p {
  font-size: var(--text-sm);
  color: var(--muted);
  margin: 2px 0 0;
}
.toolSectionContent {
  padding-left: 54px; /* align with text after icon */
}
@media (max-width: 600px) {
  .modal {
    align-items: flex-start;
    padding: 48px 8px 8px;
    background: var(--bg1);
  }
  .modal::before {
    display: none;
  }
  .modalCard {
    transform: none !important;
    opacity: 1 !important;
    transition: none !important;
    max-height: calc(100vh - 56px);
    max-height: calc(100dvh - 56px);
    width: calc(100% - 16px) !important;
    border-radius: var(--radius-12) var(--radius-12) 0 0;
    padding: var(--space-4);
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
  }
  .modalCard.fullPage {
    padding: var(--space-4);
    min-height: 100vh;
    min-height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    border-radius: 0;
    width: 100% !important;
  }
  .modalCard.fullPage .modalBody {
    max-height: calc(100dvh - 140px);
  }
  .modalCard.fullPage .modalHead {
    padding-bottom: var(--space-3);
    margin-bottom: var(--space-3);
  }
  .modalCard.wide, .modalCard.medium {
    width: calc(100% - 16px) !important;
    max-height: calc(100dvh - 56px);
    border-radius: var(--radius-12) var(--radius-12) 0 0;
  }
  .toolSectionContent {
    padding-left: 0;
  }
  /* Phase 3A: FullPage mobile polish — safe areas + scroll inertia */
  .modalCard.fullPage {
    padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  }
  .modalCard.fullPage > .modalActions,
  .modalCard.fullPage .modalActions {
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    position: sticky;
    bottom: 0;
    /* §11 mobile re-VQA (2026-07-16) — --bg-popup alone is NOT opaque: it is a
       0.96-0.98-alpha gradient in every theme, so high-contrast body text still
       ghosted through between the stacked buttons (measured Δ11 luminance at
       390px). Fix = paint the opaque base surface --bg1 (plain hex in all 3
       themes) UNDER the themed popup gradient → identical look, zero bleed. */
    background-color: var(--bg1);
    background-image: var(--bg-popup);
    border-top: 1px solid var(--border);
    box-shadow: 0 -8px 16px -12px rgba(var(--black-rgb), 0.35);
    z-index: var(--z-raised);
  }
  .modalCard.fullPage > .modalBody,
  .modalCard.fullPage .modalBody {
    -webkit-overflow-scrolling: touch;
  }
  /* Phase 3E: Sticky modal actions for wide/medium modals (job editor wizard
     #jobIntakeFooter, job preview .job-fullview__toolbar, …) */
  .modalCard .modalActions {
    position: sticky;
    bottom: 0;
    /* §11 mobile re-VQA (2026-07-16) — --bg-popup alone is NOT opaque (0.96-0.98
       alpha gradient per theme): scrolled text still ghosted through between the
       stacked buttons. Opaque --bg1 base under the themed gradient = same look,
       fully occluding. */
    background-color: var(--bg1);
    background-image: var(--bg-popup);
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
    box-shadow: 0 -8px 16px -12px rgba(var(--black-rgb), 0.35);
    z-index: var(--z-raised);
  }
}

/* Mobile: stack .field vertically inside ALL modals (label above, input full width) */
@media (max-width: 600px) {
  .modalCard .field {
    flex-direction: column;
    align-items: stretch;
  }
  .modalCard .field > label {
    min-width: unset;
  }
}

/* Phase 3C: Touch-friendly close buttons (44px minimum tap target) */
body[data-device="mobile"] .modalHead .btn--icon {
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* MOB-002: Minimum 44px tap targets on mobile */
@media (max-width: 768px) {
  .btn--icon,
  .modal-error-banner-close {
    min-width: 44px;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

/* Light theme */
body.light-theme .toolSection,
body.bento-theme .toolSection, body.atsiq-theme .toolSection {
  background: rgba(var(--black-rgb), 0.02);
}
body.light-theme .toolSectionIcon,
body.bento-theme .toolSectionIcon, body.atsiq-theme .toolSectionIcon {
  background: rgba(var(--accent-rgb), 0.08);
}

/* Option Cards (CV Rework Wizard Steps 2-3, redesigned Alpha 25.61) */
.optionCard {
  background: var(--card);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius);
  padding: var(--space-6);
  margin-bottom: var(--space-4);
  transition: all var(--duration-slow) var(--ease-default);
  position: relative;
}
/* Left accent — border-left on .optionCard is sufficient, no ::before glow needed */
.optionCard:hover {
  border-color: rgba(var(--primary-rgb), 0.25);
  box-shadow: 0 2px 16px rgba(var(--primary-rgb), 0.06);
}
.optionCardHeader {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: var(--space-4);
}
.optionCardIcon {
  font-size: var(--text-2xl);
  width: 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--primary-rgb), 0.1);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  transition: all var(--duration-slow);
}
.optionCard:hover .optionCardIcon {
  background: rgba(var(--primary-rgb), 0.15);
  box-shadow: 0 0 10px rgba(var(--primary-rgb), 0.1);
}
.optionCardHeader h3 {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--fg);
  margin: 0;
  line-height: 1.3;
}
.optionCardHeader p {
  font-size: var(--text-sm);
  color: var(--muted);
  margin: 2px 0 0;
}
.optionCardContent {
  padding-left: 56px;
}
.optionCardCollapse {
  margin-bottom: var(--space-4);
}
.optionCardCollapse summary {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
body.light-theme .optionCard,
body.bento-theme .optionCard, body.atsiq-theme .optionCard {
  background: rgba(var(--white-rgb), 0.7);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
body.light-theme .optionCardIcon,
body.bento-theme .optionCardIcon, body.atsiq-theme .optionCardIcon {
  background: rgba(var(--primary-rgb), 0.08);
}
/* optionCard::before removed — see comment above */
@media (max-width: 600px) {
  .optionCardContent {
    padding-left: 0;
  }
}
body.light-theme .mockSetupSection,
body.bento-theme .mockSetupSection, body.atsiq-theme .mockSetupSection {
  background: rgba(var(--black-rgb), 0.015);
}
body.light-theme .mockSectionIcon,
body.bento-theme .mockSectionIcon, body.atsiq-theme .mockSectionIcon {
  background: rgba(var(--accent-rgb), 0.08);
}
body.light-theme .mockConfigCard,
body.bento-theme .mockConfigCard, body.atsiq-theme .mockConfigCard {
  background: rgba(var(--black-rgb), 0.02);
}
body.light-theme .mockSetupFooter,
body.bento-theme .mockSetupFooter, body.atsiq-theme .mockSetupFooter {
  background: rgba(var(--accent-rgb), 0.04);
}
body.light-theme .toolSectionHeader h3,
body.bento-theme .toolSectionHeader h3,
body.light-theme .mockSectionHeader h3,
body.bento-theme .mockSectionHeader h3, body.atsiq-theme .toolSectionHeader h3, body.atsiq-theme .mockSectionHeader h3 {
  color: var(--text);
}
body.light-theme .mockConfigCard,
body.bento-theme .mockConfigCard, body.atsiq-theme .mockConfigCard {
  border-color: var(--border);
}
body.light-theme .mockConfigCard:hover,
body.bento-theme .mockConfigCard:hover, body.atsiq-theme .mockConfigCard:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 12px rgba(var(--accent-rgb), 0.12);
}

.modalHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-5);
}

/* Modal subtitle */
.modalHead .modalSubtitle {
  font-size: var(--text-sm);
  color: var(--muted);
  margin-top: 2px;
  font-weight: 400;
}

/* Modal close button polish */
.modalHead .btn--icon {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-base);
  color: var(--muted);
  transition: all var(--duration-fast);
  flex-shrink: 0;
}
.modalHead .btn--icon:hover {
  background: rgba(var(--white-rgb), 0.08);
  color: var(--fg);
}

/* Modal body — scrollable content area */
.modalBody {
  overflow-y: auto;
  overscroll-behavior: contain;
  max-height: calc(90vh - 160px);
  padding-right: var(--space-1);
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
  mask-image: linear-gradient(to bottom, transparent 0, black 12px, black calc(100% - 12px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 12px, black calc(100% - 12px), transparent 100%);
}
.modalCard.fullPage .modalBody {
  max-height: calc(95vh - 170px);
  max-height: calc(95dvh - 170px);
}

/* Modal footer actions — unified layout — CANON L5 (D-6). Ordre DOM : Annuler
   (.btn .btn--ghost) → Primaire (.btn .btn--primary) ; destructif = .btn .btn--danger. */
.modalActions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-3);
  padding-top: var(--space-4);
  margin-top: var(--space-5);
  border-top: 1px solid var(--border);
}

/* Modal preview / transcript zones */
.modalPreview {
  background: var(--bg0);
  border-radius: var(--radius-8);
  padding: var(--space-3);
  max-height: 200px;
  overflow-y: auto;
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.6;
}
.modalPreview.tall  { max-height: 300px; }
.modalPreview.short { max-height: 120px; }
.modalPreview.auto  { max-height: none; }

/* Responsive modal footers — stack vertically on mobile */
@media (max-width: 600px) {
  .modalActions {
    flex-direction: column;
  }
  .modalActions .btn {
    width: 100%;
  }
  /* 2-button modals: keep inline row to save vertical space */
  .modalActions.inline-mobile,
  .modalActions:has(> .btn:nth-child(2):last-child) {
    flex-direction: row;
  }
  .modalActions.inline-mobile .btn,
  .modalActions:has(> .btn:nth-child(2):last-child) .btn {
    width: auto;
    white-space: nowrap;
    font-size: var(--text-sm);
  }
  .modalActions:has(> .btn:nth-child(2):last-child) .btn:first-child {
    flex: 0 1 auto;
  }
  .modalActions:has(> .btn:nth-child(2):last-child) .btn:last-child {
    flex: 1 1 auto;
  }
}
/* Mobile modal body height fix */
@media (max-width: 600px) {
  .modalBody {
    max-height: calc(100dvh - 200px);
  }
}

/* Light theme modal overrides */
body.light-theme .modalActions,
body.bento-theme .modalActions, body.atsiq-theme .modalActions {
  border-top-color: rgba(var(--accent-rgb),0.12);
}
body.light-theme .modalPreview,
body.bento-theme .modalPreview, body.atsiq-theme .modalPreview {
  background: rgba(var(--accent-rgb),0.05);
}
body.light-theme .modalHead .btn--icon:hover,
body.bento-theme .modalHead .btn--icon:hover, body.atsiq-theme .modalHead .btn--icon:hover {
  background: rgba(var(--accent-rgb),0.08);
}

/* Tabs — CANON L3 (navigation avec panneaux, actif = underline). Promotion verbatim des tokens
   .ct-cand-tab* (recruiter-candidates.css pré-L3, seule définition conforme du repo) — 1 définition,
   thémée par tokens L2 uniquement, zéro body.<theme> re-déclaration. #roleNav.tabs est display:none
   !important (sidebar.css "Hide old horizontal navs") : les anciennes règles #roleNav-spécifiques et
   leurs jambes thème (gradient/box-shadow forcés, ~90 lignes) sont donc supprimées sans delta visuel —
   preuve : l'élément ne rend jamais. .ct-cand-tab* alias purgé en T3 (consommateurs migrés vers
   .tab/.tab__label/.tab__count le même commit) ; dernier résidu (règle touch-target mobile
   orpheline) purgé en T11. Les modificateurs `--pinned`/`__count--soon` restent (consommateurs
   vivants, distincts de l'alias de base). */
.tabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: var(--border-width-hairline) solid var(--line);
  margin-bottom: var(--space-4);
}
.tabs--sub {
  gap: var(--space-1);
  font-size: var(--text-sm);
}
.tab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: var(--border-width-medium) solid transparent;
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
  flex: 0 0 auto;
  min-width: 0;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.tab:hover { color: var(--text); }
.tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  background: var(--card-hover);
  border-top-left-radius: var(--radius-sm);
  border-top-right-radius: var(--radius-sm);
}
.tab:focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: var(--radius-xs); }
.tab__label {
  min-width: 0;
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Compteur pill neutre — REG-112 : remplace rec-filter-count et les pills de compteurs dispersées
   (unifié ici, consommé par T3+). */
.tab__count {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--text-xs);
  line-height: 1;
  padding: 1px 6px;
  border-radius: var(--radius-full, 999px);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--muted);
}
.tab.active .tab__count {
  background: rgba(var(--accent-rgb), 0.18);
  color: var(--accent);
}
.tab__count[hidden] { display: none; }
/* Icône par onglet (org-nav 2 niveaux — L3-T5, REG-118) — dimensionnement via l'attribut svg width/height. */
.tab__icon {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

/* Drawer tabs — extension scopée du canon .tabs--sub (L3-T10, REG-121 : fusion des paires
   cd-drawer__tab/pl-drawer__tab octet-identiques). Rail scrollable horizontalement (drawers
   étroits), scrollbar fine + cible tactile 44px mobile (WCAG 2.5.5) — appliqué uniformément
   aux 2 surfaces (pl-drawer__tab seul avait le touch-target avant fusion). */
.contact-detail-drawer .tabs--sub,
.placement-drawer .tabs--sub {
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.contact-detail-drawer .tabs--sub .tab,
.placement-drawer .tabs--sub .tab {
  flex-shrink: 0;
}
@media (max-width: 480px) {
  .contact-detail-drawer .tabs--sub,
  .placement-drawer .tabs--sub {
    gap: 0;
    scrollbar-width: thin;
    scrollbar-color: var(--muted) transparent;
  }
  .contact-detail-drawer .tabs--sub::-webkit-scrollbar,
  .placement-drawer .tabs--sub::-webkit-scrollbar { height: 4px; }
  .contact-detail-drawer .tabs--sub::-webkit-scrollbar-thumb,
  .placement-drawer .tabs--sub::-webkit-scrollbar-thumb {
    background: var(--muted); border-radius: var(--radius-full);
  }
  .contact-detail-drawer .tabs--sub .tab,
  .placement-drawer .tabs--sub .tab {
    padding: var(--space-2);
    font-size: var(--text-xs);
    min-height: 44px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .contact-detail-drawer .tabs--sub .tab,
  .placement-drawer .tabs--sub .tab { transition: none !important; }
}

/* Segmented control — CANON L3 (1 parmi N, sans panneaux, role="radiogroup"). Promotion verbatim de
   .ct-export-modal__seg/.ct-segmented__btn (recruiter-job-export-modal.css pré-L3, seule définition
   conforme du repo) — les tokens forkés --ds-* de la source (jamais définis, fallback toujours
   gagnant) sont résolus directement vers les tokens réels. État renommé is-active→active (vocable
   banni T14) ; :focus-visible ajouté (REG-104, manquant à la source). La définition locale a été
   un alias temporaire, purgé en T7 (même commit que la migration de ses sites). ARIA radiogroup
   tranché (REG-116) : PAS de panneaux — un segmented qui bascule des panneaux est un onglet
   (grammaire 1), voir §3. */
.ct-segmented {
  display: inline-flex;
  align-self: flex-start;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card2);
  padding: 2px;
  gap: 2px;
}
.ct-segmented__btn {
  border: none;
  background: transparent;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: 500;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--muted);
  transition: background var(--duration-fast) var(--ease-default), color var(--duration-fast) var(--ease-default);
}
.ct-segmented__btn:hover { color: var(--text); }
/* RE-JURY 2 — da-R-02 [M] : le segment ACTIF et son compteur peignaient du texte avec l'accent
   NATIF. Mesures Obsidian (harnais phase2-p2g-hub, 1440 px, fond composé en remontant les
   ancêtres) : « Grille » 13 px → 3,69:1 et le compteur « 5 » 12 px → 3,01:1, pour un seuil AA de
   4,5:1. C'est exactement la faute que le re-gate CSS a fermée sur `.btn--help` / `.rdash-rec__fees`
   (« l'accent natif n'est jamais une couleur de TEXTE en soi ») ; elle n'avait pas été portée
   jusqu'au segmented, qui vit sur la surface la plus visitée du produit.
   · le TEXTE passe sur `--accent-text` — la variante « accent lisible » du thème (Obsidian
     `--accent-light`, clair `--accent`, donc thème clair inchangé au pixel près) ;
   · le VOILE du compteur descend de 0,18 à 0,12 : à 0,18 le fond du compteur remontait assez pour
     laisser `--accent-text` à 4,51:1, à un centième du seuil — hors marge de mesure. À 0,12 la
     paire rend 4,86:1 (mesurée, cf. contrast-after.json), et le voile reste visible en clair. */
/* P3 L8 (J-209) — L'ÉTAT SÉLECTIONNÉ DOIT SE VOIR, WCAG 1.4.11 (3:1 pour un indicateur d'état).
   Mesures du jury sur le vrai hôte, thème clair : pastille active #FFFFFF contre piste #FEFEFE,
   soit UN 255ᵉ d'écart ; la seule différence réelle était une bordure de 1 px à #E2E3E4 → 1,24:1
   pour le segmenteur « Grille | Liste » et 1,15:1 pour les chips de statut. « L'utilisateur ne
   sait pas quel filtre est appliqué ni dans quelle vue il se trouve — sur une page qui annonce
   22 postes et n'en montre que 19, c'est précisément l'information qui manque. »
   ⇒ Un ANNEAU INTERNE de 2 px en `--accent-text`. Pourquoi celui-là et pas un fond teinté : la
   variante « accent lisible » du thème est déjà garantie ≥ 4,5:1 EN TEXTE sur `--card` (c'est sa
   définition, cf. le commentaire ci-dessus), donc ≥ 3:1 comme indicateur non textuel — et surtout
   AUCUNE paire texte/fond ne bouge, si bien que les contrastes mesurés au re-gate RE-JURY 2
   (« Grille » et son compteur) restent valides au centième près. `inset` ⇒ zéro décalage de
   gabarit (le bouton n'a pas de bordure et ne doit pas en gagner une). */
.ct-segmented__btn.active {
  background: var(--card);
  color: var(--accent-text, var(--accent));
  box-shadow: var(--shadow-sm), inset 0 0 0 2px var(--accent-text, var(--accent));
}
.ct-segmented__btn.active .tab__count {
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent-text, var(--accent));
}
.ct-segmented__btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
@media (prefers-reduced-motion: reduce) {
  .ct-segmented__btn { transition: none; }
}
/* §11 mobile (2026-07-16) — the segmented bar keeps its natural (content) width; on a
   phone a 5-6 segment bar (~415px on « Mes postes ») overflowed its column and was
   clipped dead by the .wrap { overflow-x: hidden } ancestor (last segment unreachable).
   ≤480px the bar becomes a horizontal scroll strip with snap — same gesture as the
   canon .tabs mobile strip (§10.9) and the Organisation rails. Buttons keep natural
   width (no shrink) so labels never crush ("En pause" wrapping over its count).
   Desktop/tablet (>480px) byte-identical. */
@media (max-width: 480px) {
  .ct-segmented {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    scroll-snap-type: x proximity;
  }
  .ct-segmented::-webkit-scrollbar { display: none; }
  .ct-segmented__btn {
    flex: 0 0 auto;
    white-space: nowrap;
    scroll-snap-align: start;
  }
}

/* Radio-cards — CANON L3-T9 (D-3 "un seul gabarit"). Grille de sélection unique
   parmi N (thèmes, plateformes ATS…) pilotée en JS : role="button"/aria-pressed
   par carte (grille 2D — pas de roving-tabindex/flèches, chaque carte reste
   Tab-focusable individuellement, cohérent avec le motif pré-existant). État
   .active (et non .selected, vocable banni T14). __media = slot optionnel pour
   thumbnail/preview (pas de crop forcé, le contenu définit sa hauteur).
   NB : ji-vis-card/ji-pk-card/ji-salary-visibility (intake step 4) utilisent un
   motif natif <label><input type="radio"> + :has(:checked) supérieur (zéro JS,
   navigation clavier native) — sciemment NON migrés ici (régression sinon) ;
   leur propre unification interne (3 implémentations quasi-dupliquées) reste
   une piste séparée, non couverte par ce lot. */
.ct-choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-3);
}
.ct-choice-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  transition: border-color var(--duration-fast) var(--ease-default), background var(--duration-fast) var(--ease-default), box-shadow var(--duration-fast) var(--ease-default);
}
.ct-choice-card:hover { border-color: var(--accent); }
.ct-choice-card.active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.06);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.25);
}
.ct-choice-card:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.ct-choice-card__media {
  display: block;
  width: 100%;
  border-radius: var(--radius-sm);
  overflow: hidden;
  position: relative;
}
.ct-choice-card__media img { display: block; width: 100%; height: auto; }
.ct-choice-card__label {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}
.ct-choice-card.active .ct-choice-card__label { color: var(--accent); }
.ct-choice-card__meta {
  font-size: var(--text-xs);
  color: var(--muted);
}
@media (prefers-reduced-motion: reduce) {
  .ct-choice-card { transition: none; }
}

/* Danger Zone */
.dangerZone {
  margin-top: var(--space-5);
  padding: var(--space-4);
  border-radius: var(--radius-12);
  background: var(--danger);
  border: 1px solid rgba(var(--red-light-rgb),0.20);
}
.hr {
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--border) 20%, var(--border) 80%, transparent);
  margin: var(--space-4) 0;
}

/* Admin panel */
.card.inner {
  margin-top: 0;
  background: rgba(var(--white-rgb), 0.03);
}
.mono { font-family: var(--font-mono, monospace); font-size: var(--text-xs); white-space: pre-wrap; }
.small { font-size: var(--text-xs); }

/* Brand colors */
.brandCareer { color: var(--text); }
.brandDot { color: var(--accent); }
.brandAI { color: var(--accent2); }

/* === Registration Stepper === */
.regStepper {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 0;
  margin-bottom: var(--space-6);
}

.regStepItem {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-width: 60px;
}

.regStepLabel {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  transition: color var(--duration-slow) var(--ease-default);
  white-space: nowrap;
}

.regStepItem:has(.regStepDot.active) .regStepLabel {
  color: var(--accent-light);
}

.regStepItem:has(.regStepDot.done) .regStepLabel {
  color: var(--accent-light);
  opacity: 0.7;
}

/* Role Cards for registration */
.roleCard {
  display: block;
  padding: var(--space-4);
  border-radius: var(--radius-sm);
  border: 2px solid var(--border);
  background: var(--card-bg);
  cursor: pointer;
  transition: all var(--duration-slow) var(--ease-default);
  position: relative;
  overflow: hidden;
}
.roleCard::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--gradient-primary);
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease-default);
}
.roleCard:hover {
  border-color: rgba(var(--accent-rgb), 0.3);
  background: rgba(var(--accent-rgb), 0.03);
}
.roleCard:hover::before {
  opacity: 0.5;
}
.roleCard:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.roleCard.selected,
.roleCard:has(input:checked) {
  border-color: var(--accent);
  background: var(--btn);
}
.roleCard.selected::before,
.roleCard:has(input:checked)::before {
  opacity: 1;
}
.roleIcon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--accent-rgb), 0.1);
  color: var(--accent-light);
  margin-bottom: 10px;
  transition: background var(--duration-slow) var(--ease-default), transform var(--duration-slow) var(--ease-default);
}
.roleCard.selected .roleIcon,
.roleCard:has(input:checked) .roleIcon {
  background: rgba(var(--accent-rgb), 0.18);
  transform: scale(1.05);
}
.roleCard .roleTitle {
  font-weight: 600;
  color: var(--accent);
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
}
.roleCard .roleFeatures {
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.6;
}
#roleCards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}

/* Plan A Phase 2.6 — Beta-invite role-locked state.
 * When the active beta invitation has role_locked=true, the non-target
 * role-cards are disabled visually + ARIA + pointer-events. The lock
 * hint below the grid uses .helper-text-style sizing for consistency
 * with the other auth-modal hints. Backend (Phase 2.3) is the source
 * of truth — this is purely UX so the user doesn't pick a role the
 * server will reject anyway. */
.roleCard.roleCard--locked {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
  filter: grayscale(0.4);
}
.roleCard.roleCard--locked .roleTitle,
.roleCard.roleCard--locked .roleFeatures {
  color: var(--muted);
}
.beta-role-locked-hint {
  grid-column: 1 / -1;
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs, 12px);
  color: var(--text-muted, var(--muted));
  background: rgba(var(--accent-rgb), 0.06);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
}
@media (prefers-reduced-motion: reduce) {
  .roleCard.roleCard--locked { transition: none; filter: none; }
}

.regStepDot {
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-xs); font-weight: 700;
  background: var(--border); color: var(--muted);
  transition: all var(--duration-slow) var(--ease-default); flex-shrink: 0;
  position: relative;
}
.regStepDot.active {
  background: var(--primary); color: var(--text-inverse);
  box-shadow: 0 0 16px rgba(var(--primary-rgb), 0.4), 0 0 4px rgba(var(--primary-rgb), 0.2);
}
.regStepDot.done {
  background: rgba(var(--primary-rgb), 0.14);
  color: transparent;
}
.regStepDot.done::after {
  content: '\2713';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--primary);
}
.regStepLine {
  width: 48px; height: 2px;
  background: var(--border);
  transition: background var(--duration-slow) var(--ease-default);
  margin-top: 15px; /* Center with dot */
}
.regStepLine.done { background: var(--primary); }
.regStep { animation: regStepIn var(--duration-slow) var(--ease-decel); }
.regStep.regSlideBack { animation: regStepInBack var(--duration-slow) var(--ease-decel); }
.regStep.regStepReplay { animation: regStepIn var(--duration-slow) var(--ease-decel); }
.regStep.regSlideBack.regStepReplay { animation: regStepInBack var(--duration-slow) var(--ease-decel); }
@keyframes regStepIn { from { opacity: 0; transform: translateX(30px); } to { opacity: 1; transform: translateX(0); } }
@keyframes regStepInBack { from { opacity: 0; transform: translateX(-30px); } to { opacity: 1; transform: translateX(0); } }

/* === Password Strength Meter === */
.pwStrength {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: 6px;
}
.pwStrength__bar {
  flex: 1;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--surface);
  overflow: hidden;
}
.pwStrength__fill {
  height: 100%;
  border-radius: var(--radius-full);
  width: 0%;
  transition: width var(--duration-base) var(--ease-decel), background var(--duration-base) var(--ease-default);
  background: var(--border);
}
.pwStrength__fill--empty { width: 0%; }
.pwStrength__fill--weak { width: 25%; }
.pwStrength__fill--fair { width: 50%; }
.pwStrength__fill--good { width: 75%; }
.pwStrength__fill--strong { width: 100%; }
.pwStrength__fill--weak { background: var(--danger-text); }
.pwStrength__fill--fair { background: var(--warning-text); }
.pwStrength__fill--good { background: var(--accent2); }
.pwStrength__fill--strong { background: var(--success-text); }

.regStepNoAnimation { animation: none !important; }
.pwStrength__text {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.3px;
  min-width: 55px;
  text-align: right;
  color: var(--fg-muted);
  transition: color var(--duration-slow) var(--ease-default);
}
.pwStrength__text--weak { color: var(--danger-text); }
.pwStrength__text--fair { color: var(--warning-text); }
.pwStrength__text--good { color: var(--accent2); }
.pwStrength__text--strong { color: var(--success-text); }
.registration-closed-input { opacity: 0.5; }
.btn-submit-pending { opacity: 0.7; }

/* === CV Upload Area (Dashboard) === */
.cvUploadArea {
  transition: all var(--duration-slow) var(--ease-default);
}
.cvUploadArea--prominent {
  padding: 0;
  margin-bottom: var(--space-2);
}
.cvUploadArea--prominent .ct-dz {
  border-style: dashed;
}
.cvUploadArea--compact {
  padding: 0 var(--space-3) var(--space-3);
}
.cvUploadArea--compact .ct-dz {
  border-style: dashed;
}
.cvUploadArea--compact .ct-dz-default {
  padding: var(--space-3) var(--space-3);
  flex-direction: row;
  align-items: center;
  gap: var(--space-3);
}
.cvUploadArea--compact .ct-dz-icon {
  margin-bottom: 0;
  flex-shrink: 0;
  display: flex;
  align-items: center;
}
.cvUploadArea--compact .ct-dz-icon svg { width: 20px; height: 20px; }
.cvUploadArea--compact .ct-dz-label { font-size: var(--text-xs); }
.cvUploadArea--compact .ct-dz-hint { font-size: var(--text-xs); }

/* CV List Action Buttons — consistent height */
.cvActions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  justify-content: flex-end;
}

.cvActions .btn.btn--small {
  height: 36px;
  min-height: 36px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
@media (max-width: 600px) {
  .cvActions {
    flex-wrap: wrap;
    gap: 4px;
    justify-content: flex-start;
  }

  .cvActions .btn.btn--small {
    height: 32px;
    min-height: 32px;
    font-size: var(--text-xs);
    padding: 0 var(--space-2);
  }
}
/* CV filename row */
.cv-filename-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.cv-filesize {
  font-size: var(--text-xs);
  color: var(--muted);
}
/* Consistent button height in CV table (all columns) */

#candidateCVsSection table .btn.btn--small {
  height: 36px;
  min-height: 36px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* CV Upload Progress */
.cvUploadProgress {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.cvUploadProgress__info {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
}
.cvUploadProgress__name {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 70%;
}
.cvUploadProgress__percent {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-light);
  font-weight: 600;
}
.cvUploadProgress__bar {
  height: 4px;
  border-radius: var(--radius-full);
  background: var(--surface);
  overflow: hidden;
}
.cvUploadProgress__fill {
  height: 100%;
  border-radius: var(--radius-full);
  background: var(--gradient-primary);
  transition: width var(--duration-slow) var(--ease-default);
}
@keyframes cvProgressIndeterminate {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}
.cvUploadProgress__fill--complete {
  background: var(--status-ok);
  transition: background var(--duration-slow) var(--ease-default);
}
.cvUploadProgress__fill--indeterminate {
  width: 40% !important;
  animation: cvProgressIndeterminate 1.5s ease-in-out infinite;
}

/* CV Empty State */
.cvEmptyState {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-6) var(--space-4) var(--space-4);
  gap: var(--space-2);
}
.cvEmptyState__icon {
  width: 64px;
  height: 64px;
  border-radius: var(--radius);
  background: rgba(var(--accent-rgb), 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-light);
  margin-bottom: var(--space-2);
  animation: cvEmptyPulse 3s ease-in-out infinite;
}
@keyframes cvEmptyPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.08); }
  50%      { box-shadow: 0 0 20px 4px rgba(var(--accent-rgb), 0.12); }
}
.cvEmptyState__title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text);
}
.cvEmptyState__sub {
  font-size: var(--text-sm);
  color: var(--fg-muted);
  max-width: 320px;
  line-height: 1.5;
}
.cvEmptyState__formats {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--fg-muted);
  letter-spacing: 0.5px;
  opacity: 0.6;
  margin-top: var(--space-1);
}

/* Light theme overrides for registration */
body.light-theme .roleIcon,
body.bento-theme .roleIcon, body.atsiq-theme .roleIcon {
  background: rgba(var(--accent-rgb), 0.08);
}
body.light-theme .roleCard.selected .roleIcon,
body.bento-theme .roleCard.selected .roleIcon, body.atsiq-theme .roleCard.selected .roleIcon {
  background: rgba(var(--accent-rgb), 0.14);
}
body.light-theme .regStepLabel,
body.bento-theme .regStepLabel, body.atsiq-theme .regStepLabel {
  color: var(--fg-muted);
}
body.light-theme .regStepItem:has(.regStepDot.active) .regStepLabel,
body.bento-theme .regStepItem:has(.regStepDot.active) .regStepLabel, body.atsiq-theme .regStepItem:has(.regStepDot.active) .regStepLabel {
  color: var(--accent);
}

@media (max-width: 480px) {
  #roleCards {
    grid-template-columns: 1fr;
  }
  .regStepLine {
    width: 32px;
  }
  .regStepLabel {
    font-size: var(--text-2xs);
  }
  .cvUploadArea--compact .ct-dz-default {
    flex-direction: column;
  }
}

/* === Auth Modal Enhanced === */
#modalAuth .modalCard {
  width: min(480px, 94vw);
  max-height: min(92vh, 780px);
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
@media (max-width: 600px) {
  #modalAuth {
    align-items: center;
    padding: var(--space-4);
  }
  #modalAuth .modalCard {
    max-height: calc(100dvh - 32px);
    border-radius: var(--radius-12);
  }
}

#modalAuth .modalHead {
  flex-shrink: 0;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.12) 0%, rgba(var(--accent-rgb), 0.04) 100%);
  padding: 24px 28px 20px;
  margin: 0;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.08);
  border-radius: var(--radius) var(--radius) 0 0;
}

#modalAuth .modalHead .h1 {
  font-weight: 700;
  background-image: linear-gradient(135deg, var(--text) 0%, var(--accent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ── Auth Modal: Tab Bar (pill toggle) ── */
/* L3-T10 (REG-121/authTab, spec §1.12) : ce fichier est PARTAGÉ par landing.html/
   landing-atsiq.html (hors périmètre dur — leur markup garde authTabBar/authTab tel
   quel). Le markup in-app (ui/index.html) porte désormais AUSSI tabs/tab (grammaire
   canon, classes cumulées) mais ce bloc bespoke reste la source visuelle réelle des
   3 surfaces (in-app + 2 landings) — purge impossible tant que les landings ne sont
   pas dans le périmètre d'un lot futur. */
.authModalHead { align-items: center; }

.authTabBar {
  flex-shrink: 0;
  display: flex;
  gap: 6px;
  margin: 0 28px 0;
  padding: var(--space-1);
  background: rgba(var(--white-rgb), 0.06);
  border-radius: var(--radius);
  border: 1px solid rgba(var(--white-rgb), 0.08);
}

.authTab {
  flex: 1;
  padding: 10px 16px;
  border-radius: calc(var(--radius) - 3px);
  border: 1px solid rgba(var(--white-rgb), 0.06);
  background: rgba(var(--white-rgb), 0.05);
  color: var(--muted);
  font-weight: 500;
  font-size: var(--text-base);
  cursor: pointer;
  transition: all var(--duration-slow) var(--ease-default);
  position: relative;
  text-align: center;
}

.authTab:hover {
  color: var(--text);
  background: rgba(var(--white-rgb), 0.06);
}

.authTab.active {
  color: var(--text-inverse);
  background: var(--gradient-primary);
  box-shadow: var(--shadow-accent-glow);
}

/* ── Auth Submit Button: loading dots ── */
.authSubmitBtn { position: relative; overflow: hidden; }
.authSubmitBtn:disabled { opacity: 0.8; cursor: wait; } /* busy, pas disabled — contrat L6a, ne pas passer sur --btn-disabled-opacity (T2.7) */
.authBtnLoading { display: inline-flex; align-items: center; justify-content: center; }
.authDots { display: inline-flex; gap: 6px; }
.authDots span {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: currentColor;
  animation: authDotPulse 1.2s ease-in-out infinite;
}
.authDots span:nth-child(2) { animation-delay: var(--duration-fast); }
.authDots span:nth-child(3) { animation-delay: var(--duration-slow); }
@keyframes authDotPulse {
  0%, 80%, 100% { opacity: 0.25; transform: scale(0.8); }
  40% { opacity: 1; transform: scale(1.1); }
}

/* ── Auth Error Message: shake animation ── */
.authErrorMsg {
  text-align: center;
  padding: 0;
  border-radius: var(--radius-sm);
  margin-top: var(--space-1);
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
  min-height: 0;
  transition: all var(--duration-base) var(--ease-default);
}
.authErrorMsg:not(:empty) {
  padding: 10px 14px;
  background: rgba(var(--red-mid-rgb), 0.18);
  border: 1px solid rgba(var(--red-mid-rgb), 0.35);
  color: var(--danger-text);
  animation: authErrorShake 0.4s ease-in-out;
}
@keyframes authErrorShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}
@keyframes authShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

#modalAuth #paneLogin,
#modalAuth #paneRegister {
  position: relative;
  padding: var(--space-5) var(--space-6) var(--space-6);
  overflow-y: auto;
  flex: 1;
  min-height: 0; /* Needed for flex child to scroll */
  /* Smooth scrollbar for inner content */
  scrollbar-width: thin;
}

#modalAuth .field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

#modalAuth .field > label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: none;
  letter-spacing: 0;
}

#modalAuth .checkboxLabel {
  display: flex !important;
  flex-direction: row !important;
  align-items: flex-start !important;
  gap: var(--space-3);
  color: var(--text);
  font-size: var(--text-sm);
  line-height: 1.5;
}

#modalAuth .checkboxLabel input[type="checkbox"] {
  appearance: auto;
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  accent-color: var(--accent, #6366f1);
  cursor: pointer;
}

#modalAuth .checkboxLabel span {
  flex: 1;
  min-width: 0;
}

#modalAuth input[type="text"],
#modalAuth input[type="email"],
#modalAuth input[type="password"],
#modalAuth select {
  height: 44px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(var(--white-rgb), 0.15);
  background: rgba(var(--black-rgb), 0.28);
  color: var(--text);
  font-size: var(--text-md);
  transition: all var(--duration-base) var(--ease-default);
}
/* Re-gate finding (2026-07-24): this base (dark, no theme class) #modalAuth
   select never had a chevron at all — only the light-theme override below
   got one in the original pass. Widened right padding to fit it. */
#modalAuth select {
  padding-right: var(--space-7);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%23f1f5f9' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.82'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}

#modalAuth input:focus,
#modalAuth select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.15);
  background: rgba(var(--black-rgb), 0.35);
}


#modalAuth .btn.btn--primary {
  height: 46px;
  font-size: var(--text-md);
  font-weight: 600;
  /* P2-Z re-gate — fond PLEIN AA (cf. .btn.btn--primary). */
  background: var(--btn-primary-bg);
  border: none;
  color: var(--text-inverse);
  box-shadow: 0 4px 15px rgba(var(--accent-rgb),0.30);
  transition: all var(--duration-base) var(--ease-default);
}


#modalAuth .btn.btn--primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(var(--accent-rgb),0.40);
}


#modalAuth .btn.btn--primary:active {
  transform: translateY(0);
}

#modalAuth .hint {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: var(--space-1);
  line-height: 1.5;
}

/* #loginMsg now uses .authErrorMsg class — see authErrorMsg rules above */
#modalAuth #regMsg {
  text-align: center;
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  margin-top: var(--space-3);
  font-size: var(--text-sm);
}

#modalAuth #regMsg:not(:empty) {
  background: rgba(var(--red-mid-rgb), 0.12);
  border: 1px solid rgba(var(--red-mid-rgb), 0.20);
  color: var(--danger-text);
}

/* Success message variant */
#modalAuth #regMsg[style*="color: rgba(var(--success-rgb), 1)"] {
  background: rgba(var(--status-ok-rgb), 0.12) !important;
  border: 1px solid rgba(var(--status-ok-rgb), 0.25) !important;
  color: var(--success-text) !important;
}

/* Role selection enhancement */
#modalAuth #regRole {
  background: rgba(var(--black-rgb), 0.25);
  cursor: pointer;
}

#modalAuth #regRole option {
  background: var(--bg1);
  padding: 10px;
}

/* === Light Theme: Auth Modal (#modalAuth) === */
body.light-theme #modalAuth .modalHead,
body.bento-theme #modalAuth .modalHead, body.atsiq-theme #modalAuth .modalHead {
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.10) 0%, rgba(var(--status-ok-rgb), 0.07) 100%);
  border-bottom: 1px solid rgba(var(--status-muted-rgb), 0.16);
}

body.light-theme .authTabBar,
body.bento-theme .authTabBar, body.atsiq-theme .authTabBar {
  background: rgba(var(--status-muted-rgb), 0.08);
  border-color: rgba(var(--status-muted-rgb), 0.15);
}

body.light-theme .authTab,
body.bento-theme .authTab, body.atsiq-theme .authTab {
  color: var(--muted);
  background: rgba(var(--status-muted-rgb), 0.06);
}

body.light-theme .authTab:hover,
body.bento-theme .authTab:hover, body.atsiq-theme .authTab:hover {
  color: var(--text);
  background: rgba(var(--status-muted-rgb), 0.14);
}

body.light-theme .authTab.active,
body.bento-theme .authTab.active, body.atsiq-theme .authTab.active {
  color: rgba(var(--white-rgb), 1);
  background: var(--gradient-primary);
}

body.light-theme #modalAuth input[type="text"],
body.bento-theme #modalAuth input[type="text"],
body.light-theme #modalAuth input[type="email"],
body.bento-theme #modalAuth input[type="email"],
body.light-theme #modalAuth input[type="password"],
body.bento-theme #modalAuth input[type="password"],
body.light-theme #modalAuth select,
body.bento-theme #modalAuth select, body.atsiq-theme #modalAuth input[type="text"], body.atsiq-theme #modalAuth input[type="email"], body.atsiq-theme #modalAuth input[type="password"], body.atsiq-theme #modalAuth select {
  background: rgba(var(--white-rgb), 0.82);
  border: 1px solid rgba(var(--status-muted-rgb), 0.22);
  color: var(--text);
}
/* Judge-panel finding (sitewide): #modalAuth's ID specificity wins over the
   tag-level select chevron rule too.
   Re-gate finding: currentColor doesn't resolve in a data-URI SVG — split
   into Bento (--muted rgba(28,25,23,0.68)) vs ATSIQ (rgba(10,20,30,0.70)). */
body.light-theme #modalAuth select,
body.bento-theme #modalAuth select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%231c1917' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.68'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}
body.atsiq-theme #modalAuth select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%230a141e' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.70'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}

body.light-theme #modalAuth input[type="text"]::placeholder,
body.bento-theme #modalAuth input[type="text"]::placeholder,
body.light-theme #modalAuth input[type="email"]::placeholder,
body.bento-theme #modalAuth input[type="email"]::placeholder,
body.light-theme #modalAuth input[type="password"]::placeholder,
body.bento-theme #modalAuth input[type="password"]::placeholder, body.atsiq-theme #modalAuth input[type="text"]::placeholder, body.atsiq-theme #modalAuth input[type="email"]::placeholder, body.atsiq-theme #modalAuth input[type="password"]::placeholder {
  color: var(--text-soft);
}

body.light-theme #modalAuth select:focus,
body.bento-theme #modalAuth select:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%231c1917' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.68'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}
body.atsiq-theme #modalAuth select:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%230a141e' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.70'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}
body.light-theme #modalAuth input:focus,
body.bento-theme #modalAuth input:focus,
body.light-theme #modalAuth select:focus,
body.bento-theme #modalAuth select:focus, body.atsiq-theme #modalAuth input:focus, body.atsiq-theme #modalAuth select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.16);
  background: rgba(var(--white-rgb), 0.95);
}

body.light-theme #modalAuth #regRole,
body.bento-theme #modalAuth #regRole, body.atsiq-theme #modalAuth #regRole {
  background: rgba(var(--white-rgb), 0.82);
}

body.light-theme #modalAuth #regRole option,
body.bento-theme #modalAuth #regRole option, body.atsiq-theme #modalAuth #regRole option {
  background: var(--bg1);
}


body.light-theme #modalAuth .btn.btn--primary,
body.bento-theme #modalAuth .btn.btn--primary, body.atsiq-theme #modalAuth .btn.btn--primary {
  box-shadow: 0 4px 15px rgba(var(--primary-rgb), 0.28);
}


body.light-theme #modalAuth .btn.btn--primary:hover,
body.bento-theme #modalAuth .btn.btn--primary:hover, body.atsiq-theme #modalAuth .btn.btn--primary:hover {
  box-shadow: 0 6px 20px rgba(var(--primary-rgb), 0.38);
}

body.light-theme #modalAuth .field > label,
body.bento-theme #modalAuth .field > label, body.atsiq-theme #modalAuth .field > label {
  color: var(--muted);
}

body.light-theme #modalAuth .hint,
body.bento-theme #modalAuth .hint, body.atsiq-theme #modalAuth .hint {
  color: var(--text-soft);
}

body.light-theme .authLinkCenter:first-of-type,
body.bento-theme .authLinkCenter:first-of-type, body.atsiq-theme .authLinkCenter:first-of-type {
  border-top-color: rgba(var(--status-muted-rgb), 0.15);
}
body.light-theme .authToggleLink,
body.bento-theme .authToggleLink, body.atsiq-theme .authToggleLink {
  color: var(--primary);
  font-weight: 500;
}

body.light-theme .authErrorMsg:not(:empty),
body.bento-theme .authErrorMsg:not(:empty),
body.light-theme #modalAuth #regMsg:not(:empty),
body.bento-theme #modalAuth #regMsg:not(:empty), body.atsiq-theme .authErrorMsg:not(:empty), body.atsiq-theme #modalAuth #regMsg:not(:empty) {
  background: rgba(var(--data-rose-rgb), 0.10);
  border: 1px solid rgba(var(--data-rose-rgb), 0.22);
}

/* === Form Controls Enhanced === */
input[type="text"],
input[type="search"],
input[type="number"],
input[type="password"],
input[type="email"],
input[type="date"],
input[type="time"],
select,
textarea {
  height: 44px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(var(--white-rgb), 0.12);
  background: rgba(var(--black-rgb), 0.20);
  color: var(--text);
  font-size: var(--text-base);
  outline: none;
  transition: all var(--duration-base) var(--ease-default);
  touch-action: manipulation; /* Prevent 300ms tap delay on iOS */
}

/* Disabled state — consistent across all form controls */
input:disabled,
select:disabled,
textarea:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: rgba(var(--black-rgb), 0.10);
}
input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* iOS Safari auto-zoom prevention: inputs must be >= 16px on mobile */
@media (max-width: 768px) {
  input, select, textarea { font-size: var(--text-md) !important; }
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.12);
}

/* Form validation error states (WCAG AA compliant) */
input.input-error,
input[aria-invalid="true"],
select.input-error,
select[aria-invalid="true"],
textarea.input-error,
textarea[aria-invalid="true"] {
  border-color: var(--status-danger);
  box-shadow: 0 0 0 3px rgba(var(--status-danger-rgb), 0.15);
}

input.input-error:focus,
input[aria-invalid="true"]:focus,
select.input-error:focus,
select[aria-invalid="true"]:focus,
textarea.input-error:focus,
textarea[aria-invalid="true"]:focus {
  border-color: var(--status-danger);
  box-shadow: 0 0 0 3px rgba(var(--status-danger-rgb), 0.25);
}

/* Success state (validated fields) */
input.input-success,
input[aria-invalid="false"].touched,
select.input-success,
textarea.input-success {
  border-color: var(--status-ok);
  box-shadow: 0 0 0 3px rgba(var(--status-ok-rgb, 34,197,94), 0.12);
}
input.input-success:focus,
select.input-success:focus,
textarea.input-success:focus {
  border-color: var(--status-ok);
  box-shadow: 0 0 0 3px rgba(var(--status-ok-rgb, 34,197,94), 0.20);
}

textarea { height: auto; min-height: 90px; resize: vertical; }
input::placeholder,
textarea::placeholder { color: rgba(var(--text-rgb), 0.55); }

/* Chrome autofill override — prevent yellow flash, respect theme */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--bg1) inset;
  -webkit-text-fill-color: var(--text);
  transition: background-color 9999s ease-in-out 0s;
}

/* Number input — hide native spinner buttons for consistent design */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type="number"] { -moz-appearance: textfield; }

/* Password visibility toggle — anchored to bottom of fieldStack to align with input center */
.pw-toggle {
  position: absolute;
  right: var(--space-3);
  /* Anchor to bottom of container (below label), then center within input height (~42px) */
  bottom: 0;
  height: 42px;
  display: flex;
  align-items: center;
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: var(--space-1);
  border-radius: var(--radius-xs);
  opacity: 0.5;
  transition: opacity var(--duration-fast), color var(--duration-fast);
  line-height: 1;
}
.pw-toggle:hover { opacity: 0.8; }
.pw-toggle.active { color: var(--accent); opacity: 0.9; }
input[data-pw-toggle] { padding-right: 40px; }
/* Judge-panel finding (sitewide, ATSIQ team-page audit 2026-07-24): no
   <select> anywhere had a visible dropdown affordance — `appearance:none`
   (base.css) strips the native arrow, and this rule's own padding-right
   reservation is evidence a chevron was intended and never added.
   Re-gate correction: an earlier version of this comment claimed
   `currentColor` resolves against the host element's computed color inside
   a data-URI SVG background-image — verified empirically FALSE (rendered
   black regardless of theme; a data-URI SVG is an isolated external
   resource, not part of the referencing document's cascade). Hardcoded hex
   below; per-theme overrides (effects.css, atsiq-theme.css) supply the
   correct color for light/ATSIQ themes, this is the dark/Obsidian default
   (--muted default: 241 245 249 at 0.82 alpha). */
select {
  padding-right: var(--space-7);
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%23f1f5f9' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.82'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}
option { background: var(--bg1); color: var(--text); }
optgroup {
  background: var(--bg2);
  color: var(--accent-light);
  font-weight: 600;
  font-style: normal;
  padding: var(--space-2) 0;
}
optgroup option {
  background: var(--bg1);
  color: var(--text);
  font-weight: 400;
  padding-left: var(--space-3);
}

/* === Buttons Enhanced === */
.btn {
  height: 44px;
  padding: 0 20px;
  border-radius: var(--radius-sm);
  /* --btn-border keeps the secondary (plain) .btn pill outline visible on Obsidian (where the
     violet --border was too faint); light themes map it back to --border (V-WOW item 5). */
  border: var(--btn-base-border);
  background: var(--btn-base-bg);
  color: var(--text);
  cursor: pointer;
  /* DS-Canon S1 (2026-07-13) — <a class="btn"> must never inherit the anchor
     underline; reset lives on the base so every variant/brand gets it (was
     previously patched per-instance on .mentor-contract-card only). */
  text-decoration: none;
  -webkit-user-select: none;
  user-select: none;
  font-size: var(--text-base);
  font-weight: 500;
  transition: all var(--duration-base) var(--ease-default);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

@media (hover: hover) {
  .btn:hover {
    background: var(--btn-base-hover-bg);
    border: var(--btn-base-hover-border);
    box-shadow: var(--btn-base-hover-shadow);
    transform: translateY(-1px);
  }
}

.btn:active {
  transform: translateY(0) scale(0.98);
}

.btn:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn:focus:not(:focus-visible) {
  outline: none;
}

.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  /* F-1612 (a11y): aria-disabled buttons stay focusable + announced to screen
     readers (native `disabled` removes them from the a11y tree). Same visual as
     :disabled; the action is no-op'd by the click dispatcher, not pointer-events
     (so the click still reaches the guard). */
  opacity: var(--btn-disabled-opacity);
  cursor: not-allowed;
  transform: none;
}

/* Global button loading state — spinner after text + subtle pulse glow.
 * 2026-05-13 audit polish (#246 follow-up) :
 * - Spinner border switched to currentColor + opacity trick so it's
 *   highly visible on every theme (white-rgba on white was almost
 *   invisible on light themes).
 * - Bumped to 16px + 2.5px stroke for better legibility.
 * - Margin-left aligned to var(--space-2-5) for breathing room.
 * - `.btn--primary.loading` gains a soft pulse glow on the box-shadow
 *   so the whole button reads as "busy", not just the corner spinner.
 */
.btn.loading,
.btn.btn--loading {
  pointer-events: none;
  cursor: progress;
  opacity: 0.92;
  position: relative;
  /* Subtle glow telegraphs activity beyond the spinner alone. */
  box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.45);
  animation: ct-btn-loading-pulse 1.6s ease-in-out infinite;
}
.btn.loading::after,
.btn.btn--loading::after {
  content: '';
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2.5px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: 0.85;
  animation: spin 0.7s linear infinite;
  margin-left: 10px;
  vertical-align: -3px;
  flex-shrink: 0;
}
/* Ghost / secondary buttons have low-contrast text — strengthen the
 * spinner border on those so it never disappears against the bg. */
.btn--ghost.loading::after,
.btn--secondary.loading::after,
.btn--secondary.btn--loading::after,
.btn--ghost.btn--loading::after {
  border-color: var(--ds-text-primary, currentColor);
  border-right-color: transparent;
  opacity: 0.75;
}
@keyframes ct-btn-loading-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.25); }
  50%      { box-shadow: 0 0 0 6px rgba(var(--accent-rgb), 0.00); }
}
@media (prefers-reduced-motion: reduce) {
  .btn.loading,
  .btn.btn--loading {
    animation: none;
    box-shadow: none;
  }
  .btn.loading::after,
  .btn.btn--loading::after {
    animation: none;
    opacity: 0.5;
  }
}

/* .btn--icon (T10 relocation, was ~:1111 before .btn — same specificity as
   .btn (0,1,0), so file order decides the shared-property winner; every
   other variant already lives here for that reason). padding/font-weight/
   gap/user-select added: the only .btn properties .btn--icon didn't
   already redeclare (verified empirically, Playwright headless computed
   style before/after — 0 delta on the 36×36 square once relocated here). */
.btn--icon {
  width: 36px;
  height: 36px;
  padding: 0;
  font-weight: normal;
  gap: 0;
  user-select: none;
  border-radius: var(--radius-full);
  border: 1px solid rgba(var(--text-rgb), 0.12);
  background: rgba(var(--text-rgb), 0.06);
  color: var(--text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-md);
  transition: all var(--duration-fast) var(--ease-default);
}
.btn--icon:hover {
  background: rgba(var(--text-rgb), 0.12);
  border-color: rgba(var(--text-rgb), 0.18);
}
.btn--icon:active {
  transform: scale(0.95);
}
.btn--icon:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.btn--icon:focus:not(:focus-visible) {
  outline: none;
}
.btn--icon:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}


.btn.btn--primary {
  /* Containing block for the `.btn.btn--primary::after` gloss (effects.css). The base .btn has
     no `position`, so the absolutely-positioned gloss resolved against a *distant* positioned
     ancestor (the viewport inside `.learning-panels`, which has none closer) and painted a
     viewport-wide 1440x405px white sheet — ~10 stacked course-card buttons = an 80% white veil
     over the learning hero (VQA CT-C5-F1). `position: relative` (no overflow:hidden, so the
     comet-ring hover is untouched) scopes the gloss to each button's own top 45%. */
  position: relative;
  /* P2-Z re-gate (grappe « CTA primaire », WCAG 1.4.3) : --gradient-primary est un dégradé
     DÉCORATIF dont les arrêts clairs tombent sous AA avec --btn-primary-fg (3,05:1 sur l'arrêt
     sage #7A9A83 en Sage & Forest, 4,47:1 sur #6366f1 en Obsidian). Le CTA primaire passe au
     fond PLEIN dédié --btn-primary-bg (variables.css / atsiq-theme.css), AA dans les 4 thèmes
     — même canon que le kit (.ctk-btn.ctk-btn--primary). `background-image: none` rend la règle
     étanche à un dégradé hérité d'une surcharge de surface. */
  background: var(--btn-primary-bg);
  background-image: none;
  border: var(--btn-primary-border);
  color: var(--btn-primary-fg);
  font-weight: 600;
  box-shadow: var(--btn-primary-shadow);
}

@media (hover: hover) {
  .btn.btn--primary:hover {
    box-shadow: var(--btn-primary-hover-shadow);
    transform: translateY(-2px);
  }
}

/* AI action buttons — violet-rosé glassmorphism */

.btn.btn--ai {
  position: relative;
  overflow: hidden;
  background: var(--btn-ai-bg);
  border: var(--btn-ai-border);
  color: var(--btn-ai-fg);
  font-weight: 600;
  box-shadow: var(--btn-ai-shadow);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  text-shadow: 0 1px 2px rgba(var(--black-rgb), 0.15);
}

@media (hover: hover) {
  .btn.btn--ai:hover {
    background: var(--btn-ai-hover-bg);
    box-shadow: var(--btn-ai-hover-shadow);
    transform: translateY(-2px);
    border: var(--btn-ai-hover-border);
  }
}


.btn.btn--ai:active {
  transform: translateY(0);
  box-shadow: 0 2px 12px rgba(var(--fuchsia-rgb), 0.25);
}


.btn.btn--ai:disabled {
  background: linear-gradient(135deg, rgba(var(--purple-rgb), 0.20) 0%, rgba(var(--fuchsia-rgb), 0.15) 100%);
  box-shadow: none;
  border-color: rgba(var(--fuchsia-rgb), 0.10);
  text-shadow: none;
}

/* AI button shimmer sweep — subtle light sweep across the gradient */

.btn.btn--ai::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -100%;
  width: 60%;
  background: linear-gradient(90deg, transparent 0%, rgba(var(--white-rgb), 0.15) 50%, transparent 100%);
  transform: skewX(-20deg);
  animation: aiShimmer 4s ease-in-out infinite;
  pointer-events: none;
  border-radius: inherit;
}
@keyframes aiShimmer {
  0%, 100% { left: -100%; }
  30%, 70% { left: 150%; }
}

/* AI button focus-visible ring */

.btn.btn--ai:focus-visible {
  outline: 2px solid rgba(var(--cyan-rgb), 0.7);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .btn.btn--ai::after { animation: none; display: none; }
}

/* Register custom property for border spinner animation (Houdini) */
@property --ai-border-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

/* ============================================
   AI Button States: Loading / Success / Error
   "Neural Pulse" — the button becomes alive
   ============================================ */

/* -- UNIVERSAL button feedback — works on ANY .btn, not just .btn.ai -- */
/* These simpler rules activate for all buttons. The .btn.ai rules below override with fancier animations. */
/* ================================================================
   BUTTON STATES: Loading + Success/Error Feedback
   ================================================================
   Architecture:
   - .ai-loading    = ANY button in loading state (spinner, disabled)
   - .ai-success    = ANY button showing success (Combo Elegant V10)
   - .ai-error      = ANY button showing error (Combo Elegant V10)
   - .btn.ai.ai-loading = AI-specific loading (gradient, comet border)

   These are STATE classes added/removed by JS (actionButton/setAiButtonLoading).
   They work on ANY .btn, regardless of whether it's .ai or .primary.
   ================================================================ */

/* ---- LOADING STATE (universal) ---- */
.btn.ai-loading {
  pointer-events: none;
  cursor: wait;
  opacity: 0.85;
}
.btn.ai-loading .ai-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(var(--white-rgb), 0.3);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: aiSpin 0.6s linear infinite;
  margin-right: 6px;
  vertical-align: middle;
}

/* ---- FEEDBACK: Combo Elegant V10 (validated 2026-04-08) ----
   Comet ring border + gradient morph + icon bounce.
   Text changes to checkmark/cross + label for 5 seconds.
   Theme-aware: bento=warm brown blend, dark=violet blend.
   ------------------------------------------------------------ */

/* Shared base */
.btn.ai-success,
.btn.ai-error {
  position: relative;
  overflow: hidden;
  color: var(--on-primary);
  text-shadow: 0 1px 2px rgba(var(--black-rgb), 0.2);
  font-weight: 700;
  letter-spacing: 0.3px;
  transition: none;
}

/* Feedback icon with bounce */
.ab-feedback-icon {
  font-size: 1.35em;
  margin-right: 4px;
  vertical-align: middle;
  display: inline-block;
}
.ai-success .ab-feedback-icon,
.ai-error .ab-feedback-icon {
  animation: abIconBounce 0.5s ease-out;
}

/* ---- SUCCESS ---- */
/* Dark theme (default): green + violet blend */
.btn.ai-success {
  background: linear-gradient(135deg, rgba(var(--status-ok-rgb),0.35) 0%, rgba(var(--call-accent-rgb), 0.2) 40%, rgba(var(--status-ok-rgb),0.2) 100%);
  border-color: transparent;
  box-shadow: 0 0 18px rgba(var(--status-ok-rgb),0.3), 0 4px 20px rgba(var(--call-accent-rgb), 0.1);
}
/* Comet ring */
.btn.ai-success::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(
    from var(--ab-ring-angle, 0deg),
    transparent 0%, transparent 60%,
    rgba(var(--status-ok-rgb),0.6) 78%,
    rgba(var(--status-ok-rgb),0.9) 88%,
    rgba(255,255,230,0.5) 94%, /* W3b: pas de var fidèle (ΔE=12.7 vs --white-rgb) — comet highlight décoratif warm */
    transparent 100%
  );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: abRingSpin 1.5s linear infinite;
  pointer-events: none;
}
/* Hide shimmer during success */
.btn.ai-success::after { display: none; }

/* ---- ERROR ---- */
/* Dark theme (default): red + violet blend */
.btn.ai-error {
  background: linear-gradient(135deg, rgba(var(--status-danger-rgb),0.35) 0%, rgba(var(--call-accent-rgb), 0.2) 40%, rgba(var(--status-danger-rgb),0.2) 100%);
  border-color: transparent;
  box-shadow: 0 0 18px rgba(var(--status-danger-rgb),0.3), 0 4px 20px rgba(var(--call-accent-rgb), 0.1);
  animation: abErrorEntry 0.5s ease-out;
}
/* Comet ring */
.btn.ai-error::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(
    from var(--ab-ring-angle, 0deg),
    transparent 0%, transparent 60%,
    rgba(var(--status-danger-rgb),0.6) 78%,
    rgba(var(--status-danger-rgb),0.9) 88%,
    rgba(255,200,200,0.5) 94%, /* W3b: pas de var fidèle (ΔE=25.5 vs --white-rgb) — comet highlight décoratif rose */
    transparent 100%
  );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: abRingSpin 1.2s linear infinite;
  pointer-events: none;
}
/* Hide shimmer during error */
.btn.ai-error::after { display: none; }

/* ---- BENTO / LIGHT THEME ----
   Replace dark violet with warm bento brown in gradient blend */
body.bento-theme .btn.ai-success,
body.light-theme .btn.ai-success,
body.atsiq-theme .btn.ai-success {
  background: linear-gradient(135deg, rgba(var(--status-ok-rgb),0.35) 0%, rgba(var(--accent-purple-rgb), 0.25) 40%, rgba(var(--status-ok-rgb),0.2) 100%);
  box-shadow: 0 0 18px rgba(var(--status-ok-rgb),0.3), 0 4px 20px rgba(var(--accent-purple-rgb), 0.12);
}
body.bento-theme .btn.ai-error,
body.light-theme .btn.ai-error,
body.atsiq-theme .btn.ai-error {
  background: linear-gradient(135deg, rgba(var(--status-danger-rgb),0.35) 0%, rgba(var(--accent-purple-rgb), 0.25) 40%, rgba(var(--status-danger-rgb),0.2) 100%);
  box-shadow: 0 0 18px rgba(var(--status-danger-rgb),0.3), 0 4px 20px rgba(var(--accent-purple-rgb), 0.12);
}

/* ---- ANIMATIONS ---- */
@property --ab-ring-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}
@keyframes abRingSpin {
  from { --ab-ring-angle: 0deg; }
  to { --ab-ring-angle: 360deg; }
}
@keyframes abIconBounce {
  0% { transform: scale(0); }
  50% { transform: scale(1.25); }
  100% { transform: scale(1); }
}
@keyframes abErrorEntry {
  0%, 15% { transform: translateX(-4px); }
  30% { transform: translateX(4px); }
  45% { transform: translateX(-2px); }
  60% { transform: translateX(2px); }
  75% { transform: translateX(-1px); }
  100% { transform: translateX(0); }
}

/* ---- AI-SPECIFIC LOADING (richer animations for .btn.ai) ---- */
@media (prefers-reduced-motion: reduce) {
  .btn.ai-success::before,
  .btn.ai-error::before { animation: none; }
  .btn.ai-success { border: 2px solid var(--status-ok) !important; /* prefers-reduced-motion: replace animated comet ring with static border */ }
  .btn.ai-error { border: 2px solid var(--status-danger) !important; /* prefers-reduced-motion: replace animated comet ring with static border */ }
}

/* -- AI-SPECIFIC LOADING: gradient flows, border breathes, shimmer accelerates -- */
/* These override the universal rules above for .btn.ai with richer animations */

.btn.btn--ai.ai-loading {
  pointer-events: none;
  cursor: wait;
  color: rgba(var(--white-rgb), 0.7);
  text-shadow: none;
  /* Animated gradient position — the gradient "flows" */
  background-size: 200% 200%;
  background-image: linear-gradient(
    135deg,
    rgba(var(--purple-rgb), 0.70) 0%,
    rgba(var(--fuchsia-rgb), 0.65) 25%,
    rgba(var(--cyan-rgb), 0.55) 50%,
    rgba(var(--fuchsia-rgb), 0.65) 75%,
    rgba(var(--purple-rgb), 0.70) 100%
  );
  animation: aiGradientFlow 2s ease-in-out infinite, aiGlowPulse 2s ease-in-out infinite;
  border-color: rgba(var(--cyan-rgb), 0.45);
}
/* Accelerated shimmer during loading */

.btn.btn--ai.ai-loading::after {
  animation: aiShimmerFast 1.4s ease-in-out infinite;
  background: linear-gradient(90deg, transparent 0%, rgba(var(--white-rgb), 0.25) 50%, transparent 100%);
}
/* Spinning comet border — conic-gradient masked to a 2px ring.
   Uses inset:0 + padding:2px (stays within overflow:hidden bounds). */

.btn.btn--ai.ai-loading::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(
    from var(--ai-border-angle),
    transparent 0%, transparent 70%,
    rgba(var(--cyan-rgb), 0.9) 85%,
    rgba(var(--fuchsia-rgb), 1) 95%,
    rgba(var(--purple-rgb), 0.7) 100%
  );
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: aiBorderSpin 1.5s linear infinite;
  pointer-events: none;
  z-index: 0;
}
/* Brighter comet on standalone / full-width buttons */

.appQuickActions .btn.btn--ai.ai-loading::before,
.skillsNotExtracted .btn.btn--ai.ai-loading::before,
.btn.btn--ai.w100.ai-loading::before {
  background: conic-gradient(
    from var(--ai-border-angle),
    transparent 0%, transparent 65%,
    rgba(var(--cyan-rgb), 0.95) 80%,
    rgba(var(--fuchsia-rgb), 1) 92%,
    rgba(var(--purple-rgb), 0.8) 100%
  );
}
/* Inline spinner — sits before text content */

.btn.btn--ai.ai-loading .ai-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(var(--white-rgb), 0.3);
  border-top-color: rgba(var(--white-rgb), 0.9);
  border-radius: 50%;
  animation: aiSpin 0.6s linear infinite;
  margin-right: var(--space-2);
  vertical-align: -2px;
  flex-shrink: 0;
}

@keyframes aiGradientFlow {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}
@keyframes aiShimmerFast {
  0% { left: -100%; }
  100% { left: 150%; }
}
@keyframes aiBorderSpin {
  to { --ai-border-angle: 360deg; }
}
@keyframes aiGlowPulse {
  0%, 100% {
    box-shadow: 0 0 10px rgba(var(--fuchsia-rgb), 0.25),
                0 0 20px rgba(var(--purple-rgb), 0.12),
                inset 0 1px 0 rgba(var(--white-rgb), 0.12);
  }
  50% {
    box-shadow: 0 0 16px rgba(var(--fuchsia-rgb), 0.40),
                0 0 32px rgba(var(--purple-rgb), 0.20),
                0 0 4px rgba(var(--cyan-rgb), 0.15),
                inset 0 1px 0 rgba(var(--white-rgb), 0.15);
  }
}
@keyframes aiSpin {
  to { transform: rotate(360deg); }
}

/* -- SUCCESS: satisfying green wash -- */

.btn.btn--ai.ai-success {
  animation: aiSuccessFlash 1s ease-out forwards;
  border-color: rgba(var(--status-ok-rgb), 0.6);
  box-shadow: 0 0 20px rgba(var(--status-ok-rgb), 0.35);
}

.btn.btn--ai.ai-success::after {
  display: none;
}
@keyframes aiSuccessFlash {
  0% {
    background: linear-gradient(135deg, rgba(var(--status-ok-rgb), 0.7) 0%, rgba(var(--status-ok-rgb), 0.5) 100%);
  }
  70% {
    background: linear-gradient(135deg, rgba(var(--status-ok-rgb), 0.5) 0%, rgba(var(--status-ok-rgb), 0.3) 100%);
  }
  100% {
    background: linear-gradient(135deg, rgba(var(--purple-rgb), 0.60) 0%, rgba(var(--fuchsia-rgb), 0.55) 40%, rgba(var(--cyan-rgb), 0.45) 100%);
    border-color: rgba(var(--fuchsia-rgb), 0.35);
    box-shadow: 0 4px 20px rgba(var(--fuchsia-rgb), 0.30), inset 0 1px 0 rgba(var(--white-rgb), 0.20);
  }
}

/* -- ERROR: obvious red flash — must be unmissable, especially on mobile -- */

.btn.btn--ai.ai-error {
  animation: aiErrorFlash 1.2s ease-out forwards;
  border-color: rgba(var(--status-danger-rgb), 0.7);
  box-shadow: 0 0 20px rgba(var(--status-danger-rgb), 0.40);
}

.btn.btn--ai.ai-error::after {
  display: none;
}
@keyframes aiErrorFlash {
  0%, 15% {
    background: linear-gradient(135deg, rgba(var(--status-danger-rgb), 0.6) 0%, rgba(var(--status-danger-rgb), 0.4) 100%);
    transform: translateX(-2px);
  }
  30% { transform: translateX(2px); }
  45% { transform: translateX(-1px); }
  60% { transform: translateX(0); }
  100% {
    background: linear-gradient(135deg, rgba(var(--purple-rgb), 0.60) 0%, rgba(var(--fuchsia-rgb), 0.55) 40%, rgba(var(--cyan-rgb), 0.45) 100%);
    border-color: rgba(var(--fuchsia-rgb), 0.35);
    box-shadow: 0 4px 20px rgba(var(--fuchsia-rgb), 0.30), inset 0 1px 0 rgba(var(--white-rgb), 0.20);
  }
}

/* -- Thinner border ring for small buttons -- */

.btn.btn--small.btn--ai.ai-loading::before { padding: 1.5px; }

/* -- Compact spinner for small buttons -- */

.btn.btn--small.btn--ai.ai-loading .ai-spinner {
  width: 12px;
  height: 12px;
  border-width: 1.5px;
  margin-right: var(--space-1);
}

/* -- Reduced motion: static states only -- */
@media (prefers-reduced-motion: reduce) {
  .btn.btn--ai.ai-loading {
    animation: none;
    opacity: 0.7;
    box-shadow: 0 0 10px rgba(var(--fuchsia-rgb), 0.25),
                0 0 20px rgba(var(--purple-rgb), 0.12),
                inset 0 1px 0 rgba(var(--white-rgb), 0.12);
  }

  .btn.btn--ai.ai-loading::after { animation: none; display: none; }
  /* Border ring visible but static — no spinning comet */

  .btn.btn--ai.ai-loading::before { animation: none; }
  /* Keep spinner rotating — it's functional feedback, not decorative animation */

  .btn.btn--ai.ai-loading .ai-spinner { animation: aiSpin 0.8s linear infinite; border-top-color: rgba(var(--white-rgb), 0.9); }

  .btn.btn--ai.ai-success { animation: none; }

  .btn.btn--ai.ai-error { animation: none; }
}

/* ── Modal inline error banner ── */
.modal-error-banner {
  display: flex; align-items: center; gap: var(--space-2);
  background: rgba(var(--status-danger-rgb), 0.12);
  border: 1px solid rgba(var(--status-danger-rgb), 0.3);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  margin: var(--space-2) var(--space-3) 0;
  color: var(--status-danger);
  font-size: var(--text-sm);
  animation: fadeIn 0.3s ease-out;
}
.modal-error-banner span { flex: 1; }
.modal-error-banner-close {
  background: none; border: none; color: var(--muted); cursor: pointer;
  font-size: var(--text-lg); line-height: 1; padding: 0;
}
/* Also tone down universal feedback on reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .btn.ai-success { animation: none; }
  .btn.ai-error { animation: none; }
}

/* ── AI action toast — enhanced CTA for post-AI-action prompts ── */
.toast-action-btn.ai-cta {
  background: var(--gradient-ai);
  border: 1px solid rgba(var(--fuchsia-rgb), 0.3);
  color: var(--text-inverse);
  font-weight: 700;
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-4);
  text-shadow: 0 1px 2px rgba(var(--black-rgb), 0.15);
  transition: all var(--duration-fast) var(--ease-default);
}
.toast-action-btn.ai-cta:hover {
  box-shadow: 0 4px 16px rgba(var(--fuchsia-rgb), 0.3);
  transform: translateY(-1px);
}
@media (max-width: 480px) {
  .toast-action-btn.ai-cta {
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-xs);
    white-space: nowrap;
  }
}


.btn.btn--secondary {
  background: var(--btn-secondary-bg);
  border: var(--btn-secondary-border);
  color: var(--btn-secondary-fg);
}


@media (hover: hover) {
  .btn.btn--secondary:hover {
    background: var(--btn-secondary-hover-bg);
    border: var(--btn-secondary-hover-border);
  }
}


.btn.btn--danger {
  background: var(--btn-danger-bg);
  border: var(--btn-danger-border);
  color: var(--btn-danger-fg);
}


@media (hover: hover) {
  .btn.btn--danger:hover {
    opacity: 0.9;
  }
}
.btn-xs,
.btn.btn--xs { padding: 4px 10px; font-size: var(--text-xs); line-height: 1.2; min-height: 28px; min-width: 28px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-4); flex-shrink: 0; white-space: nowrap; }
/* Touch targets: minimum 44px on mobile (WCAG 2.5.5) */
@media (max-width: 768px) {
  .btn--help, .btn--icon, .btn.btn--xs { min-width: 44px; min-height: 44px; }
}


.btn.btn--small {
  height: 36px;
  padding: 0 14px;
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
}

/* Transcript download dropdown */
.dropdown-item {
  display: block;
  width: 100%;
  padding: 6px 16px;
  border: none;
  background: none;
  color: var(--fg);
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.dropdown-item:hover {
  background: var(--primary);
  color: var(--text-inverse);
}
body.light-theme .dropdown-menu[id^='dl-menu-'],
body.bento-theme .dropdown-menu[id^='dl-menu-'], body.atsiq-theme .dropdown-menu[id^='dl-menu-'] {
  background: linear-gradient(168deg, rgba(var(--lavender-rgb), 0.98) 0%, rgba(var(--lavender-deep-rgb), 0.98) 100%);
  border-color: rgba(var(--status-muted-rgb), 0.22);
  box-shadow: 0 4px 12px rgba(var(--accent-rgb),0.14);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
}
body.light-theme .dropdown-item, body.atsiq-theme .dropdown-item { color: var(--fg); }
body.bento-theme .dropdown-item, body.atsiq-theme .dropdown-item { color: var(--fg); }
body.light-theme .dropdown-item:hover, body.atsiq-theme .dropdown-item:hover { background: var(--primary); color: var(--text-inverse); }
body.bento-theme .dropdown-item:hover, body.atsiq-theme .dropdown-item:hover { background: var(--primary); color: var(--text-inverse); }


.btn.btn--success {
  background: var(--btn-success-bg);
  border: var(--btn-success-border);
  color: var(--btn-success-fg);
}


@media (hover: hover) {
  .btn.btn--success:hover {
    filter: brightness(1.1);
  }
}

.btn.btn--link {
  background: transparent;
  border-color: transparent;
  color: var(--btn-link-fg);
  padding: 0;
  height: auto;
  font-weight: 500;
}

.btn.btn--link:hover {
  text-decoration: underline;
  transform: none;
}
@media (max-width: 768px) {
  .btn.btn--link,
  a.link {
    min-height: 36px;
    padding: var(--space-2) 0;
    display: inline-flex;
    align-items: center;
  }
}


.btn.btn--warn {
  background: var(--btn-warn-bg);
  border: var(--btn-warn-border);
  color: var(--btn-warn-fg);
}


@media (hover: hover) {
  .btn.btn--warn:hover {
    background: var(--btn-warn-hover-bg);
    border: var(--btn-warn-hover-border);
  }
}


.btn.btn--outline {
  background: var(--btn-outline-bg);
  border: var(--btn-outline-border);
  color: var(--btn-outline-fg);
}

@media (hover: hover) {
  .btn.btn--outline:hover {
    background: var(--btn-outline-hover-bg);
    border: var(--btn-outline-hover-border, var(--btn-outline-border));
    color: var(--btn-outline-hover-fg, var(--btn-outline-fg));
  }
}

.btn.btn--ghost {
  background: var(--btn-ghost-bg);
  border: var(--btn-ghost-border);
  color: var(--btn-ghost-fg);
}

@media (hover: hover) {
  .btn.btn--ghost:hover {
    background: var(--btn-ghost-hover-bg);
    color: var(--btn-ghost-hover-fg, var(--btn-ghost-fg));
  }
}

.btn.btn--danger.btn--outline {
  background: var(--btn-danger-outline-bg);
  border: var(--btn-danger-outline-border);
  color: var(--btn-danger-outline-fg);
}

@media (hover: hover) {
  .btn.btn--danger.btn--outline:hover {
    background: var(--btn-danger-outline-hover-bg);
    border: var(--btn-danger-outline-hover-border);
  }
}

.btn.btn--large {
  height: 52px;
  padding: 0 28px;
  font-size: var(--text-md);
  border-radius: var(--radius);
}

/* === Badges Enhanced === */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.02em;
  background: rgba(var(--accent-rgb),0.15);
  color: var(--accent-light);
  border: 1px solid rgba(var(--accent-rgb),0.25);
}

/* Chantier matching (2026-07-31) — le SCORE d'adéquation, rendu VISIBLE dans la pastille.
   Il ne vivait que dans l'attribut `title` : introuvable sans souris, hors d'atteinte au clavier et
   au tactile, et déclenché tard. Le LIBELLÉ reste dominant — c'est lui qui porte le sens, et la
   doctrine interne §8 dit le score « visible par défaut ». Le nombre le suit en second plan, dans
   la MÊME couleur de tonalité que la pastille : jamais rouge pour un score bas, puisque « faible »
   est toné `subtle` et jamais `bad` (règle D12 — aucun jugement négatif absolu sur une personne).
   Aucune couleur nouvelle, aucun composant nouveau : un filet et des chiffres tabulaires sur la
   pastille existante, donc juste dans les quatre thèmes sans code par thème.

   P2-Z re-gate (da-10, composante CONTRASTE, WCAG 1.4.3) — l'`opacity: 0.72` d'origine était la
   SEULE marque du « second plan », et elle se composait avec l'alpha de la couleur de tonalité :
   sur `.badge.subtle` (le ton du score par D12) la couleur `rgba(10,20,30,0.70)` tombait à un
   alpha effectif de 0,504. MESURÉ au navigateur sur le harnais P2-C (rangées candidats RÉELLES,
   `recruiter-candidates.js`), pastille « bon pour ce rôle 78/100 » :
     · Sage & Forest : libellé 6,28:1 — score rgb(118,125,129) sur rgb(228,231,229) = 3,36:1 ❌
     · Obsidian      : libellé 9,17:1 — score rgb(157,162,172) sur rgb(36,43,62)    = 5,50:1 ✅
   Le score pouvait donc être MOINS lisible que le libellé qu'il complète — et sous AA en clair.
   L'atténuation passe de la COULEUR à la TYPOGRAPHIE : plus d'opacité, le nombre hérite
   exactement de la couleur de tonalité de la pastille, donc son contraste est PAR CONSTRUCTION
   celui du libellé (mesuré après : 6,28:1 clair / 9,17:1 sombre). Le second plan est dit par le
   filet séparateur, le corps légèrement plus petit et la graisse ALIGNÉE sur celle du libellé
   (500 et non 600 : la graisse forte ne servait qu'à compenser l'opacité, et elle inversait la
   hiérarchie — le libellé porte le sens). Verrou : p2z_regate_css_dashboard_icons.test.mjs. */
.badge > .badge__score {
  margin-left: var(--space-1);
  padding-left: var(--space-1);
  border-left: 1px solid currentColor;
  font-size: 0.92em;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

.badge.ok {
  background: rgba(var(--status-ok-rgb), 0.15);
  color: var(--success-text);
  border: 1px solid rgba(var(--status-ok-rgb), 0.25);
}

.badge.warn {
  background: rgba(var(--amber-rgb), 0.18);
  color: var(--warning-text);
  border: 1px solid rgba(var(--amber-rgb), 0.25);
}

/* B6 LOT1 — inline warning hint (e.g. deactivating a mentor contract that still
   has active candidate links). `.hint` alone is muted body text; the `.warn`
   modifier promotes it to an amber alert callout so the safety signal reads. */
.hint.warn {
  background: rgba(var(--amber-rgb), 0.12);
  color: var(--warning-text);
  border: 1px solid rgba(var(--amber-rgb), 0.28);
  border-left-width: 3px;
  padding: 8px 10px;
  border-radius: var(--radius-xs);
}

.badge.bad {
  background: rgba(var(--red-light-rgb), 0.18);
  color: var(--danger-text);
  border: 1px solid rgba(var(--red-light-rgb), 0.25);
}

.badge.subtle {
  background: rgba(var(--white-rgb), 0.08);
  color: var(--muted);
  /* J3 polish 1 (+ gate Codex finding 4) — le bord SOMBRE (Obsidian) reste `--white-rgb` à 10 % : léger
     mais présent, et il est le meilleur choix ici (`--border` = violet 10 % est documenté TROP FAIBLE sur
     fond sombre, variables.css:131). Le vrai bug était les thèmes CLAIRS (ATSIQ/Bento) où les overrides ne
     posaient QUE bg+color → ce bord blanc 10 % y devenait invisible : on leur AJOUTE un bord `--border`
     (ink 14-18 %, visible) directement dans LEURS blocs (atsiq-theme.css:579, variables.css light+bento). */
  border: 1px solid rgba(var(--white-rgb), 0.10);
}
/* Phase E gate fix (chantier ① score de match unifié, Codex FE/DS gate) — `.badge.info` is the 4th
   tone the canonical match-category doctrine needs (bon → info, D12), promoted ONCE here into the
   shared component file (it previously lived ONLY in admin.css — not loaded on the recruiter shell
   — so it rendered background-less/broken there). Same formula as `.badge.ok` above, on the
   existing `--status-info`/`--status-info-rgb`/`--info-text` tokens (theme-complete: Obsidian
   `:root`, Sage&Forest `html.atsiq-theme`, Bento `body.bento-theme` — all 3 already define them). */
.badge.info {
  background: rgba(var(--status-info-rgb), 0.15);
  color: var(--info-text);
  border: 1px solid rgba(var(--status-info-rgb), 0.25);
}
/* Phase E gate fix — a handful of score chips (candidate-card matrix, mini-modal hero) are made
   keyboard-focusable (`tabindex="0"`) so their `title`/`aria-label` score+reason detail is reachable
   without a mouse. Scoped to `[tabindex]` so it never touches the hundreds of purely-decorative,
   non-interactive `.badge` usages elsewhere. Reuses the SAME `--shadow-focus` ring already used by
   `.ct-mini-score__info:focus-visible` (recruiter-candidacy-mini-modal.css) — no new token. */
.badge[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.badge-beta {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 8px;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  background: rgba(var(--accent-rgb), 0.15);
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), 0.3);
  vertical-align: middle;
  margin-left: 6px;
  line-height: 1.5;
}

/* === Pills Enhanced === */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 8px 14px;
  border-radius: var(--radius-full);
  background: rgba(var(--white-rgb), 0.06);
  border: 1px solid var(--border);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--muted);
  transition: all var(--duration-base) var(--ease-default);
}
.pill:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.pill:focus:not(:focus-visible) {
  outline: none;
}

.pill.ok {
  background: rgba(var(--status-ok-rgb), 0.15);
  border-color: rgba(var(--status-ok-rgb), 0.30);
  color: var(--success-text);
}

.pill.warn {
  background: rgba(var(--status-warn-rgb), 0.15);
  border-color: rgba(var(--status-warn-rgb), 0.30);
  color: var(--warning-text);
}

.pill.bad {
  background: rgba(var(--red-light-rgb), 0.15);
  border-color: rgba(var(--red-light-rgb), 0.30);
  color: var(--danger-text);
}

/* Plan #295 Phase 7 — info variant for normalized salary chip */
.pill--info {
  background: rgba(var(--info-rgb), 0.12);
  border-color: rgba(var(--info-rgb), 0.30);
  color: var(--info-text);
  font-size: var(--text-xs);
  padding: 4px 10px;
}
.pill--info .pill__prefix {
  opacity: 0.78;
  margin-right: 2px;
}
[data-theme="bento"] .pill--info,
body.bento-theme .pill--info, body.atsiq-theme .pill--info {
  background: rgba(var(--info-rgb), 0.18);
  color: var(--accent);
  border-color: rgba(var(--accent-rgb), 0.40);
}
@media (max-width: 480px) {
  .pill--info {
    white-space: normal;
    line-height: 1.35;
    flex-wrap: wrap;
  }
}

/* === Tables Enhanced === */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  min-width: 700px;
  background: var(--table-tint);
  border: 1px solid var(--table-edge);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

/* Files table: fixed layout for truncation */
#tabRecruiterFiles table {
  table-layout: fixed;
}

/* Truncatable text columns */
#tabRecruiterFiles .colTrunc,
#tabRecruiterFiles td.truncCell {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 0; /* forces ellipsis with table-layout:fixed */
}

.editable-cell {
  cursor: pointer;
  border-bottom: 1px dashed var(--muted);
  padding-bottom: 1px;
}
.editable-cell:hover {
  color: var(--primary);
  border-bottom-color: var(--primary);
}

/* Fixed-width columns */
#tabRecruiterFiles .colFixed { width: 80px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#tabRecruiterFiles .colStatus { width: 110px; }
#tabRecruiterFiles td .badge { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }

/* Actions column pinned right */
#tabRecruiterFiles .colActions {
  width: 220px;
  white-space: nowrap;
  text-align: right;
}

thead th {
  text-align: left;
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  padding: 14px 16px;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.08);
  background: rgba(var(--black-rgb), 0.12);
  white-space: nowrap;
}
thead th.right,
thead th.cellActions {
  text-align: right;
}

tbody td {
  padding: 14px 16px;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.05);
  color: var(--text);
  white-space: nowrap;
  font-size: var(--text-base);
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr:hover td {
  background: rgba(var(--accent-rgb),0.06);
}

/* === Welcome Page Enhanced === */
.welcomeLogo {
  font-size: 52px; /* hero scale — hors échelle */
  font-weight: 800;
  margin-bottom: var(--space-4);
  letter-spacing: -0.02em;
}

.welcomeTag {
  font-size: var(--text-xl);
  font-weight: 500;
  margin-bottom: var(--space-6);
  line-height: 1.4;
  color: var(--text);
}

.welcomeDesc {
  font-size: var(--text-md);
  line-height: 1.65;
  margin-bottom: var(--space-4);
  color: var(--muted);
  text-align: left;
  width: 100%;
}

.welcomeDesc strong {
  color: var(--accent);
  font-weight: 600;
}

.welcomeActions {
  margin-top: 28px;
  width: 100%;
}


.welcomeActions .btn.btn--primary {
  width: 100%;
  height: 50px;
  font-size: var(--text-md);
  font-weight: 600;
  /* P2-Z re-gate — fond PLEIN AA (cf. .btn.btn--primary). */
  background: var(--btn-primary-bg);
  border: none;
  color: var(--text-inverse);
  box-shadow: 0 4px 20px rgba(var(--accent-rgb),0.35);
}

@media (hover: hover) {
  .welcomeActions .btn.btn--primary:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 30px rgba(var(--accent-rgb),0.45);
  }
}

/* === Scrollbar Styling === */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: rgba(var(--black-rgb), 0.2);
  border-radius: var(--radius-4);
}

::-webkit-scrollbar-thumb {
  background: rgba(var(--white-rgb), 0.15);
  border-radius: var(--radius-4);
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(var(--white-rgb), 0.25);
}

/* === Cookie Consent Banner (RGPD) === */
.cookie-banner {
  position: fixed;
  bottom: 0;
  left: 240px;
  right: 0;
  z-index: calc(var(--z-modal) - 2); /* Below modals but above regular content */
  background: var(--bg-opaque);
  border-top: 1px solid var(--border);
  padding: 1rem 1.5rem;
  box-shadow: 0 -4px 20px rgba(var(--black-rgb), 0.3);
  animation: slideUp var(--duration-slow) ease-out;
  transition: left var(--duration-slow) var(--ease-default);
}
.app-sidebar.collapsed ~ .cookie-banner {
  left: 56px;
}
.app-sidebar.hidden ~ .cookie-banner {
  left: 0;
}

@keyframes slideUp {
  from { transform: translateY(100%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.cookie-banner.hidden {
  display: none;
}

.cookie-banner-content {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.cookie-banner-text h3 {
  margin: 0 0 0.25rem 0;
  font-size: var(--text-md);
  color: var(--text);
}

.cookie-banner-text p {
  margin: 0;
  font-size: var(--text-base);
  color: var(--muted);
  max-width: 700px;
}

.cookie-banner-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-shrink: 0;
}

.cookie-link {
  color: var(--accent);
  font-size: var(--text-base);
  text-decoration: none;
}

.cookie-link:hover {
  text-decoration: underline;
}

@media (max-width: 768px) {
  .cookie-banner {
    left: 0;
    padding-bottom: max(1rem, env(safe-area-inset-bottom, 0px));
  }
  .cookie-banner-content {
    flex-direction: column;
    text-align: center;
  }
  .cookie-banner-actions {
    width: 100%;
    justify-content: center;
  }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .cookie-banner {
    left: 56px;
  }
}

/* === Toast Notifications (Alpha 8) === */
.toastContainer {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 400px;
}

@media (max-width: 600px) {
  .toastContainer {
    bottom: max(68px, calc(60px + env(safe-area-inset-bottom, 0px)));
    right: var(--space-3);
    left: var(--space-3);
    max-width: none;
  }
}

.toast {
  position: relative; /* Anchor for .toastProgress absolute positioning */
  padding: 14px 18px;
  border-radius: var(--radius-sm);
  background: var(--bg-opaque);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  animation: toastIn var(--duration-slow) var(--ease-spring);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  overflow: hidden; /* Clip progress bar to toast border-radius */
}

.toast.success {
  border-color: var(--success-text);
  background: linear-gradient(135deg, rgba(var(--status-ok-rgb, 34,197,94), 0.15), var(--bg-opaque));
}

.toast.error {
  border-color: var(--danger-text);
  border-width: 2px;
  background: linear-gradient(135deg, rgba(var(--status-danger-rgb), 0.18), var(--bg-opaque));
  color: var(--danger-text);
}

.toast.warning {
  border-color: var(--status-warn);
  background: linear-gradient(135deg, rgba(var(--status-warn-rgb, 245,158,11), 0.15), var(--bg-opaque));
}
.toast.warning .toastIcon { color: var(--status-warn); }

.toast.info {
  border-color: var(--accent);
  background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.15), var(--bg-opaque));
}

.toast .toastIcon {
  font-size: var(--text-lg);
  flex-shrink: 0;
}

.toast.success .toastIcon { color: var(--success-text); }
.toast.error .toastIcon { color: var(--danger-text); }
.toast.info .toastIcon { color: var(--accent); }

.toast .toastMsg {
  flex: 1;
  font-size: var(--text-base);
}

.toast .toastClose {
  cursor: pointer;
  opacity: 0.6;
  transition: opacity var(--duration-base);
  padding: var(--space-1);
}

.toast .toastClose:hover {
  opacity: 1;
}

/* Undo button in toast (for reversible destructive actions) */
.toast .toastUndo {
  background: rgba(var(--white-rgb), 0.1);
  border: 1px solid rgba(var(--white-rgb), 0.25);
  color: inherit;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  min-height: 32px;
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: background var(--duration-fast), border-color var(--duration-fast), transform var(--duration-fast);
  white-space: nowrap;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
}
.toast .toastUndo:hover {
  background: rgba(var(--white-rgb), 0.2);
  border-color: rgba(var(--white-rgb), 0.5);
}
.toast .toastUndo:active {
  transform: scale(0.95);
}
body.bento-theme .toast .toastUndo,
body.light-theme .toast .toastUndo, body.atsiq-theme .toast .toastUndo {
  background: rgba(var(--black-rgb), 0.05);
  border-color: rgba(var(--black-rgb), 0.15);
}
body.bento-theme .toast .toastUndo:hover,
body.light-theme .toast .toastUndo:hover, body.atsiq-theme .toast .toastUndo:hover {
  background: rgba(var(--black-rgb), 0.1);
  border-color: rgba(var(--black-rgb), 0.35);
}
@media (pointer: coarse) {
  .toast .toastUndo { min-height: 44px; padding: var(--space-2) var(--space-4); }
}

.toast.hiding {
  animation: toastOut var(--duration-slow) ease forwards;
}

/* Toast progress bar — shrinks over time to show auto-dismiss countdown */
.toastProgress {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: currentColor;
  opacity: 0.45;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  transform-origin: left;
  animation: toastProgressShrink linear forwards;
}
@keyframes toastProgressShrink {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}
.toast.hiding .toastProgress {
  display: none;
}
.toast--paused .toastProgress {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
  .toast.hiding { animation: none; opacity: 0; }
  .toastProgress { animation: none; }
  .aiProcessing .spinner { animation: none !important; }
  .ct-dz.ct-dz-dragover { animation: none !important; }
  .ct-dz.ct-dz-dragover .ct-dz-icon { animation: none !important; }
  .ct-dz.ct-dz-reject { animation: none !important; }
  .ct-dz.ct-dz-success { animation: none !important; }
  .ct-dz-preview { animation: none !important; }
  .ct-dz-thumb { animation: none !important; }
  .search-modal__content { animation: none !important; }
  .progressFill::after { animation: none !important; }
  .turnstileSkeleton { animation: none !important; }
}

@keyframes toastIn {
  from {
    opacity: 0;
    transform: translateX(100px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes toastOut {
  from {
    opacity: 1;
    transform: translateX(0);
  }
  to {
    opacity: 0;
    transform: translateX(100px);
  }
}

/* === AI Processing Indicator === */
.aiProcessing {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  background: rgba(var(--accent-rgb),0.1);
  border-radius: var(--radius-sm);
  border: 1px solid rgba(var(--accent-rgb),0.3);
  margin-top: var(--space-3);
}

.aiProcessing .spinner {
  width: 24px;
  height: 24px;
  border: 3px solid rgba(var(--accent-rgb),0.2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.aiProcessing .aiProgressText {
  flex: 1;
  color: var(--accent);
  font-size: var(--text-base);
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* AI History items */
.historyItem {
  transition: background var(--duration-base);
}

.historyItem:hover {
  background: var(--card);
}

.historyItem:last-child {
  border-bottom: none !important;
}

/* Keyboard shortcut hints */
.kbdHint {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--muted);
  margin-left: var(--space-2);
}

.kbdHint kbd {
  display: inline-block;
  padding: 2px 6px;
  background: rgba(var(--white-rgb), 0.1);
  border: 1px solid rgba(var(--white-rgb), 0.2);
  border-radius: var(--radius-4);
  font-family: inherit;
  font-size: var(--text-xs);
}

/* === AI Disclosure Notice (EU AI Act) === */
.aiDisclosure {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  margin-top: var(--space-3);
  background: rgba(var(--primary-rgb), 0.06);
  border: 1px solid rgba(var(--primary-rgb), 0.15);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
}
.aiDisclosure .aiDisclosureIcon {
  flex-shrink: 0;
  font-size: var(--text-sm);
}
.aiDisclosure .aiDisclosureText {
  flex: 1;
}
.aiDisclosure .aiReportLink {
  flex-shrink: 0;
  color: var(--accent);
  cursor: pointer;
  text-decoration: none;
  font-size: var(--text-xs);
  opacity: 0.8;
  transition: opacity var(--duration-base);
}
.aiDisclosure .aiReportLink:hover {
  opacity: 1;
  text-decoration: underline;
}
body.light-theme .aiDisclosure,
body.bento-theme .aiDisclosure, body.atsiq-theme .aiDisclosure {
  background: rgba(var(--primary-rgb), 0.04);
  border-color: rgba(var(--primary-rgb), 0.12);
}

/* ============================================
   ALPHA 8: Pagination
   ============================================ */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-3);
}

.paginationInfo {
  font-size: var(--text-sm);
  color: var(--muted);
}

/* ============================================
   ALPHA 9: Journey Progress Bar
   ============================================ */
.journeyProgress {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4);
  background: rgba(var(--white-rgb), 0.03);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-4);
}

.journeyStep {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  position: relative;
}

.journeyStep::after {
  content: "";
  position: absolute;
  top: var(--space-4);
  left: 50%;
  width: 100%;
  height: 2px;
  background: var(--border);
  z-index: var(--z-base);
}

.journeyStep:last-child::after {
  display: none;
}

.journeyStepCircle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--card);
  border: 2px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-base);
  font-weight: 600;
  z-index: var(--z-decoration);
  transition: all var(--duration-slow);
}

.journeyStep.completed .journeyStepCircle {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-inverse);
}

.journeyStep.current .journeyStepCircle {
  background: var(--accent2);
  border-color: var(--accent2);
  color: var(--text-inverse);
  box-shadow: 0 0 12px rgba(var(--status-ok-rgb), 0.5);
}

.journeyStepLabel {
  font-size: var(--text-xs);
  color: var(--muted);
  text-align: center;
}

.journeyStep.completed .journeyStepLabel,
.journeyStep.current .journeyStepLabel {
  color: var(--text);
}

/* === Extension Promo Banner === */
.extension-promo-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 10px 20px;
  margin-bottom: var(--space-4);
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.15), rgba(var(--cyan-rgb), 0.10));
  border: 1px solid rgba(var(--accent-rgb),0.3);
  border-radius: var(--radius-8);
}
.extension-promo-banner.hidden { display: none; }
.extension-promo-content {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
}
.extension-promo-icon { font-size: var(--text-2xl); flex-shrink: 0; }
.extension-promo-text { font-size: var(--text-sm); color: var(--fg); }
.extension-promo-actions { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }
.extension-promo-dismiss {
  width: 36px;
  height: 36px;
  padding: 0;
  font-size: var(--text-md);
  color: var(--text);
  background: rgba(var(--text-rgb), 0.06);
  border: 1px solid rgba(var(--text-rgb), 0.12);
  border-radius: var(--radius-full);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all var(--duration-fast) var(--ease-default);
}
.extension-promo-dismiss:hover {
  color: var(--fg);
  background: rgba(var(--text-rgb), 0.12);
  border-color: rgba(var(--text-rgb), 0.18);
}

body.light-theme .extension-promo-banner,
body.bento-theme .extension-promo-banner, body.atsiq-theme .extension-promo-banner {
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.08), rgba(var(--cyan-rgb), 0.05));
  border-color: rgba(var(--accent-rgb),0.2);
}
@media (max-width: 400px) {
  .extension-promo-banner {
    flex-wrap: wrap;
    padding: var(--space-2) var(--space-3);
    gap: 6px;
  }
  .extension-promo-text { font-size: var(--text-xs); }
  .extension-promo-icon { font-size: var(--text-lg); }
  .extension-promo-actions .btn { font-size: var(--text-xs); padding: 6px 12px; }
}

/* === Extension Modal === */
.extension-features {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
.extension-feature-card {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px;
  background: rgba(var(--white-rgb), 0.04);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.extension-feature-card h4 { font-size: var(--text-base); font-weight: 600; margin: 0 0 4px 0; }
.extension-feature-card p { font-size: var(--text-xs); color: var(--muted); margin: 0; line-height: 1.4; }
.extension-browsers {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
  margin-top: var(--space-4);
  flex-wrap: wrap;
}
.extension-browser-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 20px;
  background: rgba(var(--white-rgb), 0.04);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--fg);
  cursor: pointer;
  min-width: 100px;
  font-size: var(--text-sm);
  text-decoration: none;
  transition: border-color var(--duration-base), background var(--duration-base), transform var(--duration-fast);
}
@media (hover: hover) {
  .extension-browser-btn:hover {
    border-color: var(--primary);
    background: rgba(var(--accent-rgb),0.08);
    transform: translateY(-2px);
  }
}
.extension-browser-btn:active { transform: translateY(0); }
.extension-browser-btn .download-icon { opacity: 0.5; margin-top: 2px; }
.extension-browser-btn:hover .download-icon { opacity: 1; }
.extension-browser-btn svg { opacity: 0.8; }
.extension-browser-btn:hover svg { opacity: 1; }
.extension-sideload-instructions {
  font-size: var(--text-xs);
  color: var(--muted);
  text-align: center;
  margin-top: var(--space-3);
  line-height: 1.5;
}

body.light-theme .extension-feature-card,
body.bento-theme .extension-feature-card, body.atsiq-theme .extension-feature-card {
  background: rgba(var(--black-rgb), 0.03);
}
body.light-theme .extension-browser-btn,
body.bento-theme .extension-browser-btn, body.atsiq-theme .extension-browser-btn {
  background: rgba(var(--black-rgb), 0.03);
}

@media (max-width: 480px) {
  .extension-features { grid-template-columns: 1fr; }
  .extension-promo-banner { flex-direction: column; text-align: center; }
  .extension-promo-content { flex-direction: column; }
}

/* === Mono Font Tech Elements === */
.step-number,
.hero-stat-value,
.pricing-price,
.creditsValue,
.headerCreditsValue,
.metricValue,
.stat-value,
.finKpiValue,
.finStatRow__value,
.scoreBadgeLarge,
[data-credit-cost]::after {
  font-family: var(--font-mono);
}

/* === Table Improvements === */
tbody tr:nth-child(even) td {
  background: rgba(var(--white-rgb), 0.015);
}
thead th {
  position: sticky;
  top: 0;
  z-index: var(--z-raised);
}

/* === Mobile modal full-screen === */
@media (max-width: 600px) {
  .modalCard {
    width: 100% !important;
    max-height: 100vh;
    max-height: 100dvh;
    border-radius: 0;
    padding: var(--space-4);
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
  }
  .action-dropdown, .dropdown-menu {
    max-width: calc(100% - 32px);
  }
}

/* ============================================================
   Empty States — Mockup integration (Batch 02/03/07)
   ============================================================ */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-8) var(--space-6);
  color: var(--muted);
  font-size: var(--text-base);
  line-height: 1.6;
}

.empty-state__illustration {
  width: 160px;
  height: 160px;
  position: relative;
  margin-bottom: var(--space-6);
  display: flex;
  align-items: center;
  justify-content: center;
}

.empty-state__illustration::before {
  content: '';
  position: absolute;
  inset: 0;
  border: 2px dashed rgba(var(--accent-rgb),0.20);
  border-radius: 50%;
  animation: emptyRingSpin 20s linear infinite;
}

.empty-state__icon-wrap {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.15), rgba(var(--accent2-rgb), 0.10));
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.empty-state__icon {
  font-size: 48px; /* hero scale — hors échelle */
  line-height: 1;
  filter: drop-shadow(0 4px 12px rgba(var(--accent-rgb),0.3));
  animation: emptyFloat 4s ease-in-out infinite;
  transform-origin: center center;
}

.empty-state__title {
  font-size: var(--text-lg);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

.empty-state__desc {
  font-size: var(--text-base);
  color: var(--muted);
  max-width: 380px;
  line-height: 1.6;
  margin-bottom: var(--space-5);
}

.empty-state__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 44px;
  padding: 0 24px;
  border-radius: var(--radius-sm);
  background: var(--gradient-primary);
  color: var(--text-inverse);
  font-size: var(--text-base);
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: all var(--duration-base);
  font-family: var(--font-body);
}

.empty-state__cta:hover {
  box-shadow: 0 4px 16px rgba(var(--accent-rgb),0.3);
  transform: translateY(-1px);
}

.empty-state__tips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-top: var(--space-4);
}

.empty-state__tip {
  padding: 8px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-8);
  font-size: var(--text-xs);
  color: var(--muted);
}

.empty-state__checklist {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
  text-align: left;
}

.empty-state__checklist-item {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--text-sm);
  color: var(--muted);
}

.empty-state__checklist-item::before {
  content: '';
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--border);
  flex-shrink: 0;
}

/* Empty state variants */
.empty-state--compact {
  padding: var(--space-6) var(--space-4);
}

.empty-state--compact .empty-state__illustration {
  width: 100px;
  height: 100px;
  margin-bottom: var(--space-4);
}

.empty-state--compact .empty-state__icon-wrap {
  width: 72px;
  height: 72px;
}

.empty-state--compact .empty-state__icon {
  font-size: var(--text-4xl); /* icon emoji */
  line-height: 1;
}

.empty-state--compact .empty-state__title {
  font-size: var(--text-md);
}

.empty-state--compact .empty-state__desc {
  font-size: var(--text-sm);
}

.empty-state--inline {
  flex-direction: row;
  text-align: left;
  gap: var(--space-5);
  padding: var(--space-6);
}

.empty-state--inline .empty-state__illustration {
  width: 80px;
  height: 80px;
  margin-bottom: 0;
  flex-shrink: 0;
}

.empty-state--inline .empty-state__icon-wrap {
  width: 64px;
  height: 64px;
}

.empty-state--admin {
  padding: var(--space-7) var(--space-5);
}

.empty-state--admin .empty-state__illustration::before {
  border-color: rgba(var(--status-danger-rgb), 0.15);
}

.empty-state--admin .empty-state__icon-wrap {
  background: linear-gradient(135deg, rgba(var(--status-danger-rgb), 0.12), rgba(var(--amber-rgb), 0.08));
}

/* @keyframes emptyRingSpin — deduplicated, canonical in effects.css */
/* @keyframes emptyFloat — deduplicated, canonical in effects.css */

/* ============================================================
   Proactive Tips — Dismissible suggestion banners (Alpha 18.10)
   ============================================================ */
.proactive-tip {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px 18px;
  border-radius: var(--radius-sm);
  border-left: 4px solid var(--accent);
  background: var(--card);
  border-top: 1px solid var(--border);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-4);
  position: relative;
}

.proactive-tip__icon {
  font-size: var(--text-2xl);
  flex-shrink: 0;
  line-height: 1;
}

.proactive-tip__content {
  flex: 1;
  min-width: 0;
}

.proactive-tip__title {
  font-size: var(--text-base);
  font-weight: 700;
  margin-bottom: var(--space-1);
}

.proactive-tip__desc {
  font-size: var(--text-sm);
  color: var(--muted);
  line-height: 1.5;
  margin-bottom: 10px;
}

.proactive-tip__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: var(--radius-8);
  background: var(--gradient-primary);
  color: var(--text-inverse);
  font-size: var(--text-sm);
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: all var(--duration-base);
  font-family: var(--font-body);
}

.proactive-tip__cta:hover {
  box-shadow: 0 2px 10px rgba(var(--accent-rgb),0.25);
}

.proactive-tip__cta:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.proactive-tip__cta:focus:not(:focus-visible) {
  outline: none;
}

.proactive-tip__cta:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.proactive-tip__cta:active {
  transform: scale(0.97);
  box-shadow: 0 1px 4px rgba(var(--accent-rgb),0.20);
}

.proactive-tip__dismiss {
  position: absolute;
  top: 10px;
  right: 10px;
  background: none;
  border: none;
  color: var(--muted);
  font-size: var(--text-md);
  cursor: pointer;
  padding: var(--space-1);
  line-height: 1;
  opacity: 0.6;
  transition: opacity var(--duration-base);
}

.proactive-tip__dismiss:hover {
  opacity: 1;
}

/* ============================================================
   Field Descriptions — Muted helper text under form fields
   ============================================================ */
.field-desc {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: var(--space-1);
  line-height: 1.4;
}

/* ============================================================
   Status Pills — Mockup integration (Batch 02/07)
   ============================================================ */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  letter-spacing: 0.01em;
}

.status-pill::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}

.status-pill.active,
.status-pill.completed,
.status-pill.hire {
  background: rgba(var(--status-ok-rgb), 0.12);
  color: var(--success-text);
}
.status-pill.active::before,
.status-pill.completed::before,
.status-pill.hire::before {
  background: var(--success-text);
}

.status-pill.pending,
.status-pill.in-progress,
.status-pill.maybe {
  background: rgba(var(--amber-rgb), 0.12);
  color: var(--warning-text);
}
.status-pill.pending::before,
.status-pill.in-progress::before,
.status-pill.maybe::before {
  background: var(--warning-text);
}

.status-pill.inactive,
.status-pill.failed,
.status-pill.no-hire {
  background: rgba(var(--data-rose-rgb), 0.12);
  color: var(--danger-text);
}
.status-pill.inactive::before,
.status-pill.failed::before,
.status-pill.no-hire::before {
  background: var(--danger-text);
}

.status-pill.draft,
.status-pill.neutral {
  background: rgba(var(--white-rgb), 0.06);
  color: var(--muted);
}
.status-pill.draft::before,
.status-pill.neutral::before {
  background: var(--muted);
}

.status-pill.info {
  background: rgba(var(--accent-rgb),0.12);
  color: var(--accent-light);
}
.status-pill.info::before {
  background: var(--accent-light);
}

/* ============================================================
   Action Group — Mockup integration (Batch 02)
   ============================================================ */
.action-group {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  justify-content: flex-end;
}

.action-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: var(--radius-8);
  border: 1px solid var(--border);
  background: rgba(var(--white-rgb), 0.04);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
  transition: all var(--duration-fast);
  white-space: nowrap;
}

.action-btn:hover {
  background: rgba(var(--accent-rgb),0.10);
  border-color: var(--border-accent);
  color: var(--accent-light);
}

.action-btn.primary {
  background: rgba(var(--accent-rgb),0.12);
  border-color: rgba(var(--accent-rgb),0.25);
  color: var(--accent-light);
}
.action-btn.primary:hover {
  background: rgba(var(--accent-rgb),0.20);
}

.action-btn.danger {
  color: var(--danger-text);
}
.action-btn.danger:hover {
  background: rgba(var(--data-rose-rgb), 0.12);
  border-color: rgba(var(--data-rose-rgb), 0.25);
}

.action-more {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-8);
  border: 1px solid transparent;
  background: none;
  color: var(--muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-md);
  transition: all var(--duration-fast);
  position: relative;
}
.action-more:hover {
  background: rgba(var(--white-rgb), 0.06);
  border-color: var(--border);
  color: var(--text);
}

.action-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 180px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px;
  box-shadow: var(--shadow);
  z-index: var(--z-sidebar);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity var(--duration-fast), transform var(--duration-fast);
}
.action-more:focus .action-dropdown,
.action-more.open .action-dropdown {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.action-dropdown-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: none;
  background: none;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  cursor: pointer;
  border-radius: var(--radius-xs);
  transition: background var(--duration-fast);
}
.action-dropdown-item:hover {
  background: rgba(var(--accent-rgb),0.10);
}
.action-dropdown-item .dd-icon {
  width: 18px;
  text-align: center;
  font-size: var(--text-base);
  flex-shrink: 0;
}
.action-dropdown-item.danger {
  color: var(--danger-text);
}
.action-dropdown-item.danger:hover {
  background: rgba(var(--data-rose-rgb), 0.10);
}
.action-dropdown-sep {
  height: 1px;
  background: var(--border);
  margin: var(--space-1) var(--space-2);
}

/* ============================================================
   Cell Types — Mockup integration (Batch 02)
   ============================================================ */
.cell-stack {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cell-stack .main {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text);
}
.cell-stack .sub {
  font-size: var(--text-xs);
  color: var(--muted);
}

.cell-mono {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted);
  letter-spacing: -0.02em;
}

.cell-hash {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--muted);
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 0.7;
}

.cell-with-avatar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* ============================================================
   Progress Mini — Mockup integration (Batch 02)
   ============================================================ */
.progress-mini {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.progress-mini .bar {
  width: 80px;
  height: 5px;
  border-radius: var(--radius-3);
  background: rgba(var(--white-rgb), 0.08);
  overflow: hidden;
}
.progress-mini .fill {
  height: 100%;
  border-radius: var(--radius-3);
  background: var(--accent);
  transition: width var(--duration-slow);
}
.progress-mini .fill.high { background: var(--success-text); }
.progress-mini .fill.mid { background: var(--warning-text); }
.progress-mini .fill.low { background: var(--danger-text); }
.progress-mini .val {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  min-width: 32px;
}

/* ============================================================
   Score Badge — Mockup integration (Batch 02)
   ============================================================ */
.score-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 28px;
  border-radius: var(--radius-8);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 700;
}
.score-badge.high { background: rgba(var(--status-ok-rgb), 0.15); color: var(--success-text); }
.score-badge.mid { background: rgba(var(--amber-rgb), 0.15); color: var(--warning-text); }
.score-badge.low { background: rgba(var(--data-rose-rgb), 0.15); color: var(--danger-text); }

/* ============================================================
   Avatar Mini — Mockup integration (Batch 02)
   ============================================================ */
.avatar-mini {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: var(--text-inverse);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: 700;
  flex-shrink: 0;
}

/* ============================================================
   Role Badges — Mockup integration (Batch 02/07)
   ============================================================ */
.role-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-xs);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.role-badge.admin { background: rgba(var(--accent-rgb),0.15); color: var(--accent-light); }
.role-badge.candidate { background: rgba(var(--accent2-rgb), 0.12); color: var(--accent2); }
.role-badge.recruiter { background: rgba(var(--amber-rgb), 0.12); color: var(--warning-text); }
.role-badge.mentor { background: rgba(var(--status-ok-rgb), 0.12); color: var(--success-text); }

/* ============================================================
   Bulk Bar — Mockup integration (Batch 02/07)
   ============================================================ */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  background: rgba(var(--accent-rgb),0.08);
  border-bottom: 1px solid rgba(var(--accent-rgb),0.20);
}
.bulk-bar .bulk-count {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent-light);
}
.bulk-bar .bulk-actions {
  display: flex;
  gap: var(--space-2);
  margin-left: auto;
}

/* ============================================================
   Pagination — Mockup integration (Batch 02)
   ============================================================ */
.tbl-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  font-size: var(--text-sm);
}
.tbl-pagination .pag-info {
  color: var(--muted);
}
.tbl-pagination .pag-info strong {
  color: var(--text);
  font-weight: 600;
}
.tbl-pagination .pag-controls {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.pag-btn {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-8);
  border: 1px solid var(--border);
  background: none;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: 600;
  transition: all var(--duration-fast);
  font-family: var(--font-body);
}
.pag-btn:hover {
  background: rgba(var(--accent-rgb),0.08);
  border-color: var(--border-accent);
  color: var(--accent-light);
}
.pag-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-inverse);
}
.pag-btn:disabled {
  opacity: var(--btn-disabled-opacity);
  cursor: not-allowed;
}

/* ============================================================
   Table Enhancements — Mockup integration (Batch 02)
   ============================================================ */
.tbl {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-sm);
}
.tbl thead th {
  text-align: left;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 14px 20px;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.08);
  background: rgba(var(--black-rgb), 0.15);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: var(--z-raised);
}
.tbl tbody td {
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid rgba(var(--white-rgb), 0.04);
  color: var(--text);
  font-size: var(--text-sm);
  vertical-align: middle;
  transition: background var(--duration-fast);
}
.tbl tbody tr:nth-child(even) td {
  background: rgba(var(--white-rgb), 0.015);
}
.tbl tbody tr:hover td {
  background: rgba(var(--accent-rgb),0.06);
}
.tbl tbody tr:hover td:first-child {
  box-shadow: var(--shadow-inset-accent);
}
.tbl tbody tr:last-child td {
  border-bottom: none;
}

/* Sortable headers */
.tbl thead th.sortable {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  transition: color var(--duration-fast);
}
.tbl thead th.sortable:hover {
  color: var(--accent-light);
}
.tbl thead th.sortable::after {
  content: '\2195';
  margin-left: 6px;
  opacity: 0.3;
  font-size: var(--text-2xs);
}
.tbl thead th.sorted-asc::after {
  content: '\2191';
  opacity: 0.8;
  color: var(--accent);
}
.tbl thead th.sorted-desc::after {
  content: '\2193';
  opacity: 0.8;
  color: var(--accent);
}

/* Checkbox in tables */
.tbl-check {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Table wrapper */
.tbl-wrap {
  overflow-x: auto;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: rgba(var(--black-rgb), 0.12);
}
/* DS-Canon S2 (2026-07-13) — the rgba(black) fill above is an Obsidian-only
   treatment; on the light themes it rendered as a gray slab behind every .tbl
   (VQA vca-atsiq-recruiter/15b, pixel-sampled RGB ~190 vs 254 KPI cards).
   Light themes get the card surface. Lives here (not atsiq-theme.css) because
   components.css is the only file loaded on ALL hosts — a bento leg in the
   host-scoped atsiq-theme.css would never ship to careertoolbox.ai. */
body.bento-theme .tbl-wrap,
body.atsiq-theme .tbl-wrap,
body.light-theme .tbl-wrap {
  background: var(--card);
}

/* §11 mobile re-VQA (2026-07-16) — zero-states rendered inside a horizontally
   scrollable table wrapper (a td[colspan]: Clients, Facturation, Entretiens…)
   clipped mid-word off the 390px scrollport. The first fix (sticky + max-width
   on the zero-state div) did NOT work: table AUTO layout sizes the column from
   the cell's max-content width — the long __desc/__hint sentence stretches the
   table to ~470-570px — and the div's min(100%, …) max-width is indefinite
   during intrinsic sizing, so it never caps that contribution; the block then
   centers in the overwide td and clips (sticky left:0 cannot relocate a block
   whose static position is already in view). Real fix = when the table only
   holds a zero-state, switch it to FIXED layout at the wrapper's width (same
   canon as .sched-detail-table, recruiter.css) → the td = card width, text
   wraps, the message reads whole and centered without scrolling. The thead of
   such a table carries no information — keep it hidden (also for a literally
   empty tbody). Desktop unchanged. */
@media (max-width: 480px) {
  .tbl-wrap table:has(.empty-state),
  .tableWrap table:has(.empty-state),
  .tbl-wrap table:has(.bento-empty),
  .tableWrap table:has(.bento-empty) {
    table-layout: fixed;
    width: 100%;
    min-width: 0;
  }
  /* The global `tbody td { white-space: nowrap }` (Tables Enhanced) inherits
     into the zero-state copy → single-line title/desc clipping at both edges
     no matter how narrow the cell. Restore wrapping for zero-state cells. */
  .tbl-wrap table:has(.empty-state) tbody td,
  .tableWrap table:has(.empty-state) tbody td,
  .tbl-wrap table:has(.bento-empty) tbody td,
  .tableWrap table:has(.bento-empty) tbody td {
    white-space: normal;
  }
  .tbl-wrap table:has(.empty-state) thead,
  .tableWrap table:has(.empty-state) thead,
  .tbl-wrap table:has(.bento-empty) thead,
  .tableWrap table:has(.bento-empty) thead,
  .tbl-wrap table:has(tbody:empty) thead,
  .tableWrap table:has(tbody:empty) thead {
    display: none;
  }
}

/* Responsive column hiding */
@media (max-width: 900px) {
  .tbl .col-hide-md { display: none; }
}
@media (max-width: 600px) {
  .tbl .col-hide-sm { display: none; }
}

/* ============================================================
   Section Headers — Canonical pattern (Mockup Batch 07/03 + 2026-05-15 audit polish)
   --------------------------------------------------------------
   Grid 2-col x 2-row : title + actions aligned on row 1 (centered
   vertically), subtitle on row 2 spanning full width. This avoids
   the misalignment where actions sit at the top of a tall stacked
   left column when the subtitle is long.
   ============================================================ */
.sec-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  margin-bottom: var(--space-5);
}
/* Top breathing room — every recruiter section-pane gets the same
   gap below the app topbar, whether the .sec-head header is rendered
   directly inside (10 static panes in index.html) or wrapped in a
   module-side root (Clients, partnerAgencies, feeSplit, ...). */
.section-pane:not(.hidden) {
  padding-top: var(--space-5);
}
.sec-head > :first-child {
  grid-column: 1;
  grid-row: 1 / 3;
  min-width: 0;
}
.sec-head > .row-actions,
.sec-head > .actions,
.sec-head > .sec-actions {
  grid-column: 2;
  grid-row: 1 / 3;
  align-self: center;
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.sec-title {
  font-size: var(--text-2xl);
  font-weight: 750;
  letter-spacing: -0.04em;
  line-height: 1.2;
  margin: 0;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
h1.sec-title,
h2.sec-title,
h3.sec-title {
  font-size: var(--text-2xl);
  font-weight: 750;
  letter-spacing: -0.04em;
  line-height: 1.2;
  margin: 0;
}
/* P2-I (D15, juge DA G.3.10 « 2 titres de niveau page empilés ») — variante SECTION du
   header : quand un pane empile deux modules (Accords + Factures partenaires), le second
   header doit se lire comme une section, pas comme un second titre de page.
   Spec §1 : titre de page --text-2xl (UN par écran), titre de section --text-lg semibold. */
h1.sec-title.sec-title--section,
h2.sec-title.sec-title--section,
h3.sec-title.sec-title--section {
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: normal;
}
.sec-head--section { margin-top: var(--space-6); }
.sec-subtitle {
  font-size: var(--text-sm);
  color: var(--muted);
  margin: 2px 0 0;
  line-height: 1.4;
}
@media (max-width: 768px) {
  .sec-head {
    grid-template-columns: minmax(0, 1fr);
  }
  .sec-head > .row-actions,
  .sec-head > .actions,
  .sec-head > .sec-actions {
    grid-column: 1;
    grid-row: auto;
    flex-wrap: wrap;
  }
}

/* Card flush variant */
.card-flush {
  padding: 0;
}
.card-flush .card-head {
  padding: var(--space-4) var(--space-5);
  margin-bottom: 0;
  border-bottom: 1px solid var(--border);
}
.card-flush .card-body {
  padding: 0;
}

/* Card highlight variant */
.card-highlight {
  border-color: rgba(var(--accent-rgb),0.3);
  background: linear-gradient(135deg, rgba(var(--accent-rgb),0.06), rgba(var(--accent2-rgb), 0.03));
}

/* Sub-pane switching */
.sub-pane {
  display: none;
}
.sub-pane.active {
  display: block;
  animation: tabPaneIn var(--duration-slow) ease both;
}

/* Card head enhancements */
.card-head .search-input {
  height: 38px;
  padding: 0 12px 0 32px;
  border-radius: var(--radius-sm);
  background: rgba(var(--black-rgb), 0.2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--text-xs);
  font-family: var(--font-body);
  outline: none;
  transition: border-color var(--duration-base);
}
.card-head .search-input:focus {
  border-color: var(--accent);
}

.card-head .title .count {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--muted);
}

/* ============================================================
   V2 VISUAL ENHANCEMENTS — Real HTML selector targeting
   These target ACTUAL class names in index.html (camelCase)
   to apply mockup visual improvements to real elements.
   ============================================================ */

/* --- Enhanced Table Styling (targets .tableWrap table) --- */
.tableWrap table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-sm);
}

.tableWrap table thead th {
  text-align: left;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 14px 16px;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.08);
  background: rgba(var(--black-rgb), 0.15);
  white-space: nowrap;
}
.tableWrap table thead th.right,
.tableWrap table thead th.cellActions {
  text-align: right;
}

.tableWrap table tbody td {
  padding: 14px 16px;
  border-bottom: 1px solid rgba(var(--white-rgb), 0.04);
  font-size: var(--text-sm);
  vertical-align: middle;
  transition: background var(--duration-fast), box-shadow var(--duration-fast);
}

.tableWrap table tbody tr:hover td {
  background: rgba(var(--accent-rgb),0.06);
}

.tableWrap table tbody tr:hover td:first-child {
  box-shadow: var(--shadow-inset-accent);
}

.tableWrap table tbody tr:last-child td {
  border-bottom: none;
}

/* --- Status Badge Pill Styling (targets .statusBadge) --- */
.statusBadge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  letter-spacing: 0.01em;
}

.statusBadge::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.statusBadge.active {
  background: rgba(var(--status-ok-rgb), 0.12);
  color: var(--success-text);
}
.statusBadge.active::before {
  background: var(--success-text);
}

.statusBadge.pending {
  background: rgba(var(--amber-rgb), 0.12);
  color: var(--warning-text);
}
.statusBadge.pending::before {
  background: var(--warning-text);
}

.statusBadge.inactive,
.statusBadge.expired {
  background: rgba(var(--data-rose-rgb), 0.12);
  color: var(--danger-text);
}
.statusBadge.inactive::before,
.statusBadge.expired::before {
  background: var(--danger-text);
}

/* --- Pane Transitions (smooth fadeUp on tab switch) --- */
.section-pane:not(.hidden),
.candidate-pane:not(.hidden) {
  animation: fadeUp var(--duration-slow) ease;
}

/* --- Enhanced Section Icons --- */
.sectionIcon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-8);
  background: rgba(var(--accent-rgb),0.10);
  font-size: var(--text-md);
}

/* --- Legacy emptyState alias (migrated → .empty-state) --- */
/* All instances now use .empty-state; kept as fallback for any unmigrated HTML */

.mp-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-8) var(--space-6);
}

.mp-empty-icon {
  font-size: 48px; /* hero scale — hors échelle */
  margin-bottom: var(--space-4);
  line-height: 1;
  filter: drop-shadow(0 4px 12px rgba(var(--accent-rgb),0.25));
  animation: emptyFloat 4s ease-in-out infinite;
  transform-origin: center center;
}

.mp-empty-state h3 {
  font-size: var(--text-lg);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

.mp-empty-state p {
  font-size: var(--text-base);
  color: var(--muted);
  max-width: 380px;
  line-height: 1.6;
}

.msg-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-8) var(--space-6);
  min-height: 300px;
}

/* --- Enhanced CardHead Actions (select/input styling) --- */
.cardHead .actions select,
.cardHead .actions input[type="search"],
.cardHead .actions input[type="text"] {
  height: 38px;
  border-radius: var(--radius-sm);
  background: rgba(var(--black-rgb), 0.20);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--text-xs);
  font-family: var(--font-body);
  padding: 0 12px;
  outline: none;
  transition: border-color var(--duration-base), box-shadow var(--duration-base);
}

.cardHead .actions select:focus,
.cardHead .actions input[type="search"]:focus,
.cardHead .actions input[type="text"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.12);
}

/* --- Dashboard Section Enhancement --- */
.dashboardSection {
  position: relative;
}

.dashboardSection:hover .sectionIcon {
  background: rgba(var(--accent-rgb),0.18);
  transition: background var(--duration-base);
}

/* --- Stat Card data-color borders (applied to all statCard) --- */
.statCard[data-color]::before {
  opacity: 1 !important;
}

.statCard[data-color="indigo"]::before {
  background: var(--grad-indigo) !important;
}

.statCard[data-color="cyan"]::before {
  background: var(--grad-cyan) !important;
}

.statCard[data-color="amber"]::before {
  background: var(--grad-amber) !important;
}

.statCard[data-color="green"]::before {
  background: var(--grad-green) !important;
}

.statCard[data-color="purple"]::before {
  background: var(--grad-purple) !important;
}

.statCard[data-color="rose"]::before {
  background: var(--grad-rose) !important;
}

/* --- Admin pills real targets --- */
.pill.warn,
.pill.warning {
  background: rgba(var(--amber-rgb), 0.12);
  color: var(--warning-text);
}

.pill.ok,
.pill.success {
  background: rgba(var(--status-ok-rgb), 0.12);
  color: var(--success-text);
}

/* --- Pipeline Summary Enhancement --- */
.pipelineSummary {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.pipelineStage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-4) var(--space-3);
  border-radius: var(--radius-12);
  border: 1px solid var(--border);
  background: var(--card);
  transition: all var(--duration-base);
}

.pipelineStage:hover {
  box-shadow: var(--shadow-hover);
}

.pipelineStage.success {
  border-color: rgba(var(--emerald-rgb), 0.25);
}
.pipelineStage.success:hover {
  background: rgba(var(--emerald-rgb), 0.06);
}
.pipelineStage.success .stageCount {
  color: var(--success-text);
}

.pipelineStage.warning {
  border-color: rgba(var(--amber-rgb), 0.25);
}
.pipelineStage.warning:hover {
  background: rgba(var(--amber-rgb), 0.06);
}
.pipelineStage.warning .stageCount {
  color: var(--warning-text);
}

.pipelineStage.danger {
  border-color: rgba(var(--data-rose-rgb), 0.25);
}
.pipelineStage.danger:hover {
  background: rgba(var(--data-rose-rgb), 0.06);
}
.pipelineStage.danger .stageCount {
  color: var(--danger-text);
}

.stageCount {
  font-size: var(--text-3xl);
  font-weight: 700;
  font-family: var(--font-mono);
  line-height: 1;
}

.stageLabel {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 6px;
  font-weight: 500;
}

/* --- Quick Action Cards Enhancement --- */
.quickAction {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: var(--space-4);
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid var(--border);
  border-radius: var(--radius-12);
  cursor: pointer;
  transition: all var(--duration-base);
}

.quickAction:hover {
  border-color: var(--border-accent);
  background: rgba(var(--accent-rgb),0.04);
  box-shadow: var(--shadow-hover);
}

.quickAction.primary {
  border-color: rgba(var(--accent-rgb),0.25);
  background: rgba(var(--accent-rgb),0.04);
}

.quickActionIcon {
  font-size: var(--text-3xl);
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--accent-rgb),0.08);
  border-radius: var(--radius-12);
  flex-shrink: 0;
}

.quickAction.primary .quickActionIcon {
  background: rgba(var(--accent-rgb),0.15);
}

.quickActionText h4 {
  font-size: var(--text-base);
  font-weight: 700;
  margin: 0 0 4px;
}

.quickActionText p {
  font-size: var(--text-sm);
  color: var(--muted);
  margin: 0;
  line-height: 1.4;
}

/* --- Profile Progress Enhancement --- */
.progressHeader {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.progressTitle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-md);
  font-weight: 600;
}

.progressIcon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-8);
  background: rgba(var(--accent-rgb),0.10);
  font-size: var(--text-base);
}

.progressBar {
  height: 8px;
  background: rgba(var(--white-rgb), 0.08);
  border-radius: var(--radius-4);
  overflow: hidden;
}

.progressFill {
  height: 100%;
  border-radius: var(--radius-4);
  background: linear-gradient(90deg, var(--primary), var(--accent2));
  transition: width var(--duration-slow) var(--ease-default);
  position: relative;
}

.progressFill::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(var(--white-rgb), 0.2), transparent);
  animation: shimmer 2s infinite;
}

/* --- Mentor Dashboard Sections Grid --- */
.mentorDashboardSections {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

@media (max-width: 768px) {
  .mentorDashboardSections {
    grid-template-columns: 1fr;
  }
}

/* --- Mentor Dashboard Stats Grid --- */
.mentorDashboardStatsGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-top: var(--space-3);
}

/* --- Mentor Stat Card --- */
.mentorStatCard {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-5) var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  text-align: center;
  cursor: pointer;
  transition: all var(--duration-slow);
  position: relative;
  overflow: hidden;
}

.mentorStatCard::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--primary), var(--accent-dark));
  opacity: 0;
  transition: opacity var(--duration-slow);
}

.mentorStatCard:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-card-hover);
}

.mentorStatCard:hover::before {
  opacity: 1;
}

.mentorStatIcon {
  font-size: var(--text-3xl);
  margin-bottom: var(--space-2);
}

.mentorStatValue {
  font-size: var(--text-3xl);
  font-weight: 700;
  line-height: 1.1;
  font-family: var(--font-mono);
}

.mentorStatValue.accent { color: var(--accent); }
.mentorStatValue.accent2 { color: var(--accent2); }

.mentorStatLabel {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 6px;
  font-weight: 500;
}

/* Mentor stat card data-color (always-visible top border) */
.mentorStatCard[data-color]::before {
  opacity: 1;
}
.mentorStatCard[data-color="green"]::before {
  background: var(--grad-green);
}
.mentorStatCard[data-color="cyan"]::before {
  background: var(--grad-cyan);
}
.mentorStatCard[data-color="indigo"]::before {
  background: var(--grad-indigo);
}
.mentorStatCard[data-color="amber"]::before {
  background: var(--grad-amber);
}

/* ============================
   AI DISCLAIMER (RGPD Art. 22)
   ============================ */
.aiDisclaimer {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: 10px 14px;
  margin: var(--space-3) 0;
  border-radius: var(--radius-md, 8px);
  background: var(--status-info-bg, rgba(var(--primary-rgb), 0.08));
  border-left: 3px solid var(--status-info);
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--text-secondary);
}
.aiDisclaimerIcon {
  flex-shrink: 0;
  font-size: var(--text-md);
  color: var(--status-info);
  margin-top: 1px;
}

/* === Mobile spacing reduction — less scrolling on small screens === */
@media (max-width: 768px) {
  .card {
    padding: var(--space-4);
    margin-top: var(--space-3);
  }
  .card-head {
    padding: 14px 16px;
  }
  .card-body {
    padding: 14px 16px;
  }
  .modal {
    padding: var(--space-3);
  }
  .modalCard {
    padding: var(--space-4);
  }
  h2, .section-title {
    margin-top: var(--space-4);
    margin-bottom: 10px;
  }
}

/* ============================================================
   Universal Search — Ctrl+K Omnibar (Alpha 25.19)
   ============================================================ */

/* Wrapper in topbar — hidden on desktop when sidebar provides search hint */
.search-bar-wrap {
  position: relative;
  display: none;
  align-items: center;
  flex: 0 1 340px;
  margin: 0 12px;
}

/* Mobile toggle button — hidden on desktop */
.search-toggle-btn {
  display: none;
  background: none;
  border: none;
  color: var(--text);
  font-size: var(--text-lg);
  padding: 6px;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--duration-base);
}
.search-toggle-btn:hover {
  opacity: 1;
}

/* Input wrapper */
.search-input-wrap {
  display: flex;
  align-items: center;
  width: 100%;
  height: 34px;
  box-sizing: border-box;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 10px;
  gap: var(--space-2);
  transition: border-color var(--duration-base), box-shadow var(--duration-base);
}
.search-input-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb),0.18);
}

/* Search icon inside input */
.search-input-icon {
  font-size: var(--text-base);
  opacity: 0.5;
  flex-shrink: 0;
  line-height: 1;
}

/* Input field */
.search-input-wrap input.search-input,
.search-input-wrap input.search-input[type="text"] {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  min-width: 0;
  height: 32px;
  padding: 0;
  margin: 0;
  box-shadow: none;
  border-radius: 0;
}
.search-input::placeholder {
  color: var(--muted);
  opacity: 0.5;
}

/* Kbd shortcut badge */
.search-kbd {
  display: inline-flex;
  align-items: center;
  padding: 2px 6px;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--muted);
  background: rgba(var(--white-rgb), 0.06);
  border: 1px solid rgba(var(--white-rgb), 0.08);
  border-radius: var(--radius-4);
  line-height: 1;
  flex-shrink: 0;
  opacity: 0.6;
}

/* ── Dropdown ──────────────────────────────────────────── */
.search-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  min-width: 320px;
  max-height: 420px;
  background: var(--bg-popup);
  -webkit-backdrop-filter: blur(32px);
  backdrop-filter: blur(32px);
  border: 1px solid rgba(var(--accent-rgb),0.18);
  border-radius: var(--radius);
  box-shadow: 0 18px 52px rgba(var(--black-rgb), 0.55), 0 0 0 1px rgba(var(--white-rgb), 0.04);
  z-index: var(--z-popover);
  overflow: hidden;
}

.search-dropdown-list {
  overflow-y: auto;
  max-height: 400px;
  padding: 6px 0;
}

/* Category header */
.search-category-header {
  padding: 10px 14px 5px;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-light);
  border-bottom: 1px solid rgba(var(--white-rgb), 0.04);
}

/* Result item */
.search-result {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  cursor: pointer;
  transition: background var(--duration-fast);
  border-bottom: 1px solid rgba(var(--white-rgb), 0.04);
}
.search-result:last-child {
  border-bottom: none;
}
.search-result:hover,
.search-result-active {
  background: rgba(var(--accent-rgb),0.15);
}

.search-result-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-8);
  background: rgba(var(--accent-rgb),0.18);
  border: 1px solid rgba(var(--accent-rgb),0.12);
  font-size: var(--text-md);
  flex-shrink: 0;
}

.search-result-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.search-result-title {
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 6px;
}

.search-result-subtitle {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

/* Nav badge */
.search-badge-nav {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--accent-light);
  background: rgba(var(--accent-rgb),0.18);
  border-radius: var(--radius-4);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}

/* Empty / hint */
.search-empty {
  padding: 24px 14px;
  text-align: center;
  font-size: var(--text-sm);
  color: var(--fg-muted);
}

/* ── Scroll-to highlight pulse ─────────────────────────── */
/* (removed) search-highlight-pulse — universal-search deep-link landing now uses the shared
   premium .flow-spotlight (effects.css), same as notifications. */

/* ── Light theme ───────────────────────────────────────── */
body.light-theme .search-input-wrap,
body.bento-theme .search-input-wrap, body.atsiq-theme .search-input-wrap {
  background: rgba(var(--lavender-rgb), 0.7);
  border-color: rgba(var(--status-muted-rgb), 0.18);
}
body.light-theme .search-input-wrap:focus-within,
body.bento-theme .search-input-wrap:focus-within, body.atsiq-theme .search-input-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb),0.14);
}
body.light-theme .search-input,
body.bento-theme .search-input, body.atsiq-theme .search-input {
  color: var(--fg);
}
body.light-theme .search-input::placeholder,
body.bento-theme .search-input::placeholder, body.atsiq-theme .search-input::placeholder {
  color: var(--fg-muted);
}
body.light-theme .search-kbd,
body.bento-theme .search-kbd, body.atsiq-theme .search-kbd {
  background: rgba(var(--black-rgb), 0.04);
  border-color: rgba(var(--black-rgb), 0.08);
  color: var(--fg-muted);
}
body.light-theme .search-dropdown,
body.bento-theme .search-dropdown, body.atsiq-theme .search-dropdown {
  background: linear-gradient(168deg, rgba(var(--white-rgb), 0.95) 0%, rgba(var(--lavender-rgb), 0.99) 100%);
  border-color: rgba(var(--status-muted-rgb), 0.22);
  box-shadow: 0 14px 44px rgba(var(--slate-dark-rgb), 0.18), 0 0 0 1px rgba(var(--accent-rgb),0.06);
}
body.light-theme .search-category-header,
body.bento-theme .search-category-header, body.atsiq-theme .search-category-header {
  color: var(--accent-dark);
  border-bottom-color: rgba(var(--black-rgb), 0.06);
}
body.light-theme .search-result,
body.bento-theme .search-result, body.atsiq-theme .search-result {
  border-bottom-color: rgba(var(--black-rgb), 0.05);
}
body.light-theme .search-result:hover,
body.bento-theme .search-result:hover,
body.light-theme .search-result-active,
body.bento-theme .search-result-active, body.atsiq-theme .search-result:hover, body.atsiq-theme .search-result-active {
  background: rgba(var(--accent-rgb),0.08);
}
body.light-theme .search-result-icon,
body.bento-theme .search-result-icon, body.atsiq-theme .search-result-icon {
  background: rgba(var(--accent-rgb),0.10);
  border-color: rgba(var(--accent-rgb),0.08);
}
body.light-theme .search-result-title,
body.bento-theme .search-result-title, body.atsiq-theme .search-result-title {
  color: var(--fg);
}
body.light-theme .search-result-subtitle,
body.bento-theme .search-result-subtitle, body.atsiq-theme .search-result-subtitle {
  color: var(--fg-muted);
}
body.light-theme .search-badge-nav,
body.bento-theme .search-badge-nav, body.atsiq-theme .search-badge-nav {
  color: var(--accent-dark);
  background: rgba(var(--accent-rgb),0.10);
}
body.light-theme .search-empty,
body.bento-theme .search-empty, body.atsiq-theme .search-empty {
  color: var(--fg-muted);
}

/* ── Mobile (≤768px) ───────────────────────────────────── */
@media (max-width: 768px) {
  .search-bar-wrap {
    display: flex;
    flex: 0 0 auto;
    margin: 0 4px;
  }
  .search-toggle-btn {
    display: flex;
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
  }
  .search-input-wrap {
    display: none;
  }
  .search-kbd {
    display: none;
  }

  /* Expanded state: full-screen overlay */
  .search-bar-wrap.search-expanded {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-toast);
    flex-direction: column;
    background: var(--bg1);
    margin: 0;
    padding: var(--space-3);
  }
  .search-bar-wrap.search-expanded .search-toggle-btn {
    display: none;
  }
  .search-bar-wrap.search-expanded .search-input-wrap {
    display: flex;
    height: 44px;
    border-radius: var(--radius-12);
  }
  .search-bar-wrap.search-expanded .search-dropdown {
    position: relative;
    top: var(--space-2);
    min-width: unset;
    max-height: calc(100vh - 80px);
    max-height: calc(100dvh - 80px); /* iOS Safari URL bar fix */
    border-radius: var(--radius-12);
  }
  .search-bar-wrap.search-expanded .search-dropdown-list {
    max-height: calc(100vh - 100px);
    max-height: calc(100dvh - 100px); /* iOS Safari URL bar fix */
  }
}


/* ══════════════════════════════════════════════════════════════
   Universal Dropzone Component (.ct-dz)
   ══════════════════════════════════════════════════════════════ */

/* Container — frosted glass with atmospheric depth */
.ct-dz {
  border: 1.5px dashed rgba(var(--primary-rgb), 0.20);
  border-radius: var(--radius);
  background:
    radial-gradient(ellipse 80% 60% at 50% 120%, rgba(var(--primary-rgb), 0.06) 0%, transparent 70%),
    rgba(var(--primary-rgb), 0.02);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease-default), background var(--duration-base) var(--ease-default), box-shadow var(--duration-base) var(--ease-default);
  position: relative;
  overflow: hidden;
}
/* Inner top highlight */
.ct-dz::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(var(--primary-rgb), 0.04) 0%, transparent 40%);
  pointer-events: none;
}
.ct-dz:hover {
  border-color: rgba(var(--primary-rgb), 0.35);
  background:
    radial-gradient(ellipse 80% 60% at 50% 120%, rgba(var(--primary-rgb), 0.09) 0%, transparent 70%),
    rgba(var(--primary-rgb), 0.04);
  box-shadow: var(--shadow-hover);
}

/* Drag-over state — animated border + glow */
.ct-dz.ct-dz-dragover {
  border-color: var(--accent-light);
  border-style: solid;
  background:
    radial-gradient(ellipse 90% 70% at 50% 100%, rgba(var(--accent2-rgb), 0.08) 0%, transparent 60%),
    rgba(var(--primary-rgb), 0.07);
  box-shadow:
    0 0 28px rgba(var(--primary-rgb), 0.15),
    inset 0 0 40px rgba(var(--primary-rgb), 0.04),
    0 0 0 1px rgba(var(--primary-rgb), 0.12);
  animation: ct-dz-glow-pulse 1.6s ease-in-out infinite;
  transform: scale(1.01);
}

/* Reject animation */
.ct-dz.ct-dz-reject {
  border-color: var(--status-danger) !important;
  background: rgba(var(--status-danger-rgb), 0.06) !important;
  box-shadow: 0 0 16px rgba(var(--status-danger-rgb), 0.12) !important;
  animation: ct-dz-shake 0.4s ease-in-out;
}

/* Success flash */
.ct-dz.ct-dz-success {
  border-color: var(--status-ok) !important;
  box-shadow:
    0 0 24px rgba(var(--status-ok-rgb), 0.18),
    inset 0 0 20px rgba(var(--status-ok-rgb), 0.04);
  animation: ct-dz-success-flash 1s ease-out;
}

/* Default content */
.ct-dz-default {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-6) var(--space-4);
  text-align: center;
  position: relative;
  z-index: var(--z-decoration);
}
.ct-dz-default.hidden { display: none; }

.ct-dz-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(var(--primary-rgb), 0.35);
  margin-bottom: var(--space-1);
  transition: color var(--duration-base) var(--ease-default), transform var(--duration-base) var(--ease-default), filter var(--duration-base) var(--ease-default);
}
.ct-dz:hover .ct-dz-icon {
  color: var(--accent-light);
  transform: translateY(-2px);
  filter: drop-shadow(0 4px 8px rgba(var(--primary-rgb), 0.20));
}
.ct-dz.ct-dz-dragover .ct-dz-icon {
  color: var(--accent2-light);
  filter: drop-shadow(0 6px 12px rgba(var(--accent2-rgb), 0.25));
  animation: ct-dz-icon-bounce 0.8s ease-in-out infinite;
}
@keyframes ct-dz-icon-bounce {
  0%, 100% { transform: translateY(-4px) scale(1.05); }
  50%      { transform: translateY(-8px) scale(1.08); }
}
.ct-dz-label {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
  opacity: 0.72;
  transition: opacity var(--duration-base);
}
.ct-dz:hover .ct-dz-label { opacity: 0.90; }
.ct-dz-hint {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--muted);
  opacity: 0.45;
  letter-spacing: 0.04em;
}

/* File preview card */
.ct-dz-preview {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  position: relative;
  z-index: var(--z-decoration);
  animation: ct-dz-fade-in var(--duration-slow) var(--ease-default);
}
.ct-dz-preview.hidden { display: none; }

.ct-dz-file-icon {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-xs);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  flex-shrink: 0;
  transition: transform var(--duration-base) var(--ease-default);
}
.ct-dz-preview:hover .ct-dz-file-icon { transform: scale(1.04); }

.ct-dz-file-icon.pdf {
  background: rgba(var(--status-danger-rgb), 0.12);
  color: var(--status-danger);
  box-shadow: 0 2px 8px rgba(var(--status-danger-rgb), 0.10);
}
.ct-dz-file-icon.docx {
  background: rgba(var(--status-info-rgb), 0.12);
  color: var(--status-info);
  box-shadow: 0 2px 8px rgba(var(--status-info-rgb), 0.10);
}
.ct-dz-file-icon.img {
  background: rgba(var(--accent-purple-rgb), 0.12);
  color: var(--accent-purple);
  box-shadow: 0 2px 8px rgba(var(--accent-purple-rgb), 0.10);
}
.ct-dz-file-icon.audio {
  background: rgba(var(--accent2-rgb), 0.12);
  color: var(--accent2);
  box-shadow: 0 2px 8px rgba(var(--accent2-rgb), 0.10);
}
.ct-dz-file-icon.txt {
  background: rgba(var(--primary-rgb), 0.10);
  color: var(--fg-muted);
  box-shadow: 0 2px 8px rgba(var(--primary-rgb), 0.06);
}

.ct-dz-file-info { flex: 1; min-width: 0; }
.ct-dz-file-name {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ct-dz-file-size {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--fg-muted);
  margin-top: 2px;
  letter-spacing: 0.02em;
}

.ct-dz-file-remove {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  background: rgba(var(--primary-rgb), 0.06);
  color: var(--fg-muted);
  font-size: var(--text-base);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--duration-base) var(--ease-default);
  flex-shrink: 0;
}
.ct-dz-file-remove:hover {
  background: rgba(var(--status-danger-rgb), 0.12);
  border-color: rgba(var(--status-danger-rgb), 0.20);
  color: var(--status-danger);
  transform: scale(1.08);
}

/* Image thumbnail preview */
.ct-dz-thumb {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
  z-index: var(--z-decoration);
  animation: ct-dz-fade-in var(--duration-slow) ease;
}
.ct-dz-thumb.hidden { display: none; }
.ct-dz-thumb-img {
  max-width: 100%;
  max-height: 140px;
  border-radius: var(--radius-sm);
  object-fit: contain;
  box-shadow: var(--shadow-sm);
}
.ct-dz-thumb-remove {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
}

/* ── Styled file input — turns plain <input type="file"> into a mini dropzone look ── */
.field input[type="file"],
.modalBody input[type="file"] {
  display: block;
  width: 100%;
  padding: 14px 16px;
  border: 1.5px dashed rgba(var(--primary-rgb), 0.2);
  border-radius: var(--radius);
  background: rgba(var(--primary-rgb), 0.02);
  color: var(--text);
  font-size: var(--text-sm);
  font-family: var(--font-body);
  cursor: pointer;
  transition: border-color var(--duration-slow) var(--ease-default), background var(--duration-slow) var(--ease-default), box-shadow var(--duration-slow) var(--ease-default);
}
.field input[type="file"]:hover,
.modalBody input[type="file"]:hover {
  border-color: rgba(var(--primary-rgb), 0.35);
  background: rgba(var(--primary-rgb), 0.04);
  box-shadow: 0 0 12px rgba(var(--primary-rgb), 0.06);
}
.field input[type="file"]:focus,
.modalBody input[type="file"]:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.12);
}
/* File input button styling (WebKit) */
.field input[type="file"]::file-selector-button,
.modalBody input[type="file"]::file-selector-button {
  padding: 6px 14px;
  margin-right: var(--space-3);
  border: 1px solid rgba(var(--primary-rgb), 0.2);
  border-radius: var(--radius-sm);
  background: rgba(var(--primary-rgb), 0.08);
  color: var(--primary);
  font-size: var(--text-xs);
  font-weight: 600;
  font-family: var(--font-body);
  cursor: pointer;
  transition: background var(--duration-base) var(--ease-default);
}
.field input[type="file"]::file-selector-button:hover,
.modalBody input[type="file"]::file-selector-button:hover {
  background: rgba(var(--primary-rgb), 0.15);
}

/* Compact variant (for modal fields) */
.ct-dz--compact .ct-dz-default {
  padding: var(--space-4) var(--space-3);
}
.ct-dz--compact .ct-dz-icon svg { width: 22px; height: 22px; }
.ct-dz--compact .ct-dz-label { font-size: var(--text-xs); }
.ct-dz--compact .ct-dz-preview { padding: var(--space-2) var(--space-3); }
.ct-dz--compact .ct-dz-file-icon { width: 32px; height: 32px; font-size: var(--text-2xs); }
.ct-dz--compact .ct-dz-thumb-img { max-height: 100px; }

/* Animations */
@keyframes ct-dz-glow-pulse {
  0%, 100% {
    box-shadow:
      0 0 28px rgba(var(--primary-rgb), 0.12),
      inset 0 0 40px rgba(var(--primary-rgb), 0.03),
      0 0 0 1px rgba(var(--primary-rgb), 0.10);
  }
  50% {
    box-shadow:
      0 0 36px rgba(var(--primary-rgb), 0.22),
      inset 0 0 50px rgba(var(--primary-rgb), 0.06),
      0 0 0 1px rgba(var(--primary-rgb), 0.18);
  }
}
@keyframes ct-dz-shake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-5px); }
  30% { transform: translateX(5px); }
  45% { transform: translateX(-4px); }
  60% { transform: translateX(3px); }
  75% { transform: translateX(-2px); }
  90% { transform: translateX(1px); }
}
@keyframes ct-dz-fade-in {
  from { opacity: 0; transform: scale(0.96) translateY(4px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes ct-dz-success-flash {
  0% {
    border-color: var(--status-ok);
    box-shadow: 0 0 30px rgba(var(--status-ok-rgb), 0.25), inset 0 0 20px rgba(var(--status-ok-rgb), 0.06);
    transform: scale(1.01);
  }
  50% {
    transform: scale(1);
  }
  100% {
    border-color: rgba(var(--primary-rgb), 0.20);
    box-shadow: none;
    transform: scale(1);
  }
}

/* Responsive */
@media (max-width: 480px) {
  .ct-dz-default { padding: var(--space-4) var(--space-2); }
  .ct-dz-preview { padding: var(--space-2); gap: var(--space-2); }
  .ct-dz-file-icon { width: 32px; height: 32px; font-size: var(--text-2xs); }
}

/* Light theme overrides */
body.light-theme .ct-dz,
body.bento-theme .ct-dz, body.atsiq-theme .ct-dz {
  background:
    radial-gradient(ellipse 80% 60% at 50% 120%, rgba(var(--primary-rgb), 0.04) 0%, transparent 70%),
    var(--card);
  border-color: rgba(var(--slate-dark-rgb), 0.18);
}
body.light-theme .ct-dz::before,
body.bento-theme .ct-dz::before, body.atsiq-theme .ct-dz::before {
  background: linear-gradient(180deg, rgba(var(--primary-rgb), 0.03) 0%, transparent 40%);
}
body.light-theme .ct-dz:hover,
body.bento-theme .ct-dz:hover, body.atsiq-theme .ct-dz:hover {
  background:
    radial-gradient(ellipse 80% 60% at 50% 120%, rgba(var(--primary-rgb), 0.06) 0%, transparent 70%),
    var(--card2);
}
body.light-theme .ct-dz.ct-dz-dragover,
body.bento-theme .ct-dz.ct-dz-dragover, body.atsiq-theme .ct-dz.ct-dz-dragover {
  background:
    radial-gradient(ellipse 90% 70% at 50% 100%, rgba(var(--accent2-rgb), 0.06) 0%, transparent 60%),
    var(--card);
}

/* ============================================================
   Phase 1B — .actions alias for modal footers
   Gives .actions inside .modalCard the same visual as .modalActions
   ============================================================ */
.modalCard > .actions:last-child {
  border-top: 1px solid var(--border);
  padding: var(--space-4) var(--space-6);
  margin: 0 -24px -24px;
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}
body.light-theme .modalCard > .actions:last-child,
body.bento-theme .modalCard > .actions:last-child, body.atsiq-theme .modalCard > .actions:last-child {
  border-top-color: rgba(var(--accent-rgb),0.12);
}
@media (max-width: 600px) {
  .modalCard > .actions:last-child {
    flex-direction: column;
  }
  .modalCard > .actions:last-child .btn {
    width: 100%;
  }
}

/* ============================================================
   Legal content — scrollable modal for Terms / Privacy
   ============================================================ */
.modalCard.legal {
  width: min(720px, 96vw);
}
.legalContent {
  overflow-y: auto;
  max-height: calc(80vh - 160px);
  padding-right: var(--space-1);
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--text);
}

/* ============================================================
   Auth modal utility classes
   ============================================================ */
.authForm {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.authGrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
@media (max-width: 480px) {
  .authGrid { grid-template-columns: 1fr; }
}
.authDivider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-2) 0;
  color: var(--muted);
  font-size: var(--text-sm);
}
.authDivider::before,
.authDivider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Auth modal — inline style extraction */
.authLinkCenter { text-align: center; margin-top: 14px; }
.authLinkCenter:first-of-type { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid rgba(var(--white-rgb), 0.06); }
.authToggleLink { font-size: var(--text-sm); color: var(--accent); text-decoration: none; }
.authToggleLink:hover { text-decoration: underline; }
.authToggleLink.subtle { opacity: 0.6; color: var(--muted); }

/* MOB-002: Ensure auth interactive elements meet 44px minimum tap target on mobile */
@media (max-width: 768px) {
  .authTab {
    padding: 14px 16px;
    min-height: 44px;
  }
  .authToggleLink {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: var(--space-2) var(--space-3);
  }
}

.authSubPane { margin-top: var(--space-3); }
.verifySection {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-8);
}
.codeInput {
  text-align: center;
  font-size: 1.2em;
  letter-spacing: 0.3em;
}
.resetCodeInput {
  text-transform: uppercase;
  letter-spacing: 2px;
  font-family: var(--font-mono, monospace);
}
.formHintDanger { color: var(--danger-text); min-height: 18px; }
.inputDisabled { opacity: 0.5; cursor: not-allowed; }
.hintCenter { margin-top: var(--space-2); text-align: center; }
.hintSmall { font-size: var(--text-xs); margin-bottom: var(--space-3); }

/* Mobile tabs — prevent overflow */
@media (max-width: 480px) {
  .tabs {
    gap: var(--space-1);
  }
  .tab {
    padding: 8px 10px;
    font-size: var(--text-sm);
  }
}

/* Tables — horizontal scroll on mobile */
@media (max-width: 600px) {
  .tableWrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .tableWrap table {
    min-width: 500px;
  }
}

/* Upload row — stack on mobile */
@media (max-width: 480px) {
  .uploadRow {
    flex-direction: column;
    align-items: stretch;
  }
}

/* ============================================================
   Command Palette Modal — T16 Phase A
   Centered modal overlay (Linear-style), replaces dropdown.
   ============================================================ */

.search-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 15vh;
}

.search-modal.hidden {
  display: none;
}

.search-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(var(--black-rgb), 0.55);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

.search-modal__content {
  position: relative;
  width: 560px;
  max-width: calc(100% - var(--space-6));
  max-height: 60vh;
  background: var(--bg-opaque);
  border: 1px solid var(--border-accent);
  border-radius: var(--radius-lg);
  box-shadow: 0 25px 60px rgba(var(--black-rgb), 0.4), 0 0 40px rgba(var(--accent-rgb), 0.08);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: searchModalIn var(--duration-fast) ease-out;
}

@keyframes searchModalIn {
  from {
    opacity: 0;
    transform: scale(0.96) translateY(-8px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

.search-modal__input-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}

.search-modal__input-icon {
  font-size: var(--text-lg);
  color: var(--fg-muted);
  flex-shrink: 0;
}

.search-modal__input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  font-size: var(--text-md);
  font-family: var(--font-body);
  color: var(--text);
  padding: 0;
}

.search-modal__input::placeholder {
  color: var(--fg-muted);
}

.search-modal__kbd {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  padding: 2px 6px;
  border-radius: var(--radius-4);
  background: rgba(var(--white-rgb), 0.06);
  border: 1px solid rgba(var(--white-rgb), 0.1);
  color: var(--fg-muted);
  flex-shrink: 0;
}

.search-modal__results {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) 0;
}

.search-modal__list {
  padding: 0 var(--space-2);
}

.search-modal__recent-header {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--fg-muted);
  padding: var(--space-2) var(--space-3);
}

/* Search result items (shared between dropdown and modal) */
.search-modal__list .search-category-header {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--fg-muted);
  padding: var(--space-3) var(--space-3) var(--space-1);
}

.search-modal__list .search-result {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--duration-fast);
}

.search-modal__list .search-result:hover,
.search-modal__list .search-result.search-result-active {
  background: var(--card-hover);
}

.search-modal__list .search-result-icon {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-xs);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-base);
  background: var(--surface);
  flex-shrink: 0;
}

.search-modal__list .search-result-title {
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--text);
}

.search-modal__list .search-result-subtitle {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  margin-top: 1px;
}

.search-modal__list .search-badge-nav {
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: 1px 5px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.14);
  color: var(--accent);
  margin-left: var(--space-2);
}

.search-modal__list .search-empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  color: var(--fg-muted);
  font-size: var(--text-sm);
}

.search-modal__list .search-result-shortcut {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  padding: 1px 5px;
  border-radius: var(--radius-3);
  background: rgba(var(--white-rgb), 0.06);
  border: 1px solid rgba(var(--white-rgb), 0.1);
  color: var(--fg-muted);
  margin-left: auto;
  flex-shrink: 0;
}

/* ── Toast Action Button (Phase C1) ── */
.toast-action-btn {
  display: inline-block;
  margin-left: var(--space-3);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-xs);
  background: rgba(var(--white-rgb), 0.15);
  color: inherit;
  border: 1px solid rgba(var(--white-rgb), 0.2);
  font-size: var(--text-sm);
  cursor: pointer;
  font-weight: 600;
  transition: background var(--duration-fast);
  white-space: nowrap;
}
.toast-action-btn:hover { background: rgba(var(--white-rgb), 0.25); }

/* Light theme */
body.light-theme .search-modal__backdrop,
body.bento-theme .search-modal__backdrop, body.atsiq-theme .search-modal__backdrop {
  background: rgba(var(--lavender-dark-rgb), 0.6);
}

body.light-theme .search-modal__content,
body.bento-theme .search-modal__content, body.atsiq-theme .search-modal__content {
  background: linear-gradient(170deg, rgba(var(--white-rgb), 0.95) 0%, rgba(var(--lavender-mid-rgb), 0.92) 100%);
  border-color: rgba(var(--status-muted-rgb), 0.24);
  box-shadow: 0 25px 60px rgba(var(--slate-dark-rgb), 0.20), 0 10px 30px rgba(var(--black-rgb), 0.08);
}

body.light-theme .search-modal__kbd,
body.bento-theme .search-modal__kbd,
body.light-theme .search-modal__list .search-result-shortcut,
body.bento-theme .search-modal__list .search-result-shortcut, body.atsiq-theme .search-modal__kbd, body.atsiq-theme .search-modal__list .search-result-shortcut {
  background: rgba(var(--black-rgb), 0.04);
  border-color: rgba(var(--status-muted-rgb), 0.2);
}

body.light-theme .search-modal__list .search-result:hover,
body.bento-theme .search-modal__list .search-result:hover,
body.light-theme .search-modal__list .search-result.search-result-active,
body.bento-theme .search-modal__list .search-result.search-result-active, body.atsiq-theme .search-modal__list .search-result:hover, body.atsiq-theme .search-modal__list .search-result.search-result-active {
  background: rgba(var(--status-muted-rgb), 0.1);
}

/* === Semantic Search Toggle & Badges === */
.search-semantic-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background: rgba(var(--white-rgb), 0.06);
  border: 1px solid rgba(var(--white-rgb), 0.15);
  color: var(--fg-muted);
  font-size: var(--text-xs);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all var(--duration-fast);
  flex-shrink: 0;
  line-height: 1.3;
  position: relative;
}
.search-semantic-toggle:hover {
  background: rgba(var(--white-rgb), 0.12);
  color: var(--text);
  border-color: rgba(var(--accent-rgb), 0.3);
}
.search-semantic-toggle.active {
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.25), rgba(var(--status-info-rgb), 0.2));
  border-color: rgba(var(--accent-rgb), 0.5);
  color: var(--accent-light);
  box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.15), inset 0 1px 0 rgba(var(--white-rgb), 0.08);
}
.search-semantic-toggle__icon {
  font-size: var(--text-sm);
  transition: transform var(--duration-fast);
}
.search-semantic-toggle.active .search-semantic-toggle__icon {
  transform: scale(1.15);
}

body.light-theme .search-semantic-toggle,
body.bento-theme .search-semantic-toggle, body.atsiq-theme .search-semantic-toggle {
  background: rgba(var(--black-rgb), 0.04);
  border-color: rgba(var(--status-muted-rgb), 0.2);
}
body.light-theme .search-semantic-toggle:hover,
body.bento-theme .search-semantic-toggle:hover, body.atsiq-theme .search-semantic-toggle:hover {
  background: rgba(var(--black-rgb), 0.08);
  border-color: rgba(var(--accent-rgb), 0.3);
}
body.light-theme .search-semantic-toggle.active,
body.bento-theme .search-semantic-toggle.active, body.atsiq-theme .search-semantic-toggle.active {
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.15), rgba(var(--status-info-rgb), 0.1));
  border-color: rgba(var(--accent-rgb), 0.4);
  color: var(--accent);
  box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.1);
}

/* Semantic toggle tooltip — positioned below to avoid modal overflow clipping */
.search-semantic-toggle[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: var(--bg-tooltip, var(--card2));
  color: var(--text);
  font-size: var(--text-xs);
  font-weight: 400;
  line-height: 1.4;
  max-width: 260px;
  white-space: normal;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration-fast);
  z-index: var(--z-tooltip, 1000);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
}
.search-semantic-toggle[data-tooltip]:hover::after,
.search-semantic-toggle[data-tooltip]:focus-visible::after {
  opacity: 1;
}
/* Mobile: ensure tooltip doesn't overflow viewport */
@media (max-width: 480px) {
  .search-semantic-toggle[data-tooltip]::after {
    right: 0;
    max-width: 200px;
    font-size: var(--text-2xs);
  }
}

/* Semantic input flash when toggle activated */
@keyframes semanticFlash {
  0% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.4); }
  50% { box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.15); }
  100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0); }
}
.search-modal__input.semantic-flash {
  animation: semanticFlash 0.6s ease;
}

/* --- Similarity Badge (reusable cross-feature) --- */
.similarity-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: middle;
  white-space: nowrap;
}
.similarity-badge--high {
  background: linear-gradient(135deg, rgba(var(--status-ok-rgb), 0.18), rgba(var(--status-ok-rgb), 0.08));
  color: var(--status-ok);
  border: 1px solid rgba(var(--status-ok-rgb), 0.25);
}
.similarity-badge--medium {
  background: linear-gradient(135deg, rgba(var(--status-warn-rgb), 0.18), rgba(var(--status-warn-rgb), 0.08));
  color: var(--status-warn);
  border: 1px solid rgba(var(--status-warn-rgb), 0.25);
}
.similarity-badge--low {
  background: rgba(var(--status-muted-rgb), 0.12);
  color: var(--status-muted);
  border: 1px solid rgba(var(--status-muted-rgb), 0.2);
}
/* Powered by AI micro-badge */
.ai-micro-badge {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: var(--space-1);
  padding: 1px 5px;
  border-radius: var(--radius-full);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.15), rgba(var(--accent-purple-rgb), 0.12));
  color: var(--accent-light);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  vertical-align: middle;
}
body.bento-theme .ai-micro-badge, body.atsiq-theme .ai-micro-badge {
  color: var(--accent);
}

.search-badge-semantic {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.15);
  color: var(--accent);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: middle;
}

/* === Embeddings Admin Dashboard === */
.embeddings-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

.embeddings-kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
@media (max-width: 900px) {
  .embeddings-kpi-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .embeddings-kpi-grid { grid-template-columns: 1fr; }
}

.embeddings-kpi-card,
.embeddings-types-card {
  padding: var(--space-4);
}

.embeddings-kpi-tile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  border: 1px solid var(--border);
  transition: border-color var(--duration-fast);
}
.embeddings-kpi-tile:hover {
  border-color: rgba(var(--accent-rgb), 0.3);
}
.embeddings-kpi-tile__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  font-size: var(--text-xl);
  flex-shrink: 0;
}
.embeddings-kpi-tile__icon--blue {
  background: rgba(var(--status-info-rgb), 0.12);
  color: var(--status-info);
}
.embeddings-kpi-tile__icon--green {
  background: rgba(var(--status-ok-rgb), 0.12);
  color: var(--status-ok);
}
.embeddings-kpi-tile__icon--amber {
  background: rgba(var(--status-warn-rgb), 0.12);
  color: var(--status-warn);
}
.embeddings-kpi-tile__icon--indigo {
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
}
.embeddings-kpi-tile__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.embeddings-kpi-tile__value {
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--text);
  font-family: var(--font-mono);
  line-height: 1.2;
}
.embeddings-kpi-tile__label {
  font-size: var(--text-xs);
  color: var(--fg-muted);
}

.embeddings-kpi-row {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin: var(--space-4) 0;
}

.embeddings-kpi {
  text-align: center;
  min-width: 80px;
}
.embeddings-kpi__value {
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--text);
  font-family: var(--font-mono);
}
.embeddings-kpi__label {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  margin-top: var(--space-1);
}

.embeddings-meta {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--text-sm);
  color: var(--fg-muted);
  margin-top: var(--space-3);
  flex-wrap: wrap;
}

.embeddings-type-table {
  width: 100%;
  margin-top: var(--space-3);
}
/* Coverage progress bar within type table */
.embeddings-coverage-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.embeddings-coverage-bar__track {
  flex: 1;
  height: 6px;
  border-radius: var(--radius-full);
  background: rgba(var(--white-rgb), 0.06);
  overflow: hidden;
  min-width: 60px;
}
body.light-theme .embeddings-coverage-bar__track,
body.bento-theme .embeddings-coverage-bar__track, body.atsiq-theme .embeddings-coverage-bar__track {
  background: rgba(var(--black-rgb), 0.06);
}
.embeddings-coverage-bar__fill {
  height: 100%;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--accent), rgba(var(--accent-rgb), 0.6));
  transition: width 0.5s ease;
}
.embeddings-coverage-bar__pct {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--fg-muted);
  min-width: 36px;
  text-align: right;
  font-family: var(--font-mono);
}

/* Auto-generate toggle row */
.embeddings-auto-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid var(--border);
  margin-top: var(--space-3);
}
body.light-theme .embeddings-auto-toggle,
body.bento-theme .embeddings-auto-toggle, body.atsiq-theme .embeddings-auto-toggle {
  background: rgba(var(--black-rgb), 0.02);
}
.embeddings-auto-toggle__label {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--text);
}
.embeddings-auto-toggle__hint {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  margin-top: 2px;
}

/* Zero vectors CTA */
.embeddings-zero-cta {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.06), rgba(var(--status-info-rgb), 0.04));
  border: 1px dashed rgba(var(--accent-rgb), 0.25);
}
.embeddings-zero-cta__icon {
  font-size: var(--text-4xl);
  margin-bottom: var(--space-3);
}
.embeddings-zero-cta__text {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text);
  margin-bottom: var(--space-3);
}
.embeddings-zero-cta__sub {
  font-size: var(--text-sm);
  color: var(--fg-muted);
  margin-bottom: var(--space-4);
}

.embeddings-empty {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  color: var(--fg-muted);
}

.embeddings-progress {
  margin: var(--space-3) 0;
  background: rgba(var(--white-rgb), 0.06);
  border-radius: var(--radius-full);
  height: 28px;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
}
.embeddings-progress.hidden { display: none; }
.embeddings-progress__bar {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), rgba(var(--accent-rgb), 0.6));
  border-radius: var(--radius-full);
  transition: width 0.6s ease;
  width: 0%;
}
.embeddings-progress__label {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text);
}

body.light-theme .embeddings-progress,
body.bento-theme .embeddings-progress, body.atsiq-theme .embeddings-progress {
  background: rgba(var(--black-rgb), 0.04);
}

/* === CRM Similar Profiles Section === */
.crm-similar-section {
  margin-bottom: var(--space-4);
}
.crm-similar-section.hidden { display: none; }

.crm-similar-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}
.crm-similar-card h5 {
  margin: 0 0 var(--space-3);
  font-size: var(--text-md);
  color: var(--text);
}

.crm-similar-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
}
@media (max-width: 640px) {
  .crm-similar-grid { grid-template-columns: 1fr; }
}

/* Skeleton cards while loading */
.crm-similar-skeleton {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
}
@media (max-width: 640px) {
  .crm-similar-skeleton { grid-template-columns: 1fr; }
}
.crm-similar-skeleton__card {
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-card);
}

.crm-similar-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.crm-similar-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid var(--border);
  transition: all var(--duration-fast);
  cursor: default;
}
.crm-similar-item:hover {
  background: rgba(var(--white-rgb), 0.07);
  border-color: rgba(var(--accent-rgb), 0.25);
  box-shadow: 0 2px 8px rgba(var(--black-rgb), 0.06);
}

body.light-theme .crm-similar-item,
body.bento-theme .crm-similar-item, body.atsiq-theme .crm-similar-item {
  background: rgba(var(--black-rgb), 0.02);
}
body.light-theme .crm-similar-item:hover,
body.bento-theme .crm-similar-item:hover, body.atsiq-theme .crm-similar-item:hover {
  background: rgba(var(--black-rgb), 0.05);
  box-shadow: 0 2px 8px rgba(var(--black-rgb), 0.04);
}

.crm-similar-item__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}
.crm-similar-item__info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.crm-similar-item__name {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.crm-similar-item__title {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.crm-similar-item__skills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: var(--space-1);
}
.crm-similar-item__skill {
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.1);
  color: var(--accent);
  font-size: var(--text-2xs);
  font-weight: 500;
}
.crm-similar-item__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-1);
}
.crm-similar-item__score {
  flex-shrink: 0;
}

.crm-similar-empty {
  text-align: center;
  padding: var(--space-6) var(--space-4);
  color: var(--fg-muted);
}
.crm-similar-empty__icon {
  font-size: var(--text-4xl); /* icon emoji */
  margin-bottom: var(--space-2);
  opacity: 0.5;
}
.crm-similar-empty p {
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
}
.crm-similar-empty small {
  font-size: var(--text-xs);
}

/* === Semantic Job Recommendations Widget === */
.semantic-recs__subtitle {
  font-size: var(--text-sm);
  color: var(--fg-muted);
  margin-bottom: var(--space-3);
}

.semantic-recs__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Entrance animation for rec cards */
.semantic-rec-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid var(--border);
  transition: all var(--duration-fast);
  animation: flowReveal 0.35s var(--ease-decel) both;
}
.semantic-rec-card:nth-child(2) { animation-delay: 60ms; }
.semantic-rec-card:nth-child(3) { animation-delay: 120ms; }
.semantic-rec-card:nth-child(4) { animation-delay: 180ms; }
.semantic-rec-card:nth-child(5) { animation-delay: 240ms; }

.semantic-rec-card:hover {
  background: rgba(var(--white-rgb), 0.07);
  border-color: rgba(var(--accent-rgb), 0.25);
  box-shadow: 0 2px 8px rgba(var(--black-rgb), 0.06);
}

body.light-theme .semantic-rec-card,
body.bento-theme .semantic-rec-card, body.atsiq-theme .semantic-rec-card {
  background: rgba(var(--black-rgb), 0.02);
}
body.light-theme .semantic-rec-card:hover,
body.bento-theme .semantic-rec-card:hover, body.atsiq-theme .semantic-rec-card:hover {
  background: rgba(var(--black-rgb), 0.05);
  box-shadow: 0 2px 8px rgba(var(--black-rgb), 0.04);
}

.semantic-rec-card__info {
  flex: 1;
  min-width: 0;
}
.semantic-rec-card__title {
  font-weight: 600;
  font-size: var(--text-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text);
}
.semantic-rec-card__sub {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.semantic-rec-card__skills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: var(--space-1);
}
.semantic-rec-card__skill-tag {
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.1);
  color: var(--accent);
  font-size: var(--text-2xs);
  font-weight: 500;
}
.semantic-rec-card__right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}
.semantic-rec-card__score {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.15);
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: 600;
}
/* Empty state for job recs */
.semantic-recs-empty {
  text-align: center;
  padding: var(--space-4) var(--space-3);
  color: var(--fg-muted);
}
.semantic-recs-empty__icon {
  font-size: var(--text-3xl); /* icon emoji */
  margin-bottom: var(--space-2);
  opacity: 0.5;
}
.semantic-recs-empty p {
  font-size: var(--text-sm);
  margin: 0;
}

/* === Referral acknowledgment === */
.referralAck {
  color: var(--success-text);
  font-size: var(--text-xs);
  margin-top: var(--space-1);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.referralAck::before {
  content: '✓';
  font-weight: 600;
}

/* === Turnstile captcha skeleton === */
.turnstileSkeleton {
  width: 300px;
  height: 65px;
  border-radius: var(--radius);
  background: linear-gradient(90deg, var(--card) 25%, var(--card-hover) 50%, var(--card) 75%);
  background-size: 200% 100%;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
}
/* shimmer keyframe removed — unified to skeleton-pulse from effects.css */

/* === Low-credit warning banner === */
.creditWarning {
  background: linear-gradient(135deg, rgba(var(--status-warn-rgb), 0.15), rgba(var(--status-warn-rgb), 0.05));
  border: 1px solid rgba(var(--status-warn-rgb), 0.3);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  color: var(--text);
}
.creditWarning__icon { font-size: var(--text-xl); }
.creditWarning__text { flex: 1; }
.creditWarning__cta {
  white-space: nowrap;
  background: var(--status-warn);
  color: var(--text-inverse);
  border: none;
  border-radius: var(--radius);
  padding: 6px 14px;
  font-size: var(--text-sm);
  cursor: pointer;
  font-weight: 600;
  transition: opacity var(--duration-base);
}
.creditWarning__cta:hover { opacity: 0.85; }

/* === Soft keyboard safe area — Android fixed bottom elements === */
@supports (padding-bottom: env(keyboard-inset-bottom)) {
  .modal .modalActions,
  .modal .modalCard > .actions:last-child {
    padding-bottom: env(keyboard-inset-bottom, 0px);
  }
}

/* ============================================
   FIELD VALIDATION ERRORS — Alpha 25.79
   ============================================ */
.field--error {
  border-color: var(--status-danger) !important;
  box-shadow: 0 0 0 2px rgba(var(--status-danger-rgb), 0.15);
}
.field-error-msg {
  font-size: var(--text-xs);
  color: var(--status-danger);
  margin-top: 2px;
  font-weight: 500;
}

/* ============================================
   CREDIT GATE BANNER — premium inline 402 display
   _showCreditGateBanner(container, cost)
   ============================================ */
.credit-gate-banner {
  position: relative;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

/* Ambient glow — removed (was too aggressive for a credit notice) */
.credit-gate-banner__glow {
  display: none;
}

/* Left accent stripe — subtle info color instead of danger */
.credit-gate-banner__stripe {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--status-info);
  z-index: 2;
}

/* Main content container — toned down */
.credit-gate-banner__content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4) var(--space-3) var(--space-5);
  background: var(--card);
  border: 1px solid var(--border);
  border-left: none;
  border-radius: var(--radius-sm);
}

/* Icon ring — smaller, info-colored instead of danger */
.credit-gate-banner__icon-ring {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: rgba(var(--status-info-rgb), 0.1);
  color: var(--status-info);
}

/* Body text */
.credit-gate-banner__body {
  flex: 1;
  min-width: 0;
}
.credit-gate-banner__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text);
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.credit-gate-banner__detail {
  font-size: var(--text-sm);
  color: var(--muted);
  line-height: 1.5;
  margin-top: 2px;
}
.credit-gate-banner__detail strong {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text);
}

/* Close button */
.credit-gate-banner__close {
  position: absolute;
  z-index: 3;
  top: var(--space-2);
  right: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: transparent;
  border: none;
  border-radius: var(--radius-full);
  color: var(--muted);
  cursor: pointer;
  transition: color var(--duration-fast),
              background var(--duration-fast);
}
.credit-gate-banner__close:hover {
  color: var(--text);
  background: rgba(var(--primary-rgb), 0.08);
}

/* ── Bento / Ink & Gold theme tweaks ── */
body.bento-theme .credit-gate-banner__content, body.atsiq-theme .credit-gate-banner__content {
  background: rgba(var(--paper-rgb), 0.82);
  box-shadow: 0 1px 3px rgba(var(--slate-dark-rgb), 0.06);
}

/* ── Credit gate notice (inline in buy-credits modal) ── */
.credit-gate-notice {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  background: linear-gradient(135deg,
    rgba(var(--fuchsia-rgb), 0.08) 0%,
    rgba(var(--purple-rgb), 0.06) 50%,
    rgba(var(--cyan-rgb), 0.05) 100%);
  border: 1px solid rgba(var(--fuchsia-rgb), 0.2);
  border-radius: var(--radius);
  color: var(--text);
  font-size: var(--text-sm);
  line-height: 1.5;
  animation: fadeIn var(--duration-base) var(--ease-default) both;
  position: relative;
  overflow: hidden;
}
.credit-gate-notice::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: var(--gradient-ai);
  opacity: 0.6;
}
.credit-gate-notice__icon {
  font-size: var(--text-lg);
  flex-shrink: 0;
}

/* ── Credit packs enhancement ── */
.creditPack {
  transition: all var(--duration-base) var(--ease-default);
}
.creditPack:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover);
}
.creditPack.selected {
  box-shadow: 0 0 0 2px var(--accent), var(--shadow-card-hover);
}
.creditPack .packCredits {
  position: relative;
}

/* Credit-pack BASE box + grid — consolidated here from mentor.css so the
   buy-credits tiles render in every shell that loads components.css. The
   candidate billing pane (settings-billing.js) uses these classes but the
   candidate shell does NOT load mentor.css, so the tiles rendered with width:0,
   transparent, no border ("CSS gone"). Values mirror mentor.css. */
.creditPacksList {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  margin-top: var(--space-4);
}
.creditPack {
  background: var(--bg1);
  border: 2px solid var(--border);
  border-radius: var(--radius-12);
  padding: var(--space-5);
  cursor: pointer;
  position: relative;
  text-align: center;
}
.creditPack:hover { border-color: var(--accent); }
.creditPack.selected { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.1); }
.creditPack.featured { border-color: var(--accent); }
.creditPack .packBadge {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--text-inverse);
  padding: 3px 10px;
  border-radius: var(--radius-4);
  font-size: var(--text-2xs);
  font-weight: 600;
}
.packHeader h3 { margin: 0 0 8px 0; font-size: var(--text-md); }
.packPrice { font-size: var(--text-3xl); font-weight: 700; color: var(--text); }
.packCredits { font-size: var(--text-lg); font-weight: 600; color: var(--accent); margin: var(--space-2) 0; }
.packValue { font-size: var(--text-xs); color: var(--muted); }
@media (max-width: 600px) {
  .creditPacksList { grid-template-columns: 1fr; gap: 10px; }
}

body.bento-theme .credit-gate-notice, body.atsiq-theme .credit-gate-notice {
  background: linear-gradient(135deg,
    rgba(var(--fuchsia-rgb), 0.06) 0%,
    rgba(var(--accent-purple-rgb), 0.04) 100%);
  border-color: rgba(var(--fuchsia-rgb), 0.15);
}
body.bento-theme .credit-gate-notice::before, body.atsiq-theme .credit-gate-notice::before {
  background: linear-gradient(90deg, rgba(var(--fuchsia-rgb), 0.6), rgba(var(--accent-purple-rgb), 0.4));
}
@media (max-width: 480px) {
  .credit-gate-notice {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
  }
}

/* ── Responsive ── */
@media (max-width: 640px) {
  .credit-gate-banner__content {
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4) var(--space-3) var(--space-5);
  }
  .credit-gate-banner__body { flex-basis: calc(100% - 60px); }
}
@media (prefers-reduced-motion: reduce) {
  .credit-gate-banner { animation: none; }
  .credit-gate-banner__icon-ring { transition: none; }
}

/* ── Rework error banner — lightweight alert (same family as credit-gate-banner) ── */
.rework-error-banner {
  position: relative;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-lg);
  overflow: hidden;
  animation: cgb-enter 0.45s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.rework-error-banner__stripe {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--status-danger);
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);
  z-index: 2;
}
.rework-error-banner__content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4) var(--space-3) var(--space-5);
  background: var(--card);
  border: 1px solid rgba(var(--status-danger-rgb), 0.18);
  border-left: none;
  border-radius: var(--radius-lg);
}
.rework-error-banner__icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: rgba(var(--status-danger-rgb), 0.12);
  color: var(--status-danger);
  box-shadow: 0 0 0 1px rgba(var(--status-danger-rgb), 0.15);
}
.rework-error-banner__body { flex: 1; min-width: 0; }
.rework-error-banner__title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-sm);
  color: var(--status-danger);
  line-height: 1.3;
}
.rework-error-banner__detail {
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
  margin-top: 2px;
  word-break: break-word;
}
.rework-error-banner__close {
  position: absolute;
  z-index: 3;
  top: var(--space-2);
  right: var(--space-2);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast);
}
.rework-error-banner__close:hover {
  background: rgba(var(--status-danger-rgb), 0.1);
  color: var(--status-danger);
}
@media (prefers-reduced-motion: reduce) {
  .rework-error-banner { animation: none; }
}

/* ============================================
   ANNOUNCEMENT BANNER (.announcement-*)
   Phase 10 C1 — Polished
   ============================================ */
.announcement-banner {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
}
.announcement-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  animation: fadeIn var(--duration-base) var(--ease-default) both;
}
.announcement-item:nth-child(2) { animation-delay: 80ms; }
.announcement-item:nth-child(3) { animation-delay: 160ms; }
.announcement-item--info {
  background: rgba(var(--status-info-rgb), 0.12);
  border-left: 3px solid var(--status-info);
  color: var(--text);
}
.announcement-item--warning {
  background: rgba(var(--status-warn-rgb), 0.12);
  border-left: 3px solid var(--status-warn);
  color: var(--text);
}
.announcement-item--success {
  background: rgba(var(--status-ok-rgb), 0.12);
  border-left: 3px solid var(--status-ok);
  color: var(--text);
}
.announcement-item--error {
  background: rgba(var(--status-danger-rgb), 0.12);
  border-left: 3px solid var(--status-danger);
  color: var(--text);
}
.announcement-item__content {
  flex: 1;
  display: flex;
  gap: var(--space-2);
  align-items: baseline;
}
.announcement-item__content strong {
  white-space: nowrap;
}
.announcement-item__dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--muted);
  font-size: var(--text-xl);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  transition: color var(--duration-fast) var(--ease-default),
              background var(--duration-fast) var(--ease-default);
}
.announcement-item__dismiss:hover {
  color: var(--text);
  background: rgba(var(--primary-rgb), 0.08);
}
.announcement-item__dismiss:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ============================================
   FAQ / HELP MODAL (.faq-*)
   Phase 10 C3 — Polished
   ============================================ */
.faq-modal {
  max-height: 60vh;
  overflow-y: auto;
}
.faq-guide-download {
  margin-bottom: var(--space-3);
  display: flex;
  justify-content: flex-end;
}
.faq-guide-download .btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}
.faq-search {
  margin-bottom: var(--space-3);
  position: sticky;
  top: 0;
  z-index: 1;
  padding-bottom: var(--space-2);
  background: inherit;
}
.faq-search input {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--text);
  font-size: var(--text-sm);
  transition: border-color var(--duration-fast) var(--ease-default),
              box-shadow var(--duration-fast) var(--ease-default);
}
.faq-search input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-ring-primary);
}
.faq-search input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.faq-section {
  margin-bottom: var(--space-4);
  animation: fadeIn var(--duration-base) var(--ease-default) both;
}
.faq-section:nth-child(2) { animation-delay: 50ms; }
.faq-section:nth-child(3) { animation-delay: 100ms; }
.faq-section__title {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-2);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--border);
}
.faq-article {
  margin-bottom: var(--space-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  transition: border-color var(--duration-fast) var(--ease-default);
}
.faq-article:hover { border-color: rgba(var(--primary-rgb), 0.3); }
.faq-article summary {
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  font-weight: 500;
  color: var(--text);
  font-size: var(--text-sm);
  background: var(--card);
  transition: background var(--duration-fast) var(--ease-default);
  list-style: none;
}
.faq-article summary::-webkit-details-marker { display: none; }
.faq-article summary::before {
  content: '\25B6';
  display: inline-block;
  margin-right: var(--space-2);
  font-size: var(--text-2xs);
  transition: transform var(--duration-base) var(--ease-decel);
  color: var(--muted);
}
.faq-article[open] summary::before {
  transform: rotate(90deg);
}
.faq-article summary:hover {
  background: var(--card2);
}
.faq-article summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.faq-article__body {
  padding: var(--space-3) var(--space-3);
  font-size: var(--text-sm);
  color: var(--muted);
  line-height: 1.6;
  border-top: 1px solid var(--border);
  background: var(--bg2);
  white-space: pre-wrap;
}

/* ============================================
   TIMEZONE PICKER (.settingsTimezone)
   Phase 10 C1 — Polished
   ============================================ */
.settingsTimezone select {
  width: 100%;
  max-width: 400px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-default),
              box-shadow var(--duration-fast) var(--ease-default);
}
.settingsTimezone select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-ring-primary);
}
.settingsTimezone select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Responsive for Phase 10/11 components ── */
@media (max-width: 768px) {
  .faq-modal { max-height: 80vh; }
  .announcement-item__content { flex-direction: column; gap: 2px; }
  .announcement-item__content strong { white-space: normal; }
}
@media (max-width: 480px) {
  .announcement-item { padding: var(--space-2); font-size: var(--text-xs); }
  .faq-article summary { padding: var(--space-2); }
}
/* ── Inline SVG Icons ── */
.inline-icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  line-height: 1;
}
.inline-icon {
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
}
/* ── inline-icon — COUCHES (P2-Z re-gate, finding « icônes microphone/robot/personne ») ──
   Le registre ui/modules/icon-registry.js ne peint plus AUCUNE couleur en dur : chaque couche
   d'un picto porte `fill|stroke="currentColor"` (repli theme-adaptatif quand cette feuille n'est
   pas chargée — harnais nus) + une classe de couche qui la remonte ici au TOKEN sémantique.
   Trois densités d'accent (a > a-l > a-l2) et deux de neutre (mut > mut-l) suffisent à rendre
   l'empilement d'origine (corps / détail / reflet) SANS littéral : les familles sémantiques
   (ok/warn/bad/ai) séparent leurs 2 couches par l'opacité, jamais par une seconde teinte en dur.
   `surf` = la surface « papier » d'un picto plein (lignes d'un document, cases d'un calendrier) :
   --bg1 est OPAQUE dans les 2 thèmes, donc la couche reste lisible sur l'aplat qui la porte. */
.inline-icon .iif-a      { fill: var(--accent-dark); }
.inline-icon .iif-a-l    { fill: var(--accent); }
.inline-icon .iif-a-l2   { fill: var(--accent2); }
.inline-icon .iif-ink    { fill: var(--text); }
.inline-icon .iif-mut    { fill: var(--muted); }
.inline-icon .iif-mut-l  { fill: var(--text-soft); }
.inline-icon .iif-ok     { fill: var(--success-text); }
.inline-icon .iif-ok-l   { fill: var(--success-text); opacity: 0.72; }
.inline-icon .iif-warn   { fill: var(--warning-text); }
.inline-icon .iif-warn-l { fill: var(--warning-text); opacity: 0.72; }
.inline-icon .iif-bad    { fill: var(--danger-text); }
.inline-icon .iif-bad-l  { fill: var(--danger-text); opacity: 0.72; }
.inline-icon .iif-ai     { fill: var(--ai-color-1); }
.inline-icon .iif-ai-l   { fill: var(--ai-color-1); opacity: 0.55; }
.inline-icon .iif-surf   { fill: var(--bg1); }
.inline-icon .iis-a      { stroke: var(--accent-dark); }
.inline-icon .iis-a-l    { stroke: var(--accent); }
.inline-icon .iis-a-l2   { stroke: var(--accent2); }
.inline-icon .iis-ink    { stroke: var(--text); }
.inline-icon .iis-mut    { stroke: var(--muted); }
.inline-icon .iis-mut-l  { stroke: var(--text-soft); }
.inline-icon .iis-ok     { stroke: var(--success-text); }
.inline-icon .iis-ok-l   { stroke: var(--success-text); opacity: 0.72; }
.inline-icon .iis-warn-l { stroke: var(--warning-text); opacity: 0.72; }
.inline-icon .iis-bad-l  { stroke: var(--danger-text); opacity: 0.72; }
.inline-icon .iis-ai-l   { stroke: var(--ai-color-1); opacity: 0.55; }
.inline-icon .iis-surf   { stroke: var(--bg1); }
/* Bento tile icons — match emoji sizing */
.bento-tile__icon .inline-icon-wrap,
.bento-empty__icon .inline-icon-wrap,
.welcomeFeatureIcon .inline-icon-wrap,
.welcomeEmoji .inline-icon-wrap,
.optionCardIcon .inline-icon-wrap,
.modeIcon .inline-icon-wrap,
.modeIconWrap .inline-icon-wrap { font-size: 0; }
.bento-tile__icon .inline-icon,
.bento-empty__icon .inline-icon,
.welcomeFeatureIcon .inline-icon,
.welcomeEmoji .inline-icon,
.optionCardIcon .inline-icon,
.modeIcon .inline-icon,
.modeIconWrap .inline-icon { width: 28px; height: 28px; }
.mentorStatIcon .inline-icon,
.quickActionIcon .inline-icon,
.metricIcon .inline-icon,
.statIcon .inline-icon { width: 24px; height: 24px; }
.v2-section-icon .inline-icon { width: 18px; height: 18px; }
.icon .inline-icon { width: 18px; height: 18px; }
/* Accessibility: reduce motion */
@media (prefers-reduced-motion: reduce) {
  .announcement-item,
  .faq-section { animation: none !important; }
  .announcement-item__dismiss,
  .faq-search input,
  .faq-article,
  .faq-article summary,
  .faq-article summary::before,
  .settingsTimezone select { transition: none !important; }
}

/* ============================================
   Form Draft Restore Banner (UX-004)
   ============================================ */
.form-draft-banner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0;
  margin-bottom: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border-accent);
  border-radius: var(--radius-sm);
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity var(--duration-base) ease, max-height var(--duration-base) ease, padding var(--duration-base) ease;
}
.form-draft-banner.visible {
  opacity: 1;
  max-height: 80px;
  padding: var(--space-3) var(--space-4);
}
.form-draft-banner__text {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.form-draft-banner__text::before {
  content: '\270F';
  font-size: var(--text-md);
  flex-shrink: 0;
}
.form-draft-banner__actions {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* =============================================================================
   Segmented Control — DESIGN_SYSTEM.md §26.2
   ----------------------------------------------------------------------------
   Multi-state toggle (typically 2 or 3 states). Generalised from
   .ji-panel-override__seg (employer-clients.css:2109+) which remains for
   backward compatibility.
   ============================================================================ */

.segmented-control {
  display: inline-flex;
  align-items: center;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 2px;
  gap: 2px;
  flex-shrink: 0;
}

.segmented-control__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--space-6);
  height: var(--space-6);
  padding: 0 var(--space-2);
  background: transparent;
  border: 0;
  border-radius: var(--radius-full);
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-default),
    color var(--duration-fast) var(--ease-default);
}

/* Icon-only variant (square button, used for 3-state with ✓ ○ ✗) */
.segmented-control--icons .segmented-control__btn {
  width: var(--space-6);
  padding: 0;
}

.segmented-control__btn:hover:not(.is-active) {
  background: rgba(var(--accent-rgb), 0.06);
  color: var(--text);
}

.segmented-control__btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.segmented-control__btn.is-active {
  color: rgb(var(--white-rgb));
  background: var(--accent);
  box-shadow: 0 1px 3px rgba(var(--accent-rgb), 0.30);
}

/* ATSIQ Obsidian: white on --accent is 4.46:1, just below WCAG AA. */
body.atsiq-host:not(.atsiq-theme) .segmented-control__btn.is-active:not([data-state]) {
  background: var(--accent-dark);
}

/* Semantic variants — data-state on the button for the active state */
.segmented-control__btn.is-active[data-state="off"] {
  background: var(--status-danger);
  box-shadow: 0 1px 3px rgba(var(--status-danger-rgb), 0.30);
}

.segmented-control__btn.is-active[data-state="inherit"] {
  background: var(--muted);
  box-shadow: 0 1px 3px rgba(var(--white-rgb), 0.10);
}

/* Theme variants */
body.light-theme .segmented-control,
body.bento-theme .segmented-control, body.atsiq-theme .segmented-control {
  background: rgba(var(--white-rgb), 0.65);
}

/* Mobile — bigger touch targets (WCAG 2.5.5) */
@media (max-width: 480px) {
  .segmented-control__btn {
    min-width: 44px;
    height: 44px;
    flex: 1;
  }
  .segmented-control--icons .segmented-control__btn {
    width: 44px;
  }
  .segmented-control {
    width: 100%;
    justify-content: space-between;
  }
}

@media (prefers-reduced-motion: reduce) {
  .segmented-control__btn { transition: none !important; }
}

/* =============================================================================
   Dismissible Banner — DESIGN_SYSTEM.md §26.8
   ----------------------------------------------------------------------------
   Composes with the existing `.ct-sysbanner` (employer-clients.css:1110+).
   The new class name `.dismissible-banner` is the canonical one ;
   `.ct-sysbanner` kept as alias for backwards-compat in WS-024 module.
   Persistence handled by dismissibleBanner() helper in core-utils.js.
   ============================================================================ */

.dismissible-banner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  animation: bannerSlideIn var(--duration-base) var(--ease-decel);
}

.dismissible-banner[data-tone="warn"] {
  border-left-color: var(--status-warn);
  background: rgba(var(--status-warn-rgb), 0.08);
}
.dismissible-banner[data-tone="danger"] {
  border-left-color: var(--status-danger);
  background: rgba(var(--status-danger-rgb), 0.08);
}
.dismissible-banner[data-tone="info"] {
  border-left-color: var(--accent2);
  background: rgba(var(--accent2-rgb), 0.08);
}
.dismissible-banner[data-tone="success"] {
  border-left-color: var(--status-ok);
  background: rgba(var(--status-ok-rgb), 0.08);
}

.dismissible-banner__icon {
  flex-shrink: 0;
  font-size: var(--text-md);
  line-height: 1;
}

.dismissible-banner__content {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text);
}

.dismissible-banner__title {
  font-weight: 600;
  margin-bottom: 2px;
}

.dismissible-banner__desc {
  color: var(--muted);
  font-size: var(--text-xs);
}

.dismissible-banner__cta {
  flex-shrink: 0;
}

.dismissible-banner__close {
  flex-shrink: 0;
  width: var(--space-7);
  height: var(--space-7);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-xs);
  color: var(--muted);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default), color var(--duration-fast) var(--ease-default);
}

.dismissible-banner__close:hover {
  background: rgba(var(--accent-rgb), 0.08);
  color: var(--text);
}

.dismissible-banner__close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@keyframes bannerSlideIn {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Phase 15.A audit DS-2 — dismissal motion driven by tokens (was hardcoded
   "200ms ease-out" inline in core-utils.js). Class added by dismissibleBanner()
   on close-button click ; transitionend triggers DOM removal. */
.dismissible-banner--dismissing {
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity var(--duration-base) var(--ease-default),
              transform var(--duration-base) var(--ease-default);
}

@media (max-width: 480px) {
  .dismissible-banner {
    flex-wrap: wrap;
    gap: var(--space-2);
  }
  .dismissible-banner__close {
    min-width: 44px;
    min-height: 44px;
  }
  .dismissible-banner__cta {
    width: 100%;
    order: 2;
  }
}

@media (prefers-reduced-motion: reduce) {
  .dismissible-banner { animation: none !important; }
  .dismissible-banner--dismissing { transition: none !important; }
  .dismissible-banner__close { transition: none !important; }
}

/* =============================================================================
   Progressive Feedback (multi-stage wait UX) — DESIGN_SYSTEM.md §26.7
   ----------------------------------------------------------------------------
   Used for external API calls with variable latency (VIES, Brevo, ACS).
   The message escalates over time so the user never sees a silent spinner.
   Caller drives the lifecycle via progressiveFeedback() helper in core-utils.js.
   ============================================================================ */

.progressive-feedback {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  color: var(--muted);
}

.progressive-feedback--block {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-5);
  gap: var(--space-3);
}

.progressive-feedback__spinner {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(var(--accent-rgb), 0.20);
  border-top-color: var(--accent);
  border-radius: var(--radius-full);
  animation: pfSpin 0.8s linear infinite;
}

.progressive-feedback--block .progressive-feedback__spinner {
  width: 28px;
  height: 28px;
}

.progressive-feedback__message {
  min-height: 18px; /* prevent layout shift between empty and populated */
  transition: opacity var(--duration-base) var(--ease-default);
}

@keyframes pfSpin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .progressive-feedback__spinner { animation: none !important; opacity: 0.6; }
  .progressive-feedback__message { transition: none !important; }
}

/* =============================================================================
   Permission Overrides Drawer — D3 (overnight 2026-04-26 Phase 2.2)
   ----------------------------------------------------------------------------
   Layout for the drawer body opened by openPermissionsDrawer() (recruiter-team-
   permissions.js). Composes with §26.1 (.drawer__body), §26.2 (.segmented-control),
   and §26.8 (.dismissible-banner). Tokens-only, theme-aware, mobile-responsive,
   prefers-reduced-motion compliant.
   ============================================================================ */

.perms-drawer-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 200px;
}

.perms-drawer__header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-3);
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.perms-drawer__user-name {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text);
  margin-bottom: var(--space-1);
}

.perms-drawer__role-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.perms-drawer__role-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: capitalize;
}

.perms-drawer__role-badge[data-role="owner"] {
  background: rgba(var(--status-warn-rgb), 0.15);
  color: var(--status-warn);
  border-color: rgba(var(--status-warn-rgb), 0.30);
}

.perms-drawer__user-email {
  font-size: var(--text-xs);
  color: var(--muted);
}

.perms-drawer__mode-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  background: rgba(var(--accent-rgb), 0.04);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-4);
}

.perms-drawer__mode-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  cursor: pointer;
}

.perms-drawer__mode-label > span:first-child {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}

.perms-drawer__mode-help {
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
}

.perms-drawer__matrix {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.perms-drawer__category {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.perms-drawer__category-title {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px dashed var(--border);
  margin-bottom: var(--space-2);
}

.perms-drawer__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-1);
  border-radius: var(--radius-xs);
  transition: background var(--duration-fast) var(--ease-default);
}

.perms-drawer__row:hover {
  background: rgba(var(--accent-rgb), 0.04);
}

.perms-drawer__perm-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}

.perms-drawer__perm-name {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}

.perms-drawer__perm-desc {
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.perms-drawer__perm-controls {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

.perms-drawer__source {
  display: inline-flex;
  align-items: center;
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  color: var(--muted);
  background: var(--card);
  min-width: 64px;
  justify-content: center;
}

.perms-drawer__source[data-source="granted"] {
  background: rgba(var(--status-ok-rgb), 0.12);
  color: var(--status-ok);
  border-color: rgba(var(--status-ok-rgb), 0.30);
}

.perms-drawer__source[data-source="revoked"] {
  background: rgba(var(--status-danger-rgb), 0.12);
  color: var(--status-danger);
  border-color: rgba(var(--status-danger-rgb), 0.30);
}

.perms-drawer__effective-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-6);
  height: var(--space-6);
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  font-weight: 600;
  font-size: var(--text-sm);
}

.perms-drawer__effective-pill[data-effective="1"] {
  background: rgba(var(--status-ok-rgb), 0.10);
  color: var(--status-ok);
  border-color: rgba(var(--status-ok-rgb), 0.30);
}

.perms-drawer__effective-pill[data-effective="0"] {
  background: rgba(var(--status-danger-rgb), 0.10);
  color: var(--status-danger);
  border-color: rgba(var(--status-danger-rgb), 0.30);
}

.perms-drawer__footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding-top: var(--space-4);
  margin-top: var(--space-5);
  border-top: 1px solid var(--border);
  position: sticky;
  bottom: 0;
  background: var(--bg-popup);
  margin-left: calc(-1 * var(--space-5));
  margin-right: calc(-1 * var(--space-5));
  padding-left: var(--space-5);
  padding-right: var(--space-5);
  padding-bottom: var(--space-4);
}

@media (max-width: 480px) {
  .perms-drawer__header {
    flex-direction: column;
  }
  .perms-drawer__row {
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-1);
  }
  .perms-drawer__perm-controls {
    width: 100%;
    justify-content: space-between;
  }
  .perms-drawer__footer {
    flex-direction: column-reverse;
  }
  .perms-drawer__footer .btn {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .perms-drawer__row { transition: none !important; }
}

/* =============================================================================
   Subprocessors Legal Page table — DESIGN_SYSTEM.md §26.9 (Phase 3.2)
   ----------------------------------------------------------------------------
   Used by /legal/subprocessors.html. Mobile <=768px : rows stack as cards
   with the column label rendered via ::before from data-label attribute
   (set by JS on lang switch).
   ============================================================================ */

.subprocessors-list {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  margin-top: var(--space-3);
}

.subprocessors-list th,
.subprocessors-list td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.subprocessors-list th {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--card);
}

.subprocessors-list tbody tr:hover {
  background: rgba(var(--accent-rgb), 0.04);
}

.subprocessors-list__country {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--muted);
  white-space: nowrap;
}

.subprocessors-list a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-all;
}

.subprocessors-list a:hover {
  color: var(--text);
}

@media (max-width: 768px) {
  .subprocessors-list,
  .subprocessors-list tbody,
  .subprocessors-list tr,
  .subprocessors-list td,
  .subprocessors-list th {
    display: block;
  }
  .subprocessors-list thead { display: none; }
  .subprocessors-list tr {
    border-bottom: 1px solid var(--border);
    padding: var(--space-3) 0;
  }
  .subprocessors-list td {
    padding: var(--space-2) 0;
    border-bottom: 0;
  }
  .subprocessors-list td::before {
    content: attr(data-label) " : ";
    font-weight: 600;
    color: var(--muted);
    font-size: var(--text-xs);
    text-transform: uppercase;
    display: block;
    margin-bottom: 2px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .subprocessors-list tbody tr { transition: none !important; }
}

/* =============================================================================
   Stepper — canonical `.stepper` (L3 D-3, ex-DESIGN_SYSTEM.md §26.3)
   ----------------------------------------------------------------------------
   Multi-step linear workflow indicator (GDPR employer-contact, client
   onboarding, fee_policy creation, candidate activation, intake, offers,
   ats-import…). FUSION L3-T2 : géométrie + traitement visuel premium de
   `.wizardSteps`/`.wizardStep` (effects.css ~:504 — gradient connectors,
   frosted glass, glow) × sous-éléments/état de l'ex-canon `.wizard-stepper`
   (structure __step/__dot/__label, renommée ici ; états is-active/is-completed
   renommés active/done pour matcher wizardSteps ET la grammaire nav D-3
   .active/.done commune à toutes les familles interactives).
   Interactivité UNIQUEMENT `.done.clickable` (ётape réelle = <button
   class="stepper__btn"> — jamais de saut en avant, cf. REG-119/120) ; les
   étapes futures restent des <li> non focusables. `.wizard-stepper*` ET
   `.wizardSteps`/`.wizardStep`/`.stepNum` purgés L3-T8 (tous consommateurs
   migrés : GDPR, fee-split, intake ji-head-stepper, cv-rework/mock-interview
   v2-head-stepper, ie-stepper).
   ============================================================================ */

.stepper {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 0;
  padding: 0 var(--space-2);
  list-style: none;
  overflow-x: auto;
  scrollbar-width: thin;
}

.stepper__step {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--card);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--muted);
  position: relative;
  flex-shrink: 0;
  white-space: nowrap;
  transition: background var(--duration-base) var(--ease-default), border-color var(--duration-base) var(--ease-default), color var(--duration-base) var(--ease-default);
}
/* Connector line between steps — gradient/success when the previous step is done. */
.stepper__step + .stepper__step {
  margin-left: 28px;
}
.stepper__step + .stepper__step::before {
  content: '';
  position: absolute;
  right: 100%;
  top: 50%;
  width: 28px;
  height: 2px;
  background: var(--border);
  transform: translateY(-50%);
  transition: background var(--duration-base) var(--ease-default);
}
.stepper__step.done + .stepper__step::before {
  background: var(--status-ok);
}

.stepper__step.active {
  background: var(--gradient-primary);
  color: var(--text-inverse);
  border-color: transparent;
  box-shadow: 0 0 16px rgba(var(--primary-rgb), 0.4), 0 0 32px rgba(var(--primary-rgb), 0.12);
}

.stepper__step.done {
  background: rgba(var(--status-ok-rgb), 0.10);
  color: var(--status-ok);
  border-color: rgba(var(--status-ok-rgb), 0.25);
}

.stepper__dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background: rgba(var(--primary-rgb), 0.06);
  font-weight: 700;
  font-size: var(--text-xs);
  color: var(--muted);
  position: relative;
}
.stepper__step.active .stepper__dot {
  background: var(--accent);
  color: var(--on-primary);
}
/* Done dot — digit hidden, ✓ drawn by ::after. Restores the `content:'\2713'`
   glyph lost in the L3-T8 wizardStep→canon migration: the ≤768px block below
   and the v2-head-stepper overrides (interview-v2.css:124-131) already set
   `color: transparent` + style this ::after, and rendered empty green circles
   without it. Font-size inherits from the dot (--text-xs / mobile --text-sm). */
.stepper__step.done .stepper__dot {
  background: var(--status-ok);
  color: transparent;
}
.stepper__step.done .stepper__dot::after {
  content: '\2713';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: var(--on-primary);
}

.stepper__label { white-space: nowrap; }

/* `.done.clickable` step = a real <button> wrapping the dot+label (REG-119/120 —
   back navigation only, never forward). Reset to inherit the <li>'s layout/spacing. */
.stepper__btn {
  display: inline-flex;
  align-items: center;
  gap: inherit;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.stepper__step:not(.done.clickable) { cursor: default; }

.stepper--vertical {
  flex-direction: column;
  align-items: stretch;
  overflow-x: visible;
}
.stepper--vertical .stepper__step + .stepper__step {
  margin-left: 0;
  margin-top: var(--space-2);
}

.stepper--compact .stepper__label {
  display: none;
}

/* Compact mobile treatment — moved from effects.css L3-T8 (was bare .wizardSteps/
   .wizardStep, ~768px breakpoint) : ji-head-stepper's mobile UX depends on this
   (labels hidden, circles-only, solid connector bar) — not a scoped extension in
   recruiter-jobintake-stepper.css, so it must live in the canon itself. */
@media (max-width: 768px) {
  .stepper {
    flex-wrap: nowrap;
    align-items: center;
    justify-content: center;
  }
  .stepper__step span:not(.stepper__dot) {
    display: none;
  }
  .stepper__step {
    padding: 0 !important;
    background: none !important;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .stepper__step + .stepper__step { margin-left: 0; }
  .stepper__step + .stepper__step::before {
    position: static !important;
    width: 20px;
    height: 3px;
    border-radius: var(--radius-2);
    background: var(--border);
    flex-shrink: 0;
    transform: none !important;
    top: auto !important;
    right: auto !important;
  }
  .stepper__step.done + .stepper__step::before,
  .stepper__step.done + .stepper__step.active::before {
    background: var(--status-ok);
  }
  .stepper__step .stepper__dot {
    width: 30px !important;
    height: 30px !important;
    font-size: var(--text-sm) !important;
    font-weight: 700;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--card, transparent);
    color: var(--muted);
    border: 1.5px solid var(--border);
    transition: all var(--duration-slow) var(--ease-default);
  }
  .stepper__step.active .stepper__dot {
    background: var(--gradient-primary) !important;
    color: var(--text-inverse) !important;
    border-color: transparent !important;
    box-shadow: 0 0 12px rgba(var(--primary-rgb), 0.4);
  }
  .stepper__step.done .stepper__dot {
    background: var(--status-ok) !important;
    color: transparent !important;
    border-color: var(--status-ok) !important;
  }
  .stepper__step.done .stepper__dot::after {
    color: var(--on-primary);
  }
  .stepper__step:not(.active):not(.done) .stepper__dot {
    background: transparent !important;
  }
}

@media (max-width: 480px) {
  .stepper__label { display: none; }
  .stepper__step { padding: var(--space-2); }
}

@media (prefers-reduced-motion: reduce) {
  .stepper__step { transition: none !important; }
}

/* .wizard-stepper* alias purged L3-T8 (avancé depuis T11, cf. Done-gate T8 littéral) —
   les 2 seuls consommateurs (admin-employer-contact-gdpr.js, recruiter-fee-split-
   agreements.js) ont migré vers .stepper/.active/.done/.stepper__dot/__label ce commit. */

/* =============================================================================
   GDPR employer-contact admin drawer body — Phase 4.2
   ----------------------------------------------------------------------------
   Composes with §26.1 .drawer__body. List of requests + detail wizard.
   ============================================================================ */

.gdpr-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.gdpr-list__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--duration-fast), background var(--duration-fast);
}

.gdpr-list__row:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.04);
}

.gdpr-list__row.is-selected {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.08);
}

.gdpr-list__email {
  font-weight: 500;
  color: var(--text);
  font-size: var(--text-sm);
}

.gdpr-list__meta {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 2px;
}

.gdpr-status-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--card);
  border: 1px solid var(--border);
  color: var(--muted);
  white-space: nowrap;
}

.gdpr-status-badge[data-status="received"] { background: rgba(var(--accent2-rgb), 0.12); color: var(--accent2); border-color: rgba(var(--accent2-rgb), 0.30); }
.gdpr-status-badge[data-status="identity_verified"] { background: rgba(var(--accent-rgb), 0.12); color: var(--accent); border-color: rgba(var(--accent-rgb), 0.30); }
.gdpr-status-badge[data-status="exported"] { background: rgba(var(--status-warn-rgb), 0.12); color: var(--status-warn); border-color: rgba(var(--status-warn-rgb), 0.30); }
.gdpr-status-badge[data-status="anonymized"] { background: rgba(var(--status-ok-rgb), 0.12); color: var(--status-ok); border-color: rgba(var(--status-ok-rgb), 0.30); }
.gdpr-status-badge[data-status="notified"] { background: rgba(var(--status-ok-rgb), 0.18); color: var(--status-ok); border-color: var(--status-ok); }

.gdpr-detail__header {
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

.gdpr-detail__sla {
  font-size: var(--text-xs);
  color: var(--muted);
}

.gdpr-detail__sla[data-warn="1"] { color: var(--status-warn); font-weight: 600; }
.gdpr-detail__sla[data-warn="2"] { color: var(--status-danger); font-weight: 600; }

.gdpr-detail__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
  flex-wrap: wrap;
}

.gdpr-create__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.gdpr-create__grid .form-group {
  min-width: 0;
}

.gdpr-create__full {
  grid-column: 1 / -1;
}

.gdpr-detail__notes {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border-left: 3px solid var(--border);
  color: var(--text);
  overflow-wrap: anywhere;
}

.gdpr-detail__notes p {
  margin: var(--space-1) 0 0;
  white-space: pre-wrap;
}

/* Phase 10.A P0-8 : mobile + reduced-motion blocks for the GDPR drawer
   surface. List rows stack to a single column under 480px, badge/touch
   targets bumped to WCAG 2.5.5 (44x44px), all transitions suppressed
   under prefers-reduced-motion. */
@media (max-width: 480px) {
  .gdpr-create__grid {
    grid-template-columns: 1fr;
  }
  .gdpr-create__full {
    grid-column: auto;
  }
  .gdpr-list__row {
    grid-template-columns: 1fr;
    padding: var(--space-3);
  }
  .gdpr-list__meta {
    margin-top: var(--space-1);
  }
  .gdpr-status-badge {
    align-self: flex-start;
    min-height: 28px;
    padding: var(--space-1) var(--space-3);
  }
  .gdpr-detail__actions {
    flex-direction: column-reverse;
  }
  .gdpr-detail__actions .btn {
    width: 100%;
    min-height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .gdpr-list__row { transition: none !important; }
  .gdpr-detail__sla[data-warn="2"] { animation: none !important; }
}

/* =============================================================================
   Type-to-confirm input — L5-T5.7 (D-5/A7)
   ----------------------------------------------------------------------------
   Sole surviving fragment of the old standalone destructive-confirm dialog
   (Phase 10.B P1.6). confirmDestructive() is now a thin wrapper over
   confirmDialog() (core-utils.js) — the dialog CHROME itself is the D-6
   canon .modalCard/.modalHead/.modalActions, but the optional "type X to
   confirm" input keeps its own styling here, reused verbatim.
   ============================================================================ */

.destructive-confirm__type-label {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--muted);
}

.destructive-confirm__type-label code {
  background: var(--card);
  border: 1px solid var(--border);
  padding: 1px var(--space-1);
  border-radius: var(--radius-xs);
  font-size: var(--text-xs);
  color: var(--accent);
  font-family: var(--font-mono, monospace);
}

.destructive-confirm__type-input {
  font-family: var(--font-mono, monospace);
  letter-spacing: 0.5px;
}

/* =============================================================================
   KPI Tile multi-currency variant — DESIGN_SYSTEM.md §26.5 (Phase 6)
   ----------------------------------------------------------------------------
   Composes with .kpi-tile / .bento-stat (existing; admin WS-024 scope,
   out of the §10.15 .stat-tile canon — separate documented DS §26.5 variant).
   Adds the multi-currency primary value + breakdown chips for "CA reconnu"
   when org has invoices in multiple currencies (EUR/USD/GBP/CHF + Nordic).
   ============================================================================ */

.kpi-tile--currency .kpi-tile__primary {
  font-size: var(--text-3xl);
  font-weight: 700;
  letter-spacing: -1.5px;
  font-variant-numeric: tabular-nums;
}

.kpi-tile--currency .kpi-tile__currency-code {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--muted);
  margin-left: var(--space-2);
  vertical-align: top;
}

.kpi-tile--currency .kpi-tile__breakdown {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--muted);
}

.kpi-tile--currency .kpi-tile__breakdown-item {
  padding: 2px var(--space-2);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-variant-numeric: tabular-nums;
}

.kpi-tile--currency .kpi-tile__breakdown-item[data-currency="EUR"] { border-color: rgba(var(--accent-rgb), 0.30); }
.kpi-tile--currency .kpi-tile__breakdown-item[data-currency="USD"] { border-color: rgba(var(--status-warn-rgb), 0.30); }
.kpi-tile--currency .kpi-tile__breakdown-item[data-currency="GBP"] { border-color: rgba(var(--status-ok-rgb), 0.30); }

/* =============================================================================
   Animated Counter — DESIGN_SYSTEM.md §26.6 (Phase 1.4 + Phase 6 visual)
   ----------------------------------------------------------------------------
   Pair with the animateCounter() JS helper in core-utils.js. Tabular nums
   ensure the digit width doesn't reflow during the tween.
   ============================================================================ */

.counter {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: inline-block;
}

/* =============================================================================
   Accounting card (Phase 14.C — audit retention + revenue mode)
   ----------------------------------------------------------------------------
   Composes with .company-card / .field-group. Tokens-only. Status pill
   uses data-tone attribute for semantic colors (no inline style).
   ============================================================================ */

.acct-custom-wrap {
  margin-top: var(--space-2);
}

.acct-custom-label {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
  margin-bottom: var(--space-1);
}

.acct-revenue-explainer {
  margin-top: var(--space-2);
  min-height: 18px;
  transition: color var(--duration-fast) var(--ease-default);
}

.acct-actions {
  margin-top: var(--space-3);
}

.acct-status {
  margin-left: var(--space-3);
  font-variant-numeric: tabular-nums;
  transition: color var(--duration-fast) var(--ease-default);
}

.acct-status[data-tone="pending"] { color: var(--muted); }
.acct-status[data-tone="success"] { color: var(--status-ok); }
.acct-status[data-tone="danger"]  { color: var(--status-danger); }

@media (prefers-reduced-motion: reduce) {
  .acct-revenue-explainer { transition: none !important; }
  .acct-status { transition: none !important; }
}

/* =============================================================================
   Apollo Enrichment — Sprint 1 phase AP3 (search-as-you-type org autocomplete)
   ----------------------------------------------------------------------------
   Tokens-only, theme-aware (dark/bento), reduced-motion safe, mobile ≤480
   ============================================================================ */

[data-feature="apollo_enrichment"] {
  position: relative;
}

[data-feature="apollo_enrichment"][data-feature-disabled] .apollo-search-dropdown,
[data-feature="apollo_enrichment"][data-feature-disabled] .apollo-search-status {
  display: none !important;
}

/* When premium feature is disabled, the input still works (just no Apollo) */
[data-feature="apollo_enrichment"][data-feature-disabled] [data-apollo-search] {
  /* Restore native autocomplete behavior */
}

.apollo-search-status {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: var(--space-1);
  padding-left: var(--space-2);
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.apollo-search-status[data-level="info"]    { color: var(--accent2); }
.apollo-search-status[data-level="success"] { color: var(--status-ok); }
.apollo-search-status[data-level="warn"]    { color: var(--status-warn); }
.apollo-search-status[data-level="muted"]   { color: var(--muted); }

/* ── Premium-gated controls (2026-06-02 claude) ─────────────────────────────
   Generic "locked" affordance for any [data-feature] control the current plan
   lacks. Reuses the data-feature / data-feature-disabled convention, but is
   scoped to .premium-gated so it never collides with apollo's own
   [data-feature="apollo_enrichment"] rules above. Standard pattern: VISIBLE +
   lock badge + still CLICKABLE → ctShowPremiumUpsell() (plan-aware: freelance
   self-serve vs org member → contact admin). Backend 402 stays the real gate. */
.premium-gated[data-feature-disabled] {
  position: relative;
  opacity: 0.82;
  filter: grayscale(0.3);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.premium-gated[data-feature-disabled]:hover,
.premium-gated[data-feature-disabled]:focus-visible {
  opacity: 1;
  filter: none;
}
.premium-gated[data-feature-disabled]::after {
  content: "\01F512"; /* lock — clear "out of plan" signal */
  margin-left: 0.4em;
  font-size: 0.85em;
  line-height: 1;
  vertical-align: middle;
}
/* Knob-switch variant: float the lock just past the switch (no inline label). */
.job-hub-card-autosourcing__toggle.premium-gated[data-feature-disabled] {
  overflow: visible;
}
.job-hub-card-autosourcing__toggle.premium-gated[data-feature-disabled]::after {
  position: absolute;
  right: -1.3em;
  top: 50%;
  transform: translateY(-50%);
  margin-left: 0;
}

/* ── Premium upsell dialog (ctShowPremiumUpsell, core-utils.js) ──
   The upsell body is short (a one-line intro + a single CTA, or a contact-admin
   note). In the default 460px .modal-box it rendered left-aligned with dead
   space on the right. Make it a compact, centered, square-ish dialog. Scoped via
   :has() (pattern already used across ui/css) so the shared showModal() shell is
   untouched and no other modal is affected. */
.modal-box:has(.ct-premium-upsell) {
  max-width: 380px;
}
.ct-premium-upsell {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
}
.ct-premium-upsell__intro,
.ct-premium-upsell__note {
  margin: 0;
}
.ct-premium-upsell__note {
  color: var(--text-muted);
  font-size: 0.92em;
}
.ct-premium-upsell .modalActions {
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top: var(--space-2);
}

/* Dropdown — flyout sous l'input, full-width pour matcher le champ */
.apollo-search-dropdown {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  z-index: 50;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(var(--black-rgb), 0.18),
              0 2px 6px rgba(var(--black-rgb), 0.08);
  max-height: 380px;
  overflow-y: auto;
  animation: apolloDropdownIn var(--duration-base) var(--ease-decel);
}

@keyframes apolloDropdownIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.apollo-org-item {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-default);
}

.apollo-org-item:hover,
.apollo-org-item:focus-visible {
  background: rgba(var(--accent-rgb), 0.08);
  outline: none;
  transform: translateX(2px);
}

.apollo-org-item:focus-visible {
  box-shadow: 0 0 0 2px var(--accent);
}

.apollo-org-item__logo {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg1, var(--card));
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.apollo-org-logo {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.apollo-org-logo--placeholder {
  font-weight: 700;
  color: var(--accent);
  font-size: var(--text-md);
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.18) 0%, rgba(var(--accent2-rgb), 0.10) 100%);
}

.apollo-org-item__body {
  flex: 1 1 auto;
  min-width: 0;
}

.apollo-org-item__name {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.apollo-org-item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  margin-top: 2px;
  color: var(--muted);
  font-size: var(--text-xs);
}

.apollo-org-sep {
  color: var(--muted);
  opacity: 0.6;
}

.apollo-org-footer {
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: var(--text-2xs);
  font-style: italic;
  cursor: default;
  pointer-events: none;
}

/* Mobile ≤ 480px — dropdown becomes full-screen sheet */
@media (max-width: 480px) {
  .apollo-search-dropdown {
    position: fixed;
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    max-height: 60vh;
    box-shadow: 0 -8px 24px rgba(var(--black-rgb), 0.24);
    z-index: 1000;
  }
  .apollo-org-item {
    min-height: 48px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .apollo-search-dropdown { animation: none !important; }
  .apollo-org-item, .apollo-org-item:hover, .apollo-org-item:focus-visible {
    transition: none !important; transform: none !important;
  }
}

/* Apollo enrich button (Sprint 1.AP2) — small icon button with sparkle */
.apollo-enrich-btn {
  position: relative;
  color: var(--accent);
  transition: transform var(--duration-fast) var(--ease-default),
              color var(--duration-fast) var(--ease-default);
}
.apollo-enrich-btn:hover {
  color: var(--accent2);
  transform: rotate(8deg) scale(1.08);
}
.apollo-enrich-btn.loading {
  pointer-events: none;
  opacity: 0.6;
  animation: apolloPulse 1s ease-in-out infinite;
}
@keyframes apolloPulse {
  0%, 100% { opacity: 0.6; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.1); }
}

/* Hide Apollo button when feature is gated off (non-Enterprise Premium plans) */
[data-feature="apollo_enrichment"][data-feature-disabled].apollo-enrich-btn,
.apollo-enrich-btn[data-feature-disabled] {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .apollo-enrich-btn { transition: none !important; }
  .apollo-enrich-btn:hover { transform: none !important; }
  .apollo-enrich-btn.loading { animation: none !important; }
}

/* Sprint 1.6 E1.12 + E1.13 — Contact row contextual actions (Outlook OWA, schedule, log-call) */
.contacts-row__owa-link {
  margin-left: var(--space-2);
  display: inline-flex;
  align-items: center;
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  color: var(--muted);
  transition: color var(--duration-fast) var(--ease-default),
              background var(--duration-fast) var(--ease-default);
}
.contacts-row__owa-link:hover { color: var(--accent); background: rgba(var(--accent-rgb), 0.08); }
.contacts-row__owa-link svg { width: 14px; height: 14px; }

.contact-action-btn {
  color: var(--muted);
  transition: color var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-default);
}
.contact-action-btn:hover {
  color: var(--accent);
  transform: translateY(-1px);
}
.contact-action-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .contacts-row__owa-link { transition: none !important; }
  .contact-action-btn { transition: none !important; transform: none !important; }
}

@media (max-width: 480px) {
  .contacts-row__owa-link { padding: 8px; min-width: 36px; min-height: 36px; }
}

/* =============================================================================
   Sprint 1.5 — Bulk actions on clients list (multi-select + sticky action bar)
   Tokens-only, theme-aware, mobile ≤480 ready, prefers-reduced-motion safe
   ============================================================================ */

.bulk-cb-col {
  width: 36px;
  padding-left: var(--space-3);
  padding-right: 0;
}

.bulk-cb-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.bulk-cb-wrap input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: var(--accent);
}

@media (max-width: 480px) {
  .bulk-cb-col {
    width: 44px;
    padding-left: var(--space-2);
  }
  .bulk-cb-wrap input[type="checkbox"] {
    width: 22px;
    height: 22px;
  }
}

/* Sticky bulk action bar — apparaît en bas quand ≥1 sélectionné */
.bulk-action-bar {
  position: fixed;
  bottom: var(--space-4);
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  box-shadow: 0 8px 32px rgba(var(--black-rgb), 0.16),
              0 2px 8px rgba(var(--black-rgb), 0.08);
  z-index: 100;
  animation: bulkBarRise var(--duration-base) var(--ease-decel);
}

@keyframes bulkBarRise {
  from { opacity: 0; transform: translateX(-50%) translateY(20px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

.bulk-action-bar__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  padding: 0 var(--space-2);
  background: var(--accent);
  color: rgb(var(--white-rgb));
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.bulk-action-bar__label {
  font-size: var(--text-sm);
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
}

.bulk-action-bar .btn,
.bulk-action-bar .btn--icon {
  flex-shrink: 0;
}

@media (max-width: 480px) {
  .bulk-action-bar {
    left: var(--space-2);
    right: var(--space-2);
    transform: none;
    flex-wrap: wrap;
    border-radius: var(--radius-md);
    padding: var(--space-3);
  }
  @keyframes bulkBarRiseMobile {
    from { opacity: 0; transform: translateY(40px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .bulk-action-bar { animation: bulkBarRiseMobile var(--duration-base) var(--ease-decel); }
  .bulk-action-bar__label { width: 100%; order: 2; }
}

@media (prefers-reduced-motion: reduce) {
  .bulk-action-bar { animation: none !important; }
}

/* =============================================================================
   Sprint 1.5 partie 2 — Client list hover preview popover
   Apparaît en hover (delay 350ms) avec mini-KPIs de la ligne client.
   Position-aware : right side preferred, left fallback. Tap-to-show mobile.
   ============================================================================ */

.client-hover-preview {
  position: fixed;
  width: 320px;
  padding: var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 12px 40px rgba(var(--black-rgb), 0.18),
              0 4px 12px rgba(var(--black-rgb), 0.08);
  z-index: 200;
  pointer-events: none; /* hover on row, popover ne capture pas */
  animation: previewFadeIn var(--duration-base) var(--ease-decel);
}

@keyframes previewFadeIn {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

.client-hover-preview__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

.client-hover-preview__head .ct-avatar {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  font-size: var(--text-md);
}

.client-hover-preview__title-wrap {
  flex: 1 1 auto;
  min-width: 0;
}

.client-hover-preview__title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.2px;
}

.client-hover-preview__sub {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.client-hover-preview__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.client-hover-preview__cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.client-hover-preview__label {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.2px;
}

.client-hover-preview__value {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}

.client-hover-preview__cta {
  font-size: var(--text-xs);
  color: var(--accent);
  font-weight: 500;
  text-align: right;
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
}

/* Mobile : disable hover preview (use long-press instead, or just rely on click→detail) */
@media (max-width: 768px) {
  .client-hover-preview { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .client-hover-preview { animation: none !important; }
}

/* =============================================================================
   Sprint 1.10 — Contact detail drawer (4 onglets premium)
   Composants : header avatar+name, tabs nav, lazy-loaded panes (Vue/Jobs/
   Comms/Activity), stale badge with re-engage CTA. Tokens-only.
   ============================================================================ */

.contact-detail-drawer { display: flex; flex-direction: column; gap: var(--space-4); }

.cd-drawer__head {
  display: flex; align-items: center; gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.cd-drawer__head .ct-avatar { flex-shrink: 0; width: 56px; height: 56px; font-size: var(--text-lg); }
.cd-drawer__titlewrap { flex: 1 1 auto; min-width: 0; }
.cd-drawer__name {
  font-size: var(--text-lg); font-weight: 600; color: var(--text);
  letter-spacing: -0.3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cd-drawer__role { font-size: var(--text-sm); color: var(--muted); margin-top: 2px; }

.cd-drawer__stale {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); padding: var(--space-2) var(--space-3);
  background: rgba(var(--status-warn-rgb), 0.08);
  border: 1px solid var(--status-warn);
  border-radius: var(--radius-sm);
}
.cd-drawer__stale[data-stale="1"] .cd-stale__label { color: var(--status-warn); font-weight: 500; font-size: var(--text-sm); }

.cd-drawer__panes { padding: var(--space-2) 0; }
.cd-drawer__pane { display: none; }
.cd-drawer__pane.active { display: block; animation: cdPaneIn var(--duration-base) var(--ease-decel); }

@keyframes cdPaneIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.cd-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-4); }
.cd-grid__cell { display: flex; flex-direction: column; gap: 2px; }
.cd-grid__label {
  font-size: var(--text-2xs); font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: var(--letter-tight);
}
.cd-grid__value { font-size: var(--text-sm); color: var(--text); word-break: break-word; }

.cd-roles { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-3); }

.cd-notes { margin-top: var(--space-3); }
.cd-notes__text {
  margin-top: var(--space-1); padding: var(--space-2) var(--space-3);
  background: var(--bg1, var(--card)); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: var(--text-sm); color: var(--text);
  white-space: pre-wrap; line-height: 1.5;
}

.cd-loading, .cd-empty {
  padding: var(--space-4); text-align: center;
  color: var(--muted); font-size: var(--text-sm);
}

.cd-jobs-list, .cd-comms-list { list-style: none; padding: 0; margin: 0; }
.cd-jobs-item, .cd-comms-item {
  padding: var(--space-3); border-bottom: 1px solid var(--border);
  transition: background var(--duration-fast) var(--ease-default);
}
.cd-jobs-item:hover, .cd-comms-item:hover { background: rgba(var(--accent-rgb), 0.04); }
.cd-jobs-item__title, .cd-comms-item__subject {
  font-size: var(--text-sm); font-weight: 500; color: var(--text);
}
.cd-jobs-item__meta {
  font-size: var(--text-xs); color: var(--muted); margin-top: 2px;
}
.cd-comms-item__head { display: flex; justify-content: space-between; gap: var(--space-2); }
.cd-comms-item__date { font-size: var(--text-xs); color: var(--muted); flex-shrink: 0; }
.cd-comms-status {
  display: inline-block; margin-top: var(--space-1);
  padding: 2px var(--space-2); border-radius: var(--radius-full);
  font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase;
  letter-spacing: var(--letter-tight);
  /* Contrast WCAG AA fix : alpha 0.10 → 0.18 to lift contrast on small text */
  background: rgba(var(--accent-rgb), 0.18); color: var(--accent);
}
.cd-comms-status[data-status="bounced"], .cd-comms-status[data-status="failed"] {
  background: rgba(var(--status-danger-rgb), 0.18); color: var(--status-danger);
}
.cd-comms-status[data-status="opened"], .cd-comms-status[data-status="clicked"] {
  background: rgba(var(--status-ok-rgb), 0.18); color: var(--status-ok);
}

/* Timeline (Activité tab) — vertical line + dots premium */
.cd-timeline { position: relative; padding-left: var(--space-4); }
.cd-timeline::before {
  content: ''; position: absolute; left: 6px; top: 6px; bottom: 6px;
  width: 1px; background: var(--border);
}
.cd-timeline__item {
  position: relative; padding: var(--space-2) 0;
  display: flex; align-items: flex-start; gap: var(--space-2);
}
.cd-timeline__dot {
  position: absolute; left: -16px; top: 12px; width: 12px; height: 12px;
  background: var(--accent); border: 2px solid var(--card);
  border-radius: 50%; flex-shrink: 0;
}
.cd-timeline__item[data-source="email_send"] .cd-timeline__dot { background: var(--accent2); }
.cd-timeline__item[data-source="org_activity"] .cd-timeline__dot { background: var(--status-ok); }
.cd-timeline__body { flex: 1 1 auto; min-width: 0; }
.cd-timeline__head { display: flex; justify-content: space-between; gap: var(--space-2); }
.cd-timeline__event { font-size: var(--text-sm); font-weight: 500; color: var(--text); }
.cd-timeline__date { font-size: var(--text-xs); color: var(--muted); flex-shrink: 0; }
.cd-timeline__meta {
  margin-top: 2px; font-size: var(--text-xs); color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

@media (max-width: 480px) {
  .cd-grid { grid-template-columns: 1fr; }
  .cd-drawer__head .ct-avatar { width: 48px; height: 48px; }
}

@media (prefers-reduced-motion: reduce) {
  .cd-drawer__pane.active { animation: none !important; }
  .cd-jobs-item, .cd-comms-item { transition: none !important; }
}

/* Sprint 1.A.1 audit fix — focus-visible sur dropdown options + bento theme variants */
.apollo-org-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

body.bento-theme .apollo-search-dropdown,
body.bento-theme .client-hover-preview,
body.bento-theme .contact-detail-drawer .cd-drawer__panes, body.atsiq-theme .apollo-search-dropdown, body.atsiq-theme .client-hover-preview, body.atsiq-theme .contact-detail-drawer .cd-drawer__panes {
  background: var(--card);
  border-color: var(--border);
}
body.bento-theme .cd-comms-status[data-status], body.atsiq-theme .cd-comms-status[data-status] {
  /* Bento theme uses lighter tones — re-balance alpha for visibility */
  background: rgba(var(--accent-rgb), 0.22);
}
body.bento-theme .cd-comms-status[data-status="bounced"],
body.bento-theme .cd-comms-status[data-status="failed"], body.atsiq-theme .cd-comms-status[data-status="bounced"], body.atsiq-theme .cd-comms-status[data-status="failed"] {
  background: rgba(var(--status-danger-rgb), 0.22);
}
body.bento-theme .cd-comms-status[data-status="opened"],
body.bento-theme .cd-comms-status[data-status="clicked"], body.atsiq-theme .cd-comms-status[data-status="opened"], body.atsiq-theme .cd-comms-status[data-status="clicked"] {
  background: rgba(var(--status-ok-rgb), 0.22);
}

/* =============================================================================
   Sprint 2.5/2.6/2.7 — Recruiter Placements (Phase 2 §5.3)
   List shell + status pills (state machine) + drawer 4 onglets + financials
   KPI tile + splits list with role chips + create form calculated preview.
   Tokens-only. Light + bento + mobile + prefers-reduced-motion couverts.
   ============================================================================= */

.placements-pane { display: flex; flex-direction: column; gap: var(--space-4); }

.placements-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); flex-wrap: wrap;
}
.placements-head--no-title {
  justify-content: flex-end;
}
.placements-head__title {
  font-size: var(--text-xl); font-weight: 600; color: var(--text);
  letter-spacing: -0.3px; margin: 0;
}

.placements-filters {
  display: flex; gap: var(--space-2); flex-wrap: wrap;
}
.placements-filters select {
  background: var(--card); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-7) var(--space-2) var(--space-3); font-size: var(--text-sm);
  min-height: 36px;
  /* Judge-panel finding (sitewide): chevron re-apply + right padding widened
     to make room for it (was uniform var(--space-3) on all sides).
     Re-gate finding: currentColor doesn't resolve in a data-URI SVG — this
     is the dark/Obsidian default hex, theme overrides follow below. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%23f1f5f9' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.82'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 10px 6px;
}
body.light-theme .placements-filters select,
body.bento-theme .placements-filters select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%231c1917' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.68'/%3E%3C/svg%3E");
}
body.atsiq-theme .placements-filters select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1L5 5L9 1' stroke='%230a141e' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' stroke-opacity='0.70'/%3E%3C/svg%3E");
}
.placements-filters select:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}

.placements-table tbody tr {
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default);
}
.placements-table tbody tr:focus-visible {
  outline: 2px solid var(--accent); outline-offset: -2px;
}

/* Phase 11.8 — staggered list entrance (DS-respecting via sectionChildIn).
   JS adds .staggered to the <table> after _renderRows. Reduced-motion guard
   handled JS-side (skip class add). */
.placements-table.staggered tbody tr {
  animation: sectionChildIn 360ms cubic-bezier(.2,.7,.3,1) backwards;
}

.placements-table.staggered tbody tr:nth-child(1) { animation-delay: 0ms; }
.placements-table.staggered tbody tr:nth-child(2) { animation-delay: 40ms; }
.placements-table.staggered tbody tr:nth-child(3) { animation-delay: 80ms; }
.placements-table.staggered tbody tr:nth-child(4) { animation-delay: 120ms; }
.placements-table.staggered tbody tr:nth-child(5) { animation-delay: 160ms; }
.placements-table.staggered tbody tr:nth-child(6) { animation-delay: 200ms; }
.placements-table.staggered tbody tr:nth-child(7) { animation-delay: 240ms; }
.placements-table.staggered tbody tr:nth-child(8) { animation-delay: 280ms; }
.placements-table.staggered tbody tr:nth-child(9) { animation-delay: 320ms; }
.placements-table.staggered tbody tr:nth-child(10) { animation-delay: 360ms; }
.placements-table.staggered tbody tr:nth-child(n+11) { animation-delay: 400ms; }

.placements-empty {
  text-align: center; padding: var(--space-5);
  color: var(--muted); font-size: var(--text-sm);
}

/* Status pill — state machine 7 statuts (draft/proposed/approved/booked/started/completed/cancelled) */
.placement-status {
  display: inline-flex; align-items: center; gap: 6px;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  font-size: var(--text-xs); font-weight: 600;
  white-space: nowrap; letter-spacing: 0.01em;
  background: rgba(var(--white-rgb), 0.06); color: var(--muted);
}
.placement-status::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  flex-shrink: 0; background: currentColor;
}
.placement-status[data-status="draft"] {
  background: rgba(var(--white-rgb), 0.06); color: var(--muted);
}
.placement-status[data-status="proposed"] {
  background: rgba(var(--accent-rgb), 0.12); color: var(--accent-light, var(--accent));
}
.placement-status[data-status="approved"] {
  background: rgba(var(--accent-rgb), 0.18); color: var(--accent);
}
.placement-status[data-status="booked"] {
  background: rgba(var(--amber-rgb), 0.12); color: var(--warning-text);
}
.placement-status[data-status="started"] {
  background: rgba(var(--status-warn-rgb), 0.16); color: var(--status-warn);
}
.placement-status[data-status="completed"] {
  background: rgba(var(--status-ok-rgb), 0.12); color: var(--success-text);
}
.placement-status[data-status="cancelled"] {
  background: rgba(var(--data-rose-rgb), 0.12); color: var(--danger-text);
}

/* Drawer (réutilise §26.1 openDrawer + structure cd-* parallèle) */
.placement-drawer { display: flex; flex-direction: column; gap: var(--space-4); }

.pl-drawer__head {
  display: flex; align-items: center; gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.pl-drawer__meta {
  font-size: var(--text-sm); color: var(--muted);
}

.pl-drawer__panes { padding: var(--space-2) 0; }
.pl-drawer__pane { display: none; }
.pl-drawer__pane.active {
  display: block;
  animation: plPaneIn var(--duration-base) var(--ease-decel);
}

@keyframes plPaneIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.pl-drawer__footer {
  display: flex; gap: var(--space-2); flex-wrap: wrap;
  justify-content: flex-end;
  padding-top: var(--space-3); border-top: 1px solid var(--border);
}

.pl-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-3) var(--space-4);
}
.pl-grid__cell { display: flex; flex-direction: column; gap: 2px; }
.pl-grid__label {
  font-size: var(--text-2xs); font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: var(--letter-tight);
}
.pl-grid__value {
  font-size: var(--text-sm); color: var(--text); word-break: break-word;
}
.pl-grid__value.tabular { font-variant-numeric: tabular-nums; }

.pl-notes { margin-top: var(--space-3); }
.pl-notes__text {
  margin-top: var(--space-1); padding: var(--space-2) var(--space-3);
  background: var(--bg1, var(--card)); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: var(--text-sm); color: var(--text);
  white-space: pre-wrap; line-height: 1.5;
}

/* Financials KPI tile — fee TTC headline (premium hero) */
.pl-financials-kpi {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: var(--space-1);
  padding: var(--space-4);
  border-radius: var(--radius);
  background: linear-gradient(
    135deg,
    rgba(var(--accent-rgb), 0.08) 0%,
    rgba(var(--accent-rgb), 0.02) 100%
  );
  border: 1px solid rgba(var(--accent-rgb), 0.18);
  margin-bottom: var(--space-4);
}
.pl-financials-kpi__value {
  font-size: var(--text-2xl); font-weight: 600;
  color: var(--text); letter-spacing: -0.4px;
  font-variant-numeric: tabular-nums;
}
.pl-financials-kpi__label {
  font-size: var(--text-2xs); font-weight: 600;
  color: var(--muted); text-transform: uppercase;
  letter-spacing: var(--letter-tight);
}

/* Splits list — role chips colored, percent + amount tabular */
.pl-splits-list { list-style: none; padding: 0; margin: 0; }
.pl-splits-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3); border-bottom: 1px solid var(--border);
}
.pl-splits-item:last-child { border-bottom: 0; }
.pl-splits-item__role {
  display: inline-flex; align-items: center; padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--text-2xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--letter-tight);
  background: rgba(var(--accent-rgb), 0.18); color: var(--accent);
  flex: 0 0 auto;
}
.pl-splits-item__role[data-role="originator"] {
  background: rgba(var(--accent-rgb), 0.18); color: var(--accent);
}
.pl-splits-item__role[data-role="closer"] {
  background: rgba(var(--status-ok-rgb), 0.18); color: var(--status-ok);
}
.pl-splits-item__role[data-role="manager"] {
  background: rgba(var(--amber-rgb), 0.18); color: var(--warning-text);
}
.pl-splits-item__role[data-role="referrer"] {
  background: rgba(var(--data-rose-rgb), 0.16); color: var(--danger-text);
}
.pl-splits-item__role[data-role="other"] {
  background: rgba(var(--white-rgb), 0.06); color: var(--muted);
}
.pl-splits-item__pct {
  flex: 0 0 80px; text-align: right;
  font-size: var(--text-sm); font-weight: 500; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.pl-splits-item__amount {
  flex: 0 0 auto; text-align: right;
  font-size: var(--text-sm); color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Create form — calculated preview block */
.pl-calc-wrap {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-3); margin-top: var(--space-3);
  background: var(--bg1, var(--card));
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.pl-calc-preview {
  font-size: var(--text-sm); color: var(--muted);
  padding: var(--space-2) var(--space-3);
  background: rgba(var(--accent-rgb), 0.06);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-xs, var(--radius-sm));
  font-variant-numeric: tabular-nums;
  transition: background var(--duration-fast) var(--ease-default);
}
.pl-form-actions {
  display: flex; justify-content: flex-end; gap: var(--space-2);
  margin-top: var(--space-3);
}

/* Mobile responsive */
@media (max-width: 768px) {
  .placements-head { flex-direction: column; align-items: stretch; }
  .pl-drawer__footer { justify-content: stretch; }
  .pl-drawer__footer .btn { flex: 1 1 auto; }
}
@media (max-width: 480px) {
  .pl-grid { grid-template-columns: 1fr; }
  .pl-financials-kpi__value { font-size: var(--text-xl); }
  .pl-splits-item { flex-wrap: wrap; }
  .pl-splits-item__pct,
  .pl-splits-item__amount { flex: 1 1 auto; text-align: left; }
}

/* Reduce motion */
@media (prefers-reduced-motion: reduce) {
  .pl-drawer__pane.active { animation: none !important; }
  .placements-table tbody tr,
  .pl-calc-preview { transition: none !important; }
}

/* Bento + light theme variants */
body.bento-theme .pl-financials-kpi, body.atsiq-theme .pl-financials-kpi {
  background: linear-gradient(
    135deg,
    rgba(var(--accent-rgb), 0.12) 0%,
    rgba(var(--accent-rgb), 0.04) 100%
  );
  border-color: rgba(var(--accent-rgb), 0.24);
}
body.bento-theme .pl-splits-item__role[data-role], body.atsiq-theme .pl-splits-item__role[data-role] {
  background: rgba(var(--accent-rgb), 0.22);
}
body.bento-theme .pl-splits-item__role[data-role="closer"], body.atsiq-theme .pl-splits-item__role[data-role="closer"] {
  background: rgba(var(--status-ok-rgb), 0.22);
}
body.bento-theme .pl-splits-item__role[data-role="manager"], body.atsiq-theme .pl-splits-item__role[data-role="manager"] {
  background: rgba(var(--amber-rgb), 0.22);
}
body.bento-theme .pl-splits-item__role[data-role="referrer"], body.atsiq-theme .pl-splits-item__role[data-role="referrer"] {
  background: rgba(var(--data-rose-rgb), 0.20);
}
body.light-theme .placement-status[data-status="draft"],
body.bento-theme .placement-status[data-status="draft"], body.atsiq-theme .placement-status[data-status="draft"] {
  background: rgba(var(--black-rgb), 0.04);
}
body.light-theme .pl-splits-item__role[data-role], body.atsiq-theme .pl-splits-item__role[data-role] {
  background: rgba(var(--accent-rgb), 0.14);
}

/* Invoice status — WS-024 Phase 3 (V2.0b)
   8 statuts : draft / issued / viewed / partially_paid / paid / overdue / cancelled / credited
   Hérite du squelette .placement-status (pill + dot ::before). */
.invoice-status[data-status="draft"] {
  background: rgba(var(--white-rgb), 0.06); color: var(--muted);
}
.invoice-status[data-status="issued"] {
  background: rgba(var(--accent-rgb), 0.14); color: var(--accent);
}
.invoice-status[data-status="viewed"] {
  background: rgba(var(--accent-rgb), 0.20); color: var(--accent-light, var(--accent));
}
.invoice-status[data-status="partially_paid"] {
  background: rgba(var(--status-warn-rgb), 0.16); color: var(--status-warn);
}
.invoice-status[data-status="paid"] {
  background: rgba(var(--status-ok-rgb), 0.16); color: var(--success-text);
}
.invoice-status[data-status="overdue"] {
  background: rgba(var(--data-rose-rgb), 0.16); color: var(--danger-text);
}
.invoice-status[data-status="cancelled"] {
  background: rgba(var(--data-rose-rgb), 0.10); color: var(--danger-text);
  text-decoration: line-through; text-decoration-thickness: 1px;
}
.invoice-status[data-status="credited"] {
  background: rgba(var(--accent2-rgb, var(--accent-rgb)), 0.14);
  color: var(--accent2, var(--accent));
}
body.light-theme .invoice-status[data-status="draft"],
body.bento-theme .invoice-status[data-status="draft"], body.atsiq-theme .invoice-status[data-status="draft"] {
  background: rgba(var(--black-rgb), 0.04);
}

/* Banners persistants (cancelled / credited) — drawer headers */
.invoice-banner {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm); border: 1px solid transparent;
  font-size: var(--text-sm); font-weight: 500;
  margin-bottom: var(--space-3);
}
.invoice-banner--cancelled {
  background: rgba(var(--data-rose-rgb), 0.10);
  border-color: rgba(var(--data-rose-rgb), 0.30);
  color: var(--danger-text);
}
.invoice-banner--credited {
  background: rgba(var(--accent2-rgb, var(--accent-rgb)), 0.10);
  border-color: rgba(var(--accent2-rgb, var(--accent-rgb)), 0.30);
  color: var(--accent2, var(--accent));
}

/* Money cells — alignment droite, JetBrains Mono pour tabulaire */
.invoice-money,
.inv-amount {
  font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);
  font-variant-numeric: tabular-nums;
  text-align: right; white-space: nowrap;
}

/* #57 (2026-07-13) — Recruiter own-scope invoicing KPI band. Spec :
   docs/superpowers/plans/2026-07-12-recruiter-own-scope-invoicing-spec.md
   DS-Canon §10.15 migration (2026-07-14, PW-C01/C21) — the wrapper is now the
   shared .stat-row (components.css §10.15 block above) and each tile is a
   plain .stat-tile ; the former per-metric ok/warn/danger colored-value
   scheme and pastel .inv-kpi family are retired (single .stat-tile--accent
   variant only). What remains below is functional/interactive state, scoped
   to #invoicesKpis, driven by attribute selectors — not a KPI color palette. */
#invoicesKpis.stat-row { animation: sectionChildIn 0.45s var(--ease-decel) both; }
/* P2-Z re-gate (da-13 / da-R-04) — la tuile de facture n'est plus une carte `.stat-tile` :
   `.inv-kpi` n'est qu'une ENVELOPPE (état interactif, focus, aria) autour de la carte du kit
   `.ctk-stat` rendue par ctStatCard. Une seule anatomie de stat-card dans tout le produit. */
.inv-kpi { position: relative; display: block; }
.inv-kpi > .ctk-stat { height: 100%; }
.inv-kpi__skel-value { display: block; height: 28px; width: 70%; border-radius: var(--radius-sm); }
/* Gracious empty / unavailable : the band never disappears, it greys.
   P2-I (D14, juge DA « contrastes <3:1 » sur 34) : l'`opacity:0.65` s'appliquait à TOUTE la
   tuile et se composait avec `--muted` (ATSIQ 0,70) → alpha effectif 0,455 ≈ 3,0:1 sur le
   label ET la valeur. L'atténuation ne porte plus que sur la VALEUR absente (« — »), le
   label/méta gardent leur contraste de token. */
#invoicesKpis .inv-kpi[data-empty="true"] .ctk-stat__value { color: var(--muted); }
/* Overdue tile doubles as a filter toggle (role=button, keyboard-operable) */
#invoicesKpis .inv-kpi[role="button"] { cursor: pointer; }
#invoicesKpis .inv-kpi[role="button"]:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
#invoicesKpis .inv-kpi[aria-pressed="true"] > .ctk-stat { border-color: var(--accent); }
#invoicesKpis .inv-kpi--accent > .ctk-stat { border-color: var(--accent); }
/* États vide/erreur du tableau : la hauteur de respiration reste ici, l'ANATOMIE vient du kit
   (ctEmptyState / ctErrorState). Les classes locales `__title` / `__hint` / `__msg` et le
   `.bento-empty` correspondants sont SUPPRIMÉS — plus aucun producteur (grep sur
   recruiter-invoices.js). */
.invoices-empty-state .ctk-empty,
.invoices-error-state .ctk-empty { min-height: 160px; }

/* ── P2-Z 1b-E (34 Facturation) ──────────────────────────────────────────────────────
   grincheux 1b-14 — la bande KPI decrit le PERIMETRE (toutes pages, filtres appliques),
   la table une seule page : la legende le dit, plutot que de laisser « 1 facture en
   retard » contredire des dizaines de lignes « En retard ». */
#invoicesKpis { position: relative; }
.inv-kpi__scope {
  flex: 1 0 100%;
  margin: var(--space-2) 0 0;
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

/* senior 1b-14 / DA 1b-18 — la table restait horizontale a 390 px et s'arretait apres
   STATUT (MONTANT TTC, ECHEANCE et ACTIONS hors ecran) sans ombre de debord ni
   affordance. (1) conteneur defilant NOMME + degrade de debord permanent ;
   (2) sous 640 px, patron « carte par ligne » ratifie par la surface 31 : chaque
   cellule porte son libelle, aucune colonne ne disparait, aucun statut reduit a sa
   seule pastille. */
.invoices-tablewrap { position: relative; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.invoices-tablewrap::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  width: 24px;
  pointer-events: none;
  background: linear-gradient(to left, var(--bg1), transparent);
  opacity: 0.85;
}
.invoices-tablewrap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.invoices-table { min-width: 720px; }

@media (max-width: 640px) {
  .invoices-tablewrap { overflow-x: visible; }
  .invoices-tablewrap::after { content: none; }
  .invoices-table { min-width: 0; }
  .invoices-table thead { display: none; }
  .invoices-table,
  .invoices-table tbody { display: block; width: 100%; }
  .invoices-table tbody tr {
    display: block;
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border);
  }
  .invoices-table tbody td {
    display: grid;
    grid-template-columns: minmax(0, 110px) minmax(0, 1fr);
    gap: var(--space-3);
    align-items: center;
    padding: 4px 0;
    border-bottom: 0;
    width: auto;
    max-width: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  .invoices-table tbody td::before {
    content: attr(data-label);
    font-weight: 600;
    font-size: var(--text-2xs);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--muted);
  }
  /* La cellule d'ETAT (vide / erreur) ne prend pas la grille libelle-valeur : elle
     occuperait la seule colonne de droite et deborderait. */
  .invoices-table tbody td.invoices-state-cell { display: block; }
  .invoices-table tbody td.invoices-state-cell::before { content: none; }
}

/* WS-024 V2.8b — BD pipeline Kanban */
.bd-kanban { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--space-3); }
.bd-kanban__head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 0 var(--space-3);
}
.bd-kanban__head--no-title { justify-content: flex-end; }
.bd-kanban__title { margin: 0; font-size: var(--text-lg); font-weight: 600; color: var(--text); }
/* P2-I (D14, juge QA #11 « kanban coupé au bord droit sans scrollbar ») : 6 colonnes de
   280px = 1740px, le débord est structurel à 1920px. On reprend l'ombre de débord de la
   grammaire unique G-S4 (components-recruiter.css §8 .ctk-kanban) : voiles scroll-attachés
   visibles UNIQUEMENT tant qu'il reste du contenu hors cadre, + une scrollbar épaissie
   (celle du thème ATSIQ fait 5px à alpha 0,22 — invisible sur fond clair). */
.bd-kanban__board {
  display: flex; gap: var(--space-3); overflow-x: auto;
  -webkit-overflow-scrolling: touch; padding-bottom: var(--space-3);
  min-height: 480px;
  background:
    linear-gradient(to right, var(--bg1), transparent) left / var(--space-5) 100%,
    linear-gradient(to left, var(--bg1), transparent) right / var(--space-5) 100%,
    radial-gradient(farthest-side at 0 50%, rgba(var(--text-rgb), 0.14), transparent) left / var(--space-3) 100%,
    radial-gradient(farthest-side at 100% 50%, rgba(var(--text-rgb), 0.14), transparent) right / var(--space-3) 100%;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
  scrollbar-width: auto;
}
.bd-kanban__board::-webkit-scrollbar { height: 10px; }
.bd-kanban__board::-webkit-scrollbar-thumb {
  background: rgba(var(--text-rgb), 0.28);
  border-radius: var(--radius-full);
}
.bd-kanban__board::-webkit-scrollbar-track { background: rgba(var(--text-rgb), 0.06); }
.bd-kanban__col {
  flex: 0 0 280px; display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-md); overflow: hidden;
  transition: background var(--duration-fast) var(--ease-default),
              border-color var(--duration-fast) var(--ease-default);
}
.bd-kanban__col--drag-over {
  background: rgba(var(--accent-rgb), 0.06);
  border-color: var(--accent);
}
/* P2-I (D14) — les 5 déclarations `--stage-color` (héritage « UI-coherence pipeline polish
   2026-07-12 ») sont RETIRÉES : plus aucune règle ne les consomme depuis l'alignement du
   kanban BD sur la grammaire unique G-S4 (head, carte et icône d'état vide ci-dessous).
   Les pilules `.ec-stage[data-stage]` du tableau Clients gardent leur propre mapping. */
/* P2-I (D14, juge DA G.3.4 — paire 09↔29↔32) : le liseré de 3px teinté par étape était la
   3ᵉ grammaire de kanban du produit ET une couleur JAMAIS légendée (G-S4 : « bordures :
   aucune couleur non légendée »). RACCORD : l'information portée par la couleur est
   strictement redondante avec le libellé de la colonne, qui reste — rien n'est perdu.
   Le header s'aligne sur la grammaire unique (micro-label mono uppercase + compteur pilule,
   components-recruiter.css §8 .ctk-kanban-col__label/__count). */
.bd-kanban__col-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.bd-kanban__col-label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-2xs); font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: var(--letter-tight);
}
/* Count pill — accent-tinted, parity with recruiter .kanbanCount
   (light themes re-map both to status-muted, see §kanban theme legs). */
.bd-kanban__col-count {
  display: inline-block; padding: 2px 10px; border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.12); color: var(--text-secondary);
  border: 1px solid rgba(var(--accent-rgb), 0.1);
  font-size: var(--text-xs); font-weight: 600;
}
.bd-kanban__col-list {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); overflow-y: auto; max-height: 65vh;
  min-height: 200px;
  flex: 1; /* empty drop-zone stretches to fill the column */
}
.bd-kanban__card {
  background: var(--bg1, var(--bg-elevation, var(--card)));
  border: 1px solid var(--border); border-radius: var(--radius-8);
  /* P2-I (D14 / G-S4) : plus de liseré gauche teinté non légendé — cf. .bd-kanban__col-head. */
  padding: var(--space-3); cursor: grab;
  transition: transform var(--duration-fast) var(--ease-default),
              box-shadow var(--duration-fast) var(--ease-default),
              border-color var(--duration-fast) var(--ease-default);
}
.bd-kanban__card:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
/* Hover lift — parity with recruiter .kanbanCard, fine pointers only */
@media (hover: hover) and (pointer: fine) {
  .bd-kanban__card:hover { transform: translateY(-2px); box-shadow: var(--shadow-hover); }
}
.bd-kanban__card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bd-kanban__card--dragging { opacity: 0.45; cursor: grabbing; }
.bd-kanban__card-name { font-size: var(--text-sm); font-weight: 600; margin-bottom: 4px; }
.bd-kanban__card-meta { font-size: var(--text-xs); color: var(--muted); margin-bottom: 4px; }
.bd-kanban__card-date { font-size: var(--text-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
/* Empty column = drop-zone affordance — same recipe as .kanbanEmpty */
.bd-kanban__empty {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2);
  padding: var(--space-5); text-align: center;
  color: var(--muted); font-size: var(--text-xs);
  opacity: 0.75;
  border: 1px dashed rgba(var(--accent-rgb), 0.18);
  border-radius: var(--radius-8);
  background: rgba(var(--accent-rgb), 0.03);
  transition: border-color var(--duration-base) var(--ease-default),
              background var(--duration-base) var(--ease-default),
              opacity var(--duration-base) var(--ease-default);
}
.bd-kanban__empty-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.12);
  color: var(--muted); /* P2-I (D14 / G-S4) : plus de teinte d'étape non légendée */
}
.bd-kanban__empty-icon svg { opacity: 0.85; }
.bd-kanban__col--drag-over .bd-kanban__empty {
  opacity: 1;
  border-color: transparent; /* single affordance: column border + filled zone (parity with .kanbanEmpty) */
  background: rgba(var(--accent-rgb), 0.10);
}
.bd-kanban__loading, .bd-kanban__error { padding: var(--space-6); text-align: center; color: var(--muted); }
.bd-kanban__error { color: var(--danger-text); }

@media (prefers-reduced-motion: reduce) {
  .bd-kanban__col, .bd-kanban__card, .bd-kanban__empty { transition: none; }
  .bd-kanban__card:hover { transform: none; }
}
@media (max-width: 768px) {
  .bd-kanban__board { gap: var(--space-2); }
  .bd-kanban__col { flex-basis: 75vw; }
}

/* WS-024 V2.3 — Retainer tranche cards (drawer Tranches tab) */
.pl-tranche-card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
}
.pl-tranche-card__head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: var(--space-2);
}
.pl-tranche-card__title { font-size: var(--text-base); font-weight: 600; color: var(--text); }
.pl-tranche-card__pct {
  font-size: var(--text-sm); font-weight: 600;
  background: rgba(var(--accent-rgb), 0.10); color: var(--accent);
  padding: 2px 10px; border-radius: var(--radius-full);
}
.pl-tranche-card__meta { font-size: var(--text-sm); color: var(--muted); margin-bottom: var(--space-2); }
.pl-tranche-card__status { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--muted); }
.pl-tranche-card__status.triggered { color: var(--success-text); font-weight: 500; }

/* WS-024 V2.7 — Feedback cards (drawer Feedback tab) */
.pl-feedback-card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
}
.pl-feedback-card__head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: var(--space-2);
}
.pl-feedback-card__title { font-size: var(--text-sm); font-weight: 600; color: var(--text); }
.pl-feedback-card__status {
  font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.3px;
  padding: 2px 10px; border-radius: var(--radius-full);
  background: rgba(var(--white-rgb), 0.06); color: var(--muted);
}
.pl-feedback-card__status.completed { background: rgba(var(--status-ok-rgb), 0.16); color: var(--success-text); }
.pl-feedback-card__status.sent { background: rgba(var(--accent-rgb), 0.14); color: var(--accent); }
.pl-feedback-card__meta { font-size: var(--text-xs); color: var(--muted); margin-bottom: var(--space-2); }
.pl-feedback-card__response p { margin: 4px 0; font-size: var(--text-sm); }

/* WS-024 V2.1 + V2.2 — Timesheets table (drawer Timesheets tab)
   Phase 11 visual quality polish (2026-04-27) :
   - Tabular-nums for numeric columns
   - Alternating row backgrounds for legibility
   - Hover state on rows
   - <tfoot> summary row emphasised
   - Action button row gap on right
*/
.pl-timesheets__head {
  display: flex; justify-content: flex-end; align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.pl-timesheets__head .btn { gap: 4px; }
.pl-timesheets-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.pl-timesheets-table th, .pl-timesheets-table td {
  padding: var(--space-2) var(--space-3); text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.pl-timesheets-table th {
  font-weight: 600; color: var(--muted);
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.4px;
}
.pl-timesheets-table tbody tr {
  transition: background var(--duration-fast) var(--ease-default);
}
.pl-timesheets-table tbody tr:nth-child(even) td {
  background: rgba(var(--white-rgb), 0.02);
}
.pl-timesheets-table tbody tr:hover td {
  background: rgba(var(--accent-rgb), 0.06);
}
.pl-timesheets-table tfoot td {
  font-weight: 700;
  border-top: 2px solid var(--border);
  border-bottom: none;
  padding-top: var(--space-3);
  color: var(--text);
}
.pl-timesheets-table__actions {
  text-align: right;
  white-space: nowrap;
}
.pl-timesheets-table__noaction {
  color: var(--muted);
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
}
.pl-timesheet-status {
  display: inline-block; padding: 2px 10px; border-radius: var(--radius-full);
  font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.3px;
  background: rgba(var(--white-rgb), 0.06); color: var(--muted);
}
.pl-timesheet-status--draft { background: rgba(var(--white-rgb), 0.08); color: var(--muted); }
.pl-timesheet-status--submitted { background: rgba(var(--accent-rgb), 0.14); color: var(--accent); }
.pl-timesheet-status--approved { background: rgba(var(--status-ok-rgb), 0.16); color: var(--success-text); }
.pl-timesheet-status--rejected { background: rgba(var(--data-rose-rgb), 0.14); color: var(--danger-text); }
.pl-timesheet-status--invoiced { background: rgba(var(--accent2-rgb, var(--accent-rgb)), 0.14); color: var(--accent2, var(--accent)); }
.pl-timesheet-status--paid { background: rgba(var(--status-ok-rgb), 0.20); color: var(--success-text); }

.pl-empty { padding: var(--space-4); text-align: center; color: var(--muted); font-size: var(--text-sm); }

/* Email preview modal — WS-024 V2.0c
   Réutilise le squelette de showModal (.modal-overlay + .modal-box) ; on
   styles juste les enfants spécifiques (controls, iframe wrap, send row). */
.email-preview-modal { display: flex; flex-direction: column; gap: var(--space-3); }
.email-preview-modal__context {
  display: inline-flex; align-self: flex-start; align-items: center;
  padding: var(--space-1) var(--space-3);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--accent); border-radius: var(--radius-full);
  font-size: var(--text-xs); font-weight: 600;
}
.email-preview-modal__controls {
  display: flex; gap: var(--space-3); flex-wrap: wrap;
}
.email-preview-modal__field {
  display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 160px;
}
.email-preview-modal__field > span {
  font-size: var(--text-xs); color: var(--muted); font-weight: 500;
}
.email-preview-modal__iframe-wrap {
  position: relative;
  /* R6 — theme-aware background (dark slate / bento warm / light ivory) */
  background: var(--bg-opaque, var(--card));
  border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden;
  min-height: 360px;
}
.email-preview-modal__iframe {
  width: 100%; height: 480px; border: 0; display: block;
  background: var(--white);
}
.email-preview-modal__iframe[aria-busy="true"] { opacity: 0.85; }
.email-preview-modal__send-row {
  display: flex; gap: var(--space-2); align-items: stretch;
}
.email-preview-modal__send-row .field { flex: 1; }
.email-preview-modal__hint {
  font-size: var(--text-xs); color: var(--muted); margin: 0;
}
@media (max-width: 480px) {
  .email-preview-modal__iframe { height: 360px; }
  .email-preview-modal__controls { flex-direction: column; }
  /* R7 — stacked send row on small phones to avoid horizontal scroll */
  .email-preview-modal__send-row { flex-direction: column; align-items: stretch; }
  .email-preview-modal__send-row .field { width: 100%; }
}

/* =============================================================================
   Sprint 2.7 — Guarantee timeline countdown bar + Activity feed
   ============================================================================= */

.pl-guarantee-bar {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); margin-bottom: var(--space-3);
  background: var(--bg1, var(--card));
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.pl-guarantee-bar__track {
  position: relative; height: 8px;
  background: rgba(var(--white-rgb), 0.06);
  border-radius: var(--radius-full);
  overflow: visible;
}
.pl-guarantee-bar__fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: linear-gradient(
    90deg,
    var(--status-ok) 0%,
    rgba(var(--status-ok-rgb), 0.7) 100%
  );
  border-radius: var(--radius-full);
  transition: width var(--duration-base) var(--ease-decel);
}
.pl-guarantee-bar__fill--warn {
  background: linear-gradient(
    90deg,
    var(--status-warn) 0%,
    rgba(var(--amber-rgb), 0.7) 100%
  );
}
.pl-guarantee-bar__fill--closed {
  background: var(--muted);
}
.pl-guarantee-bar__marker {
  position: absolute; top: -3px;
  width: 2px; height: 14px;
  background: var(--muted);
  z-index: 1;
}
.pl-guarantee-bar__marker[data-sent="1"] {
  background: var(--accent);
}
.pl-guarantee-bar__caption {
  font-size: var(--text-xs); color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Activity timeline (mirror cd-timeline pattern) */
.pl-timeline { position: relative; padding-left: var(--space-4); }
.pl-timeline::before {
  content: ''; position: absolute; left: 6px; top: 6px; bottom: 6px;
  width: 1px; background: var(--border);
}
.pl-timeline__item {
  position: relative; padding: var(--space-2) 0;
  display: flex; align-items: flex-start; gap: var(--space-2);
}
.pl-timeline__dot {
  position: absolute; left: -16px; top: 12px;
  width: 12px; height: 12px;
  background: var(--accent); border: 2px solid var(--card);
  border-radius: 50%; flex-shrink: 0;
}
.pl-timeline__dot[data-event="placement_created"] { background: var(--accent); }
.pl-timeline__dot[data-event="status_changed"]    { background: var(--accent2, var(--accent)); }
.pl-timeline__dot[data-event="placement_updated"] { background: var(--status-warn); }
.pl-timeline__dot[data-event="splits_replaced"]   { background: var(--status-ok); }
.pl-timeline__dot[data-event="placement_cancelled"] { background: var(--status-danger); }
.pl-timeline__body { flex: 1 1 auto; min-width: 0; }
.pl-timeline__head { display: flex; justify-content: space-between; gap: var(--space-2); }
.pl-timeline__event {
  font-size: var(--text-sm); font-weight: 500; color: var(--text);
  text-transform: capitalize;
}
.pl-timeline__date {
  font-size: var(--text-xs); color: var(--muted); flex-shrink: 0;
}
.pl-timeline__meta {
  margin-top: 2px; font-size: var(--text-xs); color: var(--muted);
}
.pl-timeline-skeleton { padding: var(--space-2) 0; }

@media (prefers-reduced-motion: reduce) {
  .pl-guarantee-bar__fill { transition: none !important; }
}

/* =============================================================================
   Sprint 2.8 — Cancel hardening : red banner + read-only terminal footer
   ============================================================================= */

.pl-cancelled-banner {
  display: flex; flex-direction: column; gap: 4px;
  padding: var(--space-3) var(--space-4);
  background: rgba(var(--data-rose-rgb), 0.10);
  border: 1px solid rgba(var(--data-rose-rgb), 0.35);
  border-left: 3px solid var(--status-danger, var(--danger-text));
  border-radius: var(--radius-sm);
}
.pl-cancelled-banner__title {
  font-size: var(--text-sm); font-weight: 600;
  color: var(--status-danger, var(--danger-text));
  letter-spacing: 0.01em;
}
.pl-cancelled-banner__meta {
  font-size: var(--text-xs); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.pl-cancelled-banner__reason {
  font-size: var(--text-sm); color: var(--text);
  font-style: italic; margin-top: var(--space-1);
  line-height: 1.5; word-break: break-word;
}

.pl-drawer__footer-lock {
  flex: 1 1 100%;
  font-size: var(--text-sm); color: var(--muted);
  font-style: italic; line-height: 1.4;
  padding: var(--space-2);
  text-align: center;
}

body.bento-theme .pl-cancelled-banner, body.atsiq-theme .pl-cancelled-banner {
  background: rgba(var(--data-rose-rgb), 0.14);
  border-color: rgba(var(--data-rose-rgb), 0.40);
}
body.light-theme .pl-cancelled-banner, body.atsiq-theme .pl-cancelled-banner {
  /* Sprint 2.11 audit fix : 6% was too faint on light bg → bumped to 12%
     to keep the danger semantic visually loud enough on white surfaces. */
  background: rgba(var(--data-rose-rgb), 0.12);
}

/* =============================================================================
   Sprint 2.11 audit cycle — token-only skeletons + mobile touch targets +
   completed reduced-motion coverage on placements module.
   ============================================================================= */

/* Token-only skeleton utilities for placements (replaces inline cssText) */
.pl-skeleton-cell {
  display: inline-block;
  width: 80%;
  height: var(--space-3, 12px);
}
.pl-skeleton-line {
  height: var(--space-4, 16px);
  margin: var(--space-2, 8px) 0;
  /* Width variance set via inline CSS variable from JS for randomized look */
  width: var(--pl-skel-w, 75%);
  border-radius: var(--radius-xs, 4px);
}

/* Mobile touch targets — WCAG 2.1 SC 2.5.5 Target Size Level AAA + 2.5.8
   Minimum (Level AA, 24×24). We standardise on 44×44 across the placements
   module to be safe for thumb-driven navigation. */
@media (max-width: 480px) {
  .placements-filters select,
  .placements-pane .btn,
  .placements-pane .btn--icon,
  .placements-table tbody tr {
    min-height: 44px;
  }
}

/* Reduced-motion coverage : the audit flagged transitions missing from the
   @media (prefers-reduced-motion: reduce) block. Adding them. */
@media (prefers-reduced-motion: reduce) {
  .pl-skeleton-cell,
  .pl-skeleton-line,
  .placement-status,
  .pl-cancelled-banner { transition: none !important; animation: none !important; }
}

/* ============================================================
   Phase 12.11 — DS §26.16/17/18 premium polish patterns.
   Coexist with existing .empty-state (which has its own
   __illustration variant). New modifiers are scoped to NOT
   collide : __icon / __title / __hint / __cta.
   ============================================================ */

/* §26.16 — Empty state (lighter, declarative variant) */
.empty-state__icon {
  color: var(--text-muted);
  opacity: 0.5;
  margin: 0 auto var(--space-3);
  display: block;
}
.empty-state__title {
  font-weight: 600;
  font-size: var(--text-md);
  color: var(--text);
  margin-bottom: var(--space-1);
}
.empty-state__hint {
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.55;
  margin-bottom: var(--space-3);
  max-width: 360px;
}
.empty-state__cta {
  margin-top: var(--space-2);
}

/* §26.18 — Skeleton loaders : 4 variants (row, card, list-item, detail) */
@keyframes skeleton-pulse {
  0% { opacity: 0.6; }
  50% { opacity: 0.95; }
  100% { opacity: 0.6; }
}
/* W3b: --surface-alt/#f5f5f4 et --border-subtle/#e7e5e4 = tokens manquants (ΔE>3 vs --surface) — à créer W5+ */
.skeleton {
  background: linear-gradient(90deg,
    var(--surface-alt, #f5f5f4) 0%,
    var(--border-subtle, #e7e5e4) 50%,
    var(--surface-alt, #f5f5f4) 100%);
  background-size: 200% 100%;
  border-radius: 6px;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
}
.skeleton--row { height: 36px; margin-bottom: 8px; }
.skeleton--card { height: 120px; margin-bottom: 12px; border-radius: var(--radius-md, 8px); }
.skeleton--list-item { height: 56px; margin-bottom: 4px; }
.skeleton--detail-line { height: 14px; margin-bottom: 8px; }
.skeleton--detail-line:nth-child(odd) { width: 90%; }
.skeleton--detail-line:nth-child(even) { width: 65%; }
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; opacity: 0.7; }
}

/* ────────────────────────────────────────────────────────────────────
 * Phase 13.A.5 — V2.2 Conversion drawer pane (9th tab) styles.
 * Read-only display + audit trail + cancel admin action.
 * Variants : light/bento via tokens, mobile ≤480, prefers-reduced-motion.
 * ──────────────────────────────────────────────────────────────────── */

.pl-conversion-pane {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-3) 0;
}

.pl-conversion-banner {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.pl-conversion-banner[data-state="pending"] {
  border-color: rgba(var(--status-warn-rgb), 0.40);
  background: rgba(var(--status-warn-rgb), 0.06);
}
.pl-conversion-banner[data-state="executed"] {
  border-color: rgba(var(--status-ok-rgb), 0.40);
  background: rgba(var(--status-ok-rgb), 0.06);
}

.pl-conversion-detail {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0;
}
.pl-conversion-detail dt {
  font-size: var(--text-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
}
.pl-conversion-detail dd {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.pl-conversion-trail h4 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
}
.pl-conversion-trail__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  position: relative;
  border-left: 2px solid var(--border);
  padding-left: var(--space-4);
}
.pl-conversion-trail__item {
  position: relative;
  display: flex;
  gap: var(--space-3);
  align-items: baseline;
  font-size: var(--text-sm);
}
.pl-conversion-trail__item::before {
  content: '';
  position: absolute;
  left: -22px;
  top: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--bg-popup);
  box-shadow: 0 0 0 1px var(--border);
}
.pl-conversion-trail__item[data-event="conversion_rejected"]::before { background: var(--status-danger); }
.pl-conversion-trail__item[data-event="conversion_executed"]::before { background: var(--status-ok); }
.pl-conversion-trail__item[data-event="conversion_cancelled"]::before { background: var(--status-warn); }
.pl-conversion-trail__ts {
  flex-shrink: 0;
  color: var(--muted);
  font-size: var(--text-xs);
  min-width: 90px;
}
.pl-conversion-trail__label {
  color: var(--text);
}

.pl-conversion-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* Conversion modal (form for "Convertir en CDI" trigger). */
.conv-modal .modal-content { max-width: 480px; }
.conv-modal-preview {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--card);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-xs);
  min-height: 32px;
}

/* Mobile responsive */
@media (max-width: 480px) {
  .pl-conversion-detail {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }
  .pl-conversion-detail dt {
    margin-top: var(--space-2);
  }
  .pl-conversion-trail__item {
    flex-direction: column;
    gap: 4px;
  }
  .pl-conversion-trail__ts { min-width: 0; }
}

/* prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .pl-conversion-banner,
  .pl-conversion-trail__item::before { transition: none !important; }
}

/* ────────────────────────────────────────────────────────────────────
 * Phase 13.B.1 (G1) — Cascade cancel modal styles
 * ──────────────────────────────────────────────────────────────────── */

.cascade-cancel-modal .modal-content--wide { max-width: 720px; }

.cascade-bulk-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.cascade-invoices-table {
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  overflow: hidden;
}
.cascade-invoices-table thead {
  background: var(--surface);
}
.cascade-invoices-table th {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
  font-weight: 600;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.cascade-invoices-table td {
  padding: var(--space-3);
  font-size: var(--text-sm);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.cascade-invoices-table tr:last-child td { border-bottom: 0; }
.cascade-invoices-table .cascade-action {
  width: 100%;
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  background: var(--card);
  color: var(--text);
  font-size: var(--text-sm);
}
.cascade-invoices-table .cascade-action:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 480px) {
  .cascade-cancel-modal .modal-content--wide { max-width: 100vw; padding: var(--space-3); }
  .cascade-invoices-table th,
  .cascade-invoices-table td { padding: var(--space-2); font-size: var(--text-xs); }
  .cascade-bulk-actions { flex-direction: column; }
  .cascade-bulk-actions .btn { width: 100%; }
}

/* ────────────────────────────────────────────────────────────────────
   Success KPIs Bento Dashboard (Plan A Phase 8.7 — 2026-05-04)
   Grid of 7 KPI cards consuming /api/admin/metrics/success-kpis.
   ──────────────────────────────────────────────────────────────────── */
.kpi-grid {
  width: 100%;
}
.kpi-grid__inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-4);
}
.kpi-grid__loading,
.kpi-grid__error {
  padding: var(--space-5);
  text-align: center;
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.kpi-grid__error { color: var(--danger-text); }

.kpi-card {
  padding: var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  transition: border-color var(--duration-base), transform var(--duration-base);
}
@media (hover: hover) {
  .kpi-card:hover {
    border-color: var(--border-accent);
    transform: translateY(-2px);
  }
}
.kpi-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.kpi-card__icon {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--accent);
}
.kpi-card__label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.kpi-card__value-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.kpi-card__value {
  font-size: var(--text-4xl);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.kpi-card__slo {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: var(--radius-full);
}
.kpi-card__slo--alert {
  background: rgba(var(--status-warn-rgb), 0.18);
  color: var(--status-warn);
  border: 1px solid rgba(var(--status-warn-rgb), 0.30);
}
.kpi-card__slo--critical {
  background: rgba(var(--status-danger-rgb), 0.18);
  color: var(--danger-text);
  border: 1px solid rgba(var(--status-danger-rgb), 0.30);
  animation: kpiSloCriticalPulse 1.6s var(--ease-default) infinite;
}
.kpi-card__helper {
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
}

@keyframes kpiSloCriticalPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--status-danger-rgb), 0.40); }
  50%      { box-shadow: 0 0 0 4px rgba(var(--status-danger-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .kpi-card { transition: none; }
  .kpi-card__slo--critical { animation: none; }
}

/* Mobile : single column, smaller value */
@media (max-width: 480px) {
  .kpi-grid__inner { grid-template-columns: 1fr; gap: var(--space-3); }
  .kpi-card__value { font-size: var(--text-3xl); }
}

/* ────────────────────────────────────────────────────────────────────
   Session Status — Avatar Pulse + Maintenance Imminent Banner
   (Plan A Phase 11.7 — 2026-05-04)
   ──────────────────────────────────────────────────────────────────── */

/* A) Token rotation visual cue — subtle pulse on header avatar */
.session-pulse {
  animation: sessionPulse 600ms var(--ease-default);
}
@keyframes sessionPulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--status-ok-rgb), 0.45); }
  60%  { box-shadow: 0 0 0 6px rgba(var(--status-ok-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--status-ok-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .session-pulse { animation: none; }
}

/* B) Maintenance imminent banner — sticky-top info, live countdown */
.banner--maintenance-imminent {
  position: sticky;
  top: 0;
  z-index: 99;
  width: 100%;
  min-height: 56px;
  padding: var(--space-3) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* Opaque base so scrolled page content never shows through the sticky banner
     (--bg-elevated is translucent — fine over a static page, not over scrolling
     content). The info→elevated gradient composites over it. */
  background-color: var(--bg1);
  background-image: linear-gradient(
    90deg,
    rgba(var(--info-rgb, var(--accent-rgb)), 0.15) 0%,
    var(--bg-elevated) 100%
  );
  border-bottom: 2px solid var(--accent);
  color: var(--text);
  animation: bannerSlideDown 300ms var(--ease-default);
}
.banner--maintenance-imminent .banner__icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}
.banner--maintenance-imminent .banner__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.banner--maintenance-imminent .banner__title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text);
}
.banner--maintenance-imminent .banner__desc {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}
.banner--maintenance-imminent .banner__countdown {
  flex: 0 0 auto;
  font-size: var(--text-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  padding: var(--space-1) var(--space-3);
  background: rgba(var(--accent-rgb), 0.10);
  border-radius: var(--radius-full);
}
.banner--maintenance-imminent.banner--dismissing {
  animation: bannerSlideUp 200ms var(--ease-default) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .banner--maintenance-imminent,
  .banner--maintenance-imminent.banner--dismissing { animation: none; }
}
@media (max-width: 480px) {
  .banner--maintenance-imminent {
    flex-wrap: wrap;
    padding: var(--space-3);
    min-height: 0;
  }
  .banner--maintenance-imminent .banner__text { flex: 1 1 calc(100% - 36px); }
  .banner--maintenance-imminent .banner__countdown {
    flex: 1 1 100%;
    text-align: center;
    margin-top: var(--space-2);
  }
}

/* ────────────────────────────────────────────────────────────────────
   Restored Data Modal (Plan A Phase 11.7 — 2026-05-04)
   Modal listing session_buffer entries (Phase 11.5) after maintenance,
   with per-item Open / Ignore + bulk Ignore-all.
   ──────────────────────────────────────────────────────────────────── */
.restore-modal {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  inset: 0;
  background: rgba(var(--black-rgb), 0.55);
  z-index: var(--z-modal);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  animation: fadeIn 0.2s var(--ease-default);
}
.restore-modal__box {
  width: min(640px, 92vw);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg, 0 20px 50px rgba(var(--black-rgb), 0.4));
  overflow: hidden;
}
.restore-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}
.restore-modal__head .h1 {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 600;
}
.restore-modal__body {
  padding: var(--space-4) var(--space-5);
  overflow-y: auto;
  max-height: calc(85vh - 180px);
}
.restore-modal__subtitle {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}
.restore-modal__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.restore-modal__loading,
.restore-modal__empty,
.restore-modal__error {
  padding: var(--space-5) var(--space-3);
  text-align: center;
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.restore-modal__error { color: var(--danger-text); }

.restore-item {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg1);
  transition: opacity var(--duration-base), transform var(--duration-base);
}
.restore-item--processed {
  opacity: 0;
  transform: translateX(20px);
  pointer-events: none;
}
.restore-item__icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--accent);
}
.restore-item__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.restore-item__title {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}
.restore-item__meta {
  font-size: var(--text-xs);
  color: var(--muted);
}
.restore-item__preview {
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-style: italic;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.restore-item__actions {
  display: flex;
  gap: var(--space-1);
  align-items: center;
}
.restore-modal__actions {
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
}

@media (prefers-reduced-motion: reduce) {
  .restore-modal { animation: none; }
  .restore-item { transition: none; }
}
@media (max-width: 480px) {
  .restore-modal__box {
    width: 100vw; height: 100vh; max-height: 100vh; border-radius: 0;
  }
  .restore-modal__body { max-height: calc(100vh - 160px); }
  .restore-item { grid-template-columns: 24px 1fr; }
  .restore-item__actions { grid-column: 1 / -1; justify-content: flex-end; }
  .restore-item__icon { width: 24px; height: 24px; }
}

/* ────────────────────────────────────────────────────────────────────
   Security Banner (Plan A Phase 11.7 — 2026-05-04)
   Sticky-top alert shown after a family compromise has been detected.
   Triggered by ?security=session_revoked URL param on landing.
   ──────────────────────────────────────────────────────────────────── */
.banner--security {
  position: sticky;
  top: 0;
  z-index: 100;
  width: 100%;
  min-height: 56px;
  padding: var(--space-3) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* Opaque base so scrolled page content never shows through the sticky banner
     (--bg-elevated is translucent — fine over a static page, not over scrolling
     content). The warn→elevated gradient composites over it. */
  background-color: var(--bg1);
  background-image: linear-gradient(
    90deg,
    rgba(var(--status-warn-rgb), 0.15) 0%,
    var(--bg-elevated) 100%
  );
  border-bottom: 2px solid var(--status-warn);
  color: var(--text);
  animation: bannerSlideDown 300ms var(--ease-default);
}
.banner--security .banner__icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--status-warn);
}
.banner--security .banner__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.banner--security .banner__title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text);
}
.banner--security .banner__desc {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.4;
}
.banner--security .banner__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.banner--security.banner--dismissing {
  animation: bannerSlideUp 200ms var(--ease-default) forwards;
}

@keyframes bannerSlideDown {
  from { transform: translateY(-100%); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes bannerSlideUp {
  from { transform: translateY(0); opacity: 1; }
  to   { transform: translateY(-100%); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .banner--security,
  .banner--security.banner--dismissing { animation: none; }
}

/* Mobile : stack title/desc above actions, reduce padding */
@media (max-width: 480px) {
  .banner--security {
    flex-wrap: wrap;
    padding: var(--space-3);
    min-height: 0;
  }
  .banner--security .banner__text { flex: 1 1 calc(100% - 36px); }
  .banner--security .banner__actions {
    flex: 1 1 100%;
    margin-top: var(--space-2);
    justify-content: flex-end;
  }
}

/* ────────────────────────────────────────────────────────────────────
   LOT G — Bannière « pack légal à régulariser » (org pending_legal)
   Sticky-top, owner/admin. Premium via variables (zéro couleur en dur) :
   fond carte, accent warning, hairline divider. Réutilise les primitives
   .banner__ partagées (icon/text/title/desc/actions/cta).
   ──────────────────────────────────────────────────────────────────── */
.banner--legal-pending {
  position: sticky;
  top: 0;
  z-index: 100;
  width: 100%;
  min-height: 56px;
  padding: var(--space-3) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* Opaque base so scrolled page content never shows through the sticky banner
     (--card/--card2/--bg-elevated are all translucent — fine over a static page,
     not over scrolling content). The warn→card gradient composites over it. */
  background-color: var(--bg1);
  background-image: linear-gradient(
    90deg,
    rgba(var(--status-warn-rgb), 0.12) 0%,
    var(--card) 100%
  );
  border-bottom: 2px solid var(--warning-text);
  color: var(--text);
  animation: bannerSlideDown 300ms var(--ease-default);
}
.banner--legal-pending .banner__icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--warning-text);
}
.banner--legal-pending .banner__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.banner--legal-pending .banner__title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text);
}
.banner--legal-pending .banner__desc {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.4;
}
.banner--legal-pending .banner__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.banner--legal-pending.banner--dismissing {
  animation: bannerSlideUp 200ms var(--ease-default) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .banner--legal-pending,
  .banner--legal-pending.banner--dismissing { animation: none; }
}

/* Mobile : stack title/desc above the CTA, reduce padding */
@media (max-width: 480px) {
  .banner--legal-pending {
    flex-wrap: wrap;
    padding: var(--space-3);
    min-height: 0;
  }
  .banner--legal-pending .banner__text { flex: 1 1 calc(100% - 36px); }
  .banner--legal-pending .banner__actions {
    flex: 1 1 100%;
    margin-top: var(--space-2);
    justify-content: flex-end;
  }
}

/* ────────────────────────────────────────────────────────────────────
   Security — Active Sessions Modal (Plan A Phase 11.7 — 2026-05-04)
   Modal listing active OAuth refresh-token families with per-item revoke
   + bulk "revoke all others". Pattern : Stripe / GitHub / 1Password.
   ──────────────────────────────────────────────────────────────────── */
.security-sessions-modal {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  inset: 0;
  background: rgba(var(--black-rgb), 0.55);
  z-index: var(--z-modal);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  animation: fadeIn 0.2s var(--ease-default);
}
.security-sessions-box {
  width: min(560px, 92vw);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg, 0 20px 50px rgba(var(--black-rgb), 0.4));
  overflow: hidden;
}
.security-sessions-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}
.security-sessions-head .h1 {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: 600;
}
.security-sessions-body {
  padding: var(--space-4) var(--space-5);
  overflow-y: auto;
  max-height: calc(85vh - 180px);
}
.security-sessions__subtitle {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
}
.security-sessions__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.security-sessions__loading,
.security-sessions__empty,
.security-sessions__error {
  padding: var(--space-5) var(--space-3);
  text-align: center;
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.security-sessions__error { color: var(--danger-text); }

.session-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg1);
  transition: border-color var(--duration-base), opacity var(--duration-base);
}
@media (hover: hover) {
  .session-item:hover {
    border-color: var(--border-accent);
  }
}
.session-item--revoked {
  opacity: 0;
  transform: translateX(20px);
  pointer-events: none;
}
.session-item__icon {
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--accent);
}
.session-item__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.session-item__device {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.session-item__meta {
  font-size: var(--text-xs);
  color: var(--muted);
}
.session-item__right {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}
.security-sessions-actions {
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
}
.security-sessions__revoke-all:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* prefers-reduced-motion : disable fade-in + transition */
@media (prefers-reduced-motion: reduce) {
  .security-sessions-modal { animation: none; }
  .session-item { transition: none; }
  .session-item--revoked { transition: none; }
}

/* Mobile — stack item layout, sticky footer */
@media (max-width: 480px) {
  .security-sessions-box {
    width: 100vw;
    height: 100vh;
    max-height: 100vh;
    border-radius: 0;
  }
  .security-sessions-body {
    max-height: calc(100vh - 160px);
  }
  .session-item {
    flex-wrap: wrap;
  }
  .session-item__body { flex: 1 1 calc(100% - 50px); }
  .session-item__right { flex: 1 1 100%; justify-content: flex-end; }
}

/* ────────────────────────────────────────────────────────────────────
   Autosave Indicator (Plan A Phase 11.7 — 2026-05-04)
   Non-intrusive status pill for forms with auto-save (CV draft, mock
   interview transcripts, IE entries, message drafts). Appears bottom-
   right of viewport (or scoped to form via [data-autosave-anchor]).
   States : idle (hidden) / saving (spinner) / saved (check) / error.
   A11y : role="status" aria-live="polite" — explicit text, not icon-only.
   ──────────────────────────────────────────────────────────────────── */
.indicator--autosave {
  position: fixed;
  bottom: var(--space-4);
  right: var(--space-4);
  z-index: var(--z-toast, 80);
  display: none; /* hidden by default — JS swaps to flex on state change */
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  font-size: var(--text-sm);
  color: var(--text);
  pointer-events: none; /* never block clicks; retry button gets pointer-events:auto */
  opacity: 0;
  transition: opacity 200ms var(--ease-default), transform 200ms var(--ease-default);
}

/* Scoped variant — anchored to a specific form/container instead of viewport */
.indicator--autosave[data-anchor="local"] {
  position: sticky;
  bottom: var(--space-4);
  right: var(--space-4);
  margin-left: auto;
}

.indicator--autosave.indicator--saving,
.indicator--autosave.indicator--saved,
.indicator--autosave.indicator--error {
  display: inline-flex;
  opacity: 1;
}

.indicator--autosave.indicator--saved {
  border-color: rgba(var(--status-ok-rgb), 0.30);
  color: var(--status-ok);
}

.indicator--autosave.indicator--error {
  border-color: rgba(var(--status-danger-rgb), 0.30);
  color: var(--danger-text);
  pointer-events: auto; /* retry button needs to be clickable */
}

/* Spinner (saving state) */
.indicator--autosave .indicator-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(var(--accent-rgb), 0.20);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
  flex-shrink: 0;
}

/* Check icon (saved state) — pulse subtle once */
.indicator--autosave.indicator--saved .indicator-icon {
  animation: indicatorSavedPulse 0.5s var(--ease-default) 1;
}

@keyframes indicatorSavedPulse {
  0%   { transform: scale(0.6); opacity: 0; }
  50%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* Retry button (error state) */
.indicator--autosave .indicator-retry {
  height: 22px;
  padding: 0 8px;
  font-size: var(--text-xs);
  border-radius: var(--radius-xs);
  border: 1px solid rgba(var(--status-danger-rgb), 0.30);
  background: transparent;
  color: var(--danger-text);
  cursor: pointer;
  transition: background 150ms var(--ease-default);
}
@media (hover: hover) {
  .indicator--autosave .indicator-retry:hover {
    background: rgba(var(--status-danger-rgb), 0.10);
  }
}
.indicator--autosave .indicator-retry:focus-visible {
  /* Plan A audit polish — box-shadow ring DS-canonical (matches all
     other Phase 11.7 components). Outline removed in favour of a
     spread shadow that matches surrounding components' focus state. */
  outline: none;
  box-shadow: 0 0 0 3px rgba(var(--status-danger-rgb), 0.30);
}

/* prefers-reduced-motion : disable spinner rotation + pulse */
@media (prefers-reduced-motion: reduce) {
  .indicator--autosave .indicator-spinner { animation: none; opacity: 0.5; }
  .indicator--autosave.indicator--saved .indicator-icon { animation: none; }
  .indicator--autosave { transition: opacity 0s; }
}

/* Mobile : compact + bottom-center alignment to avoid floating-action overlap.
   Plan A audit fix : retry button gets 44×44 min size on touch devices for
   WCAG 2.5.5 Target Size (AA). */
@media (max-width: 480px) {
  .indicator--autosave .indicator-retry {
    min-width: 44px;
    min-height: 44px;
    height: auto;
    padding: 8px 12px;
  }
  .indicator--autosave {
    bottom: calc(var(--space-3) + env(safe-area-inset-bottom));
    right: 50%;
    transform: translateX(50%);
    font-size: var(--text-xs);
    padding: 6px 10px;
  }
}

/* ────────────────────────────────────────────────────────────────────
   OAuth Activity Bento Dashboard (Plan A Phase 11.7 — 2026-05-05)
   4-axis tracking : cost / quota / errors / security.
   Sibling pattern to .kpi-grid (Phase 8.7).
   ──────────────────────────────────────────────────────────────────── */
.oauth-bento { width: 100%; }
.oauth-bento__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-4);
}
.oauth-bento__loading,
.oauth-bento__error {
  padding: var(--space-5);
  text-align: center;
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.oauth-bento__error { color: var(--danger-text); }

.oauth-axis {
  padding: var(--space-4);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.oauth-axis__head { display: flex; align-items: center; justify-content: space-between; }
.oauth-axis__title {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0;
}
.oauth-axis__body { display: flex; flex-direction: column; gap: var(--space-2); }
.oauth-axis__big {
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.oauth-axis__helper {
  font-size: var(--text-xs);
  color: var(--muted);
  line-height: 1.4;
}

.oauth-axis__table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  margin-top: var(--space-2);
}
.oauth-axis__table th,
.oauth-axis__table td {
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border-soft, var(--border));
}
.oauth-axis__table th { color: var(--text-secondary); font-weight: 500; }

.oauth-axis__breakdown {
  list-style: none;
  margin: var(--space-2) 0 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.oauth-axis__breakdown li {
  display: flex;
  justify-content: space-between;
  font-size: var(--text-sm);
  padding: 4px 6px;
  border-bottom: 1px dashed var(--border-soft, var(--border));
}
.oauth-axis__breakdown-key { color: var(--text-secondary); }
.oauth-axis__breakdown-val { color: var(--text); font-variant-numeric: tabular-nums; }

.oauth-axis__sec-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}
.oauth-axis__sec-stat {
  padding: var(--space-2);
  border-radius: var(--radius-md);
  /* W3b: --bg-rgb non défini ; rgba(12,18,32)≈bg1 Obsidian mais pas de token rgb exact — candidat nouvelle var sémantique W5+ */
  background: rgba(var(--bg-rgb, 12, 18, 32), 0.4);
  border: 1px solid var(--border);
  text-align: center;
}
.oauth-axis__sec-val {
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.oauth-axis__sec-label {
  font-size: var(--text-2xs);
  color: var(--muted);
  margin-top: 4px;
  line-height: 1.2;
}
.oauth-axis__sec-stat--critical {
  border-color: rgba(var(--status-danger-rgb), 0.30);
}
.oauth-axis__sec-stat--critical .oauth-axis__sec-val {
  color: var(--danger-text);
}
.oauth-axis__sec-stat--warn {
  border-color: rgba(var(--status-warn-rgb), 0.30);
}
.oauth-axis__sec-stat--warn .oauth-axis__sec-val {
  color: var(--status-warn);
}

@media (max-width: 480px) {
  .oauth-bento__grid { grid-template-columns: 1fr; }
  .oauth-axis__sec-grid { grid-template-columns: 1fr; }
}

/* ============================================================
 * Career Discovery — `.from-path-context-banner`
 * --------------------------------------------------------------
 * Unified DS component (Phase E refactor 2026-05-20) replacing the
 * three near-identical banners previously living in candidate.css :
 *   - .cjs-path-filter-chip (jobs pane, filter context)
 *   - .mi-path-banner       (mock interview form, prefill context)
 *   - .cert-path-banner     (cert roadmap, recommendations context)
 *
 * One DOM scaffold, one CSS rule, three consumers. Same visual
 * language, same DS tokens, dual-theme aware. Markup contract :
 *   <div class="from-path-context-banner" role="status" aria-live="polite">
 *     <span class="from-path-context-banner__dot" aria-hidden="true">🎯</span>
 *     <span class="from-path-context-banner__label">{i18n message}</span>
 *     <button class="from-path-context-banner__clear" aria-label="…">×</button>
 *   </div>
 * Used wherever the user has been "transported" from a Star Map drawer
 * CTA and we want to show the source context + offer a clear-out.
 * ============================================================ */
.from-path-context-banner {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-3);
  background: rgba(var(--accent-rgb), 0.10);
  border: 1px solid rgba(var(--accent-rgb), 0.30);
  color: var(--text);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  line-height: 1.3;
}
.from-path-context-banner__dot { font-size: var(--text-md); line-height: 1; }
.from-path-context-banner__label { flex: 1 1 auto; font-weight: 500; }
.from-path-context-banner__clear {
  appearance: none; background: transparent;
  border: 1px solid transparent; color: var(--text-secondary);
  cursor: pointer; width: 26px; height: 26px;
  border-radius: var(--radius-full);
  font-size: var(--text-lg); line-height: 1; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast);
}
.from-path-context-banner__clear:hover {
  background: rgba(var(--accent-rgb), 0.18);
  color: var(--text);
  border-color: rgba(var(--accent-rgb), 0.45);
}
.from-path-context-banner__clear:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
html.bento-theme .from-path-context-banner,
body.bento-theme .from-path-context-banner, body.atsiq-theme .from-path-context-banner {
  background: rgba(var(--accent-rgb), 0.10);
  border-color: rgba(var(--accent-rgb), 0.35);
}


/* ===== NOTIFICATION BELL + DROPDOWN — moved here from recruiter.css (2026-06-10) so the
   topbar notification component is styled for ALL roles (admin/mentor/candidate had an
   unstyled dropdown — recruiter.css is role-gated). Single source of truth. ===== */
/* ============================================================
   NOTIFICATION BELL + DROPDOWN (Alpha 23.10)
   ============================================================ */
.headerNotifBell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-size: var(--text-lg);
  cursor: pointer;
  border-radius: 50%;
  /* iOS Safari: see .langToggle / .userBtn--avatar / .themeToggle — prevents
     300ms tap delay + phantom click synthesis. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: all var(--duration-base) var(--ease-default);
}
@media (hover: hover) {
  .headerNotifBell:hover {
    background: var(--card2);
    transform: translateY(-1px);
  }
}
.headerNotifBell:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.headerNotifBell .notifBadge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--status-danger);
  color: var(--text-inverse);
  font-size: var(--text-xs);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  border: 2px solid var(--bg);
  box-shadow: 0 2px 6px rgba(var(--status-danger-rgb), 0.4);
  animation: notifPulse 2s ease-in-out infinite;
}

/* Dropdown */
.notif-dropdown {
  /* On open, toggleNotifDropdown() portals this to <body> (escape the topbar stacking
     context, iOS-Safari-safe) and sets top/left from the bell's getBoundingClientRect
     (viewport coords) via ctApplyDynamicStyles. Those JS coords are a single-class rule
     (0,1,0); if the base rule ALSO sets top/right (also 0,1,0) and recruiter.css loads
     AFTER the dynamic stylesheet (lazy role-CSS on atsiq/admin), the base wins on cascade
     order and `top:100%` drops the panel to the bottom of the screen. So the base must
     own only position+size+appearance and leave top/left/right entirely to the JS. */
  position: fixed;
  width: 360px;
  max-height: 480px;
  background: var(--card2);
  -webkit-backdrop-filter: blur(28px);
  backdrop-filter: blur(28px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-modal);
  z-index: var(--z-popover);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
@media (max-width: 768px) {
  .notif-dropdown {
    /* top/left/right are set by JS (full-width, below the bell); keep only size here so the
       base rule never competes with the JS coords on cascade order. */
    width: 100% !important; border-radius: 0 0 var(--radius-12) var(--radius-12);
    max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px);
  }
}
.notif-dropdown-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: var(--text-base);
  color: var(--text);
}
.notif-dropdown-header .btn-link {
  background: none;
  border: none;
  color: var(--primary);
  font-size: var(--text-xs);
  cursor: pointer;
  padding: 0;
}
.notif-dropdown-header .btn-link:hover {
  text-decoration: underline;
}
.notif-dropdown-list {
  /* P2-I (D19, jury 46 « item tranché à mi-hauteur / dernier item clippé ») : le double
     plafond (parent 480px + liste 380px) coupait le flux 100px avant le bas du panneau et,
     sur mobile, bridait la liste à 380px alors que le panneau montait à 100dvh. La liste
     n'a plus de plafond propre : elle prend la hauteur restante du flex (min-height:0 —
     sans lui un enfant scrollable déborde au lieu de scroller) et rend la coupe LISIBLE
     (padding de fin + scrollbar fine) au lieu de trancher un item au ras du bord. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-block-end: var(--space-2);
  scroll-padding-block-end: var(--space-2);
  scrollbar-width: thin;
}
.notif-dropdown-footer {
  border-top: 1px solid var(--border);
  padding: var(--space-2) var(--space-4);
  text-align: center;
}
.notif-dropdown-footer .btn-link {
  background: none;
  border: none;
  color: var(--primary);
  font-size: var(--text-sm);
  cursor: pointer;
  padding: 0;
}
.notif-dropdown-footer .btn-link:hover {
  text-decoration: underline;
}

/* Notification items */
.notif-item {
  display: flex;
  gap: 10px;
  padding: 10px 16px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  transition: background var(--duration-fast) var(--ease-default);
}
.notif-item:hover {
  background: var(--card2);
}
.notif-item.unread {
  border-left: 4px solid var(--primary);
  background: rgba(var(--primary-rgb), 0.08);
}
.notif-item.unread .notif-item-title::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
  margin-right: 6px;
  vertical-align: middle;
  flex-shrink: 0;
}
/* W1a §4.2 — bande de sévérité SOTA sur la ligne. `info` (défaut des ~100 autres types) = AUCUNE
   bande → zéro changement visuel (zéro-régression). ⛔ La couleur ne porte jamais le sens seule :
   l'icône expose role="img"+aria-label(sévérité) et le titre porte le mot. Jetons existants only. */
.notif-item[data-severity="critical"] {
  border-left: 3px solid var(--danger-text);
}
.notif-item[data-severity="warning"] {
  border-left: 3px solid var(--warning-text);
}
.notif-item-icon[data-severity="critical"] {
  color: var(--danger-text);
}
.notif-item-icon[data-severity="warning"] {
  color: var(--warning-text);
}
.notif-item-icon {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(var(--primary-rgb), 0.1);
  color: var(--primary);
  font-size: var(--text-xs);
}
.notif-item-content {
  flex: 1;
  min-width: 0;
}
.notif-item-title {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notif-item-body {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notif-item-time {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 3px;
}
.notif-empty {
  padding: var(--space-7) var(--space-4);
  text-align: center;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}
.notif-empty__icon {
  /* P2-I (D19 / G-S3) : plus d'emoji système dans le chrome — picto LIGNE inline, mêmes
     conventions que le set du kit (viewBox 24, stroke currentColor). */
  line-height: 0;
  color: var(--muted);
  text-align: center;
  filter: drop-shadow(0 2px 8px rgba(var(--accent-rgb), 0.15));
  animation: emptyFloat 3s ease-in-out infinite;
  transform-origin: center center;
}
.notif-empty__title {
  font-weight: 700;
  font-size: var(--text-sm);
  color: var(--text);
}
.notif-empty__hint {
  font-size: var(--text-xs);
  color: var(--muted);
  max-width: 220px;
  line-height: 1.5;
}


/* Notification preferences grid */
.notif-prefs-grid {
  display: grid;
  gap: 0;
}
.notif-pref-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) repeat(3, 80px);
  align-items: center;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-sm);
}
.notif-pref-row.notif-pref-header {
  font-weight: 600;
  font-size: var(--text-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.notif-pref-row span:not(:first-child) {
  text-align: center;
}
.notif-pref-category {
  padding: 12px 0 4px;
  font-weight: 600;
  font-size: var(--text-xs);
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border-bottom: 1px solid rgba(var(--primary-rgb), 0.15);
  margin-top: var(--space-2);
}
.notif-pref-category:first-child {
  margin-top: 0;
}

/* Light theme adjustments */
body.light-theme .notif-dropdown,
body.bento-theme .notif-dropdown, body.atsiq-theme .notif-dropdown {
  background: linear-gradient(168deg, rgba(var(--lavender-rgb), 0.98) 0%, rgba(var(--lavender-deep-rgb), 0.98) 100%);
  -webkit-backdrop-filter: blur(28px);
  backdrop-filter: blur(28px);
  border-color: rgba(var(--status-muted-rgb), 0.20);
  box-shadow: var(--shadow-modal);
}
body.light-theme .notif-dropdown-header,
body.bento-theme .notif-dropdown-header, body.atsiq-theme .notif-dropdown-header {
  color: var(--fg);
  border-bottom-color: var(--border);
}
body.light-theme .notif-item,
body.bento-theme .notif-item, body.atsiq-theme .notif-item {
  border-bottom-color: var(--border);
}
body.light-theme .notif-item:hover,
body.bento-theme .notif-item:hover, body.atsiq-theme .notif-item:hover {
  background: rgba(var(--primary-rgb), 0.06);
}
body.light-theme .notif-item.unread,
body.bento-theme .notif-item.unread, body.atsiq-theme .notif-item.unread {
  background: rgba(var(--primary-rgb), 0.06);
}
body.light-theme .notif-item-title,
body.bento-theme .notif-item-title, body.atsiq-theme .notif-item-title {
  color: var(--fg);
}
body.light-theme .notif-item-body,
body.bento-theme .notif-item-body, body.atsiq-theme .notif-item-body {
  color: var(--muted);
}
body.light-theme .notif-item-time,
body.bento-theme .notif-item-time, body.atsiq-theme .notif-item-time {
  color: var(--muted);
}
body.light-theme .notif-dropdown-footer,
body.bento-theme .notif-dropdown-footer, body.atsiq-theme .notif-dropdown-footer {
  border-top-color: var(--border);
}
body.light-theme .notif-empty,
body.bento-theme .notif-empty, body.atsiq-theme .notif-empty {
  color: var(--muted);
}

/* ────────────────────────────────────────────────────────────────
   .ct-toggle — primitive partagée (promue depuis employer-clients.css
   pour usage Settings/Confidentialité B.2.5 ; le doublon rôle-CSS sera
   dédupliqué en W5). Switch binaire data-on driven (DS §.ct-toggle).
   ──────────────────────────────────────────────────────────────── */
.ct-toggle {
  --size: 22px;
  position: relative; width: calc(var(--size) * 2); height: var(--size);
  background: rgba(var(--status-muted-rgb), 0.35);
  border-radius: var(--radius-full);
  cursor: pointer;
  transition: background var(--duration-base), box-shadow var(--duration-base);
  border: 1px solid rgba(var(--status-muted-rgb), 0.45);
  flex: 0 0 auto;
}
.ct-toggle::after {
  content: ''; position: absolute; top: 1px; left: 1px;
  width: calc(var(--size) - 4px); height: calc(var(--size) - 4px);
  background: var(--text); border-radius: 50%;
  transition: transform var(--duration-base) var(--ease-default, cubic-bezier(.2,.7,.3,1)),
              background var(--duration-base);
  box-shadow: 0 2px 5px rgba(var(--black-rgb), 0.35);
}
.ct-toggle[data-on="true"] {
  background: var(--gradient-primary);
  border-color: var(--accent);
  box-shadow: 0 0 12px -2px rgba(var(--accent-rgb), 0.5);
}
.ct-toggle[data-on="true"]::after {
  transform: translateX(var(--size));
  background: var(--text);
}
.ct-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.ct-toggle[data-disabled="true"] { opacity: 0.4; cursor: not-allowed; }

/* B.2.5 — rangées de consentement (Settings > Confidentialité) */
.privacyTrackingRow {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}
.privacyTrackingRow:last-of-type { border-bottom: none; }
.privacyTrackingText { min-width: 0; }

/* ─── B6 LOT2 — Admin "Éditer la carte mentor" contract sub-card ──────────── */

/* A1 — Contract section group card */
.mentor-contract-card {
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-4) var(--space-3);
  margin-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.mentor-contract-card__label {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
  margin: 0 0 var(--space-1);
}

/* A2 — Toggle switch (matches the pattern used in admin-finances.js;
   .toggle-switch / .toggle-slider are NOT in any other admin-cascade CSS file,
   so we define them here — components.css is in the admin cascade). */
.toggle-switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
}
.toggle-switch input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}
/* grincheux-R-06 / persona-R-03 / da-03 (re-gate P2-Z) — UNE SEULE PEINTURE POUR UN SEUL GESTE.
   Le kit a corrigé `ctSwitch` (piste OFF ≥3:1, bouton contrasté, MARQUE DE FORME ○/| pour
   WCAG 1.4.1) mais la famille LEGACY `.toggle-switch/.toggle-slider` — le même geste, rendu
   par les surfaces non encore migrées (admin finances/système, préférences d'emploi,
   notifications, société, conformité) — gardait sa peinture d'origine : piste OFF à
   `rgba(--white-rgb, 0.12)` (mesurée 1,34:1 contre le fond, invisible), bouton `--muted`,
   piste ON en voile d'accent à 25 %, et AUCUNE marque de forme. Deux interrupteurs opposés
   pour un même réglage.
   La géométrie (40×22, bouton 16, course 18) est INCHANGÉE — seule la SOURCE des couleurs
   change : les tokens du kit (components-recruiter.css), avec repli sur des voiles de la
   couleur de TEXTE pour les shells qui ne chargent pas cette feuille (candidat/mentor), où
   l'ancienne valeur était de toute façon sous le seuil. Les surcharges par thème d'origine
   disparaissent : les tokens sont déjà thémés, une seule déclaration suffit. */
.toggle-slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background: var(--ctk-switch-track-off, rgba(var(--text-rgb), 0.60));
  border: 1px solid var(--ctk-switch-track-off-border, rgba(var(--text-rgb), 0.75));
  border-radius: var(--radius-full);
  transition: background 0.2s, border-color 0.2s;
}
.toggle-slider::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  top: 2px;
  left: 2px;
  background: var(--ctk-switch-knob-off, var(--bg1));
  border-radius: var(--radius-full);
  transition: transform 0.2s, background 0.2s;
}
/* Marque de FORME dans le bouton (mêmes 7px / 2×8px que le kit) : ○ en OFF, | en ON.
   Le bouton legacy est un ::before, la marque prend donc le ::after et suit la même course. */
.toggle-slider::after {
  content: '';
  position: absolute;
  box-sizing: border-box;
  top: 10px;
  left: 10px;
  width: 7px;
  height: 7px;
  transform: translate(-50%, -50%);
  border-radius: var(--radius-full);
  border: 1px solid var(--ctk-switch-track-off-border, rgba(var(--text-rgb), 0.75));
  background: transparent;
  transition: transform 0.2s, width 0.2s, height 0.2s, background 0.2s, border-radius 0.2s;
}
.toggle-switch input:checked + .toggle-slider {
  background: var(--ctk-cta-bg, var(--accent));
  border-color: var(--ctk-cta-bg, var(--accent));
}
.toggle-switch input:checked + .toggle-slider::before {
  transform: translateX(18px);
  background: var(--on-primary, var(--bg1));
}
.toggle-switch input:checked + .toggle-slider::after {
  transform: translate(calc(-50% + 18px), -50%);
  width: 2px;
  height: 8px;
  border-width: 0;
  border-radius: var(--radius-xs);
  background: var(--ctk-cta-bg, var(--accent));
}
.toggle-switch input:focus-visible + .toggle-slider {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A3 — Warning-glyph ::before on .hint.warn (CSP-safe, survives JS textContent) */
.hint.warn::before {
  content: '⚠\FE0E';   /* U+26A0 + U+FE0F variation selector → text glyph */
  margin-right: 6px;
  color: var(--warning-text);
  font-style: normal;
}

/* A4 — "Télécharger le contrat type" as a deliberate DS secondary button inside
   the contract card. (Underline reset moved to base `.btn` — DS-Canon S1
   2026-07-13.) Adds a download glyph + hover, and sizes to content so it
   matches the modal's button family rather than looking like inline text. */
.mentor-contract-card .btn.btn--secondary {
  border-color: var(--accent);
  align-self: flex-start;
  gap: var(--space-2);
}
.mentor-contract-card .btn.btn--secondary::before {
  content: '\2913';   /* U+2913 ⤓ downwards-arrow-to-bar → download affordance */
  font-size: 1.05em;
  line-height: 1;
}
@media (hover: hover) {
  .mentor-contract-card .btn.btn--secondary:hover {
    background: rgba(var(--accent-rgb), 0.12);
    border-color: var(--accent);
  }
}
/* ─────────────────────────────────────────────────────────────────────────── */

/* ===========================================================================
   U7.4 — DS PRIMITIVES: .stat-mini + .skill-badge (gotcha #23)
   These lived in recruiter-sourcing.css, which is NOT loaded on every surface
   that needs them (the person card ② / mini-modal ③, admin-sourcing) → they
   rendered UNSTYLED. Promoted here (components.css = global DS, loaded on every
   role) so any surface can reuse them. Token-only; theme-aware via variables.css.
   =========================================================================== */
.stat-mini {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-3);
  background: var(--card);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  box-shadow: 0 1px 3px rgba(var(--black-rgb), 0.04);
  transition: border-color var(--duration-base), box-shadow var(--duration-base);
}
.stat-mini:hover {
  border-color: var(--accent);
  box-shadow: 0 2px 8px rgba(var(--primary-rgb), 0.08);
}
.stat-mini__label {
  font-size: var(--text-xs);
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.stat-mini__value {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--fg);
}
body.bento-theme .stat-mini, body.atsiq-theme .stat-mini {
  background: rgba(var(--white-rgb), 0.6);
}

/* Skill badge base + variants (matched / inferred / missing) */
.skill-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-full, 9999px);
  font-size: var(--text-xs);
  font-weight: 500;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.skill-badge--matched {
  background: rgba(var(--status-ok-rgb, 34, 197, 94), 0.12);
  color: var(--status-ok);
  font-weight: 600;
}
.skill-badge--inferred {
  background: rgba(var(--primary-rgb), 0.1);
  color: var(--accent);
  font-style: italic;
}
.skill-badge--missing {
  background: rgba(var(--status-danger-rgb, 239, 68, 68), 0.08);
  color: var(--status-danger);
  text-decoration: line-through;
  opacity: 0.7;
}
@media (prefers-reduced-motion: reduce) {
  .stat-mini { animation: none !important; transition: none !important; }
}


/* ============================================================
   Kanban base (source unique candidat/recruteur — L2 T2.5 D-2)
   Consolidation de 3 sources dupliquées (REG-082) : base non scopée
   candidate.css (job tracker), copie scopée recruiter.css
   (.pipeline-kanban-body/.rec-mini-kanban, fix régression 2026-07-08),
   override print base.css. Ordre relatif préservé (candidat d'abord,
   recruteur ensuite) — reproduit la cascade actuelle. Consommateurs :
   recruiter-job-hub.js, recruiter-pipeline.js, candidate-jobs.js,
   #jobTrackerKanban (wizard). .km-* / .kanban-mobile (candidat mobile)
   restent hors périmètre, non déplacés.
   ============================================================ */

/* ── Candidat — base historique (candidate.css) ─────────────── */
/* ============================================
   ALPHA 9: Kanban Job Tracker
   ============================================ */
.kanban {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  padding: var(--space-3) 0;
  min-height: 300px;
}

.kanbanColumn {
  flex: 1;
  min-width: 180px;
  max-width: 220px;
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid rgba(var(--white-rgb), 0.04);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
}
body.bento-theme .kanbanColumn {
  background: rgba(var(--paper-rgb), 0.5);
  border-color: rgba(var(--slate-dark-rgb), 0.08);
}

.kanbanHeader {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
}

.kanbanCards {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-height: 100px;
}

.kanbanCard {
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 3px solid rgba(var(--primary-rgb), 0.2);
  border-radius: var(--radius-8);
  padding: var(--space-3);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: all var(--duration-base) var(--ease-default);
}

.kanbanCard:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-hover);
  transform: translateY(-2px);
}
@media (hover: none), (pointer: coarse) {
  .kanbanCard:hover { transform: none; }
}

.kanbanCard.dragging {
  opacity: 0.7;
  transform: rotate(1.5deg) scale(1.03);
  cursor: grabbing;
  box-shadow: 0 12px 32px rgba(var(--black-rgb), 0.2);
  z-index: var(--z-sidebar);
}

.kanbanCard[draggable="true"] {
  cursor: grab;
  touch-action: none; /* prevent browser scroll during touch drag */
}

.kanbanCard[draggable="true"]:active {
  cursor: grabbing;
}

/* Touch drag floating clone */
.kanbanCard.touch-dragging {
  position: fixed;
  z-index: var(--z-modal-backdrop);
  pointer-events: none;
  opacity: 0.85;
  transform: rotate(2deg);
  box-shadow: var(--shadow-dropdown);
}

/* Drop target styling */
.kanbanColumn.drag-over,
.kanbanColumn.touch-drop-target {
  background: rgba(var(--accent-rgb), 0.15);
  border: 2px dashed var(--accent);
  border-radius: var(--radius-sm);
}

.kanbanColumn.drag-over .kanbanCards,
.kanbanColumn.touch-drop-target .kanbanCards {
  min-height: 120px;
}

/* Light theme drag-over */
.light-theme .kanbanColumn.drag-over,
.light-theme .kanbanColumn.touch-drop-target {
  background: rgba(var(--accent-rgb), 0.1);
}

.kanbanCardTitle {
  font-weight: 600;
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
  color: var(--text);
}

.kanbanCardCompany {
  font-size: var(--text-xs);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kanbanCardDate {
  font-size: var(--text-2xs);
  color: var(--muted);
  margin-top: 6px;
}

.kanbanCardActions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-2);
}

/* Empty column = intentional drop-zone (UI-coherence pipeline polish 2026-07-12):
   column layout + icon chip slot (.kanbanEmpty-icon, injected by the modules)
   + drag-over emphasis below. --accent-rgb (not --primary-rgb) per DS §25. */
.kanbanEmpty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--muted);
  opacity: 0.75;
  text-align: center;
  padding: var(--space-5);
  border: 1px dashed rgba(var(--accent-rgb), 0.18);
  border-radius: var(--radius-8);
  background: rgba(var(--accent-rgb), 0.03);
  transition: border-color var(--duration-base) var(--ease-default),
              background var(--duration-base) var(--ease-default),
              opacity var(--duration-base) var(--ease-default);
}
.kanbanEmpty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.12);
  color: var(--stage-color, var(--muted));
}
.kanbanEmpty-icon svg { opacity: 0.85; }
/* Drop-target emphasis while a card is dragged over the column.
   The column itself carries the dashed drop outline on .drag-over; the inner
   zone drops its own dashed border (→ single affordance, not two nested dashes)
   and instead fills with the accent tint so it reads as the active target. */
.kanbanColumn.drag-over .kanbanEmpty,
.kanbanColumn.touch-drop-target .kanbanEmpty {
  opacity: 1;
  border-color: transparent;
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--text);
}
.kanbanColumn.drag-over .kanbanEmpty-icon,
.kanbanColumn.touch-drop-target .kanbanEmpty-icon {
  border-color: rgba(var(--accent-rgb), 0.35);
  background: rgba(var(--accent-rgb), 0.15);
}
.kanbanEmpty--cta {
  flex-direction: column;
  gap: var(--space-3);
}
.kanbanEmpty--cta span {
  font-size: var(--text-xs);
  color: var(--muted);
}
.kanbanEmpty--cta .btn {
  margin-top: var(--space-1);
  font-size: var(--text-xs);
}

/* ── Application Reminders ── */
.reminderItem {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-xs);
  background: rgba(var(--primary-rgb), 0.03);
  border-left: 3px solid var(--accent);
  transition: opacity var(--duration-base), background var(--duration-base);
}
.reminderItem + .reminderItem { margin-top: var(--space-2); }
.reminderItem .reminderIcon { font-size: var(--text-lg); flex-shrink: 0; line-height: 1.4; }
.reminderItem .reminderBody { flex: 1; min-width: 0; }
.reminderItem .reminderMessage { font-size: var(--text-sm); font-weight: 500; color: var(--text); }
.reminderItem .reminderMeta { font-size: var(--text-xs); color: var(--muted); margin-top: var(--space-1); display: flex; gap: var(--space-2); align-items: center; }
.reminderItem .reminderTypeBadge { background: rgba(var(--primary-rgb), 0.08); padding: 2px var(--space-2); border-radius: var(--radius-xs); font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
.reminderItem .reminderActions { display: flex; gap: var(--space-1); flex-shrink: 0; }
/* Completed state */
.reminderItem.completed {
  opacity: 0.55;
  border-left-color: var(--status-ok);
  background: rgba(var(--status-ok-rgb), 0.03);
}
.reminderItem.completed .reminderMessage { text-decoration: line-through; color: var(--muted); }
/* Overdue — danger border + subtle red tint */
.reminderItem.overdue {
  border-left-color: var(--status-danger);
  background: rgba(var(--status-danger-rgb), 0.04);
}
.reminderItem.overdue .reminderMessage { color: var(--danger-text); font-weight: 600; }

/* 5-column grouped Kanban layout */
.kanban-5col {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-6);
  position: relative;
}

.kanban-5col .kanbanColumn {
  min-width: 0;
  max-width: none;
  position: relative;
}

/* Flow arrows between columns */
.kanban-5col .kanbanColumn:not(:last-child)::after {
  content: '→';
  position: absolute;
  right: -18px;
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--text-lg);
  color: var(--muted);
  opacity: 0.4;
  z-index: var(--z-decoration);
  pointer-events: none;
}

/* Animated flow arrows on hover */
.kanban-5col:hover .kanbanColumn:not(:last-child)::after {
  opacity: 0.7;
  color: var(--accent);
  animation: flowPulse 1.5s ease-in-out infinite;
}

@keyframes flowPulse {
  0%, 100% { opacity: 0.5; transform: translateY(-50%) translateX(0); }
  50% { opacity: 0.9; transform: translateY(-50%) translateX(3px); }
}

/* Progress indicator line */
.kanban-5col::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 10%;
  right: 10%;
  height: 2px;
  background: linear-gradient(90deg,
    rgba(var(--gray-rgb), 0.3) 0%,
    rgba(var(--accent-rgb),0.3) 25%,
    rgba(var(--status-warn-rgb), 0.3) 50%,
    rgba(var(--status-ok-rgb), 0.3) 75%,
    rgba(var(--status-danger-rgb), 0.3) 100%
  );
  border-radius: 1px;
  z-index: var(--z-base);
  opacity: 0.5;
  pointer-events: none;
}

/* Kanban header with icon and count */
.kanbanHeader {
  display: flex;
  align-items: center;
  gap: 6px;
}

.kanbanIcon {
  font-size: var(--text-base);
}

.kanbanCount {
  margin-left: auto;
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--text-secondary);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  border: 1px solid rgba(var(--accent-rgb), 0.1);
}

/* Status group colors */
.kanbanColumn[data-status-group="preparation"] .kanbanHeader { color: var(--muted); }
.kanbanColumn[data-status-group="preparation"] .kanbanCount { background: rgba(var(--gray-rgb), 0.2); }

.kanbanColumn[data-status-group="applied"] .kanbanHeader { color: var(--accent); }
.kanbanColumn[data-status-group="applied"] .kanbanCount { background: rgba(var(--accent-rgb),0.2); color: var(--accent); }

.kanbanColumn[data-status-group="interview"] .kanbanHeader { color: var(--status-warn); }
.kanbanColumn[data-status-group="interview"] .kanbanCount { background: rgba(var(--status-warn-rgb), 0.2); color: var(--status-warn); }

.kanbanColumn[data-status-group="offer"] .kanbanHeader { color: var(--accent2); }
.kanbanColumn[data-status-group="offer"] .kanbanCount { background: rgba(var(--status-ok-rgb), 0.2); color: var(--accent2); }

.kanbanColumn[data-status-group="closed"] .kanbanHeader { color: var(--danger-text); }
.kanbanColumn[data-status-group="closed"] .kanbanCount { background: rgba(var(--red-light-rgb), 0.2); color: var(--danger-text); }

/* Status badge inside cards */
.kanbanCardStatus {
  display: inline-block;
  font-size: var(--text-2xs);
  padding: 2px 6px;
  border-radius: var(--radius-4);
  background: rgba(var(--white-rgb), 0.08);
  color: var(--muted);
  margin-bottom: 6px;
  text-transform: capitalize;
}

/* Status-specific badge colors */
.kanbanCardStatus[data-status="draft"] { background: rgba(var(--gray-rgb), 0.15); }
.kanbanCardStatus[data-status="saved"] { background: rgba(var(--gray-rgb), 0.15); }
.kanbanCardStatus[data-status="applied"] { background: rgba(var(--accent-rgb),0.15); color: var(--accent); }
.kanbanCardStatus[data-status="viewed"] { background: rgba(var(--accent-rgb),0.2); color: var(--accent); }
.kanbanCardStatus[data-status="phone_screen"],
.kanbanCardStatus[data-status="technical_test"],
.kanbanCardStatus[data-status="interview_hr"],
.kanbanCardStatus[data-status="interview_tech"],
.kanbanCardStatus[data-status="interview_manager"],
.kanbanCardStatus[data-status="interview_final"],
.kanbanCardStatus[data-status="reference_check"] { background: rgba(var(--status-warn-rgb), 0.15); color: var(--status-warn); }
.kanbanCardStatus[data-status="offer_pending"],
.kanbanCardStatus[data-status="offer_received"],
.kanbanCardStatus[data-status="offer_negotiating"] { background: rgba(var(--status-ok-rgb), 0.15); color: var(--accent2); }
.kanbanCardStatus[data-status="offer_accepted"] { background: rgba(var(--status-ok-rgb), 0.25); color: var(--accent2); }
.kanbanCardStatus[data-status="offer_declined"],
.kanbanCardStatus[data-status="rejected"],
.kanbanCardStatus[data-status="withdrawn"],
.kanbanCardStatus[data-status="ghosted"] { background: rgba(var(--red-light-rgb), 0.15); color: var(--danger-text); }

/* Legacy status colors for backwards compatibility */
.kanbanColumn[data-status="draft"] .kanbanHeader { color: var(--muted); }
.kanbanColumn[data-status="applied"] .kanbanHeader { color: var(--accent); }
.kanbanColumn[data-status="interview"] .kanbanHeader { color: var(--status-warn); }
.kanbanColumn[data-status="offer"] .kanbanHeader { color: var(--accent2); }
.kanbanColumn[data-status="rejected"] .kanbanHeader { color: var(--danger-text); }

/* Mobile responsive kanban */
@media (max-width: 1280px) {
  .kanban-5col {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 768px) {
  .kanban {
    flex-direction: column;
  }
  .kanban-5col {
    grid-template-columns: 1fr;
  }
  .kanbanColumn {
    max-width: none;
    min-width: auto;
  }
}

body[data-device="mobile"] .kanban-5col { display: none; }

/* ── Candidat — additions dispersées (is-touch hover + T2.3 theme legs) ── */
/* Disable kanbanCard hover on touch */
body.is-touch .kanbanCard:hover { border-color: var(--border); box-shadow: none; }

/* .kanbanCardStatus — line 229 (0.08) */
body.light-theme .kanbanCardStatus,
body.bento-theme .kanbanCardStatus,
body.atsiq-theme .kanbanCardStatus {
  background: rgba(var(--status-muted-rgb), 0.07);
}

/* .kanbanCount — line 199 (0.1). .bd-kanban__col-count aligned (count-pill
   parity across both pipelines, UI-coherence 2026-07-12). */
body.light-theme .kanbanCount,
body.bento-theme .kanbanCount,
body.atsiq-theme .kanbanCount,
body.light-theme .bd-kanban__col-count,
body.bento-theme .bd-kanban__col-count,
body.atsiq-theme .bd-kanban__col-count {
  background: rgba(var(--status-muted-rgb), 0.10);
}

/* .kanbanColumn — hors périmètre T2.3, famille déplacée par T2.5 */
body.light-theme .kanbanColumn,
body.bento-theme .kanbanColumn,
body.atsiq-theme .kanbanColumn {
  background: rgba(var(--status-muted-rgb), 0.04);
}

/* ── Recruteur — copie scopée pipeline global + mini-kanban fiche + Dynamic Kanban (recruiter.css) ── */
/* ============================================================
   Recruiter Pipeline Kanban (6 columns)
   ============================================================ */
.kanban-6col {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--space-5);
  position: relative;
}

/* ── Kanban recruteur — BASE colonnes/cartes (fix régression 2026-07-08, owner).
   Historique : ces styles de base vivaient NON SCOPÉS dans candidate.css et le
   shell monolithique les chargeait sur toutes les surfaces ; la migration Vite
   per-rôle (c526b002f, 2026-06-26) a cessé de charger candidate.css côté
   recruteur → colonnes nues (aucun fond/bordure/padding), colonnes vides sans
   hauteur (cibles de drop invisibles → drag « mort »), zéro feedback drag-over,
   cartes sans padding : board « en vrac » signalé owner pendant ~10 jours.
   Base locale recruteur scopée aux deux boards (pane global .pipeline-kanban-body
   + mini-kanban fiche .rec-mini-kanban). Consolidation candidat/recruteur en une
   source unique = chantier cohérence UI (direction D-2). */
.pipeline-kanban-body .kanbanColumn,
.rec-mini-kanban .kanbanColumn {
  background: rgba(var(--white-rgb), 0.03);
  border: 1px solid rgba(var(--white-rgb), 0.04);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* VQA-C11 — the candidate-base .kanbanColumn cap (max-width:220px, line
     ~13047) leaked into the recruiter grids whose tracks are 280-320px
     (.pipeline-kanban-body grid-auto-columns) / 1fr (.kanban-6col), leaving
     60-116px of dead space per track and a 2900-3350px board with columns
     pushed off-screen. Columns must fill their grid track here. */
  max-width: none;
}
body.light-theme .pipeline-kanban-body .kanbanColumn,
body.bento-theme .pipeline-kanban-body .kanbanColumn,
body.atsiq-theme .pipeline-kanban-body .kanbanColumn,
body.light-theme .rec-mini-kanban .kanbanColumn,
body.bento-theme .rec-mini-kanban .kanbanColumn,
body.atsiq-theme .rec-mini-kanban .kanbanColumn {
  background: rgba(var(--paper-rgb), 0.5);
  border-color: rgba(var(--slate-dark-rgb), 0.08);
}

.pipeline-kanban-body .kanbanHeader,
.rec-mini-kanban .kanbanHeader {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
}

.pipeline-kanban-body .kanbanCards,
.rec-mini-kanban .kanbanCards {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-height: 100px; /* colonne vide = cible de drop atteignable */
}

.pipeline-kanban-body .kanbanCard,
.rec-mini-kanban .kanbanCard {
  padding: var(--space-3);
}

/* RE-JURY 2 — grincheux-R-30 [m] : « colonne vide : le message est arrivé, l'action non ».
   Le mini-kanban de la fiche poste montrait jusqu'à 3 cadres pointillés de ~200 px de haut, inertes.
   Deux corrections, ici :
     · la boîte vide cesse de S'ÉTIRER à la hauteur de la colonne la plus peuplée (`flex: 1` sur
       `.kanbanEmpty`) — elle prend la hauteur de son contenu, `.kanbanCards` gardant son
       `min-height` de colonne ;
     · l'opacité globale de 0,75 est levée SUR CETTE VARIANTE : la boîte porte désormais un
       CONTRÔLE, et un contrôle ne se peint pas à 75 % (le texte, lui, reste `--muted`).
   ⛔ Portée strictement `.rec-mini-kanban .kanbanEmpty--cta` : le board global, le tracker candidat
   et les colonnes vides SANS geste gardent leur traitement à l'octet près. */
.rec-mini-kanban .kanbanEmpty--cta {
  flex: 0 0 auto;
  opacity: 1;
  padding: var(--space-3);
}

/* Affordances drag & drop du board global (le JS pose draggable/dragging/touch-*) */
.pipeline-kanban-body .kanbanCard[draggable="true"] {
  cursor: grab;
  touch-action: none; /* requis : drag tactile custom (pas de scroll pendant le drag) */
}
.pipeline-kanban-body .kanbanCard[draggable="true"]:active { cursor: grabbing; }
.pipeline-kanban-body .kanbanCard.dragging {
  opacity: 0.7;
  transform: rotate(1.5deg) scale(1.03);
  cursor: grabbing;
  box-shadow: 0 12px 32px rgba(var(--black-rgb), 0.2);
}
.pipeline-kanban-body .kanbanCard.touch-dragging {
  position: fixed;
  z-index: var(--z-modal-backdrop);
  pointer-events: none;
  opacity: 0.85;
  transform: rotate(2deg);
  box-shadow: var(--shadow-dropdown);
}
.pipeline-kanban-body .kanbanColumn.drag-over,
.pipeline-kanban-body .kanbanColumn.touch-drop-target {
  background: rgba(var(--accent-rgb), 0.12);
  border: 2px dashed var(--accent);
}
/* Light-theme legs (body.{light,bento,atsiq}-theme .pipeline-kanban-body .kanbanColumn,
   specificity 0,3,1) override the drag-over border-color/background above → the drop
   signal was near-invisible in light themes once the inner .kanbanEmpty border went
   transparent (polish v2). Re-assert the accent outline + fill at 0,4,1 so the column
   itself carries a clear single drop affordance in light. */
body.light-theme .pipeline-kanban-body .kanbanColumn.drag-over,
body.light-theme .pipeline-kanban-body .kanbanColumn.touch-drop-target,
body.bento-theme .pipeline-kanban-body .kanbanColumn.drag-over,
body.bento-theme .pipeline-kanban-body .kanbanColumn.touch-drop-target,
body.atsiq-theme .pipeline-kanban-body .kanbanColumn.drag-over,
body.atsiq-theme .pipeline-kanban-body .kanbanColumn.touch-drop-target {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.10);
}

.kanban-6col .kanbanColumn {
  min-width: 0;
  max-width: none;
  position: relative;
}

/* Flow arrows between columns */
.kanban-6col .kanbanColumn:not(:last-child)::after {
  content: '→';
  position: absolute;
  right: -15px;
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--text-md);
  color: var(--muted);
  opacity: 0.4;
  z-index: var(--z-decoration);
  pointer-events: none;
}

.kanban-6col:hover .kanbanColumn:not(:last-child)::after {
  opacity: 0.7;
  color: var(--accent);
  animation: flowPulse 1.5s ease-in-out infinite;
}


/* Drag-over visual feedback */
.kanban-6col .kanbanColumn.drag-over {
  background: rgba(var(--accent-rgb), 0.08);
  border-radius: var(--radius-md, 10px);
  outline: 2px dashed var(--primary);
  outline-offset: -2px;
}

.kanban-6col .kanbanCard.dragging {
  opacity: 0.5;
  transform: rotate(2deg);
}

.kanban-6col .kanbanCard[draggable] {
  touch-action: none;
}

.kanban-6col .kanbanCard.touch-dragging {
  position: fixed;
  z-index: var(--z-modal-backdrop);
  pointer-events: none;
  opacity: 0.85;
  transform: rotate(2deg);
  box-shadow: var(--shadow-dropdown);
}

.kanban-6col .kanbanColumn.touch-drop-target {
  background: rgba(var(--accent-rgb), 0.08);
  border-radius: var(--radius-md, 10px);
  outline: 2px dashed var(--primary);
  outline-offset: -2px;
}

/* Compact action buttons inside narrow 6-col pipeline cards */
.kanban-6col .kanbanCardActions {
  flex-wrap: wrap;
  gap: 3px;
}

.kanban-6col .kanbanCardActions .btn.btn--small {
  height: 26px;
  padding: 0 8px;
  font-size: var(--text-xs);
  line-height: 26px;
  white-space: nowrap;
  flex: 0 0 auto;
}

/* Let the primary action (View Report) take full width for emphasis */
.kanban-6col .kanbanCardActions .btn.btn--small.btn--primary {
  flex: 1 1 100%;
  order: -1;
  text-align: center;
}

/* Danger (delete ✕) stays compact square */
.kanban-6col .kanbanCardActions .btn.btn--small.btn--danger {
  padding: 0 6px;
  flex: 0 0 auto;
}

/* ── Pipeline Kanban Card Polish ───────────────── */
.kanban-6col .kanbanCard {
  border-left: 3px solid transparent;
  transition: all var(--duration-base) var(--ease-default);
  animation: ctFadeInUp var(--duration-slow) var(--ease-default) both;
}
.kanban-6col .kanbanCard:nth-child(1) { animation-delay: 0.02s; }
.kanban-6col .kanbanCard:nth-child(2) { animation-delay: 0.04s; }
.kanban-6col .kanbanCard:nth-child(3) { animation-delay: 0.06s; }
.kanban-6col .kanbanCard:nth-child(4) { animation-delay: 0.08s; }
.kanban-6col .kanbanCard:nth-child(5) { animation-delay: 0.10s; }

.kanban-6col .kanbanCard:hover {
  border-left-color: var(--accent);
  box-shadow: var(--shadow-hover);
}

/* Score-based accent (progressive enhancement) */
.kanban-6col .kanbanCard:has(.kanbanCard-score.high):hover {
  border-left-color: var(--status-ok);
}
.kanban-6col .kanbanCard:has(.kanbanCard-score.medium):hover {
  border-left-color: var(--status-warn);
}
.kanban-6col .kanbanCard:has(.kanbanCard-score.low):hover {
  border-left-color: var(--status-danger);
}

/* Column header gradient underline */
.kanban-6col .kanbanHeader {
  position: relative;
}
.kanban-6col .kanbanHeader::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--data-indigo-deep), var(--data-indigo-light));
  opacity: 0.5;
  border-radius: 1px;
}

/* ── Enriched Pipeline Cards ───────────────────── */

/* Score badge (inline, colored background) */
.kanbanCard-score {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-xs);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  margin: var(--space-1) 0;
}

.kanbanCard-score.high {
  background: rgba(var(--emerald-rgb), 0.15);
  color: var(--status-ok);
}

.kanbanCard-score.medium {
  background: rgba(var(--status-warn-rgb), 0.15);
  color: var(--status-warn);
}

.kanbanCard-score.low {
  background: rgba(var(--status-danger-rgb), 0.15);
  color: var(--status-danger);
}

.kanbanCard-score-label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-xs);
  opacity: 0.8;
}

.kanbanCard-score-val {
  margin-left: auto;
}

/* Duration hint (muted, small, mono for data feel) */
.kanbanCard-duration {
  color: var(--muted);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  opacity: 0.7;
}

/* Notes preview (1 line, italic, truncated) */
.kanbanCard-notes {
  font-size: var(--text-xs);
  font-style: italic;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 2px 0;
  padding: 2px 0;
}

/* Recommendation dot (small circle) */
.kanbanCard-rec {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.kanbanCard-rec.rec-hire { background: var(--status-ok); }
.kanbanCard-rec.rec-maybe { background: var(--status-warn); }
.kanbanCard-rec.rec-nohire { background: var(--status-danger); }

/* Light theme adjustments (L2 T2.3 Cas B) */
body.light-theme .kanbanCard-score.high,
body.bento-theme .kanbanCard-score.high,
body.atsiq-theme .kanbanCard-score.high {
  background: rgba(var(--emerald-rgb), 0.12);
}

body.light-theme .kanbanCard-score.medium,
body.bento-theme .kanbanCard-score.medium,
body.atsiq-theme .kanbanCard-score.medium {
  background: rgba(var(--status-warn-rgb), 0.12);
}

body.light-theme .kanbanCard-score.low,
body.bento-theme .kanbanCard-score.low,
body.atsiq-theme .kanbanCard-score.low {
  background: rgba(var(--status-danger-rgb), 0.12);
}

/* Responsive: stack on small screens */
@media (max-width: 1280px) {
  .kanban-6col {
    grid-template-columns: repeat(3, 1fr);
  }
  .kanban-6col .kanbanColumn:nth-child(3)::after {
    display: none;
  }
}

/* Mobile: horizontal swipeable kanban */
@media (max-width: 768px) {
  .kanban-6col {
    display: flex;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    padding-bottom: var(--space-3);
    position: relative;
  }
  .kanban-6col::-webkit-scrollbar {
    display: none;
  }
  .kanban-6col .kanbanColumn {
    min-width: 260px;
    flex-shrink: 0;
    flex-basis: 260px;
  }
  .kanban-6col .kanbanColumn:not(:last-child)::after {
    display: none;
  }
}

@media (max-width: 480px) {
  .kanban-6col .kanbanColumn {
    min-width: 220px;
    flex-basis: 220px;
  }
  .kanban-6col .kanbanCard {
    padding: var(--space-2) var(--space-3);
  }
}

/* .kanban is the outer pane container; the JS fills it with a search bar + a .pipeline-kanban-body
   wrapper (added 2026-06-14 so a re-render doesn't wipe the search input). So .kanban stacks the search
   ABOVE the board vertically, and the horizontal stage grid lives on .pipeline-kanban-body below.
   (Regression fix: the grid used to be on .kanban itself, which — once the wrapper was inserted — laid
   out [search | body] as the two columns and stacked the real stages vertically inside the body.) */
.pipeline-main .kanban {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  overflow-y: visible;
  -webkit-overflow-scrolling: touch;
  transition: margin-right var(--duration-slow) var(--ease-default);
}

.pipeline-main .pipeline-kanban-body {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, 320px);
  grid-template-columns: none;
  gap: var(--space-4);
  min-width: max-content;
  align-self: flex-start; /* don't let the flex-column parent stretch the grid (→ over-wide columns) */
  justify-content: start;
  padding-right: var(--space-4); /* PW-A36: last column gets the same gutter as the inter-column gap instead of sitting flush against the scroll edge (read as "clipped") */
}

/* Drag-and-drop hint — a full-width note above the board (now a child of .kanban, not the column grid). */
.pipeline-main .kanban > .hint {
  margin: 0 0 var(--space-2) 0;
  text-align: center;
  font-size: var(--text-xs);
  opacity: 0.7;
}

.pipeline-main .kanban.panel-open {
  margin-right: 360px;
}

/* Stage header color bar */
.pipeline-main .kanbanHeader {
  border-top: 3px solid var(--stage-color, var(--accent));
}

/* ── Stage-colored card accent (UI-coherence pipeline polish 2026-07-12) ──
   --stage-color is set per-column via CSSOM (recruiter-pipeline.js hoists
   data-stage-color onto .kanbanColumn) and cascades to header bar + cards.
   .pipeline-main bump: the effects.css light legs (body.*-theme .kanbanCard)
   reset the border shorthand to 1px muted — (0,3,0) + explicit border-left
   keeps the 3px stage stripe alive on every theme. */
.pipeline-main .pipeline-kanban-body .kanbanCard {
  border-left: 3px solid var(--stage-color, rgba(var(--accent-rgb), 0.2));
}
.pipeline-main .pipeline-kanban-body .kanbanCard:hover {
  border-left-color: var(--stage-color, var(--accent));
}

/* ── Quiet card actions: right-aligned icon buttons, primary stays left ── */
.pipeline-kanban-body .kanbanCardActions {
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-1);
}
.pipeline-kanban-body .kanbanCardActions .btn--primary.btn--small {
  margin-right: auto;
  height: 28px;
  padding: 0 var(--space-3);
  font-size: var(--text-xs);
}
/* width/height only — the mobile touch-target canon (@media max-width:768px
   .btn--icon { min-width/min-height: 44px }, §.btn) must keep winning on
   small screens, so no min-* here. */
.pipeline-kanban-body .kanbanCardActions .btn--icon.btn--small {
  width: 28px;
  height: 28px;
  font-size: var(--text-sm);
  background: transparent;
  border-color: transparent;
  color: var(--muted);
}
.pipeline-kanban-body .kanbanCardActions .btn--icon.btn--small:hover {
  background: rgba(var(--text-rgb), 0.08);
  border-color: rgba(var(--text-rgb), 0.10);
  color: var(--text);
}
/* Delete: muted at rest, danger only on hover/focus (extra .btn--icon.btn--small
   to outrank the generic hover rule above). */
.pipeline-kanban-body .kanbanCardActions .btn--icon.btn--small.kanbanCard-action--delete:hover,
.pipeline-kanban-body .kanbanCardActions .btn--icon.btn--small.kanbanCard-action--delete:focus-visible {
  background: rgba(var(--status-danger-rgb), 0.12);
  border-color: rgba(var(--status-danger-rgb), 0.30);
  color: var(--danger-text);
}
/* Progressive disclosure — icon actions rest at half opacity, full on card
   hover/focus-within. Fine pointers only: touch/coarse keeps them fully
   visible (and the 44px mobile canon applies). */
@media (hover: hover) and (pointer: fine) {
  .pipeline-kanban-body .kanbanCard .kanbanCardActions .btn--icon.btn--small {
    opacity: 0.5;
    transition: opacity var(--duration-fast) var(--ease-default),
                background var(--duration-fast) var(--ease-default),
                border-color var(--duration-fast) var(--ease-default),
                color var(--duration-fast) var(--ease-default);
  }
  .pipeline-kanban-body .kanbanCard:hover .kanbanCardActions .btn--icon.btn--small,
  .pipeline-kanban-body .kanbanCard:focus-within .kanbanCardActions .btn--icon.btn--small {
    opacity: 1;
  }
}

/* ── Tag chips ─────────────────────────────────── */
.kanbanCard-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: var(--space-1) 0;
}

/* ── Note preview in card ──────────────────────── */
.kanbanCard-note-preview {
  font-size: var(--text-xs);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 2px 0;
}

.kanbanCard-note-preview i {
  opacity: 0.5;
  margin-right: var(--space-1);
}

/* ── Card selection (checkbox + highlight) ─────── */
.pipeline-main .kanbanCard {
  position: relative;
}

.kanbanCard-select {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-raised);
}

.kanbanCard-select input[type="checkbox"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--accent);
}

.kanbanCard.selected {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.kanbanCard-body {
  padding-left: var(--space-6);
  cursor: pointer;
}

@media (max-width: 1280px) {
  .pipeline-main .pipeline-kanban-body {
    grid-auto-columns: minmax(240px, 280px);
  }
}

@media (max-width: 768px) {
  .pipeline-main .pipeline-kanban-body {
    display: flex;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    padding-bottom: var(--space-3);
  }
  .pipeline-main .pipeline-kanban-body::-webkit-scrollbar {
    display: none;
  }
  .pipeline-main .pipeline-kanban-body > .hint {
    display: none;
  }
  .pipeline-main .pipeline-kanban-body > .kanbanColumn {
    min-width: 260px;
    flex-shrink: 0;
    flex-basis: 260px;
  }
  .pipeline-main .kanban.panel-open {
    margin-right: 0;
  }
}

@media (max-width: 480px) {
  .pipeline-main .pipeline-kanban-body > .kanbanColumn {
    min-width: 220px;
    flex-basis: 220px;
  }
  .pipeline-main .kanban .kanbanCard {
    padding: var(--space-2) var(--space-3);
  }
}

/* Stale kanban card highlight */
.kanbanCard.rec-stale {
  border-left: 3px solid var(--status-warn);
}

/* Mini-kanban in detail view */
.rec-mini-kanban {
  margin-top: var(--space-3);
  width: 100%;
  max-width: 100%;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(240px, 1fr);
  grid-template-columns: none;
  gap: var(--space-4);
  min-width: 0;
  overflow-x: auto;
  overflow-y: visible;
  padding-bottom: var(--space-3);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.rec-mini-kanban .kanbanColumn {
  min-width: 240px;
}

.rec-mini-kanban .kanbanColumn:not(:last-child)::after {
  display: none;
}

.rec-mini-kanban .kanbanCard {
  word-break: break-word;
}


/* ── Print override (base.css) — VERBATIM, 3 !important cluster justifié (T2.8) ── */
@media print {
  /* Kanban — force horizontal layout for pipeline printing */
  .kanban-5col, .kanban-grid { display: block !important; }
  .kanbanColumn { display: inline-block !important; vertical-align: top; width: 18% !important; break-inside: avoid; }
}

/* ============================================================
   DS-CANON WAVE (2026-07-13) — shared primitives for the premium
   visual-coherence backlog (vca_synthesis). Each block maps 1:1 to a
   DESIGN_SYSTEM.md section; Phase-B consumers adopt these classes
   verbatim instead of bespoke styling.
     .row-actions / .btn--icon danger  → §10.1 "Row actions (dense lists)"
     .badge.outline-muted              → §10.5
     .stat-row / .stat-tile            → §10.15
     .tabs--overline + mobile scroll   → §10.9
     .btn.w100 radius                  → §10.1 "Full-width buttons"
   ============================================================ */

/* Row-action grammar (dense admin lists) — one container, icon-only squares.
   Radius-sm (not radius-full): a row of circles reads as floating glyphs;
   squares anchor to the row grid. Never mix pill+text with icon-only in
   the same .row-actions container. */
.row-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.row-actions .btn--icon {
  border-radius: var(--radius-sm);
  flex: 0 0 auto;
}
/* Destructive row action — the solid danger canon (T2.2) applied to the
   36×36 icon square. Same tokens as .btn.btn--danger so it restyles with
   every theme (Bento/Sage/Obsidian) automatically. */
.btn--icon.btn--danger {
  background: var(--btn-danger-bg);
  border: var(--btn-danger-border);
  color: var(--btn-danger-fg);
}
@media (hover: hover) {
  .btn--icon.btn--danger:hover {
    background: var(--btn-danger-bg);
    border: var(--btn-danger-border);
    opacity: 0.9;
  }
}

/* Muted outline badge tier — equal-tier chips that must not dominate their
   siblings (provenance pills, neutral qualifiers). Border alpha 0.45 keeps
   the boundary ≥3:1 against both light paper and Obsidian surfaces
   (non-text contrast, WCAG 1.4.11). */
.badge.outline-muted {
  background: transparent;
  color: var(--muted);
  /* §P3.4.3 : α 0,45 mesuré 3,00 (ATSIQ clair) / 2,84 (Bento clair — ÉCHEC WCAG 1.4.11) ;
     0,55 = plus petit pas de 0,05 qui rend les 6 couples ≥ 3,5:1 (4,12 / 3,78 / 5,59). */
  border: 1px solid rgba(var(--text-rgb), 0.55);
}
/* §P3.4.3 — COMPLÉMENT MESURÉ (VQA 2026-08-23) : les thèmes clairs posent des règles blanket
   `body.<theme> .badge { border/background … }` (atsiq-theme.css:765 accent 0,16 ; effects.css:4634)
   à spécificité 0,2,1 > `.badge.outline-muted` (0,2,0) — la bordure 0,55 était ÉCRASÉE sous ATSIQ
   (mesurée 1,34 au harnais). Re-déclaration scoped, MÊME valeur : l'assertion ≥3,5:1 tient en cascade. */
body.atsiq-theme .badge.outline-muted,
body.bento-theme .badge.outline-muted,
body.light-theme .badge.outline-muted {
  background: transparent;
  color: var(--muted);
  border: 1px solid rgba(var(--text-rgb), 0.55);
}

/* §10.15 Stat tile — THE canonical KPI treatment (unifies colored-pastel
   cards / plain cards / chip-pill drift, backlog C4). Value uses the font's
   proportional figures (tabular-nums reserved for columns that align). */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}
.stat-tile {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-5) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.stat-tile__value {
  font-size: var(--text-3xl);
  font-weight: 600;
  line-height: 1.15;
  color: var(--text);
}
.stat-tile__label {
  font-size: var(--text-sm);
  color: var(--muted);
}
.stat-tile__delta {
  font-size: var(--text-xs);
  font-weight: 600;
}
/* P2-I (G-S6, dossier D14) — 3e slot de l'anatomie canonique « label + valeur + méta ».
   Il manquait au .stat-tile legacy : faute de slot, les surfaces écrasaient le LABEL avec
   leur phrase de contexte et rendaient des tuiles anonymes (facturation 34 : 4 tuiles
   « — / aucune facture émise » indiscernables). Miroir de .ctk-stat__meta du kit. */
.stat-tile__meta {
  font-size: var(--text-xs);
  color: var(--muted);
}
.stat-tile__delta.up   { color: var(--success-text); }
.stat-tile__delta.down { color: var(--danger-text); }
/* The ONLY sanctioned variant: accent top-border. No per-tile pastel fills. */
.stat-tile--accent { border-top: 3px solid var(--accent); }

/* §10.9 Two-level tab hierarchy — parent row wears the uppercase overline
   treatment (§4.2 --letter-loose), child row stays standard .tab. The two
   rows must never render as one flat pill list. */
.tabs--overline .tab {
  text-transform: uppercase;
  letter-spacing: var(--letter-loose);
  font-size: var(--text-xs);
  font-weight: 700;
}
/* §10.9 Mobile — tab rows are horizontal-scroll strips ≤600px, never a
   wrap-to-grid (vca-atsiq-org/32: wrapped rows pushed content below the
   fold at 390px). Scrollbar hidden, momentum scroll kept. */
@media (max-width: 600px) {
  .tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .tabs::-webkit-scrollbar { display: none; }
}

/* §10.1 Full-width buttons drop the pill radius — a stretched stadium pill
   (radius-full at 100% width) reads as a banner, not a button (backlog A5).
   .w100 is the sanctioned way to stretch a .btn; declared after .btn--small
   in the cascade so it wins the radius at equal specificity. */
.btn.w100 { border-radius: var(--radius-sm); }

/* §2 Host-brand visibility (S5, VQA 2026-07-13) — brand strings in the shared
   role shells must resolve from location.hostname BEFORE first paint. Markup
   carries both brand variants; html.atsiq-host (set synchronously in <head> by
   app-theme-init.js / landing-theme-init.js) picks exactly one — same
   mechanism as the ATSIQ boot loader (loading.css) and sidebar logos. Theme
   independent by design: brand follows the HOST, not the light/dark theme. */
html:not(.atsiq-host) .host-brand--atsiq { display: none; }
html.atsiq-host .host-brand--ct { display: none; }

/* ── J3 (composition-retenue.md §2/§P1.6) — chip d'état DÉGRADÉ du panel de juges ──
   Partagé par les 5 surfaces (rendu par ctPanelChip, core-utils.js). warn = dégradé
   exploitable ; subtle = indisponible (aucune note IA). Tokens DS uniquement. */
.ct-panel-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  max-width: 100%;
  padding: 2px var(--space-2);
  border-radius: var(--radius-xs);
  font-size: var(--text-xs);
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.ct-panel-chip--warn {
  /* --panel-chip-warn-fg = ambre « profond » AA sur le fond TEINTÉ du chip (rgba warn 0.12) : le
     token --status-warn est calibré ≥4,5:1 sur BLANC, mais sur la teinte ambre clair il tombe à
     3,86 (VQA, thème clair — composition §5.4). Défini en thème clair (bento/atsiq) ; le sombre
     retombe sur --status-warn (déjà AA sur fond sombre). */
  color: var(--panel-chip-warn-fg, var(--status-warn));
  background: rgba(var(--status-warn-rgb), 0.12);
  border: 1px solid rgba(var(--status-warn-rgb), 0.30);
}
.ct-panel-chip--subtle {
  color: var(--fg-muted);
  background: var(--surface);
  border: 1px solid var(--border);
}

/* ── J3 (composition-retenue.md §1 item 4) — avis PAR JUGE (ctRenderPanelOpinions, core-utils.js) ──
   Puces dépliables natives <details>. Patron MOBILE-SAFE (Sofia) : posture-icône gauche + nom + score
   + chevron droite ; raison repliée dessous. Tokens DS ; `--panel-rgb` de la maquette → `--surface`. */
.ct-judges { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.ct-judges__label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}
.ct-jrow { display: flex; flex-wrap: wrap; gap: var(--space-2); min-width: 0; }
.ct-jchip {
  border: 1px solid var(--line);
  border-radius: var(--radius-full);
  background: var(--card);
  min-width: 0;
}
.ct-jchip[open] {
  flex: 1 1 100%;
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.ct-jchip > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* J3 polish 6 — cible tactile ≥48px (contrainte mobile Sofia, spec §1.4 ratifiée) : le patron
     `<details>` collapsé rend une petite pastille (~26px) trop courte au doigt. `min-height` + centrage
     vertical portent la zone de tap à 48px sans changer la densité visuelle du contenu. */
  min-height: 48px;
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
  cursor: pointer;
  list-style: none;
  min-width: 0;
}
.ct-jchip > summary::-webkit-details-marker { display: none; }
.ct-jchip__posture-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15rem; height: 1.15rem;
  border-radius: 50%;
  flex: 0 0 auto;
}
.ct-jchip__posture-icon--oui { color: var(--success-text); background: rgba(var(--status-ok-rgb), 0.14); }
.ct-jchip__posture-icon--non { color: var(--danger-text); background: rgba(var(--red-light-rgb), 0.16); }
.ct-jchip__posture-icon--info { color: var(--text-muted); background: rgba(var(--text-rgb), 0.08); }
/* FE-CM-R1 — LE SIÈGE EST TOUT CE QUI EST NOMMÉ : « Juré N — modèle de la famille X ».
   ⚖️ Décision ANTÉRIEURE du chantier, re-dite par l'owner le 15/09/2026 : l'identifiant du modèle
   ne regarde pas le recruteur, la FAMILLE si. La rangée n'a donc plus DEUX identités (une pastille
   de famille + un nom de modèle en mono) mais UNE seule, en prose : `.ct-jchip__family` n'a plus
   de porteur dans le markup et disparaît — RACCORD fait, `ctRenderPanelOpinions` ne l'émet plus.
   ⛔ Plus de `--font-mono` : ce libellé est une PHRASE (« Juré 1 — modèle de la famille OpenAI »),
   pas un identifiant technique ; la mono le faisait lire comme un jeton de machine.
   ⛔ Aucune couleur par famille : ce serait un second signal coloré dans une fiche où la couleur
   appartient au SCORE (§23.1). */
.ct-jchip__name { font-size: var(--text-xs); font-weight: 600; color: var(--text); min-width: 0; }
.ct-jchip__score { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-2xs); color: var(--text-muted); }
.ct-jchip__chev { color: var(--text-muted); transition: transform var(--duration-fast, 150ms) var(--ease-default, ease); margin-left: var(--space-1); }
.ct-jchip[open] .ct-jchip__chev { transform: rotate(180deg); }
.ct-jchip__reason {
  margin: 0;
  padding: 0 var(--space-3) var(--space-2) calc(1.15rem + var(--space-2) + var(--space-2));
  color: var(--text-muted);
  font-size: var(--text-sm);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
/* Q-B4 (W-P4-290) — la mention d'un motif retenu ou non communiqué : même place, lue comme une note. */
.ct-jchip__reason--none { font-style: italic; }
/* N11 (Flow Guidance) — la révélation du raisonnement d'un juge (dépliage `<details>.ct-jchip`) ne
   doit JAMAIS apparaître sans animation d'entrée. Fade + léger translateY (patron `cdPaneIn`), via la
   var `--motion-reveal` (fallback si non définie) ; neutralisée sous `prefers-reduced-motion`. */
.ct-jchip[open] .ct-jchip__reason {
  animation: ctJchipReasonIn var(--motion-reveal, 200ms) var(--ease-decel, cubic-bezier(0, 0, 0.2, 1));
}
@keyframes ctJchipReasonIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .ct-jchip[open] .ct-jchip__reason { animation: none; }
}

/* ── J3 (composition §1 item 2) — consensus + rail de dispersion (ctRenderPanelConsensus) ──
   Tone `--panel-color`/`--panel-rgb` héritée du conteneur `.ct-panel--{tone}` (assemblage) ;
   fallback `--accent` ici pour un rendu autonome. Tokens DS ; `--panel-rgb` maquette → fallback accent. */
.ct-consensus { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.ct-consensus__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-1) var(--space-2); min-width: 0; }
.ct-consensus__count { font-size: var(--text-sm); font-weight: 700; color: var(--text); letter-spacing: 0.01em; }
.ct-consensus__sep { color: var(--text-muted); font-size: var(--text-sm); }
.ct-consensus__accord { font-size: var(--text-sm); font-weight: 600; color: var(--panel-color, var(--accent)); }
.ct-panel__regime { font-size: var(--text-xs); color: var(--text-muted); }
/* FE-CM-R1 (W-P4-132) — « Jury — version N » + le badge d'antériorité, sur UNE ligne, au-dessus des
   rangées de jurés. ⛔ Aucune grille neuve : la même fente horizontale que les autres méta du panel.
   Le badge réutilise `.ct-panel-chip--warn`, la pastille d'état DÉJÀ écrite de l'écrin. */
.ct-panel__version { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; min-width: 0; }
.ct-rail { position: relative; height: 26px; margin-top: var(--space-1); min-width: 0; }
.ct-rail__track {
  position: absolute; left: 2px; right: 2px; top: 50%; transform: translateY(-50%);
  height: 2px; border-radius: var(--radius-full); background: var(--line);
}
.ct-rail__band {
  position: absolute; top: 50%; transform: translateY(-50%); height: 12px;
  border-radius: var(--radius-full);
  background: rgba(var(--panel-rgb, var(--accent-rgb)), 0.14);
  border: 1px solid rgba(var(--panel-rgb, var(--accent-rgb)), 0.24);
}
.ct-rail__dot {
  position: absolute; top: 50%; width: 8px; height: 8px; border-radius: 50%;
  transform: translate(-50%, -50%); background: rgba(var(--text-rgb), 0.55); box-shadow: 0 0 0 2px var(--card);
}
.ct-rail__anchor {
  position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%;
  transform: translate(-50%, -50%); background: var(--panel-color, var(--accent));
  box-shadow: 0 0 0 3px rgba(var(--panel-rgb, var(--accent-rgb)), 0.20), 0 0 0 5px var(--card);
}

/* ── J3 (composition §1 items 3 & 5) — synthèse (ctRenderPanelSynthesis) + art.22 (ctRenderPanelArt22) ──
   Tone `--panel-color`/`--panel-rgb` héritée du conteneur `.ct-panel--{tone}` ; fallback `--accent`. */
.ct-synthesis {
  position: relative;
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
  border-left: var(--border-accent-width, 3px) solid var(--panel-color, var(--accent));
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: rgba(var(--panel-rgb, var(--accent-rgb)), 0.05);
  min-width: 0;
}
.ct-synthesis__label {
  display: block; margin-bottom: var(--space-1);
  font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted);
}
.ct-synthesis__text { margin: 0; color: var(--text); font-size: var(--text-base); line-height: 1.55; overflow-wrap: anywhere; }
.ct-synthesis--fallback { border-left-color: var(--text-muted); background: rgba(var(--text-rgb), 0.05); }
.ct-panel__note {
  display: flex; align-items: flex-start; gap: var(--space-2);
  padding-top: var(--space-3); border-top: 1px solid var(--line);
  color: var(--text-muted); font-size: var(--text-xs); line-height: 1.45; min-width: 0;
}
.ct-panel__note svg { flex: 0 0 auto; margin-top: 1px; opacity: 0.85; }
.ct-panel__note strong { color: var(--text); font-weight: 600; }

/* ── J3 (composition §1) — conteneur écrin panel + tone-classes (ctRenderPanelPresentation) ──
   La tone pose --panel-color/--panel-rgb, dérivée de la catégorie canonique S10. ⛔ le panel n'a PAS
   de bande propre : la tone est HÉRITÉE de l'ancre. Le thread = filet de continuité (hairline verticale). */
.ct-panel { --panel-rgb: var(--text-rgb); --panel-color: var(--text-muted); display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.ct-panel--ok     { --panel-rgb: var(--status-ok-rgb);   --panel-color: var(--status-ok); }
.ct-panel--info   { --panel-rgb: var(--status-info-rgb); --panel-color: var(--status-info); }
.ct-panel--warn   { --panel-rgb: var(--status-warn-rgb); --panel-color: var(--status-warn); }
.ct-panel--subtle { --panel-rgb: var(--text-rgb);        --panel-color: var(--text-muted); }
/* TRAIN 3b (re-gate Astra n°4, P1) — une NOTE se peint de SA bande (`ctMatchScoreTone`, §20.1) : le
   cadre reçoit donc aussi les deux tons que la table historique ne servait pas — rouge (< 50) et
   vert soutenu (≥ 85), mêmes jetons d'état que la pastille de liste. */
.ct-panel--bad       { --panel-rgb: var(--status-danger-rgb); --panel-color: var(--status-danger); }
.ct-panel--ok-strong { --panel-rgb: var(--status-ok-rgb);     --panel-color: var(--status-ok); }
.ct-panel__thread {
  position: relative; display: flex; flex-direction: column; gap: var(--space-4);
  padding-left: var(--space-4); min-width: 0;
}
.ct-panel__thread::before {
  content: ''; position: absolute; left: 0; top: var(--space-1); bottom: var(--space-1);
  width: var(--border-accent-width, 3px); border-radius: var(--radius-full);
  background: linear-gradient(180deg, rgba(var(--panel-rgb), 0.42) 0%, rgba(var(--panel-rgb), 0.14) 60%, transparent 100%);
}

/* ── J3 (composition §4 ① carte niveau 0) — texture de consensus discrète (ctPanelConsensusTexture) ──
   Points ●●● dont la couleur DÉRIVE de la bande canonique (`--panel-color` posé par `.ct-panel--{tone}`).
   ⛔ pas un 2ᵉ nombre, pas une 6ᵉ bande. Point creux = juge manquant (dégradé). Tokens DS. */
.ct-ccons { display: inline-flex; align-items: center; gap: 3px; margin-left: var(--space-2); vertical-align: middle; }
.ct-ccons__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--panel-color, var(--text-muted)); opacity: 0.85; }
.ct-ccons__dot--ghost { background: transparent; border: 1px solid rgba(var(--text-rgb), 0.45); opacity: 1; }

/* ── P2-Z 1b-E — 34 Facturation : pastille de statut « En retard » ────────────────────
   Mesurée à 4,22:1 (rgb(185,28,28) sur la teinte rosée de la pastille) en Sage & Forest.
   Même anatomie que les pastilles unifiées du lot (fond teinté + bordure sémantique +
   texte au token de CORPS) : le statut reste lisible ET encodé par plus que la couleur. */
#recruiterPaneInvoices .invoice-status--overdue,
#recruiterPaneInvoices .placement-status.invoice-status--overdue {
  background: rgba(var(--status-danger-rgb), 0.22);
  border: 1px solid rgba(var(--status-danger-rgb), 0.55);
  color: var(--text);
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   PHASE 3 · LOT 2 — SOCLE TRANSVERSE D'INTERFACE (convention §B du mapping).
   Corrections de COQUE : elles valent pour les neuf surfaces du relevé, et L3…L9 les CONSTATENT.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── `J-084` · `J-137` · `J-199` · `J-244` · `J-245` — CIBLES INTERACTIVES SOUS 44 px ──────────
   Constat, mesuré par le manifeste sur TOUTES les surfaces : « bulles d'aide "?" à 28 × 28 px
   (présentes deux fois sur la page) », « liens de pied de page h=15 ».
   La règle WCAG 2.5.8 borne la CIBLE, pas le DESSIN : on agrandit donc la zone atteignable sans
   toucher au gabarit visuel — un « ? » de 44 px serait une tache dans un en-tête de section.
   Technique : une zone d'extension en `::after`, centrée sur l'élément, sans effet de mise en page
   (`position:absolute`, aucune peinture). ⛔ Aucun changement de taille, de couleur ni de position
   visible ; ⛔ aucune règle @media : le défaut était mesuré à 1440 px comme à 390 px, et la souris
   a droit à une cible atteignable autant que le doigt (la surcharge tactile de base.css:228, qui
   n'agissait qu'en `(pointer: coarse)`, laissait le bureau à 28 px).
   ⚠️ `.btn--help` était déjà `position: relative`-compatible (inline-flex) : la relative est posée
   explicitement pour ancrer l'extension. */
.btn--help {
  position: relative;
}
.btn--help::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}

/* Liens du pied de page applicatif (`#appFooter`) — mesurés à 15 px de haut : c'est la hauteur de
   ligne d'un texte `--text-xs`, aucune hauteur n'était déclarée. Ils deviennent des cibles pleines,
   en gardant leur taille de texte (un pied de page ne se crie pas). */
#appFooter a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-2);
}

/* ── `J-242` — LE BADGE DE LA CLOCHE DÉBORDE DU BOUTON ET RECOUVRE LE GLYPHE ───────────────────
   Constat : « le badge "3" de la cloche déborde du bouton circulaire de 40 px et recouvre le
   glyphe ». Cause mesurée : `top: -4px; right: -4px` sur un bouton de 40 px — le badge (18 px +
   2 px de liseré = 22 px) sortait de 4 px du cercle en haut ET à droite, et son disque plein
   mordait sur la cloche.
   ⇒ Il reste un badge de COIN (c'est sa grammaire, et c'est ce qui le rend lisible d'un coup
   d'œil) mais il s'inscrit DANS le cercle : ancré sur le bord, il ne dépasse plus et cesse de
   couvrir le glyphe. ⛔ Ni sa couleur, ni sa taille de texte, ni son « 99+ » ne changent. */
.headerNotifBell .notifBadge {
  top: 0;
  right: 0;
}
