/*
 * fragments.css — shared HTML-fragment chrome (HaTchi-MaXchi).
 *
 * Assorted fragment/region primitives: sentinel + loading spinners, command
 * palette, toast/bulk/stepper/date-range/context-menu/slide-over/search-flow/
 * 2FA/a11y/related/tooltip/inline-edit/ref-cell/search-input/search-select/
 * app-shell/toast-stack/form-chrome/review-queue/modal/island/error-pages/
 * card-picker/pipeline-steps/experience-shell families. Heavily HM-token-based
 * (293 var(--…) refs). Migrated wholesale from Dazzle into HM (HMC-016,
 * aggressive-mode convergence 2026-07-08); the redundant `.dz-empty-dense`
 * (HM detail.css owns the canonical one) was dropped in the move.
 */

/* ─────────────────────────── empty_state fragment ───────────────
 * The `.dz-empty-state` primitive is now owned by the HM
 * `empty-state` Hyperpart (components/fragment-primitives.css:
 * base container + `__icon`/`__title`/`__description`/`__action`),
 * ingested into the dist. All emitters (the typed substrate + the
 * table/chart read-only empties) emit the `__` form; the bespoke
 * `.dz-empty-state`/`-icon`/`-message`/`-cta` rules were deleted in
 * the Bucket B empty-state convergence (build-to-replace, ADR-0003). */

/* table_pagination — the `.dz-pagination*` family moved to the HM `pagination`
 * Hyperpart (packages/hatchi-maxchi/components/pagination.css) as the canonical
 * definition; Dazzle's `_emit_pagination` consumes it unchanged (byte-identical
 * values + a focus ring). Retired here 2026-07-04. The data-table row / filter
 * bar / bulk-action families (`.dz-tr-*`, `.dz-filter-*`, `.dz-bulk-*`) likewise
 * moved to the HM `table.css` (grid Hyperpart, Slice 0b, 2026-07-04). */

/* ─────────────────────────── toast fragment ─────────────────────
 * MOVED to components/toast.css (HYPERPART: toast). Stack host,
 * title/message/actions, and level tones live there. */

/* ─────────────────────────── bulk_actions fragment ──────────────
 * Delete-only bulk actions toolbar. Visible via Alpine x-show
 * gated on bulkCount > 0. */

/* ─────────────────────────── form_stepper + steps_indicator ─────
 * MOVED to HaTchi-MaXchi components/form-chrome.css (Tier F3, the
 * fleet-convergence directive). Same selectors, via the HM dist. */

/* ─────────────────────────── date_range_picker fragment ─────────
 * MOVED to HaTchi-MaXchi components/date-range.css (Tier F3). */

/* ─────────────────────────── detail_fields fragment ─────────────
 * Definition-list renderer used by the API read handler for
 * HTMX/browser content negotiation. Lighter version of the
 * detail_view component (no header / actions / related groups). */

.dz-detail-fields-card {
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

.dz-detail-fields-body {
  padding: var(--space-lg);
}

.dz-detail-fields-title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--colour-text);
  margin: 0;
}

.dz-detail-fields-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-xs) var(--space-md);
  margin-block-start: var(--space-md);
}

/* #1533: full-length prose on detail pages — the list-cell truncate
 * wrapper never appears here. pre-wrap keeps textarea paragraphs. */
.dz-detail-text {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.dz-detail-fields-key {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--colour-text-muted);
  text-align: end;
  padding-block: 0.25rem;
}

.dz-detail-fields-value {
  font-size: var(--text-sm);
  padding-block: 0.25rem;
  word-break: break-all;
}

/* ─────────────────────────── context_menu fragment ──────────────
 * Right-click triggered menu. Panel positioned absolutely at cursor
 * coordinates via Alpine `:style`. */

.dz-context-menu {
  position: relative;
}

.dz-context-menu-panel {
  z-index: 50;
  min-width: 11rem;
  padding-block: 0.25rem;
  border-radius: var(--radius-sm);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  box-shadow: var(--shadow-md);
  font-size: var(--text-sm);
  list-style: none;
  margin: 0;
  padding-inline-start: 0;
}

