/* ============================================================================
   Lumati Clinic-OS — UI primitives styling (modal/confirm, toast, skeleton,
   states) + global accessibility (focus ring, reduced-motion).
   Depends on tokens.css. Shared by the staff app and the client portal.

   ── MOTIF DISCIPLINE (the "never spa-y" contract — load-bearing) ──
   (1) GOLD SCARCITY — ≤1 gold rule (.rule-g / .rule-spectrum) and ≤1 .lume /
       .statbox--hero per viewport region. Gold is scarcity, not decoration.
   (2) LIGHT IS A 1px HAIRLINE — no surface bloom / pastel glow. The only soft
       glow allowed is the focus aura and the single-CTA hover (.btn-primary/
       .pe-btn:hover). The spectrum reads as instrument calibration, not spa-glow.
   (3) THE SPIRAL IS QUIET — ≤1 .brand-watermark per screen; animated ONLY as the
       loader (.brand-spinner) + the Live pulse; never inside buttons or on inputs.
   (4) MOTION IS CALM — only toast/dialog arrival use --ease-spring (nothing else
       bounces); the Live pulse breathes (2.6s), entrances rise-and-settle.
   (5) NO PASTELS — warm cream/white + structural navy; status tints use -ink vars.
   (6) CONTRAST FLOOR — gold text on cream uses --gold-ink (#7a5e1a, AA 5.57);
       pure --gold (#bfa465) only on navy or as a non-text accent.
   ============================================================================ */

/* ── A11y utilities: visually-hidden content + skip-link ──────────────────────
   .sr-only hides content visually while keeping it in the a11y tree (per-screen
   <h1> hooks, landmark labels). .skip-link is the keyboard escape hatch to the
   main region; it materializes on focus into the navy/gold chrome and keeps the
   gold focus ring. Both are pure a11y scaffolding — no layout/behavior impact. */
.sr-only {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 12px; top: -48px; z-index: 10000;
  background: var(--navy); color: var(--gold);
  border: 1px solid rgba(191,164,101,0.45); border-radius: var(--radius-sm);
  padding: 9px 16px; font-family: var(--font-ui); font-size: var(--text-sm);
  font-weight: 500; letter-spacing: 0.06em; text-decoration: none;
  transition: top var(--dur-2) var(--ease-out);
}
.skip-link:focus { top: 12px; }

/* ── Global focus-visible ring (gold) ─────────────────────────────────────── */
:where(button, a, input, select, textarea, [tabindex], .nav-tab, .drawer-item,
       .svc-card, .room-btn, .build-btn, .time-btn, .fchip, .client-row,
       .nav-group-btn, .bn-item--primary, .tb-join, .skip-link,
       .ui-btn):focus-visible {
  outline: none;
  box-shadow: var(--shadow-ring);
  border-radius: var(--radius-sm);
}

