/* ------------------------------------------------------------
   6 · INPUT — flat by default
   ------------------------------------------------------------ */
.dcs-input, .dcs-select, .dcs-textarea {
  display: inline-flex; align-items: center;
  height: var(--dcs-h-in);
  padding: 0 var(--dcs-s-3);
  font-size: var(--dcs-fs-sm);
  color: var(--dcs-text);
  background: var(--dcs-well);
  border: 1px solid var(--dcs-line);
  border-radius: var(--dcs-r-2);
  outline: none;
  transition: border-color var(--dcs-t-fast), box-shadow var(--dcs-t-fast);
  font-family: var(--dcs-font);
}
.dcs-textarea { height: auto; padding: var(--dcs-s-3); line-height: var(--dcs-lh); resize: vertical; }
.dcs-input::placeholder { color: var(--dcs-text-mute); }
.dcs-input:hover, .dcs-select:hover, .dcs-textarea:hover { border-color: var(--dcs-line-strong); }
.dcs-input:focus, .dcs-select:focus, .dcs-textarea:focus {
  border-color: var(--dcs-accent);
  box-shadow: 0 0 0 2px var(--dcs-accent-haze);
}
.dcs-input--num { font-family: var(--dcs-font-num); font-variant-numeric: tabular-nums lining-nums; text-align: right; }

/* ── Search input ──────────────────────────────────────────────
   A standard text input dressed as a search field: a leading
   magnifier icon (`<i class="di di-search">` inside) and a
   placeholder. The icon is absolutely positioned inside the
   wrapper so the input itself stays a stock `.dcs-input` — apps
   can use any of the input variants inside (compact, etc.).

   Markup:
     <div class="dcs-search">
       <i class="di di-search" aria-hidden="true"></i>
       <input class="dcs-input" type="search" placeholder="Search…">
     </div>
*/
.dcs-search {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-width: 0;
}
.dcs-search > .di {
  position: absolute;
  left: var(--dcs-s-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--dcs-text-mute);
  pointer-events: none;
  font-size: 13px;
  line-height: 1;
}
.dcs-search > .dcs-input {
  padding-left: calc(var(--dcs-s-3) + 18px);
  width: 100%;
}

/* Enum dropdown trigger — a select-styled button that opens a .dcs-menu of
   options. The full form of a "choose one of N" enum; the segmented
   button-group is its shorthand for when the options fit inline. */
.dcs-select--btn {
  gap: var(--dcs-s-2);
  cursor: pointer; user-select: none;
  color: var(--dcs-text);
}
.dcs-select--btn .dcs-select__label {
  flex: 1; min-width: 0; text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dcs-select--btn .dcs-select__caret { flex: 0 0 auto; color: var(--dcs-text-mute); margin-right: calc(var(--dcs-s-1) * -1); }
.dcs-select--btn:hover { border-color: var(--dcs-line-strong); }
.dcs-select--btn.dcs-select--open,
.dcs-select--btn[aria-expanded="true"] {
  border-color: var(--dcs-accent);
  box-shadow: 0 0 0 2px var(--dcs-accent-haze);
}
.dcs-select--btn.dcs-select--open .dcs-select__caret,
.dcs-select--btn[aria-expanded="true"] .dcs-select__caret { color: var(--dcs-accent); }

/* ── Field row primitive ──────────────────────────────────────────
   `.dcs-field` is one label-plus-control row. On its own it's just a
   flex row — to get even, opinionated spacing across many rows, wrap
   them in one of the two form layouts below: `.dcs-form` (general) or
   `.dcs-props` (inspector). */
.dcs-field {
  display: flex; align-items: center; gap: var(--dcs-s-3);
  min-height: var(--dcs-h);
}
.dcs-field__label {
  flex: 0 0 96px;
  font-size: var(--dcs-fs-sm);
  color: var(--dcs-text-dim);
  user-select: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dcs-field--row > * { flex: 1; }

/* ── Form layouts: .dcs-form vs .dcs-props ─────────────────────────
   Two selectors decide how a stack of `.dcs-field` rows looks. Pick
   one based on context — they are mutually exclusive.

   `.dcs-form`   — DIALOG / MODAL layout. Use this in dialog boxes,
                   modal-like panels, preference sheets, signup forms,
                   wizards — anywhere the user is filling in a focused
                   set of values rather than tweaking live channels.
                   Labels are **right-justified** against a fixed-width
                   column; controls keep their **natural width**; bare
                   buttons self-center; a `.dcs-form__actions` footer
                   right-aligns grouped actions under the control column.

   `.dcs-props`  — INSPECTOR layout. Use this for property inspectors,
                   channel editors, attribute lists, node settings —
                   anywhere a live object's channels are exposed for
                   continuous editing. Labels are **left-justified**
                   against a fixed-width column; controls (including
                   bare buttons) **stretch to fill** the row so a tall
                   stack reads as even, same-size channel rows.

   Inline checkbox-with-text (check left, label right) — just place a
   bare `.dcs-check` outside a form/props stack; that's its default.

   Tune label-column width per instance with `--dcs-form-label-w` or
   `--dcs-props-label-w`. */

.dcs-form {
  /* In dialog mode the centerline IS the view's centerline — labels
     right-justify up to 50%, controls start from 50%. This differs
     from `.dcs-props` (inspector), where the label column is a fixed
     pixel width tuned to the longest expected prompt. Override
     `--dcs-form-label-w` per-instance if you need a different split. */
  --dcs-form-label-w: 50%;
  display: flex; flex-direction: column;
  gap: var(--dcs-s-3);
}
.dcs-form > .dcs-field {
  min-height: var(--dcs-h-in);
}
.dcs-form > .dcs-field > .dcs-field__label {
  flex: 0 0 var(--dcs-form-label-w);
  text-align: right;
}
.dcs-form__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--dcs-s-3);
  padding-left: calc(var(--dcs-form-label-w) + var(--dcs-s-3));
}
/* A bare button (or button group) dropped directly into a `.dcs-form`
   stack keeps its natural size and self-centers in the form column —
   matches the "controls keep natural width" rule above. For grouped,
   right-aligned action rows use `.dcs-form__actions`. */