.dz-context-menu-divider {
  margin-block: 0.25rem;
  border-block-start: 1px solid var(--colour-border);
}

.dz-context-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-inline: var(--space-md);
  padding-block: 0.375rem;
  color: var(--colour-text);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease-out);
}

.dz-context-menu-item:hover {
  background: var(--colour-bg);
}

.dz-context-menu-item-icon {
  width: 0.875rem;
  height: 0.875rem;
  color: var(--colour-text-muted);
}

/* ─────────────────────────── slide-over ─────────────────────────
 * DELETED (Tier F2, 2026-07-06): the peek slide_over panel converged
 * onto the HM drawer Hyperpart (native <dialog class="dz-drawer">,
 * packages/hatchi-maxchi/components/drawer.css) — focus trap, inert
 * background, Esc/backdrop dismissal are native. The .dz-slideover-*
 * family had no other producers. */

/* ─────────────────────────── table_sentinel fragment ────────────
 * Infinite-scroll sentinel row. Triggers loading more rows when
 * revealed via htmx hx-trigger="revealed". The visible spinner is
 * just a sized box with animation; sr-only text lives in the
 * fragment template. */

.dz-sentinel-cell {
  text-align: center;
  padding-block: var(--space-md);
}

.dz-sentinel-spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  animation: dz-spin 1s linear infinite;
}

/* ─────────────────────────── form_errors fragment ───────────────
 * MOVED to HaTchi-MaXchi components/form-chrome.css (Tier F3). */

/* ─────────────────────────── search-flow fragments ──────────────
 * MOVED to HaTchi-MaXchi components/search-box.css (Tier F3). */

/* ─────────────────────────── experience_transition macro ────────
 * Single source of truth for the 5 transition-button branches in
 * experience/_content.html (#EX-053). Three style variants — primary,
 * ghost, border (default) — keyed off `data-dz-transition-style`. */

.dz-experience-transition {
  display: inline-flex;
  align-items: center;
  height: 2.25rem;
  padding-inline: var(--space-md);
  font-weight: var(--weight-medium);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  border: 0;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    filter var(--duration-fast) var(--ease-out);
}

.dz-experience-transition[data-dz-transition-style="primary"] {
  background: var(--colour-brand);
  color: var(--colour-brand-contrast);
}

.dz-experience-transition[data-dz-transition-style="primary"]:hover {
  filter: brightness(1.1);
}

.dz-experience-transition[data-dz-transition-style="ghost"] {
  background: transparent;
  color: var(--colour-text-muted);
}

.dz-experience-transition[data-dz-transition-style="ghost"]:hover {
  background: var(--colour-bg);
  color: var(--colour-text);
}

.dz-experience-transition[data-dz-transition-style="default"],
.dz-experience-transition:not([data-dz-transition-style]) {
  background: transparent;
  color: var(--colour-text);
  border: 1px solid var(--colour-border);
}

.dz-experience-transition[data-dz-transition-style="default"]:hover,
.dz-experience-transition:not([data-dz-transition-style]):hover {
  background: var(--colour-bg);
}

/* ─────────────────────────── auth chrome (2FA views) ────────────
 * MOVED to HaTchi-MaXchi components/two-factor.css (Tier A2,
 * 2026-07-07 — with three latent-mismatch fixes: card-title/-subtitle
 * rule names, the classless QR img, and honest dz-auth-page
 * centering). The dead subset (product/title/subtitle/link-muted/
 * link-button and pseudo-states /qr/qr-image/qr-secret — zero producers) was deleted. */

/* ─────────────────────────── a11y helpers ───────────────────────
 * Loading spinner used as an HTMX indicator. Sized + animated host
 * for the inline span. (.visually-hidden + sr-only-fallback already
 * defined in utilities.css.) */

.dz-loading-spinner {
  display: flex;
  justify-content: center;
  padding-block: var(--space-md);
}

.dz-loading-spinner-icon {
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  animation: dz-spin 1s linear infinite;
}

