/* ============================================================
   PULSE — shared UI primitives (both themes, token-driven).
   Loaded after pulse-tokens.css on every surface. Everything here is
   opt-in by class (`pui-*`) so it never fights existing page styles, with
   two deliberate exceptions: the global focus ring and reduced-motion
   safety, which every page should share.
   ============================================================ */

/* ---- Global accessibility baseline ---- */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
  box-shadow: none;
}
:where(button, [role="button"], a) { touch-action: manipulation; }
.pui-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;
}
.pui-tnum { font-variant-numeric: tabular-nums lining-nums; font-feature-settings: var(--tnum); }
@media (prefers-reduced-motion: reduce) {
  .pui-motion, .pui-motion *, .pui-skeleton, .pui-toast, .pui-modal, .pui-modal-card { animation: none !important; transition: none !important; }
}

/* ---- Kicker / labels ---- */
.pui-kicker {
  font: 600 var(--fs-2xs) var(--font-mono); letter-spacing: var(--tracking-kicker);
  text-transform: uppercase; color: var(--text-dim);
}
.pui-kicker.accent { color: var(--cyan); }

/* ---- Buttons ---- */
.pui-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: var(--control-height); padding: 0 12px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--bg-panel-hi); color: var(--text-hi);
  font: 600 var(--fs-xs) var(--font-mono); letter-spacing: var(--tracking-wide); text-transform: uppercase;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard);
}
.pui-btn:hover { border-color: var(--cyan-line); background: var(--bg-hover); }
.pui-btn:active { transform: translateY(1px); }
.pui-btn[disabled], .pui-btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }
.pui-btn.primary { background: var(--cyan); border-color: var(--cyan); color: var(--btn-primary-text); }
.pui-btn.primary:hover { filter: brightness(1.06); }
.pui-btn.gold { background: var(--gold); border-color: var(--gold); color: var(--text-inverse); }
.pui-btn.danger { border-color: var(--red-line); color: var(--red); background: var(--red-soft); }
.pui-btn.ghost { background: transparent; border-color: transparent; color: var(--text-mid); }
.pui-btn.ghost:hover { color: var(--text-hi); background: var(--bg-hover); border-color: transparent; }
.pui-btn.sm { min-height: 28px; padding: 0 9px; font-size: var(--fs-2xs); }
.pui-btn .pui-icon { width: var(--icon-sm); height: var(--icon-sm); }
.pui-icon { display: inline-block; width: var(--icon-md); height: var(--icon-md); vertical-align: -3px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ---- Chips / applied filter summary ---- */
.pui-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  min-height: 26px; padding: 0 8px 0 10px; border-radius: var(--radius-pill);
  border: 1px solid var(--cyan-line); background: var(--cyan-soft); color: var(--text-hi);
  font: 500 var(--fs-xs) var(--font-mono); letter-spacing: .02em;
}
.pui-chip b { font-weight: 600; color: var(--cyan); }
.pui-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pui-chip .pui-chip-x {
  display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
  border: 0; background: transparent; color: var(--text-mid); cursor: pointer; padding: 0; font: inherit;
}
.pui-chip .pui-chip-x:hover { background: var(--red-soft); color: var(--red); }
.pui-chip.neutral { border-color: var(--line-strong); background: var(--status-neutral-soft); }
.pui-chip.neutral b { color: var(--text-mid); }

/* ---- Status pills ---- */
.pui-status {
  display: inline-flex; align-items: center; gap: 6px; min-height: 22px; padding: 0 9px;
  border-radius: var(--radius-pill); border: 1px solid var(--line);
  font: 600 var(--fs-2xs) var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--text-mid);
  background: var(--status-neutral-soft);
}
.pui-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.pui-status.ok, .pui-status.success, .pui-status.live { color: var(--status-success); border-color: var(--green-line); background: var(--status-success-soft); }
.pui-status.warn, .pui-status.warning, .pui-status.stale { color: var(--status-warning); border-color: var(--gold-line); background: var(--status-warning-soft); }
.pui-status.error, .pui-status.danger, .pui-status.failed { color: var(--status-danger); border-color: var(--red-line); background: var(--status-danger-soft); }
.pui-status.info { color: var(--status-info); border-color: var(--cyan-line); background: var(--status-info-soft); }
.pui-status.forecast { color: var(--status-forecast); border-color: var(--purple-soft); background: var(--status-forecast-soft); }

/* ---- Inputs ---- */
.pui-input, .pui-select, .pui-textarea {
  width: 100%; min-height: var(--control-height); padding: 6px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--bg-input); color: var(--text-hi); font: 500 var(--fs-sm) var(--font-body);
  transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
