
/* ============================================================
   Catalog / demo shell — a shared, compact framing for the preview/*.html
   component galleries, so each preview stops hand-rolling its own <style>
   (body padding, section margins, demo boxes). Mirrors webgeist's dense
   catalog: a 240px sticky sidebar + capped main + a hairline-bordered,
   flex-wrapping .ds-demo cell that packs variants inline and reflows.
   ============================================================ */
.ds-catalog { display: flex; min-height: 100vh; gap: 0; }
.ds-catalog-side {
  width: 240px; flex-shrink: 0;
  border-right: var(--bw-hair) solid var(--rule);
  padding: var(--space-3);
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.ds-catalog-side h1 { font-size: var(--fs-lg); margin: 0 0 var(--space-1); }
.ds-catalog-side .subtitle { font-size: var(--fs-micro); color: var(--fg-3); margin: 0 0 var(--space-4); }
.ds-catalog-side nav h4 {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: var(--tr-label);
  color: var(--fg-3); margin: var(--space-3) 0 var(--space-1);
}
.ds-catalog-side nav a {
  display: block; padding: var(--space-half) 0; font-size: var(--fs-tiny);
  color: var(--fg-2); text-decoration: none;
}
.ds-catalog-side nav a:hover { color: var(--accent-ink); }
.ds-catalog-main { flex: 1; padding: var(--space-5); max-width: var(--measure-wide); min-width: 0; }
.ds-catalog-section { margin-bottom: var(--space-5); padding-top: var(--space-3); border-top: var(--bw-hair) solid var(--rule); }
.ds-catalog-section > h2 { font-size: var(--fs-h3-app); margin: 0 0 var(--space-3); }

/* The gallery cell: a hairline-bordered, flex-wrapping bin that packs a
   component's variants inline and reflows — the signature "showcase" frame. */
.ds-demo {
  border: var(--bw-hair) solid var(--rule);
  border-radius: var(--r-1);
  padding: var(--space-3);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  background: var(--bg);
}
.ds-demo + .ds-demo { margin-top: var(--space-2-75); }
.ds-demo-label { font-size: var(--fs-xs); font-weight: 500; margin: 0 0 var(--space-1); }
.ds-demo-desc { font-size: var(--fs-tiny); color: var(--fg-3); margin: 0 0 var(--space-2); }

@media (max-width: 768px) {
  .ds-catalog { flex-direction: column; }
  .ds-catalog-side { width: 100%; height: auto; position: static; border-right: 0; border-bottom: var(--bw-hair) solid var(--rule); }
  .ds-catalog-main { padding: var(--space-3); }
}

/* -- File browser UX affordances ---------------------------- */
/* Toolbar filter input — compact search box. */
.ds-filter-input {
  width: clamp(120px, 22vw, 220px);
  padding: 7px 12px;
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule);
  border-radius: var(--r-pill); color: var(--fg);
  font-family: inherit; font-size: var(--fs-xs);
}
.ds-filter-input:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); }

/* Loading skeleton: FileSkeleton renders `.ds-file-grid.ds-file-skeleton` with
   `.ds-file-row.ds-file-row-skeleton` rows whose inner `.ds-skel` children shimmer
   (via .ds-skel::after). The container therefore inherits the .ds-file-grid layout
   and must NOT be a single 48px gradient bar (that collapsed every row and double-
   shimmered). The dead .ds-file-grid-loading rule + unused ds-skeleton-shimmer
   keyframe were removed; only the inner .ds-skel children animate. */

/* Drag-to-move drop target highlight on a directory row. */
.ds-file-row.ds-drop-target {
  border-color: var(--accent);
  background: var(--accent-tint);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.ds-file-row[draggable="true"] { cursor: grab; }
.ds-file-row[draggable="true"]:active { cursor: grabbing; }

/* (A stale duplicate multi-select block used to live here: an absolute-overlay
   .ds-file-check hidden until hover, plus .ds-file-check.on / .ds-file-row.selected
   / .ds-bulk-bar rules NO component ever emits. Being later in source at equal
   specificity it clobbered the real in-flow checkbox at ~1243 - the shipped
   multi-select rendered invisible-until-hover with clipped brackets. The live
   rules are the earlier block; only the still-load-bearing bits remain below.) */
.ds-file-row { position: relative; }
/* Touch / coarse-pointer devices have no hover — keep the per-row action
   buttons (rename/delete/download) visible so the file manager is fully
   reachable without a pointer (e.g. an iPad in landscape). */
@media (hover: none), (pointer: coarse) {
  .ds-file-actions { opacity: 1; }
}

/* Keyboard-shortcuts hint — compact two-column legend. */
.ds-shortcuts-hint {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 4px var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-2); border: var(--bw-hair) solid var(--rule);
  border-radius: var(--r-2); font-size: var(--fs-xs);
}
.ds-shortcut-row { display: flex; align-items: center; gap: var(--space-2); }
.ds-shortcuts-hint .ds-kbd-label { flex: 1 1 auto; opacity: .85; }
.ds-shortcuts-hint .ds-kbd { white-space: normal; max-width: 100%; }
.ds-kbd-caps { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.ds-kbd-sep { color: var(--fg-3); font-size: var(--fs-micro); padding: 0 2px; }
/* .ds-kbd base definition lives in editor-primitives.css (canonical home —
   it owns the fuller ds-kbd-group/ds-kbd-row family this key chip belongs
   to); this file only carries the .ds-shortcuts-hint contextual overrides
   above. */

/* ============================================================
   Theme toggle (segmented + compact) — bound to src/theme.js
   ============================================================ */
.ds-segmented {
  display: inline-flex; gap: 0; padding: 2px;
  background: var(--bg-2); border-radius: var(--r-pill);
  font-family: var(--ff-mono); font-size: var(--fs-xs);
}
.ds-segmented .ds-seg-btn {
  background: transparent; border: 0; color: var(--fg-3);
  padding: 4px 12px; border-radius: var(--r-pill); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  transition: color var(--dur-base) var(--ease), background var(--dur-base) var(--ease);
}
.ds-segmented .ds-seg-btn:hover { color: var(--fg); }
/* Touch floor — a segmented control is a primary mode switch but renders ~30px
   tall from its 4px padding, below the 44px minimum the rest of the system
   holds. Grows the hit area only; the pill's visual size is unchanged at
   fine-pointer sizes. */
@media (pointer: coarse) {
  .ds-segmented .ds-seg-btn { min-height: 44px; padding-inline: var(--space-3); }
}
.ds-segmented .ds-seg-btn:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
.ds-segmented .ds-seg-btn.is-on {
  background: var(--bg); color: var(--fg);
  box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--rule);
}
.ds-theme-toggle.btn {
  font-family: var(--ff-mono); font-size: var(--fs-xs);
  display: inline-flex; align-items: center; gap: 6px;
}
/* CSS-drawn half-disc mark on the compact theme toggle: keeps the control
   legible when its text label is hidden (icon-only rail strip). */
.ds-theme-disc {
  flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%;
  border: var(--bw-hair) solid var(--fg-3);
  background: linear-gradient(90deg, var(--fg-3) 0 50%, transparent 50% 100%);
}