/* Skip link — visually hidden by default, focusable via Tab. */
.dz-skip-link {
  position: absolute;
  inset-block-start: -100vh;  /* off-screen by default */
  inset-inline-start: 0;
  padding: var(--space-sm);
  background: var(--colour-brand);
  color: var(--colour-brand-contrast);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  border-radius: var(--radius-sm);
  z-index: 9999;
  text-decoration: none;
  transition: top var(--duration-fast) var(--ease-out);
}

.dz-skip-link:focus,
.dz-skip-link:focus-visible {
  inset-block-start: 0.5rem;
  inset-inline-start: 0.5rem;
}

/* ─────────────────────────── layouts/single_column ──────────────
 * Top bar + main + footer layout used by simpler app shells. */

.dz-layout-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.dz-layout-topbar {
  display: flex;
  align-items: center;
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  background: var(--colour-surface);
  border-block-end: 1px solid var(--colour-border);
  box-shadow: var(--shadow-sm);
}

.dz-layout-topbar-title {
  flex: 1 1 0;
}

.dz-layout-topbar-title-text {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

.dz-layout-topbar-nav {
  display: flex;
  gap: var(--space-sm);
  flex: none;
}

.dz-layout-nav-link {
  display: inline-flex;
  align-items: center;
  height: 2rem;
  padding-inline: var(--space-md);
  border-radius: var(--radius-sm);
  color: var(--colour-text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.dz-layout-nav-link:hover {
  background: var(--colour-bg);
  color: var(--colour-text);
}

.dz-layout-main {
  flex: 1 1 0;
  margin-inline: auto;
  padding: var(--space-md);
  max-width: 64rem;
  width: 100%;
}

@media (min-width: 64rem) {
  .dz-layout-main {
    padding: var(--space-lg);
  }
}

.dz-layout-footer {
  text-align: center;
  padding: var(--space-md);
  background: var(--colour-surface);
  color: var(--colour-text);
  border-block-start: 1px solid var(--colour-border);
}

/* Hide default disclosure marker */
/* ─────────────────────────── related-* fragments ────────────────
 * MOVED to HaTchi-MaXchi components/related-tables.css (W2, 2026-07-06 — the
 * fleet-convergence directive). Same selectors, via the HM dist. */

/* ─────────────────────────── tooltip_rich fragment ──────────────
 * HTML-content tooltip with x-anchor positioning. Trigger wraps
 * caller content; panel sits absolutely positioned + transitions
 * via Alpine x-show. */

/* ─────────────────────────── inline_edit fragment ───────────────
 * The InlineEdit fragment primitive's display span. */

.dz-inline-edit {
  position: relative;
  margin-inline: -0.25rem;
  margin-block: -0.125rem;
}

/* The editor-element rules (dz-inline-edit-input/-select/-checkbox) moved
 * to HaTchi-MaXchi table.css (HM 0.1.26 — the dz-grid-edit.js extension owns
 * them; Dazzle consumes the HM dist). The Alpine-era bool-row/spinner/error
 * chrome died with the template in C2.3. `.dz-inline-edit` above stays: the
 * InlineEdit fragment primitive still emits it. */

/* The `.dz-skeleton*` placeholder family that lived here was dead (zero
 * emitters) and collided with the HM `skeleton` Hyperpart's canonical
 * `.dz-skeleton`. Retired 2026-07-04; the live dashboard loading state is
 * `.dz-card-skeleton` (dashboard.css), which keeps the `dz-pulse` keyframe. */

/* ─────────────────────────── ref_cell macro ─────────────────────
 * Reference link styling — used by detail / grid / list / queue
 * regions. Three modes (link / link_stop / htmx_drawer) all render
 * the same anchor chrome. */

.dz-ref-link {
  color: var(--colour-brand);
  text-decoration: none;
  transition: text-decoration-color var(--duration-fast) var(--ease-out);
}

.dz-ref-link:hover {
  text-decoration: underline;
}

/* ─────────────────────────── search_input fragment ──────────────
 * DELETED (Tier F3, 2026-07-06): the dz-search-input / dz-search-clear
 * family had ZERO producers (py/html/js/examples/tests) — the reusable
 * search-input fragment died in an earlier convergence. The live FTS
 * search box (.dz-search-box-*) is styled by HM search-box.css. */

/* ─────────────────────────── attention_accent macro ─────────────
 * MOVED to HaTchi-MaXchi components/timeline.css (W2 — travels with
 * its consumers: timeline bullets + kanban card-attn). */

/* ─────────────────────────── command_palette fragment ───────────
 * Spotlight-style modal triggered by Cmd+K. Backdrop covers the
 * viewport; palette card sits centred at 20vh from the top. Three
 * regions: search input, results listbox, keyboard-hint footer.
 * Selected/hover row distinction driven by .is-selected modifier
 * Alpine binds. */

.dz-cmdk-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-block-start: 20vh;
}

.dz-cmdk-backdrop {
  position: fixed;
  inset: 0;
  background: oklch(0% 0 0 / 0.4);
}

.dz-cmdk-card {
  position: relative;
  width: 100%;
  max-width: 32rem;
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.dz-cmdk-search-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  border-block-end: 1px solid var(--colour-border);
}

.dz-cmdk-search-icon {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
  color: var(--colour-text-muted);
}

.dz-cmdk-search-input {
  width: 100%;
  background: transparent;
  font-size: var(--text-base);
  color: var(--colour-text);
  border: 0;
  outline: none;
}

.dz-cmdk-search-input::placeholder {
  color: var(--colour-text-muted);
}

.dz-cmdk-results {
  max-height: 20rem;
  overflow-y: auto;
  padding: 0.375rem;
  list-style: none;
  margin: 0;
}

.dz-cmdk-item {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.dz-cmdk-item:hover {
  background: var(--colour-bg);
}

.dz-cmdk-item.is-selected {
  background: color-mix(in oklch, var(--colour-brand) 10%, transparent);
  color: var(--colour-brand);
}

.dz-cmdk-item-icon {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
}

.dz-cmdk-item-text {
  min-width: 0;
}

.dz-cmdk-item-label {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--colour-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dz-cmdk-item-group {
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dz-cmdk-empty {
  padding-inline: var(--space-md);
  padding-block: var(--space-lg);
  text-align: center;
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--colour-text-muted);
}

.dz-cmdk-footer {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  border-block-start: 1px solid var(--colour-border);
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
}

.dz-cmdk-hint {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.dz-cmdk-key {
  display: inline-flex;
  align-items: center;
  height: 1.25rem;
  padding-inline: 0.375rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--colour-border);
  background: var(--colour-bg);
  font-family: var(--font-mono);
  font-size: 0.625rem;
  color: var(--colour-text-muted);
}

/* ─────────────────────────── search_select fragment ─────────────
 * MOVED to HaTchi-MaXchi components/search-select.css (Tier F4b),
 * where the results-panel visibility also converged from Alpine
 * x-show onto aria-expanded (dz-search-select.js). */

/* ─────────────────────────── layouts/app_shell ──────────────────
 * MOVED to HaTchi-MaXchi components/app-shell.css (S1, 2026-07-06 —
 * the app-shell directive): the whole family (shell/content/topbar/
 * sidebar-toggle/icon-button/app-main/page-purpose/backdrop/sidebar)
 * now ships via the HM dist; Dazzle's emitted contract is unchanged. */

/* ─────────────────────────── app body chrome ────────────────────
 * <body> level chrome — full-viewport background + min-height so
 * short pages still fill the screen with the surface colour.
 * Replaces inline `min-h-screen bg-[hsl(var(--background))]`. */

.dz-app-body {
  min-height: 100vh;
  background: var(--colour-bg);
}

/* ─────────────────────────── toast stack ────────────────────────
 * MOVED to components/toast.css (HYPERPART: toast). */

/* ─────────────────────────── form chrome (UX-016) ───────────────
 * Live subset (.dz-form-section/-title/-note) MOVED to HaTchi-MaXchi
 * components/form-chrome.css (Tier F3). The wrapper family
 * (.dz-form-shell/-header/-title/-body/-actions) was DELETED — its
 * producer was the legacy form_renderer.py removed in ADR-0049 Phase
 * 3b; the substrate form path never emitted it. */

/* ─────────────────────────── review queue (UX-030) ─────────────
 * One-at-a-time review chrome. Reuses .dz-detail-* primitives for
 * the field list; only review-specific shell + progress + nav +
 * action chrome lives here. */

.dz-review-shell {
  max-width: 56rem;  /* ~max-w-4xl */
}

.dz-review-progress {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
}

.dz-review-progress-text {
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
}

.dz-review-progress-bar {
  inline-size: 6rem;
  block-size: 0.25rem;
  border-radius: var(--radius-xs);
}

.dz-review-nav {
  display: flex;
  justify-content: space-between;
  margin-block-end: var(--space-md);
}

.dz-review-actions {
  display: flex;
  gap: var(--space-sm);
  justify-content: flex-end;
}

.dz-review-notes-wrap {
  margin-block-end: var(--space-md);
}

.dz-review-notes-wrap[hidden] {
  display: none;
}

.dz-review-notes-label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--colour-text);
  margin-block-end: var(--space-xs);
}

.dz-review-notes-required {
  display: inline;
  font-size: var(--text-xs);
  font-weight: var(--weight-normal);
  color: var(--colour-danger);
  margin-inline-start: 0.25rem;
}

.dz-review-notes-textarea {
  inline-size: 100%;
  min-block-size: 6rem;
  resize: vertical;
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  border-radius: var(--radius-sm);
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  color: var(--colour-text);
  font-size: var(--text-sm);
  transition: box-shadow var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}

.dz-review-notes-textarea::placeholder {
  color: var(--colour-text-muted);
}

.dz-review-notes-textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 1px var(--colour-brand);
}

.dz-review-empty {
  text-align: center;
  padding-block: var(--space-2xl);
}

.dz-review-empty-icon {
  font-size: 3rem;
  margin-block-end: var(--space-sm);
}

.dz-review-empty-title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--colour-text);
  margin-block-end: var(--space-xs);
}

