/* =============================================================================
   Harpaston Brand Palette — matches logo.png — do not hardcode colors elsewhere
   Light theme: white/light-gray content area, Harpaston navy-blue sidebar
   ============================================================================= */

:root {
  /* ── Blue scale ── */
  --hp-blue-50:   #EBF5FF;
  --hp-blue-100:  #D6EBFF;
  --hp-blue-200:  #ADD6FF;
  --hp-blue-300:  #70B8FF;
  --hp-blue-400:  #3D9EFF;
  --hp-blue-500:  #2D7CF6;   /* PRIMARY brand blue */
  --hp-blue-600:  #1E5FCC;
  --hp-blue-700:  #164AAD;
  --hp-blue-800:  #0F3380;
  --hp-blue-900:  #0A1F54;
  --hp-blue-950:  #06122E;

  /* ── Neutrals ── */
  --hp-white:      #FFFFFF;
  --hp-gray-50:    #F8FAFC;   /* page background */
  --hp-gray-100:   #F1F5F9;
  --hp-gray-200:   #E2E8F0;
  --hp-gray-300:   #CBD5E1;
  --hp-gray-400:   #94A3B8;
  --hp-gray-500:   #64748B;
  --hp-gray-600:   #475569;
  --hp-gray-700:   #334155;
  --hp-gray-800:   #1E293B;
  --hp-gray-900:   #0F172A;

  /* ── Status ── */
  --hp-success:  #10B981;
  --hp-warning:  #F59E0B;
  --hp-danger:   #EF4444;
  --hp-info:     #3D9EFF;

  /* ── Sidebar gradient ── */
  --hp-sidebar-gradient: linear-gradient(180deg, #06122E 0%, #0F3380 100%);

  /* ── Light theme semantic aliases ──
     These are what the rest of the app uses via var().
     Replacing the old dark --bg/--text tokens with light equivalents
     so all existing views inherit the new palette automatically. */
  --bg:       var(--hp-gray-50);    /* page background  → light gray */
  --bg2:      var(--hp-white);      /* card/panel bg    → white      */
  --bg3:      var(--hp-gray-100);   /* hover/alt row    → light      */
  --border:   var(--hp-gray-200);   /* main borders                  */
  --border2:  var(--hp-gray-300);   /* stronger borders              */

  --text:     var(--hp-gray-800);   /* primary body text             */
  --text2:    var(--hp-gray-600);   /* secondary text                */
  --text3:    var(--hp-gray-400);   /* muted/placeholder             */

  /* Functional accents — remapped to Harpaston blues */
  --blue:     var(--hp-blue-500);
  --red:      var(--hp-danger);
  --green:    var(--hp-success);
  --orange:   var(--hp-warning);
  --teal:     var(--hp-blue-400);
  --purple:   #7C3AED;  /* kept for HarpaInsight module colour */

  /* Gold/brand accent → Harpaston blue (direct values, no alias chain) */
  --gold:     #2D7CF6;
  --gold2:    #3D9EFF;
  --gold-dim: #164AAD;

  /* Layout dimensions (unchanged) */
  --sidebar-w: 220px;
  --topbar-h:  52px;

  /* Bootstrap 5 variable overrides → light theme */
  --bs-body-bg:           var(--hp-gray-50);
  --bs-body-color:        var(--hp-gray-800);
  --bs-body-font-family:  'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --bs-body-font-size:    13px;
  --bs-body-line-height:  1.5;
  --bs-link-color:        var(--hp-blue-500);
  --bs-link-hover-color:  var(--hp-blue-600);
  --bs-border-color:      var(--hp-gray-200);
  --bs-emphasis-color:    var(--hp-gray-900);
  --bs-secondary-color:   var(--hp-gray-600);
  --bs-tertiary-color:    var(--hp-gray-400);
  --bs-primary:           var(--hp-blue-500);
  --bs-primary-rgb:       45,124,246;
  --bs-success:           var(--hp-success);
  --bs-success-rgb:       16,185,129;
  --bs-danger:            var(--hp-danger);
  --bs-warning:           var(--hp-warning);
  --bs-info:              var(--hp-info);
  --bs-light:             var(--hp-gray-100);
  --bs-dark:              var(--hp-gray-900);
}

/* =============================================================================
   Skeleton Loading States — Sprint 2 Fix 14
   Usage: add class="skeleton" to any element, or "skeleton-text" / "skeleton-title"
   ============================================================================= */

@keyframes skeleton-shimmer {
  0%   { background-position: -400px 0; }
  100% { background-position: 400px 0; }
}

.skeleton,
.skeleton-text,
.skeleton-title,
.skeleton-card {
  background: linear-gradient(
    90deg,
    var(--hp-gray-200, #E2E8F0) 25%,
    var(--hp-gray-100, #F1F5F9) 50%,
    var(--hp-gray-200, #E2E8F0) 75%
  );
  background-size: 800px 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: 4px;
  color: transparent !important;
  pointer-events: none;
  user-select: none;
}

.skeleton-text  { height: 12px; width: 80%; margin-bottom: 6px; display: block; }
.skeleton-title { height: 20px; width: 50%; margin-bottom: 10px; display: block; }
.skeleton-card  {
  min-height: 80px;
  border-radius: 8px;
  display: block;
  width: 100%;
}

/* KPI card skeleton (applied to .harp-kpi-card to show loading state) */
.harp-kpi-card.skeleton-loading {
  pointer-events: none;
}
.harp-kpi-card.skeleton-loading .harp-kpi-value,
.harp-kpi-card.skeleton-loading .harp-kpi-sub,
.harp-kpi-card.skeleton-loading .harp-kpi-label {
  background: linear-gradient(
    90deg,
    #E2E8F0 25%,
    #F1F5F9 50%,
    #E2E8F0 75%
  );
  background-size: 800px 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: 3px;
  color: transparent !important;
  display: inline-block;
  min-width: 60px;
}

/* ── WCAG 2.1 AA — Skip link & focus styles ──────────────────────────── */
.skip-to-content {
  position: absolute;
  top: -100px;
  left: 8px;
  background: var(--hp-blue-500);
  color: #fff;
  padding: 8px 16px;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  /* UX-4.3 documented exception (see z_index.css §EXCEPTIONS):
     WCAG 2.4.1 skip link MUST sit above EVERY overlay including
     Bootstrap's modal default (1050). Cannot use --hp-z-critical-alert (90). */
  z-index: 9999;
  transition: top .15s;
}
.skip-to-content:focus {
  top: 8px;
}

/* Visible focus ring for keyboard navigation */
:focus-visible {
  outline: 2px solid var(--hp-blue-500);
  outline-offset: 2px;
}
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--hp-blue-500);
  outline-offset: 2px;
  border-radius: 3px;
}
/* =============================================================================
   Harpaston — Design System Tokens (UX-4.1 · Phase 6.B foundational)

   CANONICAL token layer for the authenticated app. Spec §1 of
   harpaston-design-system-tokens-2026-05-17.md, translated VERBATIM from
   Tailwind `theme.extend` syntax into CSS custom properties — because
   Harpaston runs sprockets + Bootstrap 5 + CSS custom properties, NOT a
   Tailwind build (see ADR 0002 §ARC-5).

   These tokens are the source UX-4.2 atomic components (ERB partials +
   Stimulus + Bootstrap) reference. Naming is locked here — a rename now
   costs nothing, a rename in UX-4.2 costs 5×.

   DEVIATION FROM SPEC (intentional · zero-regression):
     Spec §1 names the semantic state trio `success/warn/danger`. Two of
     these (`--hp-success` #10B981, `--hp-danger` #EF4444) ALREADY exist in
     harpaston_palette.css with DIFFERENT values than spec (#16A34A/#DC2626).
     tokens.css loads after the palette via require_tree, so reusing those
     names would silently re-tint every Phase 5 component. The new
     design-system state colors are therefore namespaced `--hp-ds-*`. The
     legacy `--hp-success/-warning/-danger` are left untouched. Marketing-
     token reconciliation + eventual unification tracked in docs/FOLLOWUPS.md.
   ============================================================================= */

:root {
  /* ── Brand / primary ───────────────────────────────────────────────── */
  --hp-primary:        #0052FD;
  --hp-primary-soft:   #1A6AFF;
  --hp-primary-bg:     #EEF3FF;

  /* ── Ink (text) + surfaces ─────────────────────────────────────────── */
  --hp-ink:            #0B0D12;
  --hp-ink-2:          #181C26;
  --hp-paper:          #F8F9FB;
  --hp-muted:          #5A6072;
  --hp-border:         #E5E8EE;

  /* ── Semantic state (design-system · namespaced --hp-ds-* to avoid
        clobbering legacy --hp-success/-warning/-danger; see header) ────── */
  --hp-ds-success:     #16A34A;
  --hp-ds-warn:        #F59E0B;
  --hp-ds-danger:      #DC2626;

  /* ── Typography families ───────────────────────────────────────────── */
  --hp-font-display:   'Syne', 'Inter', system-ui, sans-serif;
  --hp-font-sans:      'Inter', system-ui, sans-serif;

  /* ── Display type scale (body 14px baseline · display 20–64px) ─────── */
  --hp-text-display-xs:        20px;
  --hp-text-display-xs-lh:     28px;
  --hp-text-display-sm:        24px;
  --hp-text-display-sm-lh:     32px;
  --hp-text-display-md:        32px;
  --hp-text-display-md-lh:     40px;
  --hp-text-display-lg:        48px;
  --hp-text-display-lg-lh:     56px;
  --hp-text-display-xl:        64px;
  --hp-text-display-xl-lh:     72px;

  /* ── Border radius ─────────────────────────────────────────────────── */
  --hp-radius-lg:      8px;
  --hp-radius-xl:      12px;
  --hp-radius-2xl:     16px;
  --hp-radius-3xl:     24px;

  /* ── Elevation / shadows ───────────────────────────────────────────── */
  --hp-shadow-card:        0 4px 12px -2px rgba(11, 13, 18, 0.06);
  --hp-shadow-card-hover:  0 24px 48px -16px rgba(11, 13, 18, 0.10);
  --hp-shadow-toast:       0 20px 40px -8px rgba(11, 13, 18, 0.25);

  /* ── Motion easing (consumed by animations.css) ────────────────────── */
  --hp-ease-out:       cubic-bezier(0.16, 1, 0.3, 1);
  --hp-ease-bounce:    cubic-bezier(0.34, 1.56, 0.64, 1);

  /* ── Responsive breakpoints (UX-4.6) ─────────────────────────────────
     CANONICAL matrix, reconciled from the two pre-existing sources:
       · design-system/MASTER.md §5 + harpaston/MASTER.md → 375/768/1024/1440
         (this is what the pre-delivery checklist already tests against)
       · spec §4 / FOLLOWUPS #UX-4.6 named an `xs` tier at 380px
     We adopt 375/768/1024/1440 as the four primary tiers and keep --hp-bp-xs
     (380px) as an alias so spec-§4 references resolve. The on-the-ground
     ad-hoc values (640/900/1100) are migrated to the nearest primary tier
     in responsive.css + the two UX-4.4.c·c view <style> blocks.

     ⚠ DELIBERATE ARC-5 deviation (responsive breakpoint discipline):
     CSS does NOT permit custom properties inside @media conditions
     (`@media (max-width: var(--hp-bp-tablet))` is invalid) and Harpaston
     runs sprockets with NO PostCSS `@custom-media` transform. So @media
     blocks across the app use the LITERAL px below, each tagged in a comment
     with its token name. These custom properties are the documented source
     of truth and remain consumable in calc()/clamp() and via JS
     (getComputedStyle) — e.g. the /components viewport indicator reads them.
     See ADR 0002 §ARC-5 + COMPONENTS.md “Responsive behavior”. ─────────── */
  --hp-bp-mobile:   375px;  /* phones (primary) — MASTER §5 */
  --hp-bp-tablet:   768px;  /* tablet portrait / phone landscape (primary) */
  --hp-bp-laptop:  1024px;  /* tablet landscape / small laptop (primary) */
  --hp-bp-desktop: 1440px;  /* desktop / wide (primary) */
  --hp-bp-xs:       380px;  /* spec §4 alias (xs) — see unification note */
}
/* =============================================================================
   Harpaston — Z-index registry (UX-4.1 · spec §2)

   THE canonical stacking ladder. New / migrated overlays MUST reference these
   tokens (CSS) or ZIndexHelper (Ruby) — never a raw z-index literal.

   Mirrors Ruby: app/helpers/z_index_helper.rb (keep both in sync).

   MIGRATION STATUS — UX-4.3 sweep complete (2026-05-20):
     UX-4.1 introduced this registry and migrated 3 reference overlays
     (side-panel + backdrop, modal, toast). UX-4.2 a/b/c shipped 15 atomic
     components that all consume the registry from day 1. UX-4.3 (this PR)
     swept every remaining raw z-index literal in the layouts + views onto
     the registry, and migrated the 4 deferred inline modals
     (users/profile · communication_campaigns/show · hotels/rooming_list ·
     packages/index) onto shared/_modal. Cross-layer inversion risk is
     closed in our own code.

   EXCEPTIONS (documented, intentional, owner: design-system):
     1. .skip-to-content (WCAG 2.4.1 skip link) keeps z-index: 9999
        in harpaston_palette.css. It MUST sit above EVERY overlay
        including Bootstrap's modal default (1050) — the registry's
        critical-alert (90) is below the Bootstrap floor and would
        defeat the a11y requirement.
     2. Bootstrap modal default (1050) still exists for any third-party
        plugin that ships its own modal. None of our own modals rely on
        it anymore. If a Bootstrap modal appears at the same time as a
        --hp-z-* overlay, the Bootstrap modal wins (this is acceptable —
        Bootstrap modals are user-confirmation surfaces).
   ============================================================================= */

:root {
  --hp-z-base:             0;    /* Page content default                     */
  --hp-z-sticky-nav:       30;   /* Top navigation                           */
  --hp-z-floating-buttons: 40;   /* Quick-add · Copilot toggle               */
  --hp-z-modal-backdrop:   50;   /* Modal / drawer darkening                  */
  --hp-z-modal:            60;   /* Modal content                            */
  --hp-z-side-panels:      60;   /* Copilot · drawers · Crisis Console        */
  --hp-z-toast:            70;   /* Notifications / snackbar                  */
  --hp-z-tour-overlay:     80;   /* In-app guided tour                       */
  --hp-z-critical-alert:   90;   /* Crisis alert · cyber breach              */
  --hp-z-dev-tools:        999;  /* Dev tools only — never reached in app     */
}
/* =============================================================================
   Harpaston — Motion utilities (UX-4.1 · spec §5)

   4 reusable transition utilities + a global prefers-reduced-motion guard.
   Easing curves come from tokens.css (--hp-ease-out / --hp-ease-bounce);
   keep this file required AFTER tokens in the application.css manifest.

   Pacte §5 polish — 200–300ms ease-out feel. Prefix is `hp-` to avoid any
   collision with Bootstrap / Tailwind-CDN (marketing) utility classes.

   Usage:
     <div class="hp-transition-base">…</div>
     <button class="hp-transition-fast">…</button>
   ============================================================================= */

.hp-transition-base   { transition: all 200ms var(--hp-ease-out); }
.hp-transition-fast   { transition: all 150ms var(--hp-ease-out); }
.hp-transition-slow   { transition: all 350ms var(--hp-ease-out); }
.hp-transition-bounce { transition: all 600ms var(--hp-ease-bounce); }

/* Respect user motion preferences — neutralises animation & transition
   durations app-wide for users who request reduced motion (WCAG 2.3.3 /
   2.1 AA, consistent with the focus-ring work in harpaston_palette.css). */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* =============================================================================
   Harpaston — Design-system atomic components (UX-4.2 · Phase 6.B)

   Styling layer for the shared/_* ERB partials shipped in UX-4.2. Every rule
   here references the UX-4.1 token layer (tokens.css --hp-* / --hp-ds-*,
   animations.css .hp-transition-*) — NEVER an inline hex. Spec §3 of
   harpaston-design-system-tokens-2026-05-17.md, Tailwind class semantics
   translated to Bootstrap + CSS custom properties per ADR 0002 §ARC-5.

   Required explicitly AFTER animations in application.css so the token
   :root vars are defined before they are consumed here (require_tree would
   also pick this file up, but the explicit require pins deterministic order).

   ZERO-REGRESSION NAMESPACE (intentional · same logic as UX-4.1's --hp-ds-*):
     The legacy app already styles ~50 `.btn.btn-primary` buttons via
     Bootstrap. Redefining `.btn-primary` here would silently restyle every
     Phase 5 button. Design-system component classes are therefore namespaced
     `ds-*` (.ds-btn / .ds-pill / .ds-frame-card / .ds-avatar /
     .ds-pacte-badge). Partials emit the legacy base class too (e.g.
     "btn ds-btn ds-btn-primary") so they inherit existing layout while the
     `ds-*` class supplies design-system color/elevation. The full `.btn`
     migration is the UX-4.3/4.4 sweep, not this foundational PR.
   ============================================================================= */

/* ── A. Button — 3 variants (spec §3.A) ────────────────────────────────── */
.ds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-family: var(--hp-font-sans);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  padding: 9px 16px;
  border-radius: var(--hp-radius-lg);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: all 150ms var(--hp-ease-out);
}
.ds-btn:focus-visible {
  outline: 2px solid var(--hp-primary);
  outline-offset: 2px;
}
.ds-btn:disabled,
.ds-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.ds-btn-primary {
  background: var(--hp-primary);
  color: #fff;
}
.ds-btn-primary:hover { background: var(--hp-primary-soft); color: #fff; }

.ds-btn-ghost {
  background: #fff;
  color: var(--hp-ink);
  border-color: var(--hp-border);
}
.ds-btn-ghost:hover { background: var(--hp-paper); color: var(--hp-ink); }

.ds-btn-destructive {
  background: var(--hp-ds-danger);
  color: #fff;
}
.ds-btn-destructive:hover { filter: brightness(0.93); color: #fff; }

/* ── B. Pill — 8 status variants (spec §3.B) ───────────────────────────── */
.ds-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--hp-font-sans);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  padding: 4px 10px;
  border-radius: 9999px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.ds-pill-ico { font-size: 10px; line-height: 1; }

/* Soft tinted variants — token color as text, 12% tint over white as bg.
   color-mix keeps us token-driven (no inline tint hexes; Baseline 2023). */
.ds-pill-success {
  color: var(--hp-ds-success);
  background: color-mix(in srgb, var(--hp-ds-success) 12%, #fff);
  border-color: color-mix(in srgb, var(--hp-ds-success) 28%, #fff);
}
.ds-pill-warn {
  color: var(--hp-ds-warn);
  background: color-mix(in srgb, var(--hp-ds-warn) 14%, #fff);
  border-color: color-mix(in srgb, var(--hp-ds-warn) 30%, #fff);
}
.ds-pill-danger {
  color: var(--hp-ds-danger);
  background: color-mix(in srgb, var(--hp-ds-danger) 12%, #fff);
  border-color: color-mix(in srgb, var(--hp-ds-danger) 28%, #fff);
}
.ds-pill-info {
  color: var(--hp-primary);
  background: var(--hp-primary-bg);
  border-color: color-mix(in srgb, var(--hp-primary) 22%, #fff);
}
.ds-pill-neutral {
  color: var(--hp-muted);
  background: var(--hp-paper);
  border-color: var(--hp-border);
}

/* Distinct treatments (spec §3.B) — premium / tier1 / live stand apart from
   the soft status set so they read as "special", not "a status". */
.ds-pill-premium {
  color: #fff;
  background: linear-gradient(135deg, var(--hp-primary) 0%, var(--hp-primary-soft) 100%);
}
.ds-pill-tier1 {
  color: #fff;
  background: var(--hp-ink);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.ds-pill-live {
  color: #fff;
  background: var(--hp-ds-danger);
}
.ds-pill-live .ds-pill-dot {
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: #fff;
  animation: ds-pill-pulse 1.6s var(--hp-ease-out) infinite;
}
@keyframes ds-pill-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.7); }
}

/* ── C. Frame card — wireframe browser frame (spec §3.C) ───────────────── */
.ds-frame-card {
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-xl);
  background: #fff;
  box-shadow: var(--hp-shadow-card);
  overflow: hidden;
}
.ds-frame-card-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: var(--hp-paper);
  border-bottom: 1px solid var(--hp-border);
}
.ds-frame-lights {
  display: inline-flex;
  gap: 6px;
  flex: 0 0 auto;
}
.ds-frame-lights span {
  width: 10px;
  height: 10px;
  border-radius: 9999px;
  background: var(--hp-border);
}
.ds-frame-url {
  flex: 1 1 auto;
  font-family: var(--hp-font-sans);
  font-size: 11px;
  color: var(--hp-muted);
  background: #fff;
  border: 1px solid var(--hp-border);
  border-radius: 9999px;
  padding: 3px 12px;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ds-frame-title {
  font-family: var(--hp-font-display);
  font-size: 12px;
  font-weight: 700;
  color: var(--hp-ink);
  flex: 0 0 auto;
}
.ds-frame-card-body { padding: 20px; }

/* ── D. Avatar — gradient backgrounds, 3 sizes (spec §3.M) ─────────────── */
/* The 6 wireframe gradient palettes are component-scoped tokens (not added
   to the UX-4.1-locked tokens.css; spec §1 does not define an avatar
   palette). Confined here so ZERO hex ever lands in ERB markup. */
.ds-avatar {
  --hp-av-1: linear-gradient(135deg, #FB923C 0%, #EC4899 100%); /* orange-pink  */
  --hp-av-2: linear-gradient(135deg, #6366F1 0%, #A855F7 100%); /* indigo-purple*/
  --hp-av-3: linear-gradient(135deg, #14B8A6 0%, #06B6D4 100%); /* teal-cyan    */
  --hp-av-4: linear-gradient(135deg, #F59E0B 0%, #F97316 100%); /* amber-orange */
  --hp-av-5: linear-gradient(135deg, #F43F5E 0%, #DC2626 100%); /* rose-red     */
  --hp-av-6: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%); /* blue-violet  */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  color: #fff;
  font-family: var(--hp-font-display);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  user-select: none;
  flex: 0 0 auto;
  background: var(--hp-av-1);
}
.ds-avatar-sm { width: 28px; height: 28px; font-size: 11px; }
.ds-avatar-md { width: 40px; height: 40px; font-size: 14px; }
.ds-avatar-lg { width: 56px; height: 56px; font-size: 19px; }
.ds-avatar[data-color="1"] { background: var(--hp-av-1); }
.ds-avatar[data-color="2"] { background: var(--hp-av-2); }
.ds-avatar[data-color="3"] { background: var(--hp-av-3); }
.ds-avatar[data-color="4"] { background: var(--hp-av-4); }
.ds-avatar[data-color="5"] { background: var(--hp-av-5); }
.ds-avatar[data-color="6"] { background: var(--hp-av-6); }

/* ── E. Pacte badge — surfaces Pacte Addictif §X refs (spec §3.L) ──────── */
/* Spec note asks for a #C7D6FE border; derived from --hp-primary via
   color-mix so the component stays fully token-driven (no inline hex). */
.ds-pacte-badge {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--hp-font-sans);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  padding: 3px 8px;
  border-radius: var(--hp-radius-lg);
  color: var(--hp-primary);
  background: var(--hp-primary-bg);
  border: 1px solid color-mix(in srgb, var(--hp-primary) 22%, #fff);
}
.ds-pacte-num {
  font-family: 'SFMono-Regular', ui-monospace, 'Menlo', monospace;
  font-weight: 700;
}

/* =============================================================================
   UX-4.2 batch (b) — Form & display atomic components
   ============================================================================= */

/* ── F. Form field — text / textarea / select (spec §3.J) ──────────────── */
/* Establishes the a11y baseline (aria-invalid + aria-describedby + role=alert)
   missing app-wide. Namespaced ds-form-* so the ~360 legacy .form-group /
   .form-control fields keep their current Bootstrap styling (UX-4.3/4.4 sweep). */
.ds-form-field {
  display: block;
  margin-bottom: 14px;
}
.ds-form-label {
  display: inline-block;
  font-family: var(--hp-font-sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--hp-ink-2);
  margin-bottom: 6px;
}
.ds-form-required {
  color: var(--hp-ds-danger);
  margin-left: 2px;
  font-weight: 700;
}
.ds-form-input {
  display: block;
  width: 100%;
  background: #fff;
  color: var(--hp-ink);
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-lg);
  padding: 9px 12px;
  font-family: var(--hp-font-sans);
  font-size: 13px;
  line-height: 1.4;
  box-sizing: border-box;
  transition: border-color 150ms var(--hp-ease-out),
              box-shadow   150ms var(--hp-ease-out);
}
.ds-form-input:focus,
.ds-form-input:focus-visible {
  outline: none;
  border-color: var(--hp-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--hp-primary-soft) 28%, transparent);
}
textarea.ds-form-input { resize: vertical; min-height: 72px; }
select.ds-form-input   { appearance: auto; padding-right: 28px; }

.ds-form-field-error .ds-form-input,
.ds-form-input[aria-invalid="true"] {
  border-color: var(--hp-ds-danger);
}
.ds-form-field-error .ds-form-input:focus,
.ds-form-input[aria-invalid="true"]:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--hp-ds-danger) 24%, transparent);
}

.ds-form-help {
  font-family: var(--hp-font-sans);
  font-size: 11px;
  color: var(--hp-muted);
  margin: 6px 0 0 0;
}
.ds-form-error {
  font-family: var(--hp-font-sans);
  font-size: 11px;
  font-weight: 600;
  color: var(--hp-ds-danger);
  margin: 6px 0 0 0;
}

/* ── G. Filter chip (spec §3.K) ────────────────────────────────────────── */
/* Pill-style toggle. data-state="active" is the source of truth so JS or
   server can both flip it without re-rendering. */
.ds-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--hp-font-sans);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  padding: 6px 12px;
  border-radius: 9999px;
  border: 1px solid var(--hp-border);
  background: #fff;
  color: var(--hp-ink-2);
  text-decoration: none;
  cursor: pointer;
  transition: all 150ms var(--hp-ease-out);
}
.ds-filter-chip:hover {
  border-color: color-mix(in srgb, var(--hp-primary) 35%, var(--hp-border));
  color: var(--hp-ink);
}
.ds-filter-chip:focus-visible {
  outline: 2px solid var(--hp-primary);
  outline-offset: 2px;
}
.ds-filter-chip[data-state="active"] {
  background: var(--hp-primary-bg);
  border-color: color-mix(in srgb, var(--hp-primary) 35%, #fff);
  color: var(--hp-primary);
}
.ds-filter-chip-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9999px;
  background: var(--hp-paper);
  color: var(--hp-muted);
  font-size: 10px;
  font-weight: 700;
}
.ds-filter-chip[data-state="active"] .ds-filter-chip-count {
  background: #fff;
  color: var(--hp-primary);
}

/* ── H. KPI tile (spec §3.D) ───────────────────────────────────────────── */
.ds-kpi-tile {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px 20px;
  background: #fff;
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-xl);
  box-shadow: var(--hp-shadow-card);
}
.ds-kpi-icon {
  color: var(--hp-muted);
  font-size: 14px;
  margin-bottom: 4px;
}
.ds-kpi-label {
  font-family: var(--hp-font-sans);
  font-size: 11px;
  font-weight: 600;
  color: var(--hp-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.ds-kpi-value {
  font-family: var(--hp-font-display);
  font-size: var(--hp-text-display-md);
  line-height: var(--hp-text-display-md-lh);
  font-weight: 700;
  color: var(--hp-ink);
  letter-spacing: -0.01em;
}
.ds-kpi-sub {
  font-family: var(--hp-font-sans);
  font-size: 12px;
  color: var(--hp-muted);
}
.ds-kpi-trend {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--hp-font-sans);
  font-size: 11px;
  font-weight: 700;
  margin-top: 4px;
}
.ds-kpi-trend[data-trend="up"]   { color: var(--hp-ds-success); }
.ds-kpi-trend[data-trend="down"] { color: var(--hp-ds-danger);  }
.ds-kpi-trend[data-trend="flat"] { color: var(--hp-muted);      }
/* Optional accent recolor for the value (e.g. capacity tiles) */
.ds-kpi-value[data-color="success"] { color: var(--hp-ds-success); }
.ds-kpi-value[data-color="warn"]    { color: var(--hp-ds-warn);    }
.ds-kpi-value[data-color="danger"]  { color: var(--hp-ds-danger);  }
.ds-kpi-value[data-color="primary"] { color: var(--hp-primary);    }

/* ── I. Progress bar (spec §3.O) ───────────────────────────────────────── */
/* Width comes from inline style (Ruby helper) so the transition triggers on
   value change. ARIA role + values are required (a11y baseline). */
.ds-progress {
  display: block;
  width: 100%;
}
.ds-progress-meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
  font-family: var(--hp-font-sans);
  font-size: 11px;
  color: var(--hp-muted);
}
.ds-progress-label { font-weight: 600; color: var(--hp-ink-2); }
.ds-progress-value { font-weight: 700; }
.ds-progress-track {
  position: relative;
  height: 8px;
  background: var(--hp-paper);
  border: 1px solid var(--hp-border);
  border-radius: 9999px;
  overflow: hidden;
}
.ds-progress-fill {
  display: block;
  height: 100%;
  background: var(--hp-primary);
  border-radius: 9999px;
  transition: width 350ms var(--hp-ease-out);
}
.ds-progress-fill[data-variant="success"] { background: var(--hp-ds-success); }
.ds-progress-fill[data-variant="warn"]    { background: var(--hp-ds-warn);    }
.ds-progress-fill[data-variant="danger"]  { background: var(--hp-ds-danger);  }

/* UX-4.5 PRM parity — explicit per-component override matching the rest of
   the design system (skeleton/modal/side-panel/toast all have one). The
   global rule in animations.css already neutralises transition-duration
   to 0.01ms, so the bar still reflects the new value; this block makes the
   contract explicit (single source of truth = component CSS, not "global
   covers it"). WCAG 2.3.3 — see best-practices in COMPONENTS.md. */
@media (prefers-reduced-motion: reduce) {
  .ds-progress-fill { transition: none; }
}

/* ── J. Skeleton loader (spec §3.E) ────────────────────────────────────── */
/* Reuses the @keyframes skeleton-shimmer already defined in
   harpaston_palette.css (Sprint 2 Fix 14) — do NOT redeclare. We just
   namespace 3 new size variants on top of the same shimmer. */
.ds-skeleton {
  display: inline-block;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--hp-border) 70%, #fff) 25%,
    var(--hp-paper) 50%,
    color-mix(in srgb, var(--hp-border) 70%, #fff) 75%
  );
  background-size: 800px 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--hp-radius-lg);
  color: transparent;
  pointer-events: none;
  user-select: none;
}
.ds-skeleton-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ds-skeleton-line   { height: 12px; width: 75%; border-radius: 4px; }
.ds-skeleton-box    { height: 128px; width: 100%; display: block; }
.ds-skeleton-avatar { width: 40px; height: 40px; border-radius: 9999px; }

/* Reduced-motion: degrade to a solid muted surface (spec §3.E note).
   The global animation kill in animations.css already freezes the shimmer;
   this rule additionally drops the gradient so it reads as a calm placeholder. */
@media (prefers-reduced-motion: reduce) {
  .ds-skeleton {
    background: var(--hp-paper);
    animation: none;
  }
}

/* =============================================================================
   UX-4.2 batch (c) — Overlay & complex atomic components

   K. Modal · L. Side panel · M. Toast · N. Copilot panel · O. Data table

   Z-index ladder consumed: --hp-z-modal-backdrop (50), --hp-z-modal (60),
   --hp-z-side-panels (60), --hp-z-toast (70). Legacy Bootstrap modal default
   (1050) coexists — UX-4.3 will sweep. Components are additive: no rule in
   this block touches a non `ds-*` selector.

   Animations consume tokens.css easing (--hp-ease-out) via animations.css
   utility classes where ergonomic, and define their own keyframes here when
   tighter coupling to the component is needed. Every keyframe has a
   prefers-reduced-motion fallback (opacity-only or no animation).
   ============================================================================= */

/* ── K. Modal / Dialog (spec §3.F) ─────────────────────────────────────── */
.ds-modal {
  position: fixed;
  inset: 0;
  z-index: var(--hp-z-modal-backdrop);
  display: block;
}
.ds-modal[hidden] { display: none; }

.ds-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  z-index: var(--hp-z-modal-backdrop);
  animation: ds-modal-fade-in 200ms var(--hp-ease-out);
}