.pui-input::placeholder, .pui-textarea::placeholder { color: var(--text-dim); }
.pui-input:hover, .pui-select:hover, .pui-textarea:hover { border-color: var(--cyan-line); }
.pui-input:focus, .pui-select:focus, .pui-textarea:focus { outline: none; border-color: var(--cyan); box-shadow: var(--shadow-focus); }
.pui-input[aria-invalid="true"], .pui-select[aria-invalid="true"] { border-color: var(--red); box-shadow: 0 0 0 3px var(--red-soft); }
.pui-field-error { margin-top: 4px; color: var(--red); font: 500 var(--fs-xs) var(--font-body); }
.pui-select {
  appearance: none; -webkit-appearance: none; padding-right: 28px; cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237186a6' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
  background-repeat: no-repeat; background-position: right 9px center;
}
:root[data-theme="light"] .pui-select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23566a89' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
}

/* ---- Toggle switch ---- */
.pui-switch { position: relative; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font: 500 var(--fs-sm) var(--font-body); color: var(--text-mid); }
.pui-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.pui-switch .track { width: 34px; height: 18px; border-radius: 999px; background: var(--line-strong); position: relative; transition: background var(--dur-base) var(--ease-standard); flex: none; }
.pui-switch .track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--text-hi); transition: transform var(--dur-base) var(--ease-out); }
.pui-switch input:checked + .track { background: var(--cyan); }
.pui-switch input:checked + .track::after { transform: translateX(16px); background: var(--btn-primary-text); }
.pui-switch input:focus-visible + .track { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }

/* ---- Skeleton loading ---- */
.pui-skeleton {
  position: relative; overflow: hidden; border-radius: var(--radius-sm);
  background: var(--status-neutral-soft); min-height: 12px; color: transparent !important;
}
.pui-skeleton::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.08), transparent);
  animation: puiShimmer 1.4s var(--ease-in-out) infinite;
}
:root[data-theme="light"] .pui-skeleton::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,.7), transparent); }
@keyframes puiShimmer { to { transform: translateX(100%); } }

/* ---- Panel states: loading / empty / error / locked ---- */
.pui-state {
  display: grid; place-items: center; gap: 6px; min-height: 160px; padding: 20px;
  border: 1px dashed var(--line-strong); border-radius: var(--radius-lg); text-align: center;
  color: var(--text-mid); font: 500 var(--fs-sm) var(--font-body);
}
.pui-state .pui-state-icon { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 10px; background: var(--status-neutral-soft); color: var(--text-mid); }
.pui-state .pui-state-icon svg { width: 18px; height: 18px; }
.pui-state b { display: block; color: var(--text-hi); font: 700 var(--fs-base) var(--font-display); }
.pui-state p { margin: 0; max-width: 46ch; color: var(--text-mid); line-height: var(--lh-normal); }
.pui-state.error { border-color: var(--red-line); }
.pui-state.error .pui-state-icon { background: var(--red-soft); color: var(--red); }
.pui-state.warning { border-color: var(--gold-line); }
.pui-state.warning .pui-state-icon { background: var(--gold-soft); color: var(--gold); }
.pui-state.locked .pui-state-icon { background: var(--cyan-soft); color: var(--cyan); }
.pui-state.loading .pui-state-icon { background: var(--cyan-soft); color: var(--cyan); }
.pui-state .pui-btn { margin-top: 6px; }
.pui-spinner { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--line-strong); border-top-color: var(--cyan); animation: puiSpin .8s linear infinite; }
@keyframes puiSpin { to { transform: rotate(360deg); } }

/* ---- Tooltip (data-tip) — rendered by pulse-ui.js into a single node ---- */
.pui-tooltip {
  position: fixed; z-index: var(--z-tooltip); max-width: 300px; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--chart-tooltip-bg); color: var(--text-hi); box-shadow: var(--shadow-md);
  font: 500 var(--fs-xs) var(--font-body); line-height: var(--lh-snug); pointer-events: none;
  opacity: 0; transform: translateY(2px); transition: opacity var(--dur-fast) var(--ease-standard), transform var(--dur-fast) var(--ease-standard);
}
.pui-tooltip.show { opacity: 1; transform: none; }
.pui-tooltip b { color: var(--cyan); font-weight: 600; }