.dz-review-empty-body {
  font-size: var(--text-sm);
  color: var(--colour-text-muted);
  margin-block-end: var(--space-md);
}

/* ─────────────────────────── modal ──────────────────────────────
 * DELETED (Tier F2, 2026-07-06): the dormant .dz-modal* family — its
 * components/modal.html primitive died with the Jinja teardown and no
 * producer emits the classes. Centered modal needs are the HM dialog
 * Hyperpart (dialog.css); edge panels the HM drawer. */

/* ─────────────────────────── confirm dialog — DELETED ───────────
 * (#1546, 2026-07-07): the dormant confirm-dialog family (dialog /
 * backdrop / panel / title / message / actions / spinner rules) died
 * with its Alpine template in the Jinja teardown; the LIVE
 * confirm_action_panel wrapper chrome it accidentally provided moved
 * to the HM confirm-panel Hyperpart (components/confirm-panel.css).
 * The dz-spin keyframes below are LIVE (loading spinners in this
 * file + dashboard.css) and deliberately survive the deletion. */

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

/* ─────────────────────────── island (dormant) ───────────────────
 * Generic dashboard island wrapper — used by components/island.html
 * (UX-059), no production consumer. */

.dz-island {
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-md);
  padding: var(--space-lg);
}

.dz-island-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-block-end: var(--space-md);
}