.ds-modal-dialog {
  position: relative;
  z-index: var(--hp-z-modal);
  margin: 7vh auto 0;
  background: var(--hp-paper);
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-lg);
  box-shadow: var(--hp-shadow-card);
  display: flex;
  flex-direction: column;
  max-height: 86vh;
  overflow: hidden;
  animation: ds-modal-scale-in 220ms var(--hp-ease-out);
}
.ds-modal-dialog-sm { width: min(420px, calc(100% - 32px)); }
.ds-modal-dialog-md { width: min(560px, calc(100% - 32px)); }
.ds-modal-dialog-lg { width: min(800px, calc(100% - 32px)); }

.ds-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 24px;
  border-bottom: 1px solid var(--hp-border);
}
.ds-modal-title {
  margin: 0;
  font-family: var(--hp-font-display);
  font-size: 18px;
  font-weight: 700;
  color: var(--hp-ink);
  line-height: 1.3;
}
.ds-modal-variant-destructive .ds-modal-title {
  color: var(--hp-ds-danger);
}
.ds-modal-close {
  background: none;
  border: 0;
  color: var(--hp-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
.ds-modal-close:hover { background: var(--hp-gray-100); color: var(--hp-ink); }
.ds-modal-close:focus-visible { outline: 2px solid var(--hp-primary); outline-offset: 2px; }

.ds-modal-body {
  padding: 20px 24px;
  overflow-y: auto;
  flex: 1 1 auto;
  color: var(--hp-ink);
  font-size: 14px;
  line-height: 1.55;
}

.ds-modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 24px;
  border-top: 1px solid var(--hp-border);
  background: var(--hp-gray-50);
}

@keyframes ds-modal-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes ds-modal-scale-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .ds-modal-backdrop,
  .ds-modal-dialog { animation: none; }
}

