/* data-explorer.css: the composite's own pieces (bar, count + "i", chips, Reset all, * notes, empty state,
 * expandable number ranges, windowed list). Load it AFTER the sibling stylesheets:
 *   info-tip.css, range-slider.css, keyword-search.css, multi-select-filter.css, data-explorer.css
 * One file for the vanilla binding AND DataExplorer.tsx (same class names).
 *
 * Tokens follow Documents/Factory/UI_STANDARDS.md: section 3 OKLCH semantic tokens with dark mode designed
 * alongside (each --de-* reads the page's own --bg-surface / --text-primary / --accent-primary ... first);
 * section 4 spacing 2/4/8/12/16/24 only; section 5 motion = transform/opacity, reduced motion = fade only;
 * section 6 states (hover, active, focus-visible ring, disabled); section 11 compact 40px rows.
 * Theme keys match the siblings: :root[data-theme] wins, else prefers-color-scheme.
 */

:root {
  --de-surface: var(--bg-surface, oklch(99.2% 0.002 250));
  --de-subtle: var(--bg-subtle, oklch(96.5% 0.005 250));
  --de-elevated: var(--bg-elevated, oklch(100% 0 0));
  --de-text: var(--text-primary, oklch(23% 0.02 255));
  --de-muted: var(--text-muted, oklch(45% 0.02 255));
  --de-border: var(--border-subtle, oklch(88% 0.008 250));
  --de-border-strong: var(--border-strong, oklch(64% 0.015 250));
  --de-accent: var(--accent-primary, oklch(52% 0.18 258));
  --de-accent-soft: var(--accent-primary-soft, oklch(94% 0.04 258));
  --de-focus: var(--focus-ring, oklch(58% 0.2 258));
  --de-warn: var(--warning, oklch(48% 0.12 70));
  --de-tip-bg: oklch(23% 0.02 255);
  --de-tip-text: oklch(98% 0.004 250);
  --de-shadow: 0 8px 24px oklch(20% 0.02 255 / 0.14);
  --de-radius: 12px;
  --de-radius-sm: 8px;
  --de-control: 36px;
  --de-touch: 44px;
  --de-row-h: 40px;
  --de-fast: var(--motion-fast, 180ms);
  --de-ease: var(--ease-snappy, cubic-bezier(0.22, 1, 0.36, 1));
  --de-press: 0.97;
  --de-z: 30;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --de-surface: var(--bg-surface, oklch(20% 0.012 255));
    --de-subtle: var(--bg-subtle, oklch(24% 0.012 255));
    --de-elevated: var(--bg-elevated, oklch(27% 0.014 255));
    --de-text: var(--text-primary, oklch(94% 0.008 250));
    --de-muted: var(--text-muted, oklch(74% 0.015 250));
    --de-border: var(--border-subtle, oklch(32% 0.012 255));
    --de-border-strong: var(--border-strong, oklch(52% 0.015 255));
    --de-accent: var(--accent-primary, oklch(72% 0.14 258));
    --de-accent-soft: var(--accent-primary-soft, oklch(32% 0.07 258));
    --de-focus: var(--focus-ring, oklch(74% 0.15 258));
    --de-warn: var(--warning, oklch(80% 0.12 80));
    --de-tip-bg: oklch(94% 0.008 250);
    --de-tip-text: oklch(20% 0.012 255);
    --de-shadow: 0 8px 24px oklch(5% 0 0 / 0.5);
  }
}
:root[data-theme="dark"] {
  --de-surface: var(--bg-surface, oklch(20% 0.012 255));
  --de-subtle: var(--bg-subtle, oklch(24% 0.012 255));
  --de-elevated: var(--bg-elevated, oklch(27% 0.014 255));
  --de-text: var(--text-primary, oklch(94% 0.008 250));
  --de-muted: var(--text-muted, oklch(74% 0.015 250));
  --de-border: var(--border-subtle, oklch(32% 0.012 255));
  --de-border-strong: var(--border-strong, oklch(52% 0.015 255));
  --de-accent: var(--accent-primary, oklch(72% 0.14 258));
  --de-accent-soft: var(--accent-primary-soft, oklch(32% 0.07 258));
  --de-focus: var(--focus-ring, oklch(74% 0.15 258));
  --de-warn: var(--warning, oklch(80% 0.12 80));
  --de-tip-bg: oklch(94% 0.008 250);
  --de-tip-text: oklch(20% 0.012 255);
  --de-shadow: 0 8px 24px oklch(5% 0 0 / 0.5);
}

/* Touch screens and narrow windows: every target at least 44px. */
@media (pointer: coarse), (max-width: 480px) {
  :root { --de-control: var(--de-touch); --de-row-h: 48px; }
}

/* ---------- layout ---------- */
.de { display: grid; gap: 12px; min-width: 0; color: var(--de-text); font: inherit; }
/* A display rule must never beat [hidden] (keyword-search / range-slider lesson). */
.de[hidden], .de [hidden] { display: none !important; }
/* Every "i" here (the count's and each control's) is an info-tip button: load info-tip.css (.claude/skills/info-tip).
 * It draws a 20px "i" with an exact 44x44 hit area (regression: 2026-10-14-hit-area-42px) and puts the popover in
 * <body>, above the floating timeline and every dropdown. The explorer only lends it colours, through custom
 * properties that inherit (stylesheet order never matters). */
.de { --it-btn-text: var(--de-muted); --it-btn-border: var(--de-border-strong); }
/* Floats at the top while the page scrolls. Vanilla: the root must be a direct child of the scrolling
 * container. React: the head floats over the children rendered inside the same root. */