.dz-island-title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--colour-text);
  margin: 0;
}

.dz-island-skeleton {
  block-size: 8rem;
  inline-size: 100%;
  border-radius: var(--radius-sm);
}

/* ─────────────────────────── in-app error pages ─────────────────
 * 403 + 404 share centred chrome inside the app shell. Used by
 * app/403.html (#776 / #808) and app/404.html. */

.dz-error-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-block-size: 60vh;
  padding-inline: var(--space-md);
}

.dz-error-code {
  font-size: 3rem;
  font-weight: var(--weight-semibold);
  line-height: 1;
  color: var(--colour-text);
  margin-block-end: var(--space-md);
}

.dz-error-message {
  font-size: var(--text-md);
  color: var(--colour-text-muted);
  margin-block-end: var(--space-md);
  text-align: center;
  max-inline-size: 30rem;
}

.dz-error-suggestions-card,
.dz-error-detail-card {
  inline-size: 100%;
  max-inline-size: 30rem;
  margin-block-end: var(--space-lg);
  padding: var(--space-md);
  border-radius: var(--radius-md);
  border: 1px solid var(--colour-border);
}

.dz-error-suggestions-card {
  background: var(--colour-surface);
}

.dz-error-detail-card {
  background: color-mix(in oklch, var(--colour-bg) 70%, transparent);
  font-size: var(--text-sm);
  color: var(--colour-text);
}