/* ── L. Side panel / drawer (spec §3.G) ────────────────────────────────── */
.ds-side-panel {
  position: fixed;
  inset: 0;
  z-index: var(--hp-z-side-panels);
  display: block;
  pointer-events: none;
}
.ds-side-panel[hidden] { display: none; }

.ds-side-panel-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  z-index: var(--hp-z-modal-backdrop);
  pointer-events: auto;
  animation: ds-modal-fade-in 200ms var(--hp-ease-out);
}

.ds-side-panel-panel {
  position: absolute;
  z-index: var(--hp-z-side-panels);
  background: var(--hp-paper);
  border: 1px solid var(--hp-border);
  box-shadow: var(--hp-shadow-card-hover);
  display: flex;
  flex-direction: column;
  pointer-events: auto;
  max-width: 100vw;
  max-height: 100vh;
}

/* Right edge (default) */
.ds-side-panel-pos-right .ds-side-panel-panel {
  top: 0; right: 0; bottom: 0;
  border-left: 1px solid var(--hp-border);
  animation: ds-side-panel-slide-right 250ms var(--hp-ease-out);
}
/* Left edge */
.ds-side-panel-pos-left .ds-side-panel-panel {
  top: 0; left: 0; bottom: 0;
  border-right: 1px solid var(--hp-border);
  animation: ds-side-panel-slide-left 250ms var(--hp-ease-out);
}
/* Top edge */
.ds-side-panel-pos-top .ds-side-panel-panel {
  top: 0; left: 0; right: 0;
  border-bottom: 1px solid var(--hp-border);
  animation: ds-side-panel-slide-top 250ms var(--hp-ease-out);
}
/* Bottom edge */
.ds-side-panel-pos-bottom .ds-side-panel-panel {
  bottom: 0; left: 0; right: 0;
  border-top: 1px solid var(--hp-border);
  animation: ds-side-panel-slide-bottom 250ms var(--hp-ease-out);
}