.dcs-form > .dcs-btn,
.dcs-form > .dcs-btn-group {
  align-self: center;
}

/* A `.dcs-btn-row` is a paired-button row that adapts to its stack:
     • in `.dcs-form` (dialog): buttons sit centered at natural width
       next to each other.
     • in `.dcs-props` (inspector): buttons split the row evenly via
       `flex: 1` — two buttons cut the row in half, three split it
       into thirds, etc., matching the channel-widget contract.
   Use this when you want Cancel/Apply, Yes/No, or any paired actions
   without picking the right-aligned `.dcs-form__actions` footer. */
.dcs-btn-row {
  display: flex;
  gap: var(--dcs-s-3);
}
.dcs-form > .dcs-btn-row { justify-content: center; }
.dcs-props > .dcs-btn-row > .dcs-btn,
.dcs-props > .dcs-btn-row > .dcs-btn-group {
  flex: 1;
  min-width: 0;
  height: var(--dcs-h-in);
}

/* ── Channel-widget contract ──────────────────────────────────────
   Inside `.dcs-props`, each row is locked to --dcs-h-in tall so the
   whole stack reads as even, same-size rows. A "channel widget" is
   any control that obeys two rules:
     1. it's no taller than the row (--dcs-h-in), and
     2. if it should span the row, it stretches (flex: 1).
   Built-ins listed below already comply; a custom widget opts in by
   adding `.dcs-field__fill` (to span) or simply staying short (to
   sit LEFT-justified in the channel column, like a switch/check).
   The set is open — anything that follows the contract keeps the
   rhythm. */
.dcs-props {
  --dcs-props-label-w: 96px;
  display: flex; flex-direction: column;
  gap: var(--dcs-s-3);
}
.dcs-props > .dcs-field {
  height: var(--dcs-h-in);
  min-height: var(--dcs-h-in);
  /* No `justify-content` — defaults to flex-start so non-stretched
     widgets (Check, Switch, fixed-width chip) sit at the LEFT edge
     of the channel column, aligned with the start of stretched
     controls above/below. Stretched widgets fill the column via
     `flex: 1` below. */
}
.dcs-props > .dcs-field > .dcs-field__label {
  flex: 0 0 var(--dcs-props-label-w);
  text-align: left;
}
/* Spanning channel widgets: fill the row after the label and collapse
   to one uniform height (so the 24px-tall defaults — slider, swatch,
   button-group — match the 22px text/number fields when stacked).
   `.dcs-field__fill` is the opt-in escape hatch for custom widgets. */