.dz-error-suggestions-title {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--colour-text);
  margin-block-end: var(--space-sm);
}

.dz-error-suggestions-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  list-style: none;
  margin: 0;
  padding: 0;
}

.dz-error-suggestion-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: var(--text-sm);
  color: var(--colour-brand);
  text-decoration: none;
}

.dz-error-suggestion-link:hover {
  text-decoration: underline;
}

.dz-error-suggestion-url {
  font-family: var(--font-mono, monospace);
  font-size: var(--text-xs);
  color: var(--colour-text-muted);
}

.dz-error-detail-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-md);
  row-gap: 0.375rem;
  margin: 0;
}

.dz-error-detail-label {
  color: var(--colour-text-muted);
}

.dz-error-detail-chip {
  display: inline-block;
  margin-inline-end: 0.25rem;
  padding-inline: 0.25rem;
  padding-block: 0.125rem;
  border-radius: var(--radius-xs);
  background: var(--colour-bg);
  border: 1px solid var(--colour-border);
  font-size: var(--text-xs);
  font-family: var(--font-mono, monospace);
}

.dz-error-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

/* ─────────────────────────── workspace card picker (UX-038) ─────
 * Popover above the "Add a card" button, listing widget catalog
 * entries. Used by workspace/_card_picker.html. */

/* #982: visibility driven by `[data-show-picker]` on the ancestor
 * `.dz-workspace[x-data="dzDashboardBuilder()"]` rather than Alpine
 * `x-show` on this element. dzDashboardBuilder mirrors `showPicker`
 * to `data-show-picker="1"` via $watch; CSS reveals the picker only
 * when the flag is set. Default state hidden so there's no flash on
 * initial paint (replaces the prior `x-cloak`-style guard). */

.dz-card-picker {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-block-end: var(--space-sm);
  inline-size: 20rem;
  background: var(--colour-surface);
  color: var(--colour-text);
  box-shadow: var(--shadow-md);
  border-radius: var(--radius-md);
  border: 1px solid var(--colour-border);
  padding: var(--space-md);
  z-index: 50;
  max-block-size: 16rem;
  overflow-y: auto;
  display: none;
}

.dz-workspace[data-show-picker="1"] .dz-card-picker {
  display: block;
}

.dz-card-picker-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--colour-text-muted);
  margin-block-end: var(--space-sm);
}

.dz-card-picker-entry {
  inline-size: 100%;
  text-align: start;
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  border-radius: var(--radius-sm);
  background: transparent;
  border: 0;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out);
}

.dz-card-picker-entry:hover {
  background: var(--colour-bg);
}

.dz-card-picker-display-tag {
  padding-inline: 0.375rem;
  padding-block: 0.125rem;
  border-radius: var(--radius-sm);
  background: var(--colour-bg);
  font-size: 0.6875rem;
  font-weight: var(--weight-medium);
  color: var(--colour-text-muted);
}

.dz-card-picker-title-text {
  color: var(--colour-text);
}

.dz-card-picker-entity {
  font-size: 0.6875rem;
  color: var(--colour-text-muted);
  margin-inline-start: auto;
}

.dz-card-picker-empty {
  font-size: var(--text-sm);
  color: var(--colour-text-muted);
  padding-block: var(--space-sm);
}