/* Sizes — width for left/right, height for top/bottom */
.ds-side-panel-pos-right.ds-side-panel-size-sm  .ds-side-panel-panel,
.ds-side-panel-pos-left.ds-side-panel-size-sm   .ds-side-panel-panel  { width: 320px; }
.ds-side-panel-pos-right.ds-side-panel-size-md  .ds-side-panel-panel,
.ds-side-panel-pos-left.ds-side-panel-size-md   .ds-side-panel-panel  { width: 400px; }
.ds-side-panel-pos-right.ds-side-panel-size-lg  .ds-side-panel-panel,
.ds-side-panel-pos-left.ds-side-panel-size-lg   .ds-side-panel-panel  { width: 560px; }
.ds-side-panel-pos-top.ds-side-panel-size-sm    .ds-side-panel-panel,
.ds-side-panel-pos-bottom.ds-side-panel-size-sm .ds-side-panel-panel  { height: 240px; }
.ds-side-panel-pos-top.ds-side-panel-size-md    .ds-side-panel-panel,
.ds-side-panel-pos-bottom.ds-side-panel-size-md .ds-side-panel-panel  { height: 360px; }
.ds-side-panel-pos-top.ds-side-panel-size-lg    .ds-side-panel-panel,
.ds-side-panel-pos-bottom.ds-side-panel-size-lg .ds-side-panel-panel  { height: 520px; }