.dcs-props > .dcs-field > .dcs-slider,
.dcs-props > .dcs-field > .dcs-input,
.dcs-props > .dcs-field > .dcs-select,
.dcs-props > .dcs-field > .dcs-combo,
.dcs-props > .dcs-field > .dcs-swatch,
.dcs-props > .dcs-field > .dcs-colorfield,
.dcs-props > .dcs-field > .dcs-btn-group,
.dcs-props > .dcs-field > .dcs-field__fill {
  flex: 1;
  min-width: 0;
  height: var(--dcs-h-in);
}
.dcs-props > .dcs-field > .dcs-btn-group {
  /* Never shrink a button-group past its natural content size — Local /
     Global / Local-Global rows get illegible when they squeeze under
     an icon-only floor. Keeps flex:1 so the group still stretches to
     fill the channel column when there's room. */
  min-width: max-content;
}
.dcs-props > .dcs-field > .dcs-btn-group .dcs-btn {
  height: calc(var(--dcs-h-in) - 6px);
  min-width: calc(var(--dcs-h-in) - 6px);
  padding: 0 var(--dcs-s-3);
}

/* ── Vector row primitive ──────────────────────────────────────
   `.dcs-vec` is a flex row of equal-width controls — typically the
   X/Y/Z numeric editors of a Location / Rotation / Scale channel.
   Children share row width evenly but won't shrink below
   `--dcs-xform-minwidth` (default 48px) so labels stay readable; below
   that floor the row overflows rather than crushing the values.
   Drops into a `.dcs-props > .dcs-field` slot and stretches to fill
   the channel column.

   Combos inside a `.dcs-vec` drop the range-fill bar — XYZ values
   are coordinates, not a range, so a left-to-right fill would be
   meaningless (and visually confused with a slider). */
.dcs-vec {
  --dcs-xform-minwidth: 72px;
  display: flex;
  gap: var(--dcs-s-1);
  min-width: 0;
}
.dcs-vec > * {
  flex: 1 1 0;
  min-width: var(--dcs-xform-minwidth);
  min-height: var(--dcs-h-in);   /* never collapse to thin horizontal lines */
}
.dcs-vec > .dcs-combo .dcs-combo__fill { display: none; }
/* Override the stock `.dcs-combo { min-width: 96px }` so the combo
   inside a vec respects the vec's per-item floor (`--dcs-xform-minwidth`).
   Without this, combos refuse to shrink past 96px and the JS observer
   can never observe a constrained width — the synchronized flip
   threshold is meaningless if the children block the shrink. */
.dcs-vec > .dcs-combo {
  min-width: var(--dcs-xform-minwidth);
}
.dcs-props > .dcs-field > .dcs-vec {
  flex: 1;
  min-width: 0;
}

/* Field hosting a vec — anchor the prompt to the TOP of the row so a
   stacked vec keeps its label at the upper-left where the eye lands. */
.dcs-field:has(> .dcs-vec) {
  align-items: flex-start;
}
.dcs-field:has(> .dcs-vec) > .dcs-field__label {
  padding-top: 3px;
}

/* When the vec can't fit its N children at `--dcs-xform-minwidth` apiece, JS
   (initVecLayout, ResizeObserver-driven) toggles `.dcs-vec--stacked`.
   The flip threshold is computed from the SAME `--dcs-xform-minwidth` that
   sets the horizontal floor, so changing the floor automatically
   adjusts the flip point — they stay synchronized. */
.dcs-vec--stacked {
  flex-direction: column;
}
.dcs-vec--stacked > * {
  min-width: 0;
  width: 100%;
}
/* Field gets `height: auto` so it can grow tall when its vec stacks
   three combos vertically — otherwise the fixed channel-row height
   (var(--dcs-h-in)) collides with the per-combo min-height and the
   row content gets crushed. */
.dcs-props > .dcs-field:has(> .dcs-vec.dcs-vec--stacked) {
  height: auto;
}
.dcs-props > .dcs-field:has(> .dcs-vec) {
  min-height: var(--dcs-h-in);
}

/* ── Standalone note / info / warning row ────────────────────────
   A `.dcs-note` is a full-width text strip inside a form/props stack
   — no prompt, no editor, just text spanning the row. Use it for
   section hints, derived/status values, info messages, or warnings
   that sit *between* the editable channels rather than next to one.
   Variants colorize the text via semantic tokens; pair with a small
   `<Icon>` for an at-a-glance affordance. */