/* ─────────────────────────── pipeline_steps region (#890/#911) ──
 * Sequential-stage workflow visualisation. Stack vertically on
 * narrow viewports, row of cards on >=md (40rem) with chevron
 * connectors between cards. Used by workspace/regions/pipeline_steps.html. */

.dz-pipeline-stages {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-block-start: var(--space-sm);
  list-style: none;
  padding: 0;
}

@media (min-width: 48rem) {
  .dz-pipeline-stages {
    flex-direction: row;
  }
}

.dz-pipeline-stage {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-md);
  border-radius: var(--radius-md);
  border: 1px solid var(--colour-border);
  background: var(--colour-surface);
}

.dz-pipeline-stage-label {
  font-size: 0.6875rem;
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--colour-text-muted);
}

.dz-pipeline-stage-value {
  font-size: 1.5rem;
  font-weight: var(--weight-semibold);
  line-height: 1;
  color: var(--colour-text);
}

.dz-pipeline-stage-caption {
  font-size: var(--text-xs);
  line-height: 1.3;
  color: var(--colour-text-muted);
}

.dz-pipeline-stage-progress {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-block-start: var(--space-xs);
}

.dz-pipeline-stage-progress-track {
  position: relative;
  flex: 1;
  block-size: 0.25rem;
  border-radius: 9999px;
  background: var(--colour-bg);
  overflow: hidden;
}

.dz-pipeline-stage-progress-fill {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  background: var(--colour-brand);
  border-radius: 9999px;
  transition: width 0.2s var(--ease-out);
}

.dz-pipeline-stage-progress-label {
  font-size: 0.6875rem;
  font-weight: var(--weight-medium);
  color: var(--colour-text-muted);
  font-variant-numeric: tabular-nums;
}

.dz-pipeline-connector {
  position: absolute;
  display: none;
  align-items: center;
  justify-content: center;
  inset-inline-end: -0.875rem;
  inset-block-start: 50%;
  transform: translateY(-50%);
  inline-size: 1.75rem;
  block-size: 1.75rem;
  z-index: 5;
  color: var(--colour-text-muted);
}

@media (min-width: 48rem) {
  .dz-pipeline-connector {
    display: flex;
  }
}

.dz-pipeline-connector-mobile {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-block-start: var(--space-xs);
  color: var(--colour-text-muted);
}

@media (min-width: 48rem) {
  .dz-pipeline-connector-mobile {
    display: none;
  }
}

/* ─────────────────────────── experience shell (UX-072) ──────────
 * Step-progress + inner-surface chrome for experience flows. Used
 * by experience/_content.html. */

.dz-experience {
  max-inline-size: 56rem;
  margin-inline: auto;
}

.dz-experience-title {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--colour-text);
  margin-block-end: var(--space-xl);
}

/* Experience stepper reuses the existing .dz-steps* family from
 * the steps_indicator fragment block above (line ~448). The pattern
 * uses .is-completed on the .dz-steps-circle / .dz-steps-label /
 * .dz-steps-connector children rather than a modifier on the item. */

.dz-experience-form-shell {
  max-inline-size: 42rem;
}

.dz-experience-form-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.dz-experience-stage-title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  margin-block-end: var(--space-md);
}

.dz-experience-actions {
  display: flex;
  gap: var(--space-md);
  padding-block-start: var(--space-md);
}

.dz-experience-actions-centered {
  justify-content: center;
}

.dz-experience-ready {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  border-radius: var(--radius-sm);
  background: color-mix(in oklch, var(--colour-brand) 8%, transparent);
  border: 1px solid color-mix(in oklch, var(--colour-brand) 20%, transparent);
  font-size: var(--text-sm);
  color: var(--colour-text);
}

.dz-experience-placeholder {
  border-radius: var(--radius-md);
  background: var(--colour-bg);
  padding: var(--space-2xl);
  text-align: center;
}

.dz-experience-placeholder-title {
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  margin-block-end: var(--space-sm);
}

.dz-experience-placeholder-body {
  color: var(--colour-text-muted);
}