/* ---- Modal ---- */
.pui-modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center; padding: 16px; background: var(--bg-overlay); backdrop-filter: blur(2px); animation: puiFade var(--dur-base) var(--ease-standard); }
.pui-modal-card {
  width: min(560px, 100%); max-height: min(88vh, 900px); overflow: auto;
  border: 1px solid var(--line-strong); border-radius: var(--radius-lg); background: var(--bg-panel);
  box-shadow: var(--shadow-lg); padding: 18px 20px; animation: puiRise var(--dur-slow) var(--ease-out);
}
.pui-modal-card h2 { margin: 0 0 6px; font: 700 var(--fs-2xl) var(--font-display); color: var(--text-hi); }
.pui-modal-card p { margin: 0 0 10px; color: var(--text-mid); font-size: var(--fs-md); line-height: var(--lh-normal); }
.pui-modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
@keyframes puiFade { from { opacity: 0; } }
@keyframes puiRise { from { opacity: 0; transform: translateY(8px); } }

/* ---- Toasts ---- */
.pui-toast-host { position: fixed; right: 16px; bottom: 16px; z-index: var(--z-toast); display: flex; flex-direction: column; gap: 8px; max-width: min(380px, calc(100vw - 32px)); }
.pui-toast {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px;
  border: 1px solid var(--line-strong); border-left: 3px solid var(--cyan); border-radius: var(--radius-sm);
  background: var(--bg-panel); color: var(--text-hi); box-shadow: var(--shadow-md);
  font: 500 var(--fs-sm) var(--font-body); line-height: var(--lh-snug); animation: puiRise var(--dur-slow) var(--ease-out);
}
.pui-toast.success { border-left-color: var(--green); }
.pui-toast.warning { border-left-color: var(--gold); }
.pui-toast.error { border-left-color: var(--red); }
.pui-toast .pui-toast-x { margin-left: auto; border: 0; background: transparent; color: var(--text-dim); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; }

/* ---- Table baseline ---- */
.pui-table-wrap { overflow: auto; border: 1px solid var(--line); border-radius: var(--radius); max-width: 100%; }
.pui-table { width: 100%; border-collapse: separate; border-spacing: 0; font: 500 var(--fs-sm) var(--font-body); }
.pui-table th {
  position: sticky; top: 0; z-index: 1; text-align: left; padding: 9px 12px;
  background: var(--bg-panel-hi); color: var(--text-dim);
  font: 600 var(--fs-2xs) var(--font-mono); letter-spacing: var(--tracking-kicker); text-transform: uppercase;
  border-bottom: 1px solid var(--line-strong); white-space: nowrap;
}
.pui-table td { padding: 9px 12px; border-bottom: 1px solid var(--line); color: var(--text-mid); vertical-align: middle; }
.pui-table td.num, .pui-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.pui-table tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--bg-panel-hi) 40%, transparent); }
.pui-table tbody tr:hover td { background: var(--bg-hover); color: var(--text-hi); }
.pui-table tbody tr[aria-selected="true"] td { background: var(--bg-selected); }
.pui-table th[aria-sort] { cursor: pointer; }
.pui-table th[aria-sort="ascending"]::after { content: " ▲"; color: var(--cyan); }
.pui-table th[aria-sort="descending"]::after { content: " ▼"; color: var(--cyan); }

/* ---- Freshness / data trust indicator ---- */
.pui-fresh { display: inline-flex; align-items: center; gap: 6px; font: 500 var(--fs-2xs) var(--font-mono); letter-spacing: .04em; color: var(--text-dim); }
.pui-fresh i { width: 7px; height: 7px; border-radius: 50%; background: var(--status-neutral); flex: none; }
.pui-fresh.ok i { background: var(--status-success); box-shadow: 0 0 0 3px var(--status-success-soft); }
.pui-fresh.stale i { background: var(--status-warning); box-shadow: 0 0 0 3px var(--status-warning-soft); }
.pui-fresh.failed i { background: var(--status-danger); box-shadow: 0 0 0 3px var(--status-danger-soft); }

/* ---- Keyboard hint ---- */
.pui-kbd { display: inline-block; padding: 1px 5px; border: 1px solid var(--line-strong); border-bottom-width: 2px; border-radius: 4px; background: var(--bg-panel-hi); color: var(--text-mid); font: 600 var(--fs-2xs) var(--font-mono); }

/* ---- Skip link ---- */
.pui-skip { position: absolute; left: 8px; top: -60px; z-index: var(--z-toast); padding: 8px 12px; border-radius: var(--radius-sm); background: var(--cyan); color: var(--btn-primary-text); font: 600 var(--fs-sm) var(--font-body); text-decoration: none; transition: top var(--dur-fast); }
.pui-skip:focus { top: 8px; }
/* V20.14.157 -- a skip link is a keyboard affordance for a scrolling page. On
   paper there is nothing to skip and nothing to focus, and `top: -60px` only
   hides it while there is a viewport to hide it above -- in print it landed on
   the page, so every exported PDF opened with the words "Skip to report
   content" above the masthead. Stated here, beside the component, rather than
   in whichever print block noticed it. */
@media print { .pui-skip { display: none !important; } }
