/* VMnodes design system — GENERATED by scripts/sync-design-system.ts.
   Edit the vmnodes-design skill, then re-run the script. */
@import url("https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap");

/* ── tokens/fonts.css ── */
/* Geist / Geist Mono via Google Fonts.
   SUBSTITUTION FLAG: no VMnodes font binaries were supplied. Geist is the
   nearest neutral grotesque to the dark-agency reference. Drop real .woff2
   files into assets/fonts/ and replace this import with @font-face rules. */

:root {
  --font-sans: "Geist", "Helvetica Neue", Helvetica, system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --font-display: var(--font-sans);
}
/* ── tokens/colors.css ── */
/* ── VMnodes colour system ───────────────────────────────────────────────
   Dark-first. Cool ink (hue 265) so blues/violets sit in the same family as
   the surface, the way the reference dark UI does. Accents nod to ShapeIT:
   blue -> violet, identical lightness and chroma, hue is the only variable.
   All text pairings below meet WCAG 2.2 AA (>=4.5:1 body, >=3:1 large/UI).
   ------------------------------------------------------------------------ */
:root {
  color-scheme: dark;

  /* Base ink ramp — page through raised surfaces */
  --ink-900: oklch(0.145 0.012 265);   /* canvas, deepest */
  --ink-850: oklch(0.170 0.013 265);   /* sunken wells, table stripes */
  --ink-800: oklch(0.196 0.014 265);   /* panel */
  --ink-700: oklch(0.232 0.016 265);   /* card */
  --ink-600: oklch(0.272 0.017 265);   /* hover / raised */
  --ink-500: oklch(0.330 0.019 265);   /* pressed, strong border */
  --ink-400: oklch(0.420 0.020 265);   /* disabled fill */

  /* Paper ramp — foreground */
  --paper-100: oklch(0.975 0.004 265); /* 15.9:1 on ink-900 */
  --paper-200: oklch(0.880 0.006 265); /* 12.0:1 */
  --paper-300: oklch(0.780 0.008 265); /*  8.9:1 — secondary text */
  --paper-400: oklch(0.665 0.010 265); /*  5.7:1 — muted text, min for body */
  --paper-500: oklch(0.545 0.012 265); /*  3.5:1 — non-text UI only */

  /* Accents: shared L 0.62 / C 0.17, hue varies (ShapeIT blue -> violet) */
  --accent-blue:   oklch(0.620 0.170 262);
  --accent-indigo: oklch(0.620 0.170 278);
  --accent-violet: oklch(0.620 0.170 296);
  /* Cyan — the ShapeIT nod. Narrow role: links, live/streaming state, data viz.
     Never a button fill, never a large area. */
  --accent-cyan:        oklch(0.760 0.130 205);
  --accent-cyan-text:   oklch(0.840 0.110 205);
  --accent-cyan-fill:   oklch(0.760 0.130 205 / 0.14);
  /* Legible-on-dark accent text variants */
  --accent-blue-text:   oklch(0.790 0.120 262);
  --accent-violet-text: oklch(0.790 0.120 296);
  /* Solid action fills — darkened so --paper-100 text clears 4.5:1 on them */
  --accent-solid:        oklch(0.480 0.170 268);
  --accent-solid-hover:  oklch(0.540 0.175 268);
  --accent-solid-active: oklch(0.430 0.160 268);
  --danger-solid:        oklch(0.480 0.180 22);
  --danger-solid-hover:  oklch(0.535 0.190 22);
  --danger-solid-active: oklch(0.430 0.170 22);

  /* Tinted fills / hairlines */
  --accent-blue-fill:   oklch(0.620 0.170 262 / 0.14);
  --accent-violet-fill: oklch(0.620 0.170 296 / 0.14);
  --accent-line:        oklch(0.620 0.170 278 / 0.42);
  --accent-gradient: linear-gradient(90deg, var(--accent-blue), var(--accent-violet));
  --accent-gradient-diag: linear-gradient(135deg, oklch(0.620 0.170 262 / 0.22), oklch(0.620 0.170 296 / 0.10));

  /* Semantic — same construction, product meanings */
  --success:        oklch(0.700 0.145 155);
  --success-text:   oklch(0.830 0.120 155);
  --success-fill:   oklch(0.700 0.145 155 / 0.14);
  --warning:        oklch(0.790 0.135 82);
  --warning-text:   oklch(0.880 0.115 82);
  --warning-fill:   oklch(0.790 0.135 82 / 0.14);
  --danger:         oklch(0.630 0.195 22);
  --danger-text:    oklch(0.790 0.140 22);
  --danger-fill:    oklch(0.630 0.195 22 / 0.16);
  --info:           var(--accent-cyan);
  --info-text:      var(--accent-cyan-text);
  --info-fill:      var(--accent-cyan-fill);

  /* Data-viz series — cyan first, then the violet band. Same L, walking hue. */
  --viz-1: oklch(0.760 0.130 205);
  --viz-2: oklch(0.700 0.150 262);
  --viz-3: oklch(0.680 0.160 296);
  --viz-4: oklch(0.720 0.140 330);
  --viz-5: oklch(0.750 0.120 175);
  --viz-grid: oklch(1 0 0 / 0.07);

  /* ── Semantic aliases: use THESE in components ── */
  --surface-canvas:  var(--ink-900);
  --surface-panel:   var(--ink-800);
  --surface-card:    var(--ink-700);
  --surface-raised:  var(--ink-600);
  --surface-sunken:  var(--ink-850);
  --surface-overlay: oklch(0.196 0.014 265 / 0.92);
  --surface-scrim:   oklch(0.100 0.010 265 / 0.72);

  --text-primary:   var(--paper-100);
  --text-body:      var(--paper-200);
  --text-secondary: var(--paper-300);
  --text-muted:     var(--paper-400);
  --text-inverse:   oklch(0.150 0.012 265);
  --text-link:      var(--accent-cyan-text);
  --text-link-hover: var(--paper-100);

  --border-subtle: oklch(1 0 0 / 0.07);
  --border-default: oklch(1 0 0 / 0.11);
  --border-strong: oklch(1 0 0 / 0.20);
  --border-accent: var(--accent-line);

  --control-bg:        oklch(1 0 0 / 0.04);
  --control-bg-hover:  oklch(1 0 0 / 0.075);
  --control-bg-active: oklch(1 0 0 / 0.11);
  --control-disabled-bg: oklch(1 0 0 / 0.03);
  --control-disabled-text: var(--paper-500);
}