.ds-side-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--hp-border);
}
.ds-side-panel-title {
  margin: 0;
  font-family: var(--hp-font-display);
  font-size: 17px;
  font-weight: 700;
  color: var(--hp-ink);
}
.ds-side-panel-close {
  background: none;
  border: 0;
  color: var(--hp-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
.ds-side-panel-close:hover { background: var(--hp-gray-100); color: var(--hp-ink); }
.ds-side-panel-close:focus-visible { outline: 2px solid var(--hp-primary); outline-offset: 2px; }

.ds-side-panel-body {
  padding: 18px 20px;
  overflow-y: auto;
  flex: 1 1 auto;
  color: var(--hp-ink);
  font-size: 14px;
}

.ds-side-panel-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--hp-border);
  background: var(--hp-gray-50);
}

@keyframes ds-side-panel-slide-right {
  from { transform: translateX(100%); opacity: 0.5; }
  to   { transform: translateX(0);    opacity: 1;   }
}
@keyframes ds-side-panel-slide-left {
  from { transform: translateX(-100%); opacity: 0.5; }
  to   { transform: translateX(0);     opacity: 1;   }
}
@keyframes ds-side-panel-slide-top {
  from { transform: translateY(-100%); opacity: 0.5; }
  to   { transform: translateY(0);     opacity: 1;   }
}
@keyframes ds-side-panel-slide-bottom {
  from { transform: translateY(100%); opacity: 0.5; }
  to   { transform: translateY(0);    opacity: 1;   }
}
@media (prefers-reduced-motion: reduce) {
  .ds-side-panel-backdrop,
  .ds-side-panel-panel { animation: none; }
}

/* ── M. Toast (spec §3.H · 4 variants) ─────────────────────────────────── */
/* Stacking is provided by .ds-toast-stack — the canonical wrapper rendered in
   application.html.erb / auth.html.erb. Individual toasts can also be
   rendered standalone in absolute-positioned regions. */
.ds-toast-stack {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: var(--hp-z-toast);
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 420px;
  width: calc(100vw - 32px);
  pointer-events: none;
}
.ds-toast-stack > .ds-toast { pointer-events: auto; }

.ds-toast {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px 12px 14px;
  border-radius: var(--hp-radius-lg);
  background: var(--hp-paper);
  border: 1px solid var(--hp-border);
  box-shadow: var(--hp-shadow-toast);
  color: var(--hp-ink);
  font-size: 13px;
  line-height: 1.45;
  animation: ds-toast-slide-in 250ms var(--hp-ease-out);
}
.ds-toast-leaving {
  animation: ds-toast-fade-out 250ms var(--hp-ease-out) forwards;
}

.ds-toast-icon {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13px;
  color: var(--hp-paper);
}
.ds-toast-message { flex: 1 1 auto; word-break: break-word; }

.ds-toast-action {
  background: none;
  border: 0;
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  padding: 4px 6px;
  border-radius: 4px;
  cursor: pointer;
}
.ds-toast-action:hover { background: rgba(15, 23, 42, 0.06); }
.ds-toast-action:focus-visible { outline: 2px solid var(--hp-primary); outline-offset: 2px; }

.ds-toast-close {
  background: none;
  border: 0;
  color: var(--hp-muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.ds-toast-close:hover { background: rgba(15, 23, 42, 0.06); color: var(--hp-ink); }
.ds-toast-close:focus-visible { outline: 2px solid var(--hp-primary); outline-offset: 2px; }

.ds-toast-success { border-color: rgba(22, 163, 74, 0.30); }
.ds-toast-success .ds-toast-icon { background: var(--hp-ds-success); }
.ds-toast-info    { border-color: var(--hp-blue-200); }
.ds-toast-info    .ds-toast-icon { background: var(--hp-blue-500); }
.ds-toast-warn    { border-color: rgba(245, 158, 11, 0.35); }
.ds-toast-warn    .ds-toast-icon { background: var(--hp-ds-warn); color: #1f1300; }
.ds-toast-error   { border-color: rgba(220, 38, 38, 0.30); }
.ds-toast-error   .ds-toast-icon { background: var(--hp-ds-danger); }

@keyframes ds-toast-slide-in {
  from { transform: translateY(-12px); opacity: 0; }
  to   { transform: translateY(0);     opacity: 1; }
}
@keyframes ds-toast-fade-out {
  from { transform: translateY(0);     opacity: 1; }
  to   { transform: translateY(-12px); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ds-toast,
  .ds-toast-leaving {
    animation-duration: 200ms !important;
    animation-name: ds-toast-opacity-only !important;
  }
}
@keyframes ds-toast-opacity-only {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── N. Copilot panel (spec §3.I · shell only · AI wiring deferred to AI-1) */
.ds-copilot-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(420px, 100vw);
  z-index: var(--hp-z-side-panels);
  background: var(--hp-paper);
  border-left: 1px solid var(--hp-border);
  box-shadow: var(--hp-shadow-card-hover);
  display: flex;
  flex-direction: column;
  animation: ds-side-panel-slide-right 250ms var(--hp-ease-out);
}
.ds-copilot-panel[hidden] { display: none; }

.ds-copilot-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--hp-border);
}
.ds-copilot-avatar {
  width: 32px;
  height: 32px;
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-family: var(--hp-font-display);
  color: var(--hp-paper);
  background: linear-gradient(135deg, var(--hp-primary) 0%, var(--hp-primary-soft) 100%);
}
.ds-copilot-title {
  flex: 1 1 auto;
  margin: 0;
  font-family: var(--hp-font-display);
  font-size: 16px;
  font-weight: 700;
  color: var(--hp-ink);
}
.ds-copilot-close {
  background: none;
  border: 0;
  color: var(--hp-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
.ds-copilot-close:hover { background: var(--hp-gray-100); color: var(--hp-ink); }
.ds-copilot-close:focus-visible { outline: 2px solid var(--hp-primary); outline-offset: 2px; }

.ds-copilot-messages {
  flex: 1 1 auto;
  list-style: none;
  margin: 0;
  padding: 16px 18px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: var(--hp-ink);
  font-size: 14px;
  line-height: 1.5;
}
.ds-copilot-message {
  padding: 10px 12px;
  border-radius: var(--hp-radius-lg);
  background: var(--hp-gray-100);
  max-width: 85%;
}
.ds-copilot-message-user {
  align-self: flex-end;
  background: var(--hp-primary-bg);
}

.ds-copilot-input {
  border-top: 1px solid var(--hp-border);
  padding: 12px 14px;
  background: var(--hp-paper);
}
.ds-copilot-input form {
  display: flex;
  gap: 8px;
  align-items: center;
}
.ds-copilot-prompt {
  flex: 1 1 auto;
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-lg);
  padding: 8px 12px;
  font-size: 14px;
  font-family: inherit;
  color: var(--hp-ink);
  background: var(--hp-gray-50);
  outline: none;
}
.ds-copilot-prompt:focus-visible {
  border-color: var(--hp-primary);
  background: var(--hp-paper);
  box-shadow: 0 0 0 3px var(--hp-primary-bg);
}
.ds-copilot-prompt:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}
.ds-copilot-send {
  border: 0;
  background: var(--hp-primary);
  color: var(--hp-paper);
  font-weight: 600;
  padding: 8px 14px;
  border-radius: var(--hp-radius-lg);
  cursor: pointer;
}
.ds-copilot-send:hover:not(:disabled) { background: var(--hp-primary-soft); }
.ds-copilot-send:disabled { opacity: 0.5; cursor: not-allowed; }
.ds-copilot-send:focus-visible { outline: 2px solid var(--hp-primary); outline-offset: 2px; }

/* ── O. Data table (spec §3.N · foundation for Phase 6.B flow views) ───── */
.ds-data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: var(--hp-paper);
  border: 1px solid var(--hp-border);
  border-radius: var(--hp-radius-lg);
  overflow: hidden;
  font-size: 13px;
  color: var(--hp-ink);
}

.ds-data-table-caption {
  caption-side: top;
  text-align: left;
  padding: 12px 14px;
  font-weight: 600;
  font-size: 13px;
  color: var(--hp-ink);
}

.ds-data-table thead {
  background: var(--hp-gray-50);
}
.ds-data-table-th {
  text-align: left;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--hp-muted);
  padding: 12px 14px;
  border-bottom: 1px solid var(--hp-border);
  white-space: nowrap;
}
.ds-data-table-align-right  { text-align: right; }
.ds-data-table-align-center { text-align: center; }

.ds-data-table-sortable .ds-data-table-sort-btn {
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
}
.ds-data-table-sort-btn:hover { color: var(--hp-ink); }
.ds-data-table-sort-btn:focus-visible {
  outline: 2px solid var(--hp-primary);
  outline-offset: 2px;
}
.ds-data-table-sort-icon {
  font-size: 10px;
  opacity: 0.7;
}

.ds-data-table-row + .ds-data-table-row .ds-data-table-td {
  border-top: 1px solid var(--hp-border);
}
.ds-data-table-row:hover { background: var(--hp-gray-50); }
.ds-data-table-td {
  padding: 12px 14px;
  vertical-align: middle;
  color: var(--hp-ink);
}

.ds-data-table-select-col {
  width: 40px;
  text-align: center;
}

