/* Internal dashboard chrome (not a standalone gallery Hyperpart — no HYPERPART
 * marker, matching the other migrated chrome components detail/fragments/etc.). */
/* Moved from Dazzle dashboard.css (HMC-007d) — the dashboard card grid +
 * card chrome (wrapper/header/actions/titles/notice/body/skeleton/resize) +
 * add-card CTA. Byte-faithful, HM-tokenised. The dz-pulse keyframe used by the
 * skeleton is HM's (tokens.css); .dz-card base is unique to this file. */

/* ─────────────────────────── card grid ──────────────────────────
 * 1-col on mobile, 12-col on >=md. items-start to collapse to
 * intrinsic content height (#844). */

.dz-dashboard-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  align-items: start;
}

@media (min-width: 48rem) {
  .dz-dashboard-grid {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }
}

/* ─────────────────────────── card wrapper ───────────────────────
 * Layout/positioning element only. Visible card chrome lives on
 * the inner <article>. Wrapper stays square (no rounding) so the
 * focus ring traces a clean rectangle (#794). */

.dz-card-wrapper {
  position: relative;
  outline: none;
}

.dz-card-wrapper:focus {
  box-shadow: 0 0 0 2px var(--colour-surface), 0 0 0 4px var(--colour-brand);
}

/* Smooth transitions on all reposition/resize except while dragging
 * (the wrapper sets style.transform directly during drag). Toggled
 * via .is-animating class (Alpine sets it when not dragging and not
 * mid-drag). */
.dz-card-wrapper.is-animating {
  transition: all var(--duration-base) var(--ease-out);
}

/* ─────────────────────────── card chrome ────────────────────────
 * The visible card surface. Default border + bg + clipping. When
 * resizing, swap to a dashed brand-coloured border. */

.dz-card {
  border-radius: var(--radius-md);
  border: 1px solid var(--colour-border);
  background: var(--colour-surface);
  /* TASTE-2: quiet stacked shadow at rest — elevation reads as a surface,
     not decoration; hover transition already declared below. */
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.dz-card.is-resizing {
  border-style: dashed;
  border-color: var(--colour-brand);
}

/* Card header — drag handle zone. */
.dz-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline: var(--space-md);
  padding-block: var(--space-sm);
  cursor: grab;
  min-height: 2.25rem;
}

.dz-card-header:active {
  cursor: grabbing;
}

.dz-card-header.is-dragging {
  cursor: grabbing;
}

.dz-card-titles {
  display: flex;
  flex-direction: column;
}

.dz-card-eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--colour-text-muted);
  line-height: 1;
}

.dz-card-title {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--colour-text);
  user-select: none;
  margin: 0;
}

/* Header actions — fade in on hover/focus-within of the wrapper.
 * Was opacity-0 + group-hover only; #799 set rest opacity to 0.6 so
 * touch + keyboard users can still see them. */
.dz-card-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  opacity: 0.6;
  transition: opacity var(--duration-fast) var(--ease-out);
}

.dz-card-wrapper:hover .dz-card-actions,
.dz-card-wrapper:focus-within .dz-card-actions {
  opacity: 1;
}

.dz-card-action-button {
  width: 1.5rem;
  height: 1.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--colour-text-muted);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition:
    background var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.dz-card-action-button:hover {
  background: var(--colour-bg);
  color: var(--colour-text);
}

/* Notice band — between header and body. Layout shape here; the tone tints
 * (below) travel with the component (migrated from Dazzle dz-tones.css, HMC-005b
 * 2026-07-09 — the last of the dz-tones tint families). `.dz-notice-band` is the
 * visual carrier the emitter co-emits with `.dz-card-notice`. */
.dz-card-notice {
  margin-inline: var(--space-md);
  margin-block-end: var(--space-sm);
  padding-inline: var(--space-sm);
  padding-block: var(--space-xs);
  border-radius: var(--radius-sm);
  border-inline-start-width: 2px;
  border-inline-start-style: solid;
}

/* Notice-band tone tints — background + left-rail colour per data-dz-notice-tone.
 * Static rules (not Tailwind JIT) so IR-render-time tone class strings still
 * paint; tokens follow any project theme override. */
.dz-notice-band[data-dz-notice-tone="positive"] {
  background: color-mix(in oklab, var(--colour-success) 8%, transparent);
  border-left-color: var(--colour-success);
}
.dz-notice-band[data-dz-notice-tone="warning"] {
  background: color-mix(in oklab, var(--colour-warning) 10%, transparent);
  border-left-color: var(--colour-warning);
}
.dz-notice-band[data-dz-notice-tone="destructive"] {
  background: color-mix(in oklab, var(--colour-danger) 8%, transparent);
  border-left-color: var(--colour-danger);
}
.dz-notice-band[data-dz-notice-tone="accent"] {
  background: color-mix(in oklab, var(--colour-brand) 8%, transparent);
  border-left-color: var(--colour-brand);
}
.dz-notice-band[data-dz-notice-tone="neutral"],
.dz-notice-band:not([data-dz-notice-tone]) {
  background: color-mix(in oklab, var(--colour-surface-muted) 40%, transparent);
  border-left-color: var(--colour-border);
}