/* ── Toast (upgrades the existing #toast element) ─────────────────────────── */
.toast {
  position: fixed; bottom: 24px; right: 24px; z-index: 9999;
  display: flex; align-items: center; gap: 10px; max-width: 360px;
  background: var(--navy); color: var(--cream);
  border: 1px solid rgba(191,164,101,0.30);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius-lg);
  padding: 13px 18px; font-size: var(--text-base);
  box-shadow: var(--shadow-lg);
  transform: translateY(80px); opacity: 0;
  transition: transform var(--dur-3) var(--ease-out), opacity var(--dur-3) var(--ease-out);
}
.toast.show { transform: translateY(0); opacity: 1; }
.toast-icon {
  flex-shrink: 0; width: 20px; height: 20px; border-radius: var(--radius-round);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; color: var(--navy); background: var(--gold);
}
.toast-icon:empty { display: none; }
.toast--success { border-left-color: var(--green); }
.toast--success .toast-icon { background: var(--green); color: #06301a; }
.toast--error { border-left-color: var(--red); }
.toast--error .toast-icon { background: var(--red); color: #3b0a0a; }

/* ── Dialog (modal / confirm) ─────────────────────────────────────────────── */
.ui-dialog {
  border: none; padding: 0; max-width: 440px; width: calc(100vw - 40px);
  background: var(--surface); color: var(--charcoal);
  border-radius: var(--radius-2xl); box-shadow: var(--shadow-lg);
  overflow: hidden;
  opacity: 0; transform: translateY(8px) scale(0.98);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.ui-dialog.is-open { opacity: 1; transform: none; }
.ui-dialog--wide { max-width: 640px; }
.ui-dialog::backdrop {
  background: rgba(6,20,31,0.55);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.ui-dialog-head {
  padding: 22px 24px 0;
}
.ui-dialog-title {
  font-family: var(--font-display); font-weight: 300; font-size: var(--text-xl);
  color: var(--navy); letter-spacing: 0.02em; line-height: var(--leading-tight);
}
.ui-dialog-body { padding: 14px 24px 4px; }
.ui-dialog-msg { font-size: var(--text-md); color: var(--mid); line-height: var(--leading-normal); }
.ui-dialog-actions {
  display: flex; justify-content: flex-end; gap: 10px; padding: 18px 24px 22px;
}
.ui-btn {
  padding: 11px 20px; border-radius: var(--radius-md);
  font-family: var(--font-ui); font-size: var(--text-sm); font-weight: 500;
  letter-spacing: 0.06em; cursor: pointer; transition: all var(--dur-2) var(--ease-out);
  border: 1px solid transparent;
}
.ui-btn--primary { background: var(--navy); color: var(--gold); border-color: rgba(191,164,101,0.3); }
.ui-btn--primary:hover { background: var(--navy-600); }
.ui-btn--danger { background: var(--red); color: #fff; }
.ui-btn--danger:hover { filter: brightness(0.94); }
.ui-btn--ghost { background: transparent; color: var(--mid); border-color: var(--border-s); }
.ui-btn--ghost:hover { border-color: var(--navy); color: var(--navy); }

/* ── Skeleton loaders ─────────────────────────────────────────────────────── */
.ui-skel { display: flex; flex-direction: column; gap: 12px; padding: 8px 0; }
.ui-skel-board { display: flex; gap: 12px; padding: 4px 0; overflow: hidden; }
.ui-skel-col {
  width: 220px; flex-shrink: 0; background: var(--surface);
  border: 1px solid var(--border-s); border-radius: var(--radius-xl);
  padding: 16px; display: flex; flex-direction: column; gap: 12px;
}
.ui-skel-bar {
  height: 14px; border-radius: var(--radius-sm);
  background: linear-gradient(90deg,
    rgba(26,60,64,0.06) 25%, rgba(191,164,101,0.14) 37%, rgba(26,60,64,0.06) 63%);
  background-size: 400% 100%;
  animation: uiShimmer 1.4s var(--ease-in-out) infinite;
}
.ui-skel-bar.lg { height: 22px; }
.ui-skel-bar.sm { width: 60%; }
@keyframes uiShimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

/* ── Empty / error states ─────────────────────────────────────────────────── */
.ui-state {
  text-align: center; padding: 48px 24px; color: var(--mid);
}
.ui-state--compact { padding: 24px 16px; }
.ui-state-icon {
  width: 48px; height: 48px; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  color: var(--gold); font-size: 26px;
}
.ui-state--compact .ui-state-icon { width: 34px; height: 34px; font-size: 18px; margin-bottom: 10px; }
/* the error/info glyph (a text char) still wants the soft disc; the spiral mark
   does NOT — its own .state-spiral rule below clears the disc + raises opacity */
.ui-state-icon:not(:has(.state-spiral)) { border-radius: var(--radius-round); background: var(--gold-pale); }
.ui-state--error .ui-state-icon { background: rgba(248,113,113,0.12); color: var(--red-ink); }
.ui-state-title { font-size: var(--text-md); font-weight: 500; color: var(--charcoal); }
.ui-state-msg { font-size: var(--text-base); color: var(--mid); margin-top: 5px; line-height: var(--leading-normal); }

/* ============================================================================
   Design vocabulary (§C) — Labs-Catalog system ported to the clinic.
   Gold discipline: exactly ONE gold rule / ONE --hero statbox per viewport
   region. Mono = data voice; display serif = brand voice.
   ============================================================================ */

/* ── C1 .eyebrow — mono eyebrow with one gold keyword (print 0.30em tracking) ── */
.eyebrow{font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:var(--tracking-eyebrow);text-transform:uppercase;color:var(--mid);font-weight:500;margin-bottom:4px}
.eyebrow .g{color:var(--gold-ink)}
.eyebrow--dark{color:rgba(248,244,238,.45)}
.eyebrow--dark .g{color:var(--gold)}

/* ── C2 .sec — label—hairline—annotation divider (live counts in the right slot) */
.sec{display:flex;align-items:center;gap:10px;margin:var(--space-6) 0 var(--space-3)}
.sec-label{font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:var(--tracking-wider);text-transform:uppercase;color:var(--navy);font-weight:600;white-space:nowrap}
.sec-line{flex:1;height:1px;background:var(--border-s)}
.sec-meta{font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:.08em;color:var(--faint-ink);white-space:nowrap}

/* ── C3 .statbox — statement numerals + gold "investment box" hero variant ── */
.statbox{background:var(--surface);border:1px solid var(--border-s);border-radius:var(--radius-lg);padding:var(--space-5) var(--space-6)}
/* statbox-val → print statement figure (Inter 800 / tighter / tabular) */
.statbox-val{font-family:var(--font-ui);font-size:44px;font-weight:800;color:var(--navy);letter-spacing:-.04em;line-height:.9;font-variant-numeric:tabular-nums}
/* recede the denominator (' of 16') like the print ' / diode' subscript */
.statbox-of{font-size:55%;font-weight:500;color:var(--mid)}
.statbox-label{font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:var(--tracking-wider);text-transform:uppercase;color:var(--mid);margin-top:var(--space-2)}
/* Hero "investment box": gold numerals on NAVY (6.98:1 AAA) — the premium
   inversion that keeps gold as the luxury signal AND satisfies the two-token
   law (§C6). The old gold-on-cream-wash rendered the loudest numeral at
   2.09:1 — failing WCAG even as large text and violating the law stated above.
   The .statbox.statbox--hero compound (0-2-0) intentionally outranks the
   later .lume wash (0-1-0) so the hero, which carries BOTH classes on the
   Dashboard, keeps its navy fill instead of reverting to the failing wash. */
.statbox.statbox--hero{border:1.5px solid var(--gold);background:linear-gradient(135deg,var(--navy-700),var(--navy))}
.statbox--hero .statbox-val{color:var(--gold)}
.statbox--hero .statbox-label{color:rgba(248,244,238,0.62)}
.statbox--hero .statbox-of{color:rgba(248,244,238,0.55)}
.statbox--alert .statbox-val{color:var(--red-ink)}

/* ── C4 Three-rank pill vocabulary ────────────────────────────────────────── */
/* chip-solid = tier/brand statements · tag-outline = attributes · pill-check = verified facts */
.chip-solid{display:inline-block;background:var(--gold);color:var(--navy);font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:var(--tracking-wide);text-transform:uppercase;padding:5px 12px;border-radius:3px;font-weight:600}
.tag-outline{display:inline-block;border:1px solid var(--gold);color:var(--gold-ink);border-radius:3px;padding:2px 7px;font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:.05em;text-transform:uppercase;white-space:nowrap}
.pill-check{display:inline-flex;align-items:center;gap:7px;background:var(--surface);border:1px solid var(--border-s);border-radius:var(--radius-pill);padding:5px 12px;font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--charcoal)}
.pill-check::before{content:'✓';color:var(--gold-ink);font-weight:700;font-family:var(--font-ui)}

/* ── C5 .kv-row — mono key-value spec rows ────────────────────────────────── */
.kv-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px solid var(--border-s)}
.kv-row:last-child{border-bottom:none}
.kv-label{font-family:var(--font-mono);font-size:var(--text-2xs);letter-spacing:.08em;text-transform:uppercase;color:var(--faint-ink);padding-top:2px;flex:0 0 auto}
.kv-val{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--charcoal);text-align:right;line-height:1.35}

/* ── C7 .idx — zero-padded mono gold numbered sequences ───────────────────── */
/* pad in JS: String(i+1).padStart(2,'0') */
.idx{display:flex;gap:10px;align-items:flex-start}
.idx-num{font-family:var(--font-mono);font-size:var(--text-sm);font-weight:600;color:var(--gold-ink);flex:0 0 auto;padding-top:1px}
.idx-name{font-size:var(--text-base);font-weight:600;color:var(--charcoal);letter-spacing:-.01em;line-height:1.2}
.idx-desc{font-size:var(--text-xs);color:var(--mid);margin-top:2px;line-height:1.4}

/* ── C8 .rule-g + .card-foot — gold-discipline rhythm ─────────────────────── */
.rule-g{width:56px;height:3px;background:var(--gold);border-radius:2px;margin:var(--space-2) 0 var(--space-4)}
.card-foot{margin-top:var(--space-4);padding-top:var(--space-3);border-top:1.5px solid var(--gold);display:flex;justify-content:space-between;align-items:baseline;gap:10px}

/* ── C9 .meter — gradient capacity/wallet bar with mono ticks ─────────────── */
/* width is set via data-fill-w + applyFillStyles (zero inline styles); transition
   only animates that value-change — no regression to the data flow. */
.meter{height:8px;border-radius:3px;background:linear-gradient(90deg,var(--teal) 0%,var(--teal-light) 62%,var(--gold) 100%);transition:width var(--dur-4) var(--ease-out)}
.meter-ticks{display:flex;margin-top:5px}
.meter-tick{flex:1;font-family:var(--font-mono);font-size:9px;letter-spacing:.02em;color:var(--faint-ink);text-align:center;line-height:1.3}
.meter-tick b{display:block;font-weight:600;color:var(--charcoal);font-size:10px}

/* ── C10 .rule-spectrum — calibration hairline (the ONLY place --spectrum renders) ── */
.rule-spectrum{height:1px;border:none;background:var(--spectrum);margin:var(--space-2) 0 var(--space-4)}

/* ── C11 .lume — calibrated hero wash (formalizes statbox--hero's 135° angle) ──
   apply to exactly ONE hero region per screen */
.lume{background:linear-gradient(135deg,var(--glow-2),var(--glow-3))}

/* ── C12 .brand-spinner — spiral loader for indeterminate global waits ──
   (skeletons stay for content-shaped waits) */
.brand-spinner{width:40px;height:40px;margin:0 auto;
  background:url(/static/img/lumati-mark-gold.png) center/contain no-repeat;
  animation:spiralTurn var(--dur-spiral) var(--ease-in-out) infinite}
@keyframes spiralTurn{to{transform:rotate(360deg)}}

/* ── C13 .brand-watermark — MAX ONE per screen, never animated ── */
.brand-watermark{position:fixed;bottom:-40px;right:-40px;width:260px;opacity:.03;
  pointer-events:none;background:url(/static/img/lumati-mark-gold.png) center/contain no-repeat;z-index:0}

/* ── C14 single-CTA ambient gold-light glow (hover/active only — NOT a surface bloom) ── */
.pe-btn:hover,.btn-primary:hover{box-shadow:0 0 0 1px var(--gold),0 0 16px -4px var(--glow-1)}

/* ── Branded empty-state spiral glyph (class-driven — zero inline styles) ──
   The spiral is a deliberate brand watermark, NOT a loader. It fills its icon
   slot at full size and a confident .7 opacity so it reads crisp — the muddy
   ~33px @ 40%-on-gold-pale disc (which antialiased into a fuzzy spinner blob)
   is retired. No soft disc behind it: the mark carries itself. */
.ui-state-icon:has(.state-spiral){background:transparent}
.ui-state-icon .state-spiral,.state-spiral{width:100%;height:auto;opacity:.7;filter:none}

/* ── Shared entrance: rise-and-settle (promotes portal's @keyframes fi) ──
   stagger via data-i + applyFillStyles (animation-delay:calc(var(--i)*40ms)) */
.enter{animation:fi var(--dur-3) var(--ease-out)}
@keyframes fi{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ── Reduced motion ───────────────────────────────────────────────────────── */
@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;
  }
  .ui-skel-bar { animation: none !important; background: rgba(26,60,64,0.08); }
  /* spiral devices: stop cleanly (static spiral) rather than freeze mid-rotation */
  .brand-spinner, .brand-watermark { animation: none !important; }
}