.dcs-note {
  display: flex; align-items: center; gap: var(--dcs-s-2);
  font-size: var(--dcs-fs-sm);
  line-height: var(--dcs-lh);
  color: var(--dcs-text-dim);   /* match `.dcs-field__label` prompts */
  font-weight: 400;
  min-width: 0;
}
.dcs-note--mono {
  font-family: var(--dcs-font-num);
  font-variant-numeric: tabular-nums lining-nums;
}
.dcs-note--mute   { color: var(--dcs-text-mute); }
.dcs-note--info   { color: var(--dcs-info); }
.dcs-note--warn   { color: var(--dcs-warn); }
.dcs-note--ok     { color: var(--dcs-ok); }
.dcs-note--danger { color: var(--dcs-danger); }
/* When dropped directly into a form/props stack, the note spans the
   full row width (no prompt, no channel column) and stays at one
   channel-row of height for a single line. Text is plain — normal
   weight, no title hierarchy, no chrome — so it reads as a quiet
   line in the dialog rather than a callout. In `.dcs-form` (dialog)
   the text centers like a dialog blurb; in `.dcs-props` (inspector)
   it stays left-aligned with the rest of the channel column. */
.dcs-form > .dcs-note,
.dcs-props > .dcs-note {
  width: 100%;
  min-height: var(--dcs-h-in);
  font-weight: 400;
}
.dcs-form > .dcs-note {
  justify-content: center;
  text-align: center;
}

/* `.dcs-alert` dropped into a form/props stack — the heavier sibling
   of `.dcs-note`. Restyled to a soft "callout" box: rounded rect,
   semantic-tinted background, matching tinted border, icon on the
   left, plain text on the right. The default `.dcs-alert` accent
   stripe + raised-surface chrome (its standalone-panel look) is
   dropped here — inline in a dialog, that visual weight fights the
   rest of the form. */
.dcs-form > .dcs-alert,
.dcs-props > .dcs-alert {
  width: 100%;
  padding: var(--dcs-s-3) var(--dcs-s-4);
  border: 1px solid var(--dcs-accent-haze);
  background: var(--dcs-accent-dim);
  border-radius: var(--dcs-r-2);
  align-items: center;
  gap: var(--dcs-s-3);
  font-weight: 400;
}
.dcs-form > .dcs-alert.dcs-alert--ok,
.dcs-props > .dcs-alert.dcs-alert--ok {
  background: rgba(78, 209, 138, .12);
  border-color: rgba(78, 209, 138, .35);
}
.dcs-form > .dcs-alert.dcs-alert--warn,
.dcs-props > .dcs-alert.dcs-alert--warn {
  background: rgba(242, 177, 74, .12);
  border-color: rgba(242, 177, 74, .35);
}
.dcs-form > .dcs-alert.dcs-alert--danger,
.dcs-props > .dcs-alert.dcs-alert--danger {
  background: rgba(239, 107, 107, .12);
  border-color: rgba(239, 107, 107, .35);
}
/* Inline-callout text: full-strength color, normal weight, no nested
   title/msg distinction. The body can be a bare string — the existing
   `.dcs-alert__title` / `.dcs-alert__msg` two-tier structure is
   collapsed so a single line reads cleanly. */
.dcs-form > .dcs-alert .dcs-alert__title,
.dcs-props > .dcs-alert .dcs-alert__title {
  font-weight: 400;
  margin: 0;
}
.dcs-form > .dcs-alert .dcs-alert__msg,
.dcs-props > .dcs-alert .dcs-alert__msg {
  color: var(--dcs-text);
}

/* Textareas — the "larger edit box" — default to two channel rows tall
   in both form and inspector contexts (so a freshly-dropped textarea
   reads as the multi-line variant of an input, not a one-liner that
   happens to scroll). The row holding it expands vertically, and the
   label aligns to the top of the textarea so it doesn't float in the
   middle of a tall block.

   Resize affordance follows context: in `.dcs-form` the textarea has
   natural width so it resizes BOTH ways; in `.dcs-props` the textarea
   stretches to fill the channel column (`flex: 1`) so only vertical
   resize is meaningful — horizontal resize would fight the layout. */
.dcs-form > .dcs-field > .dcs-textarea,
.dcs-props > .dcs-field > .dcs-textarea {
  height: calc(var(--dcs-h-in) * 2 + var(--dcs-s-3));
  min-height: calc(var(--dcs-h-in) * 2 + var(--dcs-s-3));
}
.dcs-form > .dcs-field > .dcs-textarea { resize: both; }
.dcs-props > .dcs-field > .dcs-textarea {
  flex: 1; min-width: 0;
  resize: vertical;
}
/* Row containing a textarea: lets the row grow vertically, drops the
   middle-centering (no point centering a short label against a tall
   box), and aligns the label's first line with the textarea's first
   line of text. The label uses normal line-height so its top edge
   matches the textarea's interior top padding (--dcs-s-3). */