.dz-card-notice-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--leading-tight);
  color: var(--colour-text);
}

.dz-card-notice-body {
  font-size: var(--text-xs);
  line-height: var(--leading-tight);
  color: var(--colour-text-muted);
  margin-block-start: 0.125rem;
}

/* Card body — HTMX-loaded region content slot.
 *
 * #962 — `min-height` per display mode reserves space before the htmx
 * region fetch lands so the page doesn't bounce as content arrives.
 * Web Vitals classifies CLS > 0.1 as "needs improvement"; pre-fix
 * surveyed surfaces hit 0.18–0.37. If content exceeds the
 * reservation, only that card grows (one shift, bounded). If content
 * fits, no shift.
 *
 * Selector values match `DisplayMode` (src/dazzle/core/ir/workspaces.py)
 * — lowercased by the template's `| lower` filter. Adding a new
 * display mode? Either add a rule here OR add the value to the
 * fall-through allow-list in test_workspace_cls_reservation.py.
 */
.dz-card-body {
  padding-inline: var(--space-md);
  padding-block-end: var(--space-md);
  /* No default min-height: static / gallery cards (KPI tiles, content) must
   * size to content. Workspace HTMX regions always set data-display and use
   * the reservation rules below for CLS (#962). */
}

/* CLS reservation — only when a workspace DisplayMode is declared. */
.dz-card-body[data-display] {
  min-height: 280px; /* default — matches LIST / TABBED_LIST shape */
}

.dz-card-body[data-display="summary"],
.dz-card-body[data-display="summary_row"] {
  min-height: 96px;
}

.dz-card-body[data-display="metrics"],
.dz-card-body[data-display="metric"] {
  min-height: 140px;
}

.dz-card-body[data-display="bar_chart"],
.dz-card-body[data-display="chart"],
.dz-card-body[data-display="line_chart"],
.dz-card-body[data-display="bar_track"],
.dz-card-body[data-display="bullet"],
.dz-card-body[data-display="funnel_chart"],
.dz-card-body[data-display="heatmap"],
.dz-card-body[data-display="radar"] {
  min-height: 280px;
}

.dz-card-body[data-display="kanban"] {
  min-height: 480px;
}

.dz-card-body[data-display="diagram"] {
  min-height: 360px;
}

.dz-card-body[data-display="profile_card"] {
  min-height: 200px;
}

.dz-card-body[data-display="action_grid"],
.dz-card-body[data-display="pipeline_steps"],
.dz-card-body[data-display="status_list"] {
  min-height: 200px;
}

.dz-card-body[data-display="pivot_table"],
.dz-card-body[data-display="timeline"] {
  min-height: 320px;
}

/* Skeleton loader (shown until HTMX swap completes) */
.dz-card-skeleton {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding-block: var(--space-sm);
  animation: dz-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.dz-card-skeleton-line {
  height: 1rem;
  background: var(--colour-bg);
  border-radius: var(--radius-sm);
}

.dz-card-skeleton-line.is-thin {
  height: 0.75rem;
}

.dz-card-skeleton-line.w-3-4 { width: 75%; }
.dz-card-skeleton-line.w-5-6 { width: 83.333%; }

/* @keyframes dz-pulse dropped — HM tokens.css owns it (identical). */

/* Resize handle — right edge. Same fade-on-hover pattern as the
 * action buttons. */
.dz-card-resize {
  position: absolute;
  top: 0;
  inset-inline-end: 0;
  width: 0.375rem;
  height: 100%;
  cursor: col-resize;
  opacity: 0;
  transition:
    opacity var(--duration-fast) var(--ease-out),
    background var(--duration-fast) var(--ease-out);
  border-end-end-radius: var(--radius-md);
  border-start-end-radius: var(--radius-md);
}

.dz-card-wrapper:hover .dz-card-resize,
.dz-card-wrapper:focus-within .dz-card-resize {
  opacity: 1;
}

.dz-card-resize:hover {
  background: color-mix(in oklch, var(--colour-brand) 30%, transparent);
}

/* ─────────────────────────── add-card CTA ───────────────────────
 * Centred dashed-border button below the grid. Picker pops up
 * relative to it (positioning lives in the picker template). */

.dz-add-card-row {
  position: relative;
  display: flex;
  justify-content: center;
  margin-block-start: var(--space-md);
}

.dz-add-card-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  height: 2rem;
  padding-inline: var(--space-lg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  border-radius: var(--radius-md);
  border: 2px dashed var(--colour-border);
  color: var(--colour-text-muted);
  background: transparent;
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.dz-add-card-button:hover {
  border-color: var(--colour-brand);
  color: var(--colour-text);
}