/* Light scope — for Service Desk long-reading views and printed output.
   Apply with <div data-theme="light"> or on <html>. */
[data-theme="light"] {
  color-scheme: light;

  --surface-canvas:  oklch(0.985 0.003 265);
  --surface-panel:   oklch(1 0 0);
  --surface-card:    oklch(1 0 0);
  --surface-raised:  oklch(0.975 0.004 265);
  --surface-sunken:  oklch(0.960 0.005 265);
  --surface-overlay: oklch(1 0 0 / 0.95);
  --surface-scrim:   oklch(0.200 0.015 265 / 0.45);

  --text-primary:   oklch(0.200 0.014 265);
  --text-body:      oklch(0.285 0.014 265);
  --text-secondary: oklch(0.400 0.013 265);
  --text-muted:     oklch(0.500 0.012 265);
  --text-inverse:   oklch(0.985 0.003 265);
  --text-link:      oklch(0.470 0.170 262);
  --text-link-hover: oklch(0.360 0.160 262);

  --accent-blue-text:   oklch(0.470 0.170 262);
  --accent-violet-text: oklch(0.470 0.170 296);
  --accent-cyan-text:   oklch(0.470 0.110 205);
  --success-text: oklch(0.440 0.130 155);
  --warning-text: oklch(0.470 0.120 70);
  --danger-text:  oklch(0.500 0.190 22);

  --border-subtle: oklch(0.200 0.014 265 / 0.08);
  --border-default: oklch(0.200 0.014 265 / 0.14);
  --border-strong: oklch(0.200 0.014 265 / 0.26);

  --control-bg:        oklch(0.200 0.014 265 / 0.035);
  --control-bg-hover:  oklch(0.200 0.014 265 / 0.065);
  --control-bg-active: oklch(0.200 0.014 265 / 0.10);
  --control-disabled-bg: oklch(0.200 0.014 265 / 0.04);
  --control-disabled-text: oklch(0.600 0.010 265);
}
/* ── tokens/typography.css ── */
/* Type scale. Console is dense, so the step below 14px exists for metadata
   only — never for reading copy. Line heights are unitless. */