.dcs-form > .dcs-field:has(.dcs-textarea),
.dcs-props > .dcs-field:has(.dcs-textarea) {
  height: auto;
  align-items: flex-start;
}
.dcs-form > .dcs-field:has(.dcs-textarea) > .dcs-field__label,
.dcs-props > .dcs-field:has(.dcs-textarea) > .dcs-field__label {
  padding-top: var(--dcs-s-3);
  line-height: var(--dcs-lh);
  /* Tall labels with a textarea should wrap, not ellipsis-clip — there
     is room for the wrap, and clipping looks worse than two short
     lines next to a multi-line edit box. */
  white-space: normal;
  text-overflow: clip;
}

/* ── List / Tree as a field control ──────────────────────────────
   Lists and trees are too tall and too "object-like" to share a row
   with a label the way a slider or input does. When a `.dcs-list` or
   `.dcs-tree` is the value side of a `.dcs-field`, the row flips
   vertical: prompt sits ABOVE the list, list sits below as a sunken
   chrome'd well.
     • `.dcs-props` (inspector): list spans the full row width, label
       left-aligned above it.
     • `.dcs-form` (dialog): list takes two-thirds width and centers
       under a centered label.
   Default height is four channel rows so an engineer dropping a list
   into a form doesn't have to size it. Adjust per-instance with the
   `--dcs-list-h` custom property. */
.dcs-form > .dcs-field:has(> .dcs-list, > .dcs-tree, > .dcs-table),
.dcs-props > .dcs-field:has(> .dcs-list, > .dcs-tree, > .dcs-table) {
  --dcs-list-h: calc(var(--dcs-h) * 4);
  flex-direction: column;
  align-items: flex-start;
  height: auto;
  min-height: 0;
  gap: var(--dcs-s-2);
}
/* In .dcs-form the entire prompt/list pair container is 66% wide and
   centered in the form. Inside that container, the prompt sits at
   top-left and the list fills the container's full width — so both
   align to the container's left edge, and the whole pair sits in
   the visual center of the form. */
.dcs-form > .dcs-field:has(> .dcs-list, > .dcs-tree, > .dcs-table) {
  width: 66%;
  align-self: center;
}
.dcs-form > .dcs-field:has(> .dcs-list, > .dcs-tree, > .dcs-table) > .dcs-field__label,
.dcs-props > .dcs-field:has(> .dcs-list, > .dcs-tree, > .dcs-table) > .dcs-field__label {
  flex: 0 0 auto;
  width: auto;
  text-align: left;
}
/* The list/tree/table fills the pair container's width — in .dcs-form
   that's 66% of the form, in .dcs-props that's 100% of the inspector. */
.dcs-form > .dcs-field > .dcs-list,
.dcs-form > .dcs-field > .dcs-tree,
.dcs-form > .dcs-field > .dcs-table,
.dcs-props > .dcs-field > .dcs-list,
.dcs-props > .dcs-field > .dcs-tree,
.dcs-props > .dcs-field > .dcs-table {
  width: 100%;
}
/* Shared chrome: sunken well + border + scrollable + default height.
   Tables need `display: block` to honour `overflow: auto` (default
   `display: table` ignores overflow); this loses native column
   auto-sizing — set `<th>`/`<td>` widths explicitly if needed. */
.dcs-form > .dcs-field > .dcs-list,
.dcs-form > .dcs-field > .dcs-tree,
.dcs-form > .dcs-field > .dcs-table,
.dcs-props > .dcs-field > .dcs-list,
.dcs-props > .dcs-field > .dcs-tree,
.dcs-props > .dcs-field > .dcs-table {
  height: var(--dcs-list-h);
  background: var(--dcs-well);
  border: 1px solid var(--dcs-line);
  border-radius: var(--dcs-r-2);
  overflow: auto;
}
.dcs-form > .dcs-field > .dcs-table,
.dcs-props > .dcs-field > .dcs-table {
  display: block;
}
/* A bare button (or button group) dropped directly into a `.dcs-props`
   stack — not wrapped in a `.dcs-field` — acts as a channel-sized
   widget: full row width, locked to row height. Stretch is the inspector
   contract. */