.ds-data-table-empty {
  padding: 32px 14px;
  text-align: center;
  color: var(--hp-muted);
  font-style: italic;
}

/* =============================================================================
   UX-4.6 — Responsive behavior (mobile-first audit of the 15 atomic components)

   Convention (see tokens.css ARC-5 note): @media uses LITERAL px matching the
   canonical breakpoint tokens — CSS forbids var() in media conditions and
   sprockets has no @custom-media transform. --hp-bp-tablet (768) is the
   primary "compact" gate for component-level rules; --hp-bp-mobile (375) is
   the narrowest width at which we guarantee readable text + no h-scroll.

   Audit outcome (15/15):
     • 8 components gain explicit mobile rules below — touch targets ≥44px on
       every interactive control (WCAG 2.5.5 / iOS HIG), padding + type
       compaction, and full-bleed overlays.
     • 7 need NO rule and are asserted compliant in the smoke spec +
       COMPONENTS.md: Pill, Pacte badge (read-only inline badges); Avatar
       (fixed small sizes); Progress bar, Skeleton (fluid width: 100%); Toast
       (width: calc(100vw - 32px)); Copilot panel (width: min(420px, 100vw)).
   ============================================================================= */

@media (max-width: 768px) { /* --hp-bp-tablet — component compaction gate */

  /* (1) Button — guarantee a ≥44px tap target. */
  .ds-btn { min-height: 44px; padding-top: 11px; padding-bottom: 11px; }

  /* (7) Filter chip — same tap-target floor (it is an interactive toggle). */
  .ds-filter-chip { min-height: 44px; }

  /* (6) Form field — 16px input font stops iOS Safari auto-zoom on focus;
     44px min-height keeps the field a comfortable tap target. */
  .ds-form-input,
  select.ds-form-input { font-size: 16px; min-height: 44px; }

  /* (3) Frame card — tighten body padding on small screens. */
  .ds-frame-card-body { padding: 14px; }

  /* (8) KPI tile — compact padding + step the value down one display tier
     (md 32px → sm 24px) so big numbers fit a 2-up mobile grid. */
  .ds-kpi-tile { padding: 14px 16px; }
  .ds-kpi-value {
    font-size: var(--hp-text-display-sm);
    line-height: var(--hp-text-display-sm-lh);
  }

  /* (11) Modal — near-full-bleed dialog, tighter padding, stacked full-width
     footer buttons for thumb reach. */
  .ds-modal-dialog { margin-top: 4vh; max-height: 92vh; }
  .ds-modal-dialog-sm,
  .ds-modal-dialog-md,
  .ds-modal-dialog-lg { width: calc(100% - 24px); }
  .ds-modal-header,
  .ds-modal-body,
  .ds-modal-footer { padding-left: 16px; padding-right: 16px; }
  .ds-modal-footer { flex-direction: column-reverse; align-items: stretch; }
  .ds-modal-footer .ds-btn { width: 100%; }

  /* (12) Side panel — left/right drawers go full-width (a 320–560px panel on a
     375px screen otherwise leaves a sliver of backdrop). Bottom-sheet variant
     is a separate #NEW followup; this only removes horizontal overflow. */
  .ds-side-panel-pos-right .ds-side-panel-panel,
  .ds-side-panel-pos-left  .ds-side-panel-panel { width: 100vw; }

  /* (15) Data table — compact cells. A wide table must still be wrapped in
     .table-responsive (responsive.css) for horizontal scroll; tighter cells
     just reduce how often that scroll is needed. */
  .ds-data-table-th,
  .ds-data-table-td { padding: 10px 10px; }

  /* Overlay close controls — lift sub-44px icon buttons to a tap target
     (modal · side-panel · toast · copilot). */
  .ds-modal-close,
  .ds-side-panel-close,
  .ds-copilot-close,
  .ds-toast-close {
    min-width: 44px;
    min-height: 44px;
  }
}

@media (max-width: 375px) { /* --hp-bp-mobile — narrowest guaranteed floor */
  .ds-toast-stack { left: 16px; right: 16px; width: auto; } /* symmetric full-bleed */
  .ds-data-table { font-size: 12px; }                       /* keep dense tables legible */
}



/* ═══════════════════════════════════════════════════════════════════════════
   UX-3.b · ACTIVATION FUNNEL CHROME
   Sandbox trial banner (W253) + activation checklist widget (W52). Consumes
   tokens.css / harpaston_palette.css custom props (no raw hex).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Sandbox trial banner ── full-width strip below the header ── */
.hp-sandbox-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 28px;
  background: var(--hp-blue-50);
  border-bottom: 1px solid var(--hp-blue-200);
  color: var(--hp-blue-700);
  font-size: 12px;
}
.hp-sandbox-banner__msg { display: flex; align-items: center; gap: 7px; }
.hp-sandbox-banner__msg i { font-size: 12px; opacity: 0.8; }
.hp-sandbox-banner__sub { color: var(--hp-blue-600); opacity: 0.8; }
.hp-sandbox-banner__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 5px 12px;
  border-radius: var(--hp-radius-lg);
  background: var(--hp-blue-500);
  color: #fff !important;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.15s var(--hp-ease-out);
}
.hp-sandbox-banner__cta:hover { background: var(--hp-blue-600); color: #fff !important; }
.hp-sandbox-banner__cta i { font-size: 10px; }

/* ── Activation checklist widget (W52) ── */
.hp-checklist { display: flex; flex-direction: column; gap: 2px; }
.hp-checklist__item {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px 14px;
  border-radius: var(--hp-radius-lg);
  border: 1px solid transparent;
}
.hp-checklist__item--spotlight {
  background: var(--hp-blue-50);
  border-color: var(--hp-blue-200);
}
.hp-checklist__check {
  flex-shrink: 0;
  width: 20px; height: 20px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px;
  border: 1.5px solid var(--hp-border);
  color: var(--hp-muted);
  margin-top: 1px;
}
.hp-checklist__item--done .hp-checklist__check {
  background: var(--hp-success);
  border-color: var(--hp-success);
  color: #fff;
}
.hp-checklist__item--spotlight .hp-checklist__check {
  border-color: var(--hp-blue-500);
  color: var(--hp-blue-600);
}
.hp-checklist__body { flex: 1; min-width: 0; }
.hp-checklist__label { font-size: 13px; color: var(--hp-ink); font-weight: 500; }
.hp-checklist__item--done .hp-checklist__label { color: var(--hp-muted); text-decoration: line-through; }
.hp-checklist__item--locked .hp-checklist__label { color: var(--hp-muted); }
.hp-checklist__meta { font-size: 10px; color: var(--hp-muted); margin-top: 2px; letter-spacing: .02em; }
.hp-checklist__cta { flex-shrink: 0; align-self: center; }

@media (max-width: 768px) {
  .hp-sandbox-banner { padding: 8px 16px; flex-wrap: wrap; }
  .hp-sandbox-banner__cta { min-height: 40px; }                /* WCAG 2.5.5 tap target */
  .hp-checklist__item { padding: 12px 12px; }
}

/* ── UX-3.c · cross-module nudges (W258) ── */
.hp-nudges { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.hp-nudge {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--hp-blue-50);
  border: 1px solid var(--hp-blue-200);
  border-radius: var(--hp-radius-lg);
  font-size: 12px;
  color: var(--hp-blue-700);
}
.hp-nudge__icon { flex-shrink: 0; color: var(--hp-blue-500); }
.hp-nudge__msg { flex: 1; min-width: 0; line-height: 1.4; }
.hp-nudge__cta {
  flex-shrink: 0;
  padding: 5px 12px;
  border-radius: var(--hp-radius-lg);
  background: var(--hp-blue-500);
  color: #fff !important;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.15s var(--hp-ease-out);
}
.hp-nudge__cta:hover { background: var(--hp-blue-600); color: #fff !important; }
.hp-nudge__dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--hp-blue-600);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  opacity: 0.6;
}
.hp-nudge__dismiss:hover { opacity: 1; }

@media (max-width: 768px) {
  .hp-nudge { flex-wrap: wrap; }
  .hp-nudge__cta { min-height: 40px; display: inline-flex; align-items: center; } /* WCAG 2.5.5 */
}
/* Harpaston — Global Styles */
/*







*/

/* Ensure all form controls use Inter, not the monospace fallback */
input, select, textarea, button {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* ── FORM COMPONENTS (extracted from _form.html.erb partial) ────────── */
.form-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--text2, #475569);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.form-input {
  display: block;
  width: 100%;
  background: var(--bg2, var(--hp-white));
  border: 1px solid var(--border, var(--hp-gray-200));
  color: var(--text1, var(--hp-gray-800));
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13px;
  font-family: inherit;
  box-sizing: border-box;
}
textarea.form-input { resize: vertical; }

.tier-segment { display: flex; gap: 6px; flex-wrap: wrap; }
.tier-segment__btn {
  border-radius: 9999px;
  border: 1px solid transparent;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  opacity: 0.45;
  transition: opacity 0.15s, box-shadow 0.15s;
  font-family: inherit;
}
.tier-segment__btn:hover { opacity: 0.75; }
.tier-segment__btn--active { opacity: 1 !important; box-shadow: 0 0 0 2px currentColor; }

/* ── AUDIT ROUND 2 — TIER 1 FIXES ─────────────────────────────────────── */

/* FIX 2: tabular-nums on ALL numeric data */
td, .kpi-val, .mc-stat-val, .detail-value,
[class*="-count"], [class*="-metric"], [class*="-value"] {
  font-variant-numeric: tabular-nums;
}