.de[data-sticky], .de-head[data-sticky] { position: sticky; top: 0; z-index: var(--de-z); padding: 8px 0; background: var(--de-surface); }
.de-head { display: grid; gap: 12px; min-width: 0; }
.de-content { min-width: 0; }

.de-bar { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; min-width: 0; }
.de-search { flex: 1 1 16rem; min-width: 0; }
/* The explorer owns the one count, so the search box's own meta line (count: false) is empty: drop its
 * reserved 20px unless an async status is showing (found in the demo: a dead band under the box). */
.de-search .ks-meta { min-height: 0; }
.de-search .ks-meta:not(:has(> :not([hidden]))) { display: none; }
.de-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }

/* ---------- extra number ranges: trigger + expandable box (NK 2026-10-14T12:05:33 "a dropdown arrow, which creates an expandable box") */
.de-rangef { display: inline-flex; }
.de-rtrigger {
  display: inline-flex; align-items: center; gap: 8px; min-height: var(--de-control); padding: 0 12px;
  border: 1px solid var(--de-border); border-radius: var(--de-radius-sm); background: var(--de-surface);
  color: var(--de-text); font: inherit; font-size: 0.875rem; line-height: 1.2; cursor: pointer;
  transition: border-color var(--de-fast) var(--de-ease), background-color var(--de-fast) var(--de-ease), transform var(--de-fast) var(--de-ease);
}
.de-rtrigger:hover { border-color: var(--de-border-strong); }
.de-rtrigger:active { transform: scale(var(--de-press)); }
.de-rtrigger[data-active] { border-color: var(--de-accent); background: var(--de-accent-soft); }
.de-rlabel { color: var(--de-muted); }
.de-rsummary { max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.de-chev { display: inline-block; font-size: 0.75rem; opacity: 0.6; transition: transform var(--de-fast) var(--de-ease); }
.de-rtrigger[aria-expanded="true"] .de-chev { transform: rotate(180deg); }
/* The sliders' own "N rows have no X" note counts the whole dataset; the explorer's * note under the count
 * counts only rows the OTHER filters keep, which is what the count leaves out. Show one, not both
 * (found in the demo: "12 rows have no date" beside "* 1 order has no date"). */
.de-slider .rs-note { display: none; }
.de-rpanels { display: grid; gap: 8px; }
.de-rpanels:empty { display: none; }
.de-rpanel { padding: 12px; border: 1px solid var(--de-border); border-radius: var(--de-radius); background: var(--de-elevated); }

/* ---------- status: count + "i", chips, Reset all ---------- */
.de-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; min-width: 0; }
.de-countwrap { display: inline-flex; align-items: center; gap: 8px; }
.de-count { margin: 0; font-size: 0.875rem; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.de-chips { display: flex; flex-wrap: wrap; gap: 4px 8px; margin: 0; padding: 0; list-style: none; min-width: 0; }
.de-chips:empty { display: none; }
.de-chip {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%; min-height: 28px; padding: 0 8px 0 12px;
  border: 1px solid var(--de-accent); border-radius: 999px; background: var(--de-accent-soft); color: var(--de-text);
  font: inherit; font-size: 0.8125rem; line-height: 1.2; cursor: pointer;
  transition: background-color var(--de-fast) var(--de-ease), transform var(--de-fast) var(--de-ease);
}
.de-chip:hover { background: var(--de-subtle); }
.de-chip:active { transform: scale(var(--de-press)); }
.de-chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.de-chip-x { font-size: 1rem; line-height: 1; opacity: 0.7; }

.de-reset, .de-btn {
  min-height: var(--de-control); padding: 0 12px; border: 1px solid var(--de-border-strong); border-radius: var(--de-radius-sm);
  background: var(--de-surface); color: var(--de-text); font: inherit; font-size: 0.875rem; cursor: pointer;
  transition: background-color var(--de-fast) var(--de-ease), transform var(--de-fast) var(--de-ease);
}
.de-reset { margin-left: auto; }
.de-reset:hover, .de-btn:hover { background: var(--de-subtle); }
.de-reset:active, .de-btn:active { transform: scale(var(--de-press)); }
.de-reset:disabled, .de-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.de-btn--primary { border-color: var(--de-accent); background: var(--de-accent); color: var(--de-surface); }
.de-btn--primary:hover { background: var(--de-accent); opacity: 0.9; }

@media (pointer: coarse), (max-width: 480px) {
  .de-chip { min-height: var(--de-touch); }
}

.de-chip:focus-visible, .de-reset:focus-visible, .de-btn:focus-visible, .de-rtrigger:focus-visible {
  outline: 2px solid var(--de-focus); outline-offset: 2px;
}

/* ---------- * gap notes (info-tooltips-default: missing data is a visible gap, never filled) ---------- */
.de-gaps:empty { display: none; }
.de-gap { margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--de-warn); }

/* ---------- empty state: says why, and the first button fixes it ---------- */
.de-empty {
  display: grid; gap: 8px; padding: 16px; border: 1px dashed var(--de-border-strong); border-radius: var(--de-radius);
  background: var(--de-subtle);
}
.de-empty-title { margin: 0; font-weight: 600; }
.de-empty-list { margin: 0; padding-left: 20px; font-size: 0.875rem; color: var(--de-muted); }
.de-empty-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------- windowed list (UI_STANDARDS section 11: virtualise over 100 rows) ---------- */
.de-vlist { position: relative; overflow-y: auto; overscroll-behavior: contain; contain: content; }
.de-vrow { box-sizing: border-box; height: var(--de-row-h); overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .de-rtrigger, .de-chev, .de-chip, .de-reset, .de-btn { transition: none; }
  .de-rtrigger:active, .de-chip:active, .de-reset:active, .de-btn:active { transform: none; }
}