:root {
  --text-2xs: 11px;   /* uppercase eyebrows, table units */
  --text-xs:  12px;   /* metadata, chip labels */
  --text-sm:  13px;   /* dense table cells, console body */
  --text-base:14px;   /* default UI body */
  --text-md:  15px;   /* Service Desk reading copy */
  --text-lg:  17px;
  --text-xl:  20px;
  --text-2xl: 24px;
  --text-3xl: 30px;
  --text-4xl: 38px;
  --text-5xl: 52px;
  --text-6xl: 72px;   /* marketing display only */

  --leading-tight: 1.15;
  --leading-snug: 1.35;
  --leading-normal: 1.5;
  --leading-relaxed: 1.65;

  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --tracking-display: -0.03em;  /* 30px and up */
  --tracking-tight: -0.015em;   /* 17-24px */
  --tracking-normal: 0;
  --tracking-wide: 0.02em;
  --tracking-eyebrow: 0.10em;   /* uppercase 11-12px */

  /* Semantic roles */
  --font-display-1: var(--weight-medium) var(--text-5xl)/var(--leading-tight) var(--font-display);
  --font-display-2: var(--weight-medium) var(--text-4xl)/var(--leading-tight) var(--font-display);
  --font-title-1: var(--weight-semibold) var(--text-2xl)/var(--leading-snug) var(--font-sans);
  --font-title-2: var(--weight-semibold) var(--text-xl)/var(--leading-snug) var(--font-sans);
  --font-title-3: var(--weight-semibold) var(--text-lg)/var(--leading-snug) var(--font-sans);
  --font-body: var(--weight-regular) var(--text-base)/var(--leading-normal) var(--font-sans);
  --font-body-reading: var(--weight-regular) var(--text-md)/var(--leading-relaxed) var(--font-sans);
  --font-label: var(--weight-medium) var(--text-sm)/var(--leading-snug) var(--font-sans);
  --font-meta: var(--weight-regular) var(--text-xs)/var(--leading-snug) var(--font-sans);
  --font-code: var(--weight-regular) var(--text-sm)/var(--leading-snug) var(--font-mono);
}
/* ── tokens/spacing.css ── */
/* 4px base. --density-* are the row heights the two products differ on. */
:root {
  --space-0: 0;
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 12px;
  --space-6: 16px;
  --space-7: 20px;
  --space-8: 24px;
  --space-9: 32px;
  --space-10: 40px;
  --space-11: 56px;
  --space-12: 72px;
  --space-13: 96px;

  --control-h-sm: 28px;
  --control-h-md: 34px;
  --control-h-lg: 40px;

  --row-h-compact: 36px;      /* platform console tables */
  --row-h-comfortable: 48px;  /* Service Desk queues */

  --gutter-page: var(--space-8);
  --gutter-card: var(--space-6);
  --sidebar-w: 232px;
  --sidebar-w-collapsed: 56px;
  --topbar-h: 52px;
  --detail-panel-w: 320px;
  --measure-reading: 68ch;
  --tap-min: 44px;            /* WCAG 2.2 target size floor */
}
/* ── tokens/radius.css ── */
:root {
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;
  --radius-2xl: 28px;
  --radius-pill: 999px;
  --radius-control: var(--radius-sm);
  --radius-card: var(--radius-lg);
  --radius-panel: var(--radius-xl);
  --border-w: 1px;
  --border-w-emphasis: 2px;
}
/* ── tokens/elevation.css ── */
/* Dark UI: separation comes from hairlines + a 1px top highlight, not soft
   drop shadows. Only overlays cast real shadow. */