/* FIX 3: Table alternating rows */
table tbody tr:nth-child(even) {
  background-color: var(--hp-gray-50) !important;
}
table tbody tr:hover {
  background-color: var(--hp-blue-50) !important;
  transition: background-color 0.1s ease;
}

/* FIX 4: Table column header differentiation */
table thead th {
  font-size: 10px !important;
  font-weight: 700 !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase !important;
  color: var(--hp-gray-500) !important;
  border-bottom: 2px solid var(--hp-gray-200) !important;
  padding-bottom: 10px !important;
}

/* FIX 5: Form focus ring — blue only, never gold/amber */
.form-input:focus,
input:focus,
select:focus,
textarea:focus {
  outline: none !important;
  border-color: var(--hp-blue-500) !important;
  box-shadow: 0 0 0 3px rgba(45, 124, 246, 0.15) !important;
}

/* FIX 6: Tier segment pill padding — fix Ultra VIP line wrap */
.tier-segment__btn {
  padding: 5px 10px !important;
  white-space: nowrap !important;
}

/* FIX 7: Secondary metric hierarchy */
.mc-secondary-metric {
  font-size: 13px !important;
  font-weight: 400 !important;
  color: var(--hp-gray-500) !important;
}

/* FIX 8: Empty/zero module card visual distinction */
.mc-kpi-val[data-value="0"],
.mc-kpi-val[data-value="0%"],
.mc-kpi-val[data-value="—"],
.mc-kpi-val[data-value="€0"],
.mc-kpi-val[data-value="$0"],
.mc-kpi-val[data-value="£0"] {
  color: var(--hp-gray-300) !important;
  font-weight: 400 !important;
}

/* FIX 9: KPI card icon — constrained to ghost position, never dominant */
.kpi-card {
  position: relative !important;
}
.kpi-card .kpi-icon {
  position: absolute !important;
  top: 12px !important;
  right: 12px !important;
  font-size: 20px !important;
  opacity: 0.12 !important;
  color: var(--text, var(--hp-gray-800)) !important;
  width: auto !important;
  height: auto !important;
  background: none !important;
}

/* FIX 10: Breadcrumb top margin */
.page-bc {
  margin-top: 8px !important;
}

/* ── GUEST DETAIL — Operational Details section ──────────────────────── */
.detail-section {
  margin-top: 24px;
}
.detail-section-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hp-gray-400);
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--hp-gray-200);
}
.detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  background: var(--hp-white);
  border: 1px solid var(--hp-gray-200);
  border-radius: 8px;
  padding: 20px 24px;
}
.detail-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.detail-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--hp-gray-400);
}
.detail-value {
  font-size: 14px;
  color: var(--hp-gray-800);
  font-weight: 500;
}
.text-muted {
  color: var(--hp-gray-300);
  font-weight: 400;
}
.empty-module-card {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border: 1px dashed var(--hp-gray-300);
  border-radius: 6px;
  color: var(--hp-gray-400);
  font-size: 13px;
}

/* ── EVENT STATUS BAR (T3-1) ─────────────────────────────────────────── */
.event-status-bar {
  display: flex;
  align-items: center;
  background: var(--hp-white);
  border: 1px solid var(--hp-gray-200);
  border-radius: 8px;
  padding: 14px 24px;
  margin-bottom: 20px;
  gap: 0;
}
.esb-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  gap: 3px;
}
.esb-value {
  font-size: 24px;
  font-weight: 700;
  color: var(--hp-gray-800);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  font-family: 'Syne', sans-serif;
}
.esb-label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hp-gray-400);
}
.esb-divider {
  width: 1px;
  height: 36px;
  background: var(--hp-gray-200);
  flex-shrink: 0;
}
.esb-time {
  font-size: 13px !important;
  font-weight: 500 !important;
  font-family: 'Inter', sans-serif !important;
}
.text-warning { color: var(--hp-warning) !important; }
.text-success { color: var(--hp-success) !important; }

/* ── MODULE CARD EMPTY STATE (T3-3) ─────────────────────────────────── */
.mc-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  gap: 8px;
}
.mc-empty-state-icon {
  font-size: 24px;
  opacity: 0.2;
}
.mc-empty-state-text {
  font-size: 12px;
  color: var(--hp-gray-300);
  text-align: center;
  font-style: italic;
}

/* ── Turbolinks progress bar — brand blue ── */
.turbolinks-progress-bar {
  background-color: var(--hp-blue-500) !important;
  height: 3px !important;
}

/* ── PRINT STYLES ─────────────────────────────────────────────────────────── */
@media print {
  /* Hide all chrome */
  .sidebar,
  .topbar,
  .mobile-menu-btn,
  .sidebar-overlay,
  .mc-actions,
  .btn,
  .dropdown,
  .flash-wrap,
  .bulk-toolbar,
  .breadcrumbs,
  .page-nav,
  .print-hide,
  nav { display: none !important; }

  /* Reset layout — no sidebar margin, no topbar padding */
  .page-wrap  { margin-left: 0 !important; padding-top: 0 !important; }
  .page-content { padding: 16px !important; }

  /* Typography — all black, no colored backgrounds */
  body, * { color: #000 !important; background: #fff !important; }

  /* Flatten shadows and borders for laser printers */
  * { box-shadow: none !important; text-shadow: none !important; }
  .harp-panel, .harp-kpi-card, .detail-grid {
    border: 1px solid #ccc !important;
    border-radius: 0 !important;
  }

  /* Badges — border-only in print (no colored backgrounds) */
  .status-badge, .mc-pill, .sidebar-nav-badge {
    background: transparent !important;
    border: 1px solid #000 !important;
    color: #000 !important;
    padding: 1px 4px !important;
  }

  /* Page break control */
  .detail-section, .harp-panel, .mc.harp-panel { page-break-inside: avoid; }
  .harp-mod-grid { display: block !important; }
  .harp-mod-grid .mc.harp-panel { margin-bottom: 12px !important; }

  /* Show print-only elements */
  .print-header { display: block !important; }
}
/* =============================================================================
   Harpaston — Accessibility modes (UX-1.b · W264)

   Four user-toggleable display modes, applied as <body> classes. For logged-in
   users the class is rendered server-side from User#a11y_body_classes (survives
   reloads); a11y_controller.js flips it live and persists. Guests get the same
   classes from localStorage on connect.

   Overriding the semantic aliases (--text / --border / …) on the body scope
   out-specifies the :root definitions in harpaston_palette.css, so every
   descendant inherits the high-contrast values without per-component edits.
   ============================================================================= */

/* ── High contrast ──────────────────────────────────────────────────────────
   Push body text to near-black, secondary/muted text up to AA-on-white, and
   borders to a visible grey. Targets WCAG 1.4.3 (≥4.5:1) + 1.4.11 (≥3:1 UI). */
body.a11y-high-contrast {
  --text:   #000000;
  --text2:  #1F2430;  /* was --hp-gray-600 #475569 */
  --text3:  #3A4151;  /* was --hp-gray-400 #94A3B8 (failed AA) */
  --border:  #6B7280;
  --border2: #4B5563;

  --bs-body-color:      #000000;
  --bs-secondary-color: #1F2430;
  --bs-tertiary-color:  #3A4151;
  --bs-border-color:    #6B7280;

  --hp-muted: #3A4151;
  --hp-ink:   #000000;
}
/* Strengthen hairline separators that relied on the faint default border. */
body.a11y-high-contrast .panel,
body.a11y-high-contrast .card,
body.a11y-high-contrast table th,
body.a11y-high-contrast table td {
  border-color: #6B7280;
}

/* ── Larger text ──────────────────────────────────────────────────────────── */
body.a11y-large-text {
  --bs-body-font-size: 16px;            /* was 13px ≈ +23% */
  font-size: 16px;
}
body.a11y-large-text .page-title  { font-size: 1.4em; }
body.a11y-large-text .panel-title,
body.a11y-large-text .form-label,
body.a11y-large-text .sidebar-nav-item span { font-size: 1.15em; }

/* ── Underline links ──────────────────────────────────────────────────────────
   WCAG 1.4.1 reinforcement: links no longer rely on colour alone. Scope to
   content areas; skip nav/sidebar/button-styled links to avoid noise. */
body.a11y-underline-links a:not(.btn):not(.sidebar-nav-item):not(.skip-to-content) {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ── Reduce motion (user override) ────────────────────────────────────────────
   prefers-reduced-motion is already honoured at the OS level; this lets a user
   force it on regardless of the OS setting. */
body.a11y-reduce-motion *,
body.a11y-reduce-motion *::before,
body.a11y-reduce-motion *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}

/* =============================================================================
   Stress (focus) mode — UX-7

   A focus mode that simplifies the UI when an operator is under pressure. Toggled
   by the always-visible floating "I'm stressed" button and the /profile panel;
   applied as the single <body> class "stress-mode" (server-rendered so it
   survives reloads, flipped live by stress_controller.js). Composes cleanly with
   the four a11y modes above — Stress + A11y is just two body classes at once.

   Achievable-today subset (per personas v2 §2-3): larger base text, animations
   off, and longer toast dwell (the 15s timing lives in toast_controller.js since
   a setTimeout can't read a CSS var). Deferred to Phase 6: top-5-widget
   dashboard simplification, one-question-per-screen wizards, B/W KPI tiles,
   table→card stacking, and the always-visible voice mic — all need infra that
   doesn't exist yet (logged as #UX-7.deferred-auto-triggers + deferred-ui).
   ============================================================================= */
body.stress-mode {
  --bs-body-font-size: 16px;            /* was 13px — match the Larger-text bump */
  font-size: 16px;
}
body.stress-mode .page-title { font-size: 1.4em; }
body.stress-mode .panel-title,
body.stress-mode .form-label { font-size: 1.12em; }

/* Animations off — same treatment as a11y-reduce-motion so focus mode is calm
   regardless of the OS prefers-reduced-motion setting. */
body.stress-mode *,
body.stress-mode *::before,
body.stress-mode *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}