.dcs-props > .dcs-btn,
.dcs-props > .dcs-btn-group {
  width: 100%;
  height: var(--dcs-h-in);
}
.dcs-props > .dcs-btn-group .dcs-btn {
  height: calc(var(--dcs-h-in) - 6px);
  min-width: calc(var(--dcs-h-in) - 6px);
}

/* Link field — a channel widget that accepts a dragged asset/node (DnD).
   Dashed while empty, solid once linked; flips to accent/danger as a drop
   target. Sits at channel-row height so it stacks with the others. */
.dcs-linkfield {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--dcs-s-2);
  height: var(--dcs-h-in); padding: 0 var(--dcs-s-2);
  background: var(--dcs-well);
  border: 1px dashed var(--dcs-line-strong);
  border-radius: var(--dcs-r-2);
  color: var(--dcs-text-dim); font-size: var(--dcs-fs-sm);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.dcs-linkfield--set { border-style: solid; color: var(--dcs-text); }
.dcs-linkfield__empty { color: var(--dcs-text-mute); font-style: italic; }
.dcs-linkfield.dcs-drop--valid { border-style: solid; border-color: var(--dcs-accent); background: var(--dcs-accent-dim); box-shadow: none; }
.dcs-linkfield.dcs-drop--invalid { border-color: var(--dcs-danger); box-shadow: none; }

/* ZBrush-style combo number/slider — flat by default */
.dcs-combo {
  position: relative;
  display: inline-flex; align-items: stretch;
  height: var(--dcs-h-in);
  background: var(--dcs-well);
  border: 1px solid var(--dcs-line);
  border-radius: var(--dcs-r-2);
  overflow: hidden;
  user-select: none;
  min-width: 96px;
  cursor: ew-resize;
}
.dcs-combo--sm {
  height: var(--dcs-h-sm);
  min-width: 56px;
}
.dcs-combo--sm .dcs-combo__label,
.dcs-combo--sm .dcs-combo__value {
  font-size: var(--dcs-fs-xs);
  padding: 0 var(--dcs-s-2);
}
.dcs-combo--lg {
  height: calc(var(--dcs-h-lg) - 2px);
  min-width: 120px;
}
.dcs-combo--lg .dcs-combo__label,
.dcs-combo--lg .dcs-combo__value {
  font-size: var(--dcs-fs-md);
  padding: 0 var(--dcs-s-4);
}
.dcs-combo__fill {
  position: absolute; left: 0; bottom: 0;
  height: 2px;
  width: var(--fill, 50%);
  background: var(--dcs-accent);
  pointer-events: none;
  opacity: .7;
}
.dcs-combo__label, .dcs-combo__value {
  position: relative; z-index: 1;
  display: flex; align-items: center;
  padding: 0 var(--dcs-s-3);
  font-size: var(--dcs-fs-sm);
  font-family: var(--dcs-font-num);
  font-variant-numeric: tabular-nums lining-nums;
}
.dcs-combo__label {
  color: var(--dcs-text-mute);
  flex: 0 0 auto;
  min-width: 0;
  padding-right: var(--dcs-s-2);
}
.dcs-combo__value {
  color: var(--dcs-text);
  flex: 1; min-width: 0;
  justify-content: flex-end;
  padding-right: var(--dcs-s-3);
}
/* Combo chevrons — hidden in flat mode (no fly-out animation), always-visible in 3D */
.dcs-combo__btn {
  display: none;
  width: 14px;
  align-items: center; justify-content: center;
  color: var(--dcs-text-mute);
  background: transparent;
  border: none;
  cursor: pointer;
  z-index: 1;
}
.dcs-combo__btn:hover { color: var(--dcs-text); background: rgba(255,255,255,.04); }
.dcs-combo:hover {
  border-color: var(--dcs-line-strong);
  background: var(--dcs-bg);
}
.dcs-combo:focus-within {
  border-color: var(--dcs-accent);
  box-shadow: 0 0 0 2px var(--dcs-accent-haze);
}
.dcs-combo--editing { cursor: text; }
.dcs-combo--editing .dcs-combo__fill { opacity: 0; }
.dcs-combo__edit {
  position: absolute; inset: 0; z-index: 2;
  background: var(--dcs-well);
  border: none; outline: none;
  padding: 0 var(--dcs-s-3);
  font-family: var(--dcs-font-mono);
  font-size: var(--dcs-fs-sm);
  color: var(--dcs-text);
  text-align: right;
}