:root {
  --highlight-top: inset 0 1px 0 oklch(1 0 0 / 0.06);
  --shadow-none: none;
  --shadow-card: var(--highlight-top);
  --shadow-raised: 0 1px 2px oklch(0.10 0.01 265 / 0.40), var(--highlight-top);
  --shadow-popover: 0 8px 24px -6px oklch(0.08 0.01 265 / 0.65), 0 2px 6px oklch(0.08 0.01 265 / 0.40), var(--highlight-top);
  --shadow-dialog: 0 32px 64px -16px oklch(0.06 0.01 265 / 0.80), 0 4px 12px oklch(0.06 0.01 265 / 0.50), var(--highlight-top);
  --glow-accent: 0 0 0 1px var(--accent-line), 0 8px 32px -12px oklch(0.620 0.170 278 / 0.45);
}
[data-theme="light"] {
  --highlight-top: inset 0 1px 0 oklch(1 0 0 / 0.60);
  --shadow-card: 0 1px 2px oklch(0.20 0.015 265 / 0.06);
  --shadow-raised: 0 1px 3px oklch(0.20 0.015 265 / 0.10);
  --shadow-popover: 0 8px 24px -6px oklch(0.20 0.015 265 / 0.16), 0 2px 6px oklch(0.20 0.015 265 / 0.08);
  --shadow-dialog: 0 32px 64px -16px oklch(0.20 0.015 265 / 0.24);
}
/* ── tokens/motion.css ── */
/* Fast, short, no bounce. Nothing decorative moves. */
:root {
  --ease-standard: cubic-bezier(0.2, 0, 0.13, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --duration-instant: 80ms;
  --duration-fast: 120ms;
  --duration-normal: 180ms;
  --duration-slow: 260ms;
  --transition-control: background-color var(--duration-fast) var(--ease-standard),
                        border-color var(--duration-fast) var(--ease-standard),
                        color var(--duration-fast) var(--ease-standard),
                        box-shadow var(--duration-fast) var(--ease-standard);
}
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-instant: 0ms; --duration-fast: 0ms;
    --duration-normal: 0ms; --duration-slow: 0ms;
  }
}
/* ── tokens/focus.css ── */
/* WCAG 2.2 2.4.11/2.4.13: a 2px ring with 2px offset, >=3:1 against both the
   control and the adjacent surface. Never remove it; never rely on colour alone. */
:root {
  --focus-color: oklch(0.800 0.130 275);
  --focus-ring: 0 0 0 var(--border-w-emphasis) var(--focus-color);
  --focus-ring-offset: 0 0 0 var(--border-w-emphasis) var(--surface-canvas),
                       0 0 0 4px var(--focus-color);
  --focus-outline: var(--border-w-emphasis) solid var(--focus-color);
  --focus-outline-offset: 2px;
}
[data-theme="light"] { --focus-color: oklch(0.500 0.180 275); }
/* ── tokens/base.css ── */
/* Minimal reset + document defaults. */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--surface-canvas);
  color: var(--text-body);
  font: var(--font-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5, h6, p, figure, blockquote { margin: 0; }
h1, h2, h3, h4 { color: var(--text-primary); text-wrap: balance; }
p { text-wrap: pretty; }
a { color: var(--text-link); text-decoration-color: color-mix(in oklab, currentColor 40%, transparent); text-underline-offset: 2px; }
a:hover { color: var(--text-link-hover); text-decoration-color: currentColor; }
button, input, select, textarea { font: inherit; color: inherit; }
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-outline-offset);
  border-radius: var(--radius-xs);
}
::selection { background: var(--accent-violet-fill); color: var(--text-primary); }
::placeholder { color: var(--text-muted); }
[hidden] { display: none !important; }
code, kbd, samp, pre { font: var(--font-code); }
hr { border: 0; border-top: var(--border-w) solid var(--border-subtle); margin: 0; }
table { border-collapse: collapse; }
:where(svg) { flex: none; }
.vm-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Tap-target floor (WCAG 2.2). On coarse pointers every button, [role="button"]
   and .vm-tap control grows an invisible centred pseudo-element so its hit box
   reaches --tap-min (44px). Layout and paint move by zero pixels; fine pointers
   are untouched. Native input/select/textarea cannot host pseudo-elements —
   consuming apps raise those to --tap-min under the same media query instead.
   A control nested inside another control (Tag's remove ×) never grows: the
   parent is the guaranteed 44px target. Adjacency rule: keep ≥8px between the
   visible edges of sm controls and ≥12px between stacked checkboxes/radios,
   otherwise a LATER sibling's halo covers an EARLIER sibling's visible box and
   steals its taps. See guidelines/tap-targets.card.html. */
@media (pointer: coarse) {
  :where(button, [role="button"], .vm-tap) { position: relative; }
  :where(button, [role="button"], .vm-tap)::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: max(100%, var(--tap-min));
    height: max(100%, var(--tap-min));
    transform: translate(-50%, -50%);
  }
  /* Never inside another control — the parent owns the halo. */
  :where(button, [role="button"], .vm-tap) :where(button, [role="button"], .vm-tap)::after {
    content: none;
  }
}