/* ── Floating "I'm stressed" button (shared/_stress_button) ─────────────────
   Fixed bottom-right on every authenticated layout. ≥44px tap target (WCAG
   2.5.5 / 2.1.1, per UX-1.a discipline). is-active is server-rendered when the
   mode is already on and toggled live by stress_controller.js. */
.hp-stress-btn {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 1200;                        /* above content, below modals/toasts */
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid var(--hp-blue-500, #2D7CF6);
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--hp-blue-600, #1E63D0);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
}
.hp-stress-btn:hover { background: var(--hp-blue-50, #EFF5FF); }
.hp-stress-btn:focus-visible {
  outline: 2px solid var(--hp-blue-500, #2D7CF6);
  outline-offset: 2px;
}
.hp-stress-btn-icon { font-size: 18px; line-height: 1; }
/* Active state — mode is on; invite to turn it off. */
.hp-stress-btn.is-active {
  background: var(--hp-blue-600, #1E63D0);
  border-color: var(--hp-blue-600, #1E63D0);
  color: #FFFFFF;
}
.hp-stress-btn.is-active:hover { background: var(--hp-blue-700, #1A57B8); }
/* Stress mode forces motion off, so no transition rule here is needed. */
@media (max-width: 768px) {
  /* Collapse to an icon-only pill on small screens to avoid covering content. */
  .hp-stress-btn-label { display: none; }
  .hp-stress-btn { padding: 10px; min-width: 44px; justify-content: center; }
}

/* ── Toggle control (shared/_a11y_toggle) ─────────────────────────────────── */
.a11y-toggle-group { display: flex; flex-direction: column; gap: 4px; }
.a11y-toggle-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 12px 4px; border-bottom: 1px solid var(--border, #E2E8F0);
  cursor: pointer;
}
.a11y-toggle-row:last-child { border-bottom: 0; }
.a11y-toggle-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.a11y-toggle-title { font-size: 13px; font-weight: 600; color: var(--text, #1E293B); }
.a11y-toggle-desc  { font-size: 11px; color: var(--text2, #475569); }
/* Native checkbox kept (keyboard + a11y); just enlarged to a comfortable tap. */
.a11y-toggle-input {
  width: 20px; height: 20px; flex-shrink: 0; accent-color: var(--hp-blue-500, #2D7CF6);
  cursor: pointer;
}
.a11y-toggle-input:focus-visible {
  outline: 2px solid var(--hp-blue-500, #2D7CF6); outline-offset: 2px;
}
/* =============================================================================
   Harpaston Print Styles — guest manifests, rooming lists, itineraries
   Complements the @media print block in application.css
   ============================================================================= */

@media print {
  /* ── Page setup ── */
  @page {
    size: A4 portrait;
    margin: 18mm 20mm;
  }

  /* ── Print header (hidden on screen, shown on print) ── */
  .print-header {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    border-bottom: 2px solid #000;
    padding-bottom: 10px;
    margin-bottom: 20px;
  }
  .print-header-logo {
    font-family: Arial, sans-serif;
    font-weight: 700;
    font-size: 16px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }
  .print-header-meta {
    font-size: 10px;
    text-align: right;
    line-height: 1.5;
  }

  /* ── Guest detail ── */
  .detail-grid {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 12px 24px !important;
    page-break-inside: avoid;
  }
  .detail-field { page-break-inside: avoid; }
  .detail-label { font-size: 9px !important; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: #666 !important; }
  .detail-value { font-size: 13px !important; }

  /* ── Guest table ── */
  table { page-break-inside: auto; }
  table thead { display: table-header-group; }
  table tr { page-break-inside: avoid; }
  table thead th { border-bottom: 2px solid #000 !important; font-size: 9px !important; }
  table tbody td { font-size: 11px !important; padding: 4px 8px !important; }
  table tbody tr { border-bottom: 1px solid #ccc !important; }

  /* ── KPI cards on dashboard ── */
  .harp-kpi-grid {
    display: grid !important;
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 8px !important;
    page-break-inside: avoid;
  }
  .harp-kpi-card { border: 1px solid #ccc !important; padding: 12px !important; }
  .harp-kpi-value { font-size: 24px !important; }
  .harp-kpi-label { font-size: 8px !important; }

  /* ── Module card KPI row ── */
  .mc-kpis { background: transparent !important; border: 1px solid #ddd !important; }
  .mc-kpi { background: #fff !important; }
  .mc-kpi-val { font-size: 18px !important; }
  .mc-kpi ~ .mc-kpi .mc-kpi-val { font-size: 13px !important; }
  .mc-util-track { display: none !important; }

  /* ── Module card header ── */
  .mc-head { border-bottom: 1px solid #ccc !important; padding: 8px 12px !important; }
  .mc-name { font-size: 11px !important; font-weight: 700; }
  .mc-icon { display: none !important; }
}
/* Harpaston — Responsive / Mobile-Tablet Breakpoints
   Auto-loaded via application.css require_tree .

   UX-4.6: breakpoints aligned to the canonical token matrix in tokens.css
   (--hp-bp-mobile 375 / --hp-bp-tablet 768 / --hp-bp-laptop 1024 /
   --hp-bp-desktop 1440). @media conditions use literal px (CSS forbids
   var() in media queries + no PostCSS @custom-media transform — see
   tokens.css ARC-5 note); each block is tagged with its token name. The
   former ad-hoc 900/1100 values collapsed to the nearest primary tier
   (900 → 768 tablet, 1100 → 1024 laptop). */

/* ── Utility: hide on mobile ──────────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet */
  .hide-mobile { display: none !important; }
}
@media (max-width: 1024px) { /* --hp-bp-laptop */
  .hide-tablet { display: none !important; }
}

/* ── Scrollable table wrapper ─────────────────────────────────────────── */
.table-responsive {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.table-responsive table {
  min-width: 600px;
}

/* ── Layout: sidebar ──────────────────────────────────────────────────── */
@media (max-width: 1024px) { /* --hp-bp-laptop */
  :root { --sidebar-w: 0px; }

  .sidebar {
    position: fixed;
    left: -240px;
    top: 0;
    bottom: 0;
    width: 240px;
    z-index: var(--hp-z-side-panels); /* UX-4.1 z-index registry (was 200) */
    transition: left .2s ease;
    box-shadow: 2px 0 16px rgba(0,0,0,.3);
  }

  .sidebar.is-open { left: 0; }

  .main-content {
    margin-left: 0 !important;
    padding: 12px;
  }

  .mobile-menu-btn { display: flex !important; }
}

@media (min-width: 1025px) { /* --hp-bp-laptop +1 */
  .mobile-menu-btn { display: none !important; }
}

/* ── Layout: topbar ───────────────────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet */
  .topbar-clock { display: none !important; }
  .topbar-breadcrumb { display: none !important; }

  .topbar-right {
    gap: 4px !important;
  }
}

/* ── KPI grid ─────────────────────────────────────────────────────────── */
@media (max-width: 1024px) { /* --hp-bp-laptop */
  .kpi-row.cols-4 { grid-template-columns: repeat(2, 1fr) !important; }
  .kpi-row.cols-3 { grid-template-columns: repeat(2, 1fr) !important; }
}
@media (max-width: 768px) { /* --hp-bp-tablet */
  .kpi-row { grid-template-columns: repeat(2, 1fr) !important; }
  .kpi-row.cols-4 { grid-template-columns: repeat(2, 1fr) !important; }
}

/* ── Page header ──────────────────────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet */
  .page-header {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 10px !important;
  }

  .page-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
}

/* ── Grid-2 (two-column panels) ───────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet (was ad-hoc 900) */
  .grid-2 { grid-template-columns: 1fr !important; }
}

/* ── Guest Command Centre 3-col ───────────────────────────────────────── */
@media (max-width: 1024px) { /* --hp-bp-laptop (was ad-hoc 1100) */
  /* Collapse to 2 cols: left panel + main */
  .guest-command-centre {
    grid-template-columns: 260px 1fr !important;
  }
  .guest-command-centre .right-col { display: none !important; }
}
@media (max-width: 768px) { /* --hp-bp-tablet */
  .guest-command-centre {
    grid-template-columns: 1fr !important;
  }
}

/* ── Forms ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet */
  .form-row-2 { grid-template-columns: 1fr !important; }
  .form-row-3 { grid-template-columns: 1fr !important; }
}

/* ── Toolbar ──────────────────────────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet */
  .toolbar {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 8px !important;
  }

  .toolbar-l,
  .toolbar-r {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
}

/* ── Panel tables ─────────────────────────────────────────────────────── */
@media (max-width: 768px) { /* --hp-bp-tablet */
  .panel table { font-size: 11px; }
  .panel .panel-head { padding: 10px 14px; }
  .panel > div { padding-left: 14px; padding-right: 14px; }
}

/* ── Mobile sidebar overlay backdrop ─────────────────────────────────── */
.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  z-index: var(--hp-z-modal-backdrop); /* UX-4.1 z-index registry (was 199) */
}
.sidebar-backdrop.active { display: block; }
