/* @netcomposer/nc-ui: generated by scripts/build-dist.mjs from tokens/tokens.json and src/. Do not edit. */
/* Generated by scripts/build-tokens.mjs from tokens/tokens.json. Do not edit by hand.
   nc-ui was created by Peter Semmelhack (https://psem.me/). MIT License. */

:root {
  /* Tier 1: base values */
  /* color */
  --nc-ui-color-paper: #F5F5F5;
  --nc-ui-color-ink: #242424;
  --nc-ui-color-ink-label: var(--nc-ui-color-ink);
  --nc-ui-color-white: #FFFFFF;
  --nc-ui-color-ivory: #FBFBFB;
  --nc-ui-color-surf: #EAEAEA;
  --nc-ui-color-accent: #003153;
  --nc-ui-color-accent-wash: color-mix(in srgb, var(--nc-ui-color-accent) 7%, transparent);
  --nc-ui-color-astrid-orange: #EB512E;
  --nc-ui-color-petra-blue: #5AC4F7;
  --nc-ui-color-olive-green: #9CA536;
  --nc-ui-color-lucy-purple: #9B30FF;
  --nc-ui-color-paper-bright: #FCFCFC;
  --nc-ui-color-accent-pad: #1A6193;
  --nc-ui-color-accent-velocity-min: #477399;
  --nc-ui-color-shade-1: #F3F3F3;
  --nc-ui-color-shade-2: #EEEEEE;
  --nc-ui-color-shade-3: #E9E9E9;
  --nc-ui-color-shade-4: #E4E4E4;
  --nc-ui-color-shade-5: #FAFAFA;
  --nc-ui-color-shade-6: #EDEDED;
  --nc-ui-color-shade-7: #E0E0E0;
  --nc-ui-color-shade-8: #D3D3D3;
  --nc-ui-color-sub-0: #595959;
  --nc-ui-color-sub-1: #575757;
  --nc-ui-color-sub-2: #555555;
  --nc-ui-color-sub-3: #535353;
  --nc-ui-color-sub-4: #515151;
  --nc-ui-color-div-0: #DDDDDD;
  --nc-ui-color-div-1: #F2F2F2;
  --nc-ui-color-div-2: #E5E5E5;
  --nc-ui-color-div-3: #D8D8D8;
  --nc-ui-color-div-4: #CCCCCC;
  --nc-ui-color-drawer: #F1F1F1;
  --nc-ui-color-mf-1: #F2F2F2;
  --nc-ui-color-mf-2: #EFEFEF;
  --nc-ui-color-mf-3: #ECECEC;
  --nc-ui-color-mf-4: #E8E8E8;
  --nc-ui-color-skeleton-hi: #F0F0F0;
  --nc-ui-color-map-off: #9F9F9F;
  --nc-ui-color-red: hsl(8 55% 44%);
  --nc-ui-color-red-soft: hsl(8 55% 44% / .5);
  --nc-ui-color-red-tension: #A04A3F;
  --nc-ui-color-amber: #9A6B34;
  --nc-ui-color-amber-stale: hsl(38 50% 38%);
  --nc-ui-color-slate: #56688C;
  --nc-ui-color-plum: #774A84;
  --nc-ui-color-filter-blue: #3E6FB0;
  --nc-ui-color-filter-accent: color-mix(in srgb, var(--nc-ui-color-accent) 80%, var(--nc-ui-color-paper));
  --nc-ui-color-filter-red: #B8443A;
  --nc-ui-color-tw-gray-50: oklch(98.5% 0.002 247.839);
  --nc-ui-color-tw-gray-100: oklch(96.7% 0.003 264.542);
  --nc-ui-color-tw-gray-600: oklch(44.6% 0.03 256.802);
  --nc-ui-color-tw-gray-700: oklch(37.3% 0.034 259.733);
  --nc-ui-color-tw-gray-800: oklch(27.8% 0.033 256.848);
  --nc-ui-color-tw-gray-900: oklch(21% 0.034 264.665);
  --nc-ui-color-tw-red-500: oklch(63.7% 0.237 25.331);
  --nc-ui-color-tw-red-600: oklch(57.7% 0.245 27.325);
  --nc-ui-color-tw-red-700: oklch(50.5% 0.213 27.518);
  --nc-ui-color-tw-red-50: oklch(97.1% 0.013 17.38);
  --nc-ui-color-tw-red-300: oklch(80.8% 0.114 19.571);
  --nc-ui-color-tw-red-400: oklch(70.4% 0.191 22.216);
  --nc-ui-color-black: #000000;
  /* font-family */
  --nc-ui-font-family-sans: 'Inter', 'Geist', sans-serif;
  --nc-ui-font-family-mono: 'IBM Plex Mono', monospace;
  --nc-ui-font-family-mono-generic: monospace;
  /* font-size */
  --nc-ui-font-size-4xs: 8px;
  --nc-ui-font-size-3xs: 9px;
  --nc-ui-font-size-2xs: 10px;
  --nc-ui-font-size-2xs-plus: 10.5px;
  --nc-ui-font-size-xs: 11px;
  --nc-ui-font-size-sm: 12px;
  --nc-ui-font-size-md: 13px;
  --nc-ui-font-size-lg: 14px;
  --nc-ui-font-size-xl: 15px;
  --nc-ui-font-size-2xl: 18px;
  --nc-ui-font-size-3xl: 20px;
  --nc-ui-font-size-4xl: 24px;
  /* font-weight */
  --nc-ui-font-weight-regular: 400;
  --nc-ui-font-weight-medium: 500;
  --nc-ui-font-weight-semibold: 600;
  --nc-ui-font-weight-bold: 700;
  /* tracking */
  --nc-ui-tracking-1: .06em;
  --nc-ui-tracking-2: .08em;
  --nc-ui-tracking-3: .1em;
  --nc-ui-tracking-4: .12em;
  --nc-ui-tracking-5: .14em;
  --nc-ui-tracking-6: 0.15em;
  --nc-ui-tracking-7: .2em;
  --nc-ui-tracking-8: .28em;
  --nc-ui-tracking-grip: -.22em;
  --nc-ui-tracking-tight: -.01em;
  --nc-ui-tracking-normal: 0em;
  --nc-ui-tracking-tw-tight: -0.025em;
  /* leading */
  --nc-ui-leading-none: 1;
  --nc-ui-leading-readout: 1.35;
  --nc-ui-leading-snug: 1.375;
  --nc-ui-leading-body: 1.55;
  --nc-ui-leading-relaxed: 1.625;
  --nc-ui-leading-slot: 12px;
  --nc-ui-leading-tw-xs: calc(1 / 0.75);
  --nc-ui-leading-tw-sm: calc(1.25 / 0.875);
  --nc-ui-leading-tw-xl: calc(1.75 / 1.25);
  --nc-ui-leading-tw-2xl: calc(2 / 1.5);
  --nc-ui-leading-tight: 1.25;
  --nc-ui-leading-normal: 1.5;
  --nc-ui-leading-tw-base: calc(1.5 / 1);
  --nc-ui-leading-tw-lg: calc(1.75 / 1.125);
  /* space */
  --nc-ui-space-1: 1px;
  --nc-ui-space-2: 2px;
  --nc-ui-space-3: 3px;
  --nc-ui-space-4: 4px;
  --nc-ui-space-5: 5px;
  --nc-ui-space-6: 6px;
  --nc-ui-space-7: 7px;
  --nc-ui-space-8: 8px;
  --nc-ui-space-10: 10px;
  --nc-ui-space-12: 12px;
  --nc-ui-space-14: 14px;
  --nc-ui-space-16: 16px;
  --nc-ui-space-18: 18px;
  --nc-ui-space-20: 20px;
  --nc-ui-space-24: 24px;
  --nc-ui-space-28: 28px;
  --nc-ui-space-32: 32px;
  --nc-ui-space-40: 40px;
  --nc-ui-space-44: 44px;
  --nc-ui-space-48: 48px;
  --nc-ui-space-64: 64px;
  --nc-ui-space-unit: 0.25rem;
  /* radius */
  --nc-ui-radius-none: 0;
  --nc-ui-radius-xs: 2px;
  --nc-ui-radius-round: 50%;
  /* border */
  --nc-ui-border-hairline: 1px;
  --nc-ui-border-thick: 2px;
  /* stroke */
  --nc-ui-stroke-hairline: 1;
  --nc-ui-stroke-fine: 1.25;
  --nc-ui-stroke-curve: 1.4;
  --nc-ui-stroke-bold: 1.5;
  --nc-ui-stroke-dot: 7;
  /* easing */
  --nc-ui-easing-ease: ease;
  --nc-ui-easing-ease-out: ease-out;
  --nc-ui-easing-linear: linear;
  /* duration */
  --nc-ui-duration-meter: .07s;
  --nc-ui-duration-meter-rise: 0s;
  --nc-ui-duration-meter-fall: .2s;
  --nc-ui-duration-meter-hold: 1.5s;
  --nc-ui-duration-press: .1s;
  --nc-ui-duration-fast: .15s;
  --nc-ui-duration-fade: .2s;
  --nc-ui-duration-drawer: .22s;
  --nc-ui-duration-trig: .25s;
  --nc-ui-duration-shimmer: 1.4s;
  /* opacity */
  --nc-ui-opacity-30: .3;
  --nc-ui-opacity-35: .35;
  --nc-ui-opacity-40: .4;
  --nc-ui-opacity-45: .45;
  --nc-ui-opacity-55: .55;
  --nc-ui-opacity-60: .6;
  --nc-ui-opacity-70: .7;
  --nc-ui-opacity-75: .75;
  --nc-ui-opacity-80: .8;
  /* breakpoint */
  --nc-ui-breakpoint-md: 768px;
  --nc-ui-breakpoint-desktop: 1024px;
  --nc-ui-breakpoint-wide: 1280px;
  --nc-ui-breakpoint-drawer-push: 1920px;
  --nc-ui-breakpoint-row-min: 360px;
  /* legacy */
  --nc-ui-legacy-background: 0 0% 95.7%;
  --nc-ui-legacy-foreground: 0 0% 13.3%;
  --nc-ui-legacy-border: 0 0% 86.7%;
  --nc-ui-legacy-card: 0 0% 91.4%;
  --nc-ui-legacy-primary: 205 100% 16%;
  --nc-ui-legacy-muted-foreground: 0 0% 34.9%;
  --nc-ui-legacy-destructive: 8 55% 44%;
  --nc-ui-legacy-chart-3: 0 0% 76.9%;
  --nc-ui-legacy-outline-light: rgba(0, 0, 0, 0.1);
  --nc-ui-legacy-outline-light-faint: rgba(0, 0, 0, 0.05);
  --nc-ui-legacy-outline-dark: rgba(255, 255, 255, 0.1);
  --nc-ui-legacy-outline-dark-faint: rgba(255, 255, 255, 0.05);
  --nc-ui-legacy-elevate-1-light: rgba(0, 0, 0, 0.03);
  --nc-ui-legacy-elevate-2-light: rgba(0, 0, 0, 0.08);
  --nc-ui-legacy-elevate-1-dark: rgba(255, 255, 255, 0.04);
  --nc-ui-legacy-elevate-2-dark: rgba(255, 255, 255, 0.09);
  --nc-ui-legacy-shadow-color: hsl(202.8169 89.1213% 53.1373% / 0);
  --nc-ui-legacy-font-sans: 'Inter', sans-serif;
  --nc-ui-legacy-radius: 0.5rem;
  --nc-ui-legacy-text-xs: 0.75rem;
  --nc-ui-legacy-text-sm: 0.875rem;
  --nc-ui-legacy-text-base: 1rem;
  --nc-ui-legacy-text-lg: 1.125rem;
  --nc-ui-legacy-text-xl: 1.25rem;
  --nc-ui-legacy-text-2xl: 1.5rem;
  --nc-ui-legacy-font-serif: Georgia, serif;

  /* Tier 2: semantic roles (use these in modules) */
  --nc-ui-surface-page: var(--nc-ui-color-paper);
  --nc-ui-text: var(--nc-ui-color-ink);
  --nc-ui-text-sub: var(--nc-ui-color-sub-0);
  --nc-ui-divider: var(--nc-ui-color-div-0);
  --nc-ui-surface-raised: var(--nc-ui-color-surf);
  --nc-ui-accent: var(--nc-ui-color-accent);
  --nc-ui-accent-tint: color-mix(in srgb, var(--nc-ui-color-accent) 12%, var(--nc-ui-color-paper));
  --nc-ui-accent-soft: color-mix(in srgb, var(--nc-ui-color-accent) 10%, transparent);
  --nc-ui-accent-faint: color-mix(in srgb, var(--nc-ui-color-accent) 35%, transparent);
  --nc-ui-on-accent: var(--nc-ui-color-paper);
  --nc-ui-danger: var(--nc-ui-color-red);
  --nc-ui-danger-soft: var(--nc-ui-color-red-soft);
  --nc-ui-warning: var(--nc-ui-color-amber);
  --nc-ui-warning-text: var(--nc-ui-color-amber-stale);
  --nc-ui-module-bg-adjacent-1: var(--nc-ui-color-shade-1);
  --nc-ui-module-bg-adjacent-2: var(--nc-ui-color-shade-2);
  --nc-ui-module-bg-adjacent-3: var(--nc-ui-color-shade-3);
  --nc-ui-module-bg-adjacent-4: var(--nc-ui-color-shade-4);
  --nc-ui-module-bg-stack-1: var(--nc-ui-color-shade-5);
  --nc-ui-module-bg-stack-2: var(--nc-ui-color-shade-6);
  --nc-ui-module-bg-stack-3: var(--nc-ui-color-shade-7);
  --nc-ui-module-bg-stack-4: var(--nc-ui-color-shade-8);
  --nc-ui-module-sub-stack-1: var(--nc-ui-color-sub-1);
  --nc-ui-module-sub-stack-2: var(--nc-ui-color-sub-2);
  --nc-ui-module-sub-stack-3: var(--nc-ui-color-sub-3);
  --nc-ui-module-sub-stack-4: var(--nc-ui-color-sub-4);
  --nc-ui-module-div-stack-1: var(--nc-ui-color-div-1);
  --nc-ui-module-div-stack-2: var(--nc-ui-color-div-2);
  --nc-ui-module-div-stack-3: var(--nc-ui-color-div-3);
  --nc-ui-module-div-stack-4: var(--nc-ui-color-div-4);
  --nc-ui-module-pad: var(--nc-ui-space-24);
  --nc-ui-module-pad-y-desktop: var(--nc-ui-space-28);
  --nc-ui-module-pad-x-desktop: var(--nc-ui-space-32);
  --nc-ui-module-pad-x-slim: var(--nc-ui-space-14);
  --nc-ui-module-slim-column: 120px;
  --nc-ui-stack-card-pad-y: var(--nc-ui-space-20);
  --nc-ui-section-gap: var(--nc-ui-space-48);
  --nc-ui-section-rule-gap: var(--nc-ui-space-40);
  --nc-ui-font-ui: var(--nc-ui-font-family-sans);
  --nc-ui-font-readout: var(--nc-ui-font-family-mono);
  --nc-ui-title-size: var(--nc-ui-font-size-4xl);
  --nc-ui-title-size-slim: var(--nc-ui-font-size-2xl);
  --nc-ui-title-weight: var(--nc-ui-font-weight-regular);
  --nc-ui-title-tracking: var(--nc-ui-tracking-tight);
  --nc-ui-label-size: var(--nc-ui-font-size-xs);
  --nc-ui-label-weight: var(--nc-ui-font-weight-medium);
  --nc-ui-label-tracking: var(--nc-ui-tracking-5);
  --nc-ui-readout-size: var(--nc-ui-font-size-sm);
  --nc-ui-readout-size-small: var(--nc-ui-font-size-xs);
  --nc-ui-body-size: var(--nc-ui-font-size-md);
  --nc-ui-slider-track: var(--nc-ui-color-div-0);
  --nc-ui-slider-progress: var(--nc-ui-color-accent);
  --nc-ui-slider-thumb: var(--nc-ui-color-ink);
  --nc-ui-slider-thumb-size: 11px;
  --nc-ui-focus-ring: var(--nc-ui-color-accent);
  --nc-ui-playhead: var(--nc-ui-color-accent);
  --nc-ui-playhead-width: var(--nc-ui-border-thick);
  --nc-ui-playhead-offset: var(--nc-ui-border-hairline);
  --nc-ui-slot-size: 14px;
  --nc-ui-slot-span: 60px;
  --nc-ui-slot-block: var(--nc-ui-space-48);
  --nc-ui-beat-gap: var(--nc-ui-space-8);
  --nc-ui-row-inset: var(--nc-ui-space-8);
  --nc-ui-marker-width: var(--nc-ui-space-4);
  --nc-ui-slot-radius: var(--nc-ui-radius-xs);
  --nc-ui-slot-gap: var(--nc-ui-space-2);
  --nc-ui-slot-font-size: var(--nc-ui-font-size-3xs);
  --nc-ui-slot-filled-bg: var(--nc-ui-color-surf);
  --nc-ui-slot-active-bg: var(--nc-ui-color-accent);
  --nc-ui-slot-active-ink: var(--nc-ui-color-paper);
  --nc-ui-slot-dot: 3px;
  --nc-ui-slot-dot-playing: 5px;
  --nc-ui-sparkle-size: 14px;
  --nc-ui-sparkle-icon-size: 12px;
  --nc-ui-label-on-fill-dark: var(--nc-ui-color-ink-label);
  --nc-ui-label-on-fill-light: var(--nc-ui-color-white);
  --nc-ui-skeleton-highlight: var(--nc-ui-color-skeleton-hi);
  --nc-ui-transition-feedback: var(--nc-ui-duration-fast);
  --nc-ui-motion-fade: var(--nc-ui-duration-fade);
  --nc-ui-motion-fade-easing: var(--nc-ui-easing-ease);
  --nc-ui-motion-fade-out: var(--nc-ui-duration-trig);
  --nc-ui-motion-fade-out-easing: var(--nc-ui-easing-ease-out);
  --nc-ui-motion-slide: var(--nc-ui-duration-drawer);
  --nc-ui-motion-slide-easing: var(--nc-ui-easing-ease-out);
  --nc-ui-motion-press-easing: var(--nc-ui-easing-ease-out);
  --nc-ui-motion-thumb: var(--nc-ui-duration-fast);
  --nc-ui-motion-thumb-easing: var(--nc-ui-easing-ease);
  --nc-ui-motion-meter-rise: var(--nc-ui-duration-meter-rise);
  --nc-ui-motion-meter-fall: var(--nc-ui-duration-meter-fall);
  --nc-ui-motion-meter-easing: var(--nc-ui-easing-linear);
  --nc-ui-motion-meter-hold: var(--nc-ui-duration-meter-hold);
  --nc-ui-meter-fill: var(--nc-ui-color-accent-pad);
  --nc-ui-meter-peak: color-mix(in srgb, var(--nc-ui-color-accent-pad) 40%, transparent);
  --nc-ui-meter-hold-mark: var(--nc-ui-color-accent);
  --nc-ui-meter-clip: var(--nc-ui-color-red);
  --nc-ui-meter-track: var(--nc-ui-color-div-0);
  --nc-ui-meter-width: var(--nc-ui-space-8);
  --nc-ui-clip-size: var(--nc-ui-space-6);
  --nc-ui-fader-height: 220px;
  --nc-ui-fader-cap-width: var(--nc-ui-space-28);
  --nc-ui-fader-cap-height: var(--nc-ui-space-14);
  --nc-ui-fader-cap: var(--nc-ui-color-ink);
  --nc-ui-fader-cap-line: var(--nc-ui-color-paper);
  --nc-ui-fader-cap-master: var(--nc-ui-color-accent);
  --nc-ui-fader-track: color-mix(in srgb, var(--nc-ui-color-ink) 25%, transparent);
  --nc-ui-strip-width: 88px;
  --nc-ui-strip-width-master: 112px;
  --nc-ui-fx-card-width: 232px;
  --nc-ui-head-margin-compact: var(--nc-ui-space-12);
  --nc-ui-scale-size: var(--nc-ui-font-size-3xs);
  --nc-ui-focus-width: var(--nc-ui-border-hairline);
  --nc-ui-focus-width-strong: var(--nc-ui-border-thick);
  --nc-ui-target-min: var(--nc-ui-space-44);
  --nc-ui-target-min-coarse: var(--nc-ui-space-44);
  --nc-ui-hairline: var(--nc-ui-border-hairline);
  --nc-ui-rule-strong: var(--nc-ui-border-thick);
  --nc-ui-trigger-dot: 6px;
  --nc-ui-filter-lowpass: var(--nc-ui-color-filter-blue);
  --nc-ui-filter-highpass: var(--nc-ui-color-filter-accent);
  --nc-ui-filter-bandpass: var(--nc-ui-color-filter-red);
  --nc-ui-curve-stroke: var(--nc-ui-stroke-bold);
  --nc-ui-trace-stroke: var(--nc-ui-stroke-fine);
  --nc-ui-grid-stroke: var(--nc-ui-stroke-hairline);
  --nc-ui-toast-bg: var(--nc-ui-color-ink);
  --nc-ui-toast-text: var(--nc-ui-color-paper);
  --nc-ui-toast-action: var(--nc-ui-color-white);
  --nc-ui-toast-font-size: var(--nc-ui-font-size-sm);
  --nc-ui-toast-pad-x: var(--nc-ui-space-16);
  --nc-ui-toast-gap: var(--nc-ui-space-8);
  --nc-ui-toast-radius: var(--nc-ui-radius-xs);
  --nc-ui-toast-offset: var(--nc-ui-space-16);
  --nc-ui-toast-anchor-gap: var(--nc-ui-space-8);
  --nc-ui-toast-target: var(--nc-ui-space-44);
  --nc-ui-on-danger: var(--nc-ui-color-paper);
  --nc-ui-dialog-scrim: color-mix(in srgb, var(--nc-ui-color-ink) 35%, transparent);
  --nc-ui-dialog-width: 320px;
  --nc-ui-dialog-pad: var(--nc-ui-space-16);
  --nc-ui-dialog-gap: var(--nc-ui-space-12);
  --nc-ui-dialog-button-gap: var(--nc-ui-space-8);
  --nc-ui-dialog-radius: var(--nc-ui-radius-xs);
  --nc-ui-dialog-leading: var(--nc-ui-leading-readout);
  --nc-ui-module-gap: var(--nc-ui-space-8);
  --nc-ui-control-gap: var(--nc-ui-space-4);
  --nc-ui-header-gap: var(--nc-ui-space-12);
  --nc-ui-head-margin: var(--nc-ui-space-32);
  --nc-ui-name-width: var(--nc-ui-space-48);
  --nc-ui-slider-pitch: var(--nc-ui-space-20);
  --nc-ui-knob-size: var(--nc-ui-space-20);
  --nc-ui-display-height: 96px;
  --nc-ui-button-tracking: var(--nc-ui-tracking-7);
  --nc-ui-button-pad-y: var(--nc-ui-space-12);
  --nc-ui-fx-name-weight: var(--nc-ui-font-weight-bold);
  --nc-ui-label-leading: var(--nc-ui-leading-readout);
  --nc-ui-motion-press: var(--nc-ui-duration-press);
  --nc-ui-control-weight: var(--nc-ui-font-weight-regular);
  --nc-ui-tab-size: var(--nc-ui-font-size-sm);
  --nc-ui-tab-pad-y: var(--nc-ui-space-6);
  --nc-ui-tab-mark: var(--nc-ui-border-thick);
  --nc-ui-select-pad-end: var(--nc-ui-space-18);
  --nc-ui-page-head-layer: 20;
  --nc-ui-page-head-bg: var(--nc-ui-color-paper-bright);
  --nc-ui-instrument-astrid: var(--nc-ui-color-astrid-orange);
  --nc-ui-instrument-petra: var(--nc-ui-color-petra-blue);
  --nc-ui-instrument-olive: var(--nc-ui-color-olive-green);
  --nc-ui-instrument-lucy: var(--nc-ui-color-lucy-purple);
  --nc-ui-page-title-size: var(--nc-ui-font-size-xl);
  --nc-ui-page-title-tracking: var(--nc-ui-tracking-8);
  --nc-ui-page-sub-size: var(--nc-ui-font-size-lg);
  --nc-ui-page-sub-gap: var(--nc-ui-space-8);
  --nc-ui-page-action-gap: var(--nc-ui-space-24);
  --nc-ui-page-pad-x: var(--nc-ui-space-24);
  --nc-ui-page-pad-x-md: var(--nc-ui-space-48);
  --nc-ui-page-pad-x-xl: var(--nc-ui-space-64);
  --nc-ui-page-pad-y: var(--nc-ui-space-32);
  --nc-ui-page-pad-y-md: var(--nc-ui-space-48);
  --nc-ui-page-head-gap: var(--nc-ui-space-32);
  --nc-ui-page-head-gap-md: var(--nc-ui-space-48);
  --nc-ui-page-body-gap: var(--nc-ui-space-16);
  --nc-ui-page-body-gap-lg: var(--nc-ui-space-48);

  /* Tier 3: component roles, one namespace per domain (a module uses only its own domain) */
  /* synth */
  --nc-synth-key-white: var(--nc-ui-color-ivory);
  --nc-synth-key-black: var(--nc-ui-text);
  --nc-synth-key-hint-on-dark: var(--nc-ui-color-paper);
  --nc-synth-key-held-base: var(--nc-ui-color-white);
  --nc-synth-keybed-height: 64px;
  --nc-synth-curve-label-font: var(--nc-ui-font-family-mono-generic);
  --nc-synth-curve-label-size: var(--nc-ui-font-size-4xs);
  --nc-synth-slim-curve-width: 48px;
  /* meaning */
  --nc-meaning-area-1: var(--nc-ui-color-mf-1);
  --nc-meaning-area-2: var(--nc-ui-color-mf-2);
  --nc-meaning-area-3: var(--nc-ui-color-mf-3);
  --nc-meaning-area-4: var(--nc-ui-color-mf-4);
  --nc-meaning-intimacy: var(--nc-ui-accent);
  --nc-meaning-energy: var(--nc-ui-color-amber);
  --nc-meaning-tension: var(--nc-ui-color-red-tension);
  --nc-meaning-ambiguity: var(--nc-ui-color-slate);
  --nc-meaning-movement: var(--nc-ui-color-plum);
  --nc-meaning-highlight: var(--nc-ui-color-accent-wash);
  /* situation */
  --nc-situation-drawer-bg: var(--nc-ui-color-drawer);
  --nc-situation-drawer-width: 600px;
  --nc-situation-map-marker-off: var(--nc-ui-color-map-off);
  --nc-situation-chart-tick-size: var(--nc-ui-font-size-2xs);
  --nc-situation-chart-tooltip-size: var(--nc-ui-font-size-xs);
  /* rhythm */
  --nc-rhythm-step-cell-off: var(--nc-ui-surface-page);
  --nc-rhythm-step-cell-on: var(--nc-ui-color-accent-pad);
  --nc-rhythm-step-cell-ink: var(--nc-ui-on-accent);
  --nc-rhythm-step-cell-accent: var(--nc-ui-text);
  --nc-rhythm-step-cell-size: var(--nc-ui-slot-size);
  --nc-rhythm-step-gap: var(--nc-ui-slot-gap);
  --nc-rhythm-playhead: var(--nc-ui-playhead);
  --nc-rhythm-track-mute: var(--nc-ui-text-sub);
  --nc-rhythm-track-solo: var(--nc-ui-accent);
  --nc-rhythm-velocity-bar: var(--nc-ui-accent);
  --nc-rhythm-velocity-min: var(--nc-ui-color-accent-velocity-min);
  --nc-rhythm-velocity-max: var(--nc-ui-color-accent);
  --nc-rhythm-accent-mark: var(--nc-ui-on-accent);
  --nc-rhythm-accent-mark-size: var(--nc-ui-space-3);
  --nc-rhythm-bar-accent: var(--nc-ui-text);
  --nc-rhythm-lane-1: var(--nc-ui-color-ink);
  --nc-rhythm-lane-2: var(--nc-ui-color-accent);
  --nc-rhythm-lane-3: var(--nc-ui-color-amber);
  --nc-rhythm-lane-4: var(--nc-ui-color-sub-0);
  --nc-rhythm-sparkle-gap: var(--nc-ui-space-6);
  --nc-rhythm-morph-max: var(--nc-ui-space-40);
  --nc-rhythm-morph-min: var(--nc-ui-space-24);
  --nc-rhythm-morph-readout: 34px;
  --nc-rhythm-brand-size: var(--nc-ui-font-size-xl);
  --nc-rhythm-brand-tracking: var(--nc-ui-tracking-8);
  --nc-rhythm-brand-weight: var(--nc-ui-font-weight-medium);
  --nc-rhythm-brand-sub-size: var(--nc-ui-font-size-lg);
  --nc-rhythm-brand-sub-gap: var(--nc-ui-space-8);

  /* Runtime: defaults; code may override them on an element (see src/color.js) */
  --nc-ui-surprise-fill: var(--nc-ui-color-surf);
  --nc-ui-surprise-ink: var(--nc-ui-color-ink);
  --nc-ui-surprise-on: var(--nc-ui-color-accent);
  --nc-ui-surprise-on-ink: var(--nc-ui-color-paper);
  --nc-ui-velocity-fill: var(--nc-ui-color-accent-pad);
}

/* kit: kitCss() */
*, *::before, *::after { box-sizing: border-box; }
html, body {
  margin: 0;
  background: var(--nc-ui-surface-page);
  color: var(--nc-ui-text);
  font-family: var(--nc-ui-font-ui);
  font-size: var(--nc-ui-body-size);
  font-weight: var(--nc-ui-title-weight);
  line-height: var(--nc-ui-label-leading);
}
button, input, select { font: inherit; color: inherit; }
.nc [hidden] { display: none !important; }
.nc-stack { display: flex; flex-direction: column; min-width: 0; }
/* ASTRID's page frame: side gutters, a header with a divider under it, then the modules, inset from the edges. */
.nc-page {
  min-width: 0;
  padding: var(--nc-ui-page-pad-y) var(--nc-ui-page-pad-x);
}
.nc-page-hd {
  display: flex;
  flex-direction: column;
  gap: var(--nc-ui-page-action-gap);
  min-width: 0;
  padding-bottom: var(--nc-ui-page-head-gap);
  border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  position: relative;
  /* Its own layer above the page body: the band sits behind the header's content, and a menu that opens from the
     header (Bass's and Rhythm's phone menu) draws over the modules, not under them. */
  z-index: var(--nc-ui-page-head-layer);
}
/* The title band (Peter): page-head-bg from the top of the page down to the header's divider, edge to edge. It
   reaches into the page's padding, so it never widens the page; the divider keeps its inset. */
.nc-page-hd::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: calc(var(--nc-ui-page-pad-y) * -1);
  bottom: 0;
  left: calc(var(--nc-ui-page-pad-x) * -1);
  right: calc(var(--nc-ui-page-pad-x) * -1);
  background: var(--nc-ui-page-head-bg);
  pointer-events: none;
}
.nc-page-body { min-width: 0; padding-top: var(--nc-ui-page-body-gap); }
/* Page title (ASTRID: "ASTRID / SYNTH / 01"), the line under it, and the header's text actions (Save, Load, Panic). */
.nc-page-title {
  margin: 0;
  font-size: var(--nc-ui-page-title-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-page-title-tracking);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nc-page-sub { margin: var(--nc-ui-page-sub-gap) 0 0; font-size: var(--nc-ui-page-sub-size); color: var(--nc-ui-text-sub); }
.nc-page-title .nc-page-sep { color: var(--nc-ui-text-sub); }
.nc-page-actions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--nc-ui-control-gap) var(--nc-ui-page-action-gap); min-width: 0; }
.nc-page-action {
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid transparent;
  background: transparent;
  padding: 0 0 var(--nc-ui-control-gap);
  color: var(--nc-ui-text-sub);
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-control-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition-property: color, border-color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-page-action:hover { color: var(--nc-ui-text); border-bottom-color: var(--nc-ui-text); }
.nc-page-action:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-control-gap); }
.nc-module {
  background: var(--nc-ui-module-bg-adjacent-1);
  color: var(--nc-ui-text);
  padding: var(--nc-ui-module-pad);
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  border-radius: 0;
  min-width: 0;
  position: relative;
  font-family: var(--nc-ui-font-ui);
  transition: none;
}
.nc-module[data-nc-place="adjacent"][data-nc-shade="1"] { background: var(--nc-ui-module-bg-adjacent-1); }
.nc-module[data-nc-place="adjacent"][data-nc-shade="2"] { background: var(--nc-ui-module-bg-adjacent-2); }
.nc-module[data-nc-place="adjacent"][data-nc-shade="3"] { background: var(--nc-ui-module-bg-adjacent-3); }
.nc-module[data-nc-place="adjacent"][data-nc-shade="4"] { background: var(--nc-ui-module-bg-adjacent-4); }

    .nc-module[data-nc-place="stack"][data-nc-shade="1"],
    .nc-ui-fx[data-nc-depth="1"] {
      background: var(--nc-ui-module-bg-stack-1);
      --nc-ui-text-sub: var(--nc-ui-module-sub-stack-1);
      --nc-ui-divider: var(--nc-ui-module-div-stack-1);
      --nc-ui-slider-track: var(--nc-ui-module-div-stack-1);
    }

    .nc-module[data-nc-place="stack"][data-nc-shade="2"],
    .nc-ui-fx[data-nc-depth="2"] {
      background: var(--nc-ui-module-bg-stack-2);
      --nc-ui-text-sub: var(--nc-ui-module-sub-stack-2);
      --nc-ui-divider: var(--nc-ui-module-div-stack-2);
      --nc-ui-slider-track: var(--nc-ui-module-div-stack-2);
    }

    .nc-module[data-nc-place="stack"][data-nc-shade="3"],
    .nc-ui-fx[data-nc-depth="3"] {
      background: var(--nc-ui-module-bg-stack-3);
      --nc-ui-text-sub: var(--nc-ui-module-sub-stack-3);
      --nc-ui-divider: var(--nc-ui-module-div-stack-3);
      --nc-ui-slider-track: var(--nc-ui-module-div-stack-3);
    }

    .nc-module[data-nc-place="stack"][data-nc-shade="4"],
    .nc-ui-fx[data-nc-depth="4"] {
      background: var(--nc-ui-module-bg-stack-4);
      --nc-ui-text-sub: var(--nc-ui-module-sub-stack-4);
      --nc-ui-divider: var(--nc-ui-module-div-stack-4);
      --nc-ui-slider-track: var(--nc-ui-module-div-stack-4);
    }
.nc-module[data-nc-shade="1"] .nc-section[data-nc-inset="true"] { background: var(--nc-ui-module-bg-adjacent-2); }
.nc-module[data-nc-shade="2"] .nc-section[data-nc-inset="true"] { background: var(--nc-ui-module-bg-adjacent-3); }
.nc-module[data-nc-shade="3"] .nc-section[data-nc-inset="true"] { background: var(--nc-ui-module-bg-adjacent-4); }
.nc-module[data-nc-shade="4"] .nc-section[data-nc-inset="true"] {
      background: var(--nc-ui-module-bg-stack-1);
      --nc-ui-text-sub: var(--nc-ui-module-sub-stack-1);
      --nc-ui-divider: var(--nc-ui-module-div-stack-1);
    }
.nc-module-hd {
  display: flex;
  flex-wrap: nowrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--nc-ui-header-gap);
  min-width: 0;
}
.nc-module[data-nc-open="true"] .nc-module-hd { margin-bottom: var(--nc-ui-head-margin); }
/* A compact header (defineModule compact): the title at the slim size and the index on one slim line, a small gap
   under it. For a module that sits over others (the Studio's Mix). */
.nc-module[data-nc-compact] .nc-title { font-size: var(--nc-ui-title-size-slim); }
.nc-module[data-nc-compact][data-nc-open="true"] .nc-module-hd { margin-bottom: var(--nc-ui-head-margin-compact); }
.nc-module[data-nc-compact]:not([data-nc-slim]) { padding-top: var(--nc-ui-module-gap); }
.nc-module[data-nc-compact][data-nc-slim] { padding-block: var(--nc-ui-module-gap); }
.nc-title {
  margin: 0;
  min-width: 0;
  font-size: var(--nc-ui-title-size);
  font-weight: var(--nc-ui-title-weight);
  letter-spacing: var(--nc-ui-title-tracking);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nc-module[data-nc-slim] .nc-title { font-size: var(--nc-ui-title-size-slim); }
.nc-module-end { display: flex; align-items: baseline; gap: var(--nc-ui-header-gap); flex: none; }
.nc-index {
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  color: var(--nc-ui-text-sub);
}
.nc-hide, .nc-slim {
  padding: 0 var(--nc-ui-control-gap);
  border: 0;
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-body-size);
  line-height: var(--nc-ui-label-leading);
  cursor: pointer;
  transition: none;
}
.nc-slim {
  display: flex;
  align-items: center;
  gap: var(--nc-ui-module-gap);
  flex: 1;
  min-width: 0;
  margin-top: var(--nc-ui-module-gap);
  text-align: left;
}
.nc-hide:hover, .nc-slim:hover { color: var(--nc-ui-text); }
.nc-hide:focus-visible, .nc-slim:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-control-gap);
}
.nc-slim-lines {
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nc-module-body {
  display: flex;
  flex-direction: column;
  gap: var(--nc-ui-module-pad);
  min-width: 0;
  transition: none;
}
.nc-section { display: flex; flex-direction: column; gap: var(--nc-ui-module-gap); min-width: 0; }
.nc-row, .nc-field, .nc-controls, .nc-slot-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--nc-ui-module-gap);
  min-width: 0;
}
.nc-label {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  color: var(--nc-ui-text-sub);
}
.nc-readout, .nc-mono {
  font-family: var(--nc-ui-font-readout);
  font-variant-numeric: tabular-nums;
  font-size: var(--nc-ui-readout-size);
  color: var(--nc-ui-text);
  white-space: nowrap;
}
/* One label column (the lane-name width), so the sliders in a module start together, as in ASTRID. A label is never
   cut below that column (TEMPO, SWING and DECAY stay whole), but longer text gives way on one line with an ellipsis
   instead of widening the page; the full text stays in the DOM, so the accessible name is never cut. */
.nc-field .nc-label { flex: 0 1 auto; min-width: min(var(--nc-ui-name-width), 100%); }
/* A value never gives way to its label: it keeps its width (flex: none), so a long label is cut first and 0.3 stays
   0.3. Only a value that is itself longer than the row beside a name-width label is cut, with an ellipsis. The control
   beside it (range, knob, canvas, select) keeps its size. */
.nc-field .nc-readout {
  flex: none;
  min-width: 0;
  max-width: calc(100% - var(--nc-ui-name-width) - var(--nc-ui-module-gap));
  overflow: hidden;
  text-overflow: ellipsis;
}
.nc-field .nc-range, .nc-field .nc-canvas { flex: 1 1 0; min-width: 0; }
/* A display beside a label keeps the width it has next to a column-wide label: a long label is cut, not the display. */
.nc-field > .nc-label + .nc-canvas { min-width: calc(100% - var(--nc-ui-name-width) - var(--nc-ui-module-gap)); }
/* ASTRID slider rows: label and value on one baseline, the slider full width under them. */
.nc-field[data-nc-slider] {
  display: grid;
  grid-template-columns: minmax(min(var(--nc-ui-name-width), 100%), 1fr) auto;
  grid-template-areas: "label value" "range range";
  align-items: baseline;
  column-gap: var(--nc-ui-module-gap);
  row-gap: var(--nc-ui-control-gap);
  padding-bottom: var(--nc-ui-module-gap);
}
.nc-field[data-nc-slider] .nc-label { grid-area: label; min-width: 0; }
/* In the slider grid the value column is auto (sized to the value), so the flex-row cap does not apply. */
.nc-field[data-nc-slider] .nc-readout { grid-area: value; max-width: none; text-align: right; }
.nc-field[data-nc-slider] .nc-range { grid-area: range; width: 100%; margin: 0; }
/* Tap tempo: a small outlined button on the label line, between the label and the value. */
.nc-field[data-nc-slider]:has(> .nc-tap) {
  grid-template-columns: minmax(min(var(--nc-ui-name-width), 100%), 1fr) auto auto;
  grid-template-areas: "label tap value" "range range range";
}
.nc-tap {
  grid-area: tap;
  position: relative;
  align-self: center;
  padding: 0 var(--nc-ui-control-gap);
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  border-radius: var(--nc-ui-slot-radius);
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-ui);
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  line-height: var(--nc-ui-label-leading);
  text-transform: uppercase;
  cursor: pointer;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  transition: none;
}
/* The chip stays small; an invisible 44 px box takes the touch. It stops at the slider's top edge (the row gap
   under the chip) and grows upward into the row spacing, so it never takes a drag meant for the slider. */
.nc-tap::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: calc(-1 * var(--nc-ui-control-gap));
  width: max(100%, var(--nc-ui-target-min));
  height: max(100%, var(--nc-ui-target-min));
  transform: translateX(-50%);
}
/* The chip's ::before is already its touch box and stops at the slider; a hit pad on top of it covered the top
   half of the tempo slider, so a drag there tapped instead (Rhythm #40). */
.nc-tap > .nc-hit { display: none; }
.nc-tap:hover { border-color: var(--nc-ui-text-sub); color: var(--nc-ui-text); }
.nc-tap:active { background: var(--nc-ui-text); border-color: var(--nc-ui-text); color: var(--nc-ui-surface-page); }
.nc-tap:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
/* ASTRID row spacing: a 48 px row every 72 px (measured on ASTRID's VCA at 1280 and 390). */
.nc-section:has(> .nc-field[data-nc-slider]) { row-gap: var(--nc-ui-module-pad); }
.nc-section[data-nc-inset="true"] {
  margin-inline: calc(var(--nc-ui-module-pad) * -1);
  margin-bottom: calc(var(--nc-ui-module-pad) * -1);
  padding: var(--nc-ui-module-pad);
}
.nc-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: var(--nc-ui-slider-pitch);
  background: transparent;
  cursor: pointer;
  transition: none;
  accent-color: var(--nc-ui-accent);
}
/* Dimming is by colour, never opacity (plan 5.1): a disabled or bypassed control's label, value, track and thumb go
   to text-sub at full strength, so every pair keeps its contrast (Lucy's panel fix: 38 of 38 pairs pass). */
.nc-range:disabled { cursor: not-allowed; accent-color: var(--nc-ui-text-sub); }
.nc-range:disabled::-webkit-slider-thumb { background: var(--nc-ui-text-sub); }
.nc-range:disabled::-moz-range-thumb { background: var(--nc-ui-text-sub); }
.nc-range:disabled::-moz-range-progress { background: var(--nc-ui-text-sub); }
[data-nc-dim="true"] .nc-label, [data-nc-dim="true"] .nc-readout, [data-nc-dim="true"] .nc-ui-fx-name,
[data-nc-dim="true"] .nc-select { color: var(--nc-ui-text-sub); }
[data-nc-dim="true"] .nc-range { accent-color: var(--nc-ui-text-sub); }
[data-nc-dim="true"] .nc-range::-webkit-slider-thumb { background: var(--nc-ui-text-sub); }
[data-nc-dim="true"] .nc-range::-moz-range-thumb { background: var(--nc-ui-text-sub); }
[data-nc-dim="true"] .nc-range::-moz-range-progress { background: var(--nc-ui-text-sub); }
.nc-range::-webkit-slider-runnable-track {
  height: var(--nc-ui-hairline);
  background: var(--nc-ui-slider-track);
  transition: none;
}
.nc-range::-moz-range-track {
  height: var(--nc-ui-hairline);
  background: var(--nc-ui-slider-track);
  transition: none;
}
.nc-range::-moz-range-progress {
  height: var(--nc-ui-hairline);
  background: var(--nc-ui-slider-progress);
  transition: none;
}
.nc-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: var(--nc-ui-slider-thumb-size);
  height: var(--nc-ui-slider-thumb-size);
  margin-top: calc(var(--nc-ui-slider-thumb-size) / -2);
  border: 0;
  border-radius: 50%;
  background: var(--nc-ui-slider-thumb);
  transition: none;
}
.nc-range::-moz-range-thumb {
  width: var(--nc-ui-slider-thumb-size);
  height: var(--nc-ui-slider-thumb-size);
  border: 0;
  border-radius: 50%;
  background: var(--nc-ui-slider-thumb);
  transition: none;
}
[data-modulated], [data-modulated] * { transition: none; }
.nc-range:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-control-gap); }
.nc-btn {
  width: 100%;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: var(--nc-ui-hairline) solid var(--nc-ui-text);
  background: transparent;
  color: var(--nc-ui-text);
  min-height: var(--nc-ui-target-min);
  padding: var(--nc-ui-button-pad-y) 0;
  font-size: var(--nc-ui-readout-size);
  letter-spacing: var(--nc-ui-button-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition-property: color, background-color, border-color, transform;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-btn:hover { background: var(--nc-ui-surface-raised); }
.nc-btn:active { transform: scale(0.985); }
.nc-btn[data-on="true"] {
  background: var(--nc-ui-accent);
  border-color: var(--nc-ui-accent);
  color: var(--nc-ui-on-accent);
}
.nc-btn:focus-visible {
  outline: var(--nc-ui-focus-width-strong) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-control-gap);
}
.nc-btn:disabled { color: var(--nc-ui-text-sub); border-color: var(--nc-ui-divider); cursor: not-allowed; }
.nc-toggle {
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid transparent;
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-control-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  padding: 0 0 var(--nc-ui-control-gap);
  cursor: pointer;
  align-self: flex-start;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition-property: color, border-color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-toggle:hover, .nc-toggle[aria-pressed="true"] { color: var(--nc-ui-text); }
.nc-toggle:hover { border-bottom-color: var(--nc-ui-text); }
.nc-toggle[aria-pressed="true"] { border-bottom-color: var(--nc-ui-accent); }
.nc-toggle[data-nc-role="mute"][aria-pressed="true"] { color: var(--nc-rhythm-track-mute); }
.nc-toggle[data-nc-role="solo"][aria-pressed="true"] {
  color: var(--nc-rhythm-track-solo);
  border-bottom-color: var(--nc-rhythm-track-solo);
}
.nc-toggle:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-control-gap);
}
/* Underline tabs (ASTRID .nc-seg): words on a hairline, the chosen one in text with a tab-mark accent bar on the
   line. Radio semantics stay (role="radio", aria-checked). */
.nc-seg {
  display: flex;
  border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  margin-bottom: var(--nc-ui-module-gap);
  min-width: 0;
}
.nc-seg > button {
  flex: 1 1 0;
  position: relative;
  min-width: 0;
  padding: var(--nc-ui-tab-pad-y) 0;
  border: 0;
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-size: var(--nc-ui-tab-size);
  font-weight: var(--nc-ui-control-weight);
  white-space: nowrap;
  cursor: pointer;
  transition-property: color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-seg:has(> button:nth-child(4)) > button { font-size: var(--nc-ui-label-size); padding-inline: var(--nc-ui-control-gap); }
.nc-seg > button:hover { color: var(--nc-ui-text); }
.nc-seg > button[aria-checked="true"] { color: var(--nc-ui-text); }
.nc-seg > button[aria-checked="true"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--nc-ui-hairline) * -1);
  height: var(--nc-ui-tab-mark);
  background: var(--nc-ui-accent);
}
.nc-seg > button:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: calc(var(--nc-ui-focus-width) * -1);
}
.nc-select {
  flex: 1 1 auto;
  min-width: 0;
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  border-radius: 0;
  color: var(--nc-ui-text);
  font-size: var(--nc-ui-body-size);
  padding: var(--nc-ui-control-gap) var(--nc-ui-select-pad-end) var(--nc-ui-control-gap) 0;
  cursor: pointer;
  transition: none;
}
.nc-select:hover:not(:disabled) { border-bottom-color: var(--nc-ui-text-sub); }
.nc-select:focus-visible { outline: none; border-bottom-color: var(--nc-ui-accent); }
/* Slots on one line, Morph under them as a slider row (label and value, then the slider). */
.nc-slot-row { flex-direction: column; align-items: stretch; gap: var(--nc-ui-module-gap); }
.nc-slot-line { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--nc-ui-slot-gap); min-width: 0; }
.nc-morph-field { padding-bottom: 0; }
.nc-snap-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--nc-ui-slot-gap);
  min-width: 0;
  flex: 1 1 auto;
}
.nc-snap-wrap {
  position: relative;
  flex: 1 1 var(--nc-ui-slot-size);
  width: var(--nc-ui-slot-size);
  max-width: var(--nc-ui-slot-size);
  min-width: 0;
  height: var(--nc-ui-slot-size);
  -webkit-touch-callout: none;
  user-select: none;
}
.nc-snap {
  display: block;
  width: 100%;
  height: 100%;
  -webkit-touch-callout: none;
  user-select: none;
  touch-action: manipulation;
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  border-radius: var(--nc-ui-slot-radius);
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-slot-font-size);
  line-height: var(--nc-ui-label-leading);
  padding: 0;
  cursor: pointer;
  transition: none;
}
.nc-snap:hover { border-color: var(--nc-ui-text-sub); }
/* Has saved content: an ink outline and ink digit, as in Bass (no grey fill). Empty: hairline, sub ink. */
.nc-snap[data-filled="true"] {
  border-color: var(--nc-ui-text-sub);
  color: var(--nc-ui-text);
}
/* Active (Bass): the accent outline, ink and underline, in every theme and surprise palette. */
.nc-snap[data-active="true"] {
  background: transparent;
  border-color: var(--nc-ui-accent);
  color: var(--nc-ui-accent);
  box-shadow: inset 0 calc(-1 * var(--nc-ui-focus-width) * 2) 0 var(--nc-ui-accent);
}
/* Queued for the end of the bar (Bass): a faint accent underline and outline that go full accent on each beat
   (audio-driven, from the playhead), steady under reduced motion. A second tap switches now. */
.nc-snap[data-queued="true"] {
  color: var(--nc-ui-accent);
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-accent-faint);
  outline-offset: var(--nc-ui-hairline);
  box-shadow: inset 0 calc(-1 * var(--nc-ui-focus-width) * 2) 0 var(--nc-ui-accent-faint);
}
.nc-snap[data-queued="true"][data-pulse="true"] {
  outline-color: var(--nc-ui-accent);
  background: var(--nc-ui-accent-soft);
  box-shadow: inset 0 calc(-1 * var(--nc-ui-focus-width) * 2) 0 var(--nc-ui-accent);
}
/* Edited since it was stored or recalled: a small dot in the corner, in the slot's ink. */
.nc-snap[data-edited="true"] { position: relative; }
.nc-snap[data-edited="true"]::after {
  content: "";
  position: absolute;
  top: var(--nc-ui-control-gap);
  right: var(--nc-ui-control-gap);
  width: var(--nc-ui-control-gap);
  height: var(--nc-ui-control-gap);
  border-radius: 50%;
  background: currentColor;
}
.nc-snap:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-sparkle {
  position: relative;
  flex: 0 0 var(--nc-ui-sparkle-size);
  width: var(--nc-ui-sparkle-size);
  height: var(--nc-ui-sparkle-size);
  margin-inline: var(--nc-rhythm-sparkle-gap);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--nc-ui-text-sub);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition-property: color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-play-row {
  display: flex;
  align-items: stretch;
  gap: var(--nc-rhythm-sparkle-gap);
}
.nc-play-row > .nc-btn { flex: 1 1 auto; width: auto; }
.nc-sparkle-btn {
  flex: 0 0 var(--nc-ui-target-min);
  width: var(--nc-ui-target-min);
  min-height: var(--nc-ui-target-min);
  padding: 0;
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  background: var(--nc-ui-surprise-fill);
  color: var(--nc-ui-surprise-ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition-property: color, background-color, transform;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-sparkle-btn svg { width: calc(var(--nc-ui-target-min) / 2); height: calc(var(--nc-ui-target-min) / 2); display: block; }
.nc-sparkle-btn:hover { background: var(--nc-ui-surface-raised); }
.nc-sparkle-btn:active { transform: scale(0.985); }
.nc-sparkle-btn:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-sparkle svg { width: var(--nc-ui-sparkle-icon-size); height: var(--nc-ui-sparkle-icon-size); display: block; }
.nc-sparkle:hover { color: var(--nc-ui-text); }
.nc-sparkle:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-module-hd:has(> .nc-snap-msg:not(:empty)) { flex-wrap: wrap; row-gap: 0; }
.nc-snap-msg:not(:empty) { order: 1; flex-basis: 100%; }
.nc-snap-msg {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  color: var(--nc-ui-text-sub);
  white-space: normal;
  overflow: hidden;
  transition: none;
}
.nc-module[data-nc-slim] {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--nc-ui-header-gap);
}
.nc-module[data-nc-slim] .nc-module-hd { display: contents; }
.nc-module[data-nc-slim] .nc-title { order: 0; }
.nc-module[data-nc-slim] .nc-snap-msg { order: 1; }
.nc-module[data-nc-slim] .nc-slim { order: 2; margin-top: 0; }
.nc-module[data-nc-slim] .nc-module-end { order: 3; }
.nc-steps {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--nc-rhythm-step-gap);
  min-width: 0;
  flex: 1 1 auto;
}
.nc-name {
  flex: 0 1 var(--nc-ui-name-width);
  width: var(--nc-ui-name-width);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  border: 0;
  background: transparent;
  padding: 0;
  text-align: left;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.nc-name:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
/* Beats read at a glance: every 4 steps the gap widens from step-gap to beat-gap (one beat = one pad row on phones). */
/* Counted among the cells only ("of .nc-step-wrap"): the lane's end handle sits between cells when the lane is short,
   and must not push a beat gap onto the wrong cell. */
.nc-steps > .nc-step-wrap:nth-child(4n + 1 of .nc-step-wrap):not(:first-child) {
  margin-inline-start: calc(var(--nc-ui-beat-gap) - var(--nc-rhythm-step-gap));
}
/* Every lane row bleeds a little into the module padding, so the selected one can be tinted edge to edge (M, S,
   name, steps, menu) with its marker clear of the M button, without moving anything when the selection changes. */
.nc-row[data-nc-row] {
  margin-inline: calc(-1 * var(--nc-ui-row-inset));
  padding-inline: var(--nc-ui-row-inset);
}
/* The selected lane is lit, not just underlined: the whole row tinted, with a solid accent bar at its start. */
.nc-row[data-selected="true"] {
  background: var(--nc-ui-accent-tint);
  box-shadow: inset var(--nc-ui-marker-width) 0 0 var(--nc-ui-accent);
}
.nc-row[data-selected="true"] .nc-name {
  color: var(--nc-ui-text);
  text-decoration: underline;
  text-decoration-color: var(--nc-ui-accent);
  text-decoration-thickness: var(--nc-ui-hairline);
  text-underline-offset: var(--nc-ui-control-gap);
}
/* On the tint, off steps and unlit M/S are paper squares (step-cell-off), as in the mockup, so their outlines stay
   crisp instead of melting into the tint. */
.nc-row[data-selected="true"] .nc-step:not([aria-pressed="true"]):not([data-accent="true"]):not([data-out="true"]),
.nc-row[data-selected="true"] .nc-ms:not([aria-pressed="true"]) { background: var(--nc-rhythm-step-cell-off); }
/* Muted, or silenced by another lane's solo: the lane's steps dim by colour, not just its button. On steps fill with
   text-sub (the velocity shade is set aside while silent), off steps keep only a divider outline. */
.nc-row[data-silent="true"] .nc-step { border-color: var(--nc-ui-divider); }
.nc-row[data-silent="true"] .nc-step[aria-pressed="true"] { background: var(--nc-ui-text-sub); border-color: var(--nc-ui-text-sub); }
.nc-name[data-nc-lane="1"] { color: var(--nc-rhythm-lane-1); }
.nc-name[data-nc-lane="2"] { color: var(--nc-rhythm-lane-2); }
.nc-name[data-nc-lane="3"] { color: var(--nc-rhythm-lane-3); }
.nc-name[data-nc-lane="4"] { color: var(--nc-rhythm-lane-4); }
.nc-ms-wrap {
  position: relative;
  flex: 0 0 var(--nc-ui-slider-pitch);
  height: var(--nc-ui-slider-pitch);
}
.nc-ms {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  border-radius: var(--nc-ui-slot-radius);
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  cursor: pointer;
  transition: none;
}
.nc-ms:hover { color: var(--nc-ui-text); }
.nc-ms[data-nc-ms="mute"][aria-pressed="true"] {
  background: var(--nc-rhythm-track-mute);
  border-color: var(--nc-rhythm-track-mute);
  color: var(--nc-ui-surface-page);
}
.nc-ms[data-nc-ms="solo"][aria-pressed="true"] {
  background: var(--nc-rhythm-track-solo);
  border-color: var(--nc-rhythm-track-solo);
  color: var(--nc-ui-surface-page);
}
.nc-ms:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-step-wrap {
  position: relative;
  flex: 1 1 var(--nc-rhythm-step-cell-size);
  min-width: 0;
  aspect-ratio: 1;
  max-height: var(--nc-ui-slider-pitch);
}
.nc-step {
  position: absolute;
  inset: 0;
  overflow: hidden;
  width: 100%;
  height: 100%;
  border: var(--nc-ui-hairline) solid var(--nc-ui-text-sub);
  border-radius: var(--nc-ui-slot-radius);
  background: transparent;
  padding: 0;
  cursor: pointer;
  transition: none;
}
/* Readable grid: off = empty outline, on = solid. The fill is the step's velocity (velocity-fill, set per cell from
   velocityFill: 5% = rhythm.velocity-min, 100% = rhythm.velocity-max, the accent; step-cell-on when a cell has no
   velocity). Shade means velocity, so an accent is a mark instead: a paper bar inside the step's bottom edge (an inset
   shadow, no layout), clear on every fill of the ramp. No transition: the shade snaps when the velocity changes. */
.nc-step[aria-pressed="true"] {
  background: var(--nc-ui-velocity-fill);
  border-color: var(--nc-ui-velocity-fill);
  color: var(--nc-rhythm-step-cell-ink);
}
.nc-step[aria-pressed="true"][data-accent="true"] {
  box-shadow: inset 0 calc(-1 * var(--nc-rhythm-accent-mark-size)) 0 0 var(--nc-rhythm-accent-mark);
}
/* The playing step, Bass's method: an accent ring outside the step, one hairline clear of it, so it reads the same on an
   empty step or a filled one at any velocity, and every lane's ring at the playhead forms one column. It lifts
   above its neighbours (the ring is wider than step-gap). No transition: it follows the audio clock, step by step. */
.nc-step[data-playhead="true"] {
  z-index: 1;
  outline: var(--nc-ui-playhead-width) solid var(--nc-rhythm-playhead);
  outline-offset: var(--nc-ui-playhead-offset);
}
.nc-step[data-bar="true"] { border-bottom-color: var(--nc-rhythm-bar-accent); }
/* Chance below 100%: a dashed outline at the same width (style only, no opacity, since shade means velocity). The fill
   stops at the padding box, so the dashes are the step's own colour with the row showing between them. */
.nc-step[data-dim="true"] { border-style: dashed; background-clip: padding-box; }
/* Per-lane length: steps past the end are ghosted on the selected row; the end handle sits after the last step. */
.nc-step[data-out="true"] { border-color: var(--nc-ui-divider); background: transparent; pointer-events: none; }
/* Every lane lays its handle out the same way, selected or not, and the handle takes no width in the row: its negative
   margins cancel its own width and the step gap it adds, so it sits centred in the gap after the last step and the
   cells never move when the selection changes. Unselected lanes keep it hidden (visibility, so it cannot be focused). */
.nc-len-handle {
  display: block;
  visibility: hidden;
  position: relative;
  flex: none;
  align-self: stretch;
  width: var(--nc-ui-control-gap);
  margin-inline: calc((var(--nc-ui-control-gap) + var(--nc-rhythm-step-gap)) / -2);
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: ew-resize;
  touch-action: none;
  transition: none;
}
/* The bar itself overhangs the step row (a lane-height grip) without changing the row's layout. */
.nc-len-handle::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--nc-ui-hairline);
  height: var(--nc-ui-target-min);
  max-height: calc(var(--nc-ui-target-min) / 2);
  transform: translate(-50%, -50%);
  border-inline: var(--nc-ui-hairline) solid var(--nc-ui-text-sub);
  background: var(--nc-ui-text-sub);
}
.nc-row[data-selected="true"] .nc-len-handle { visibility: visible; z-index: 1; }
.nc-len-handle:hover::before, .nc-len-handle[data-dragging="true"]::before { background: var(--nc-ui-text); border-color: var(--nc-ui-text); }
.nc-len-handle:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
button.nc-pads-label {
  border: 0;
  background: transparent;
  min-height: var(--nc-ui-target-min);
  padding: 0;
  font-family: inherit;
  cursor: pointer;
}
button.nc-pads-label[aria-pressed="true"] { color: var(--nc-ui-accent); }
.nc-pad[data-out="true"] { border-color: var(--nc-ui-divider); border-style: dashed; background: transparent; color: var(--nc-ui-text-sub); }
.nc-pad[data-end="true"] { box-shadow: inset calc(-1 * var(--nc-ui-focus-width) * 2) 0 0 var(--nc-ui-text); }
.nc-pad[data-end="true"][aria-pressed="true"][data-accent="true"] {
  box-shadow: inset calc(-1 * var(--nc-ui-focus-width) * 2) 0 0 var(--nc-ui-text), inset 0 calc(-1 * var(--nc-rhythm-accent-mark-size)) 0 0 var(--nc-rhythm-accent-mark);
}
.nc-pads { display: none; }
.nc-pads-head { display: none; }
.nc-pads-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  color: var(--nc-ui-text);
}
.nc-step-tools {
  display: flex;
  align-items: stretch;
  gap: var(--nc-ui-module-gap);
  margin-bottom: var(--nc-ui-module-gap);
}
.nc-step-tools > .nc-seg { flex: 1 1 auto; align-self: flex-end; margin-bottom: 0; }
/* No margin (nor the sparkle's): the row gap already sets the dice off the length handle, and 1024 needs the
   width for 18 px cells now that beats are split by beat-gap. */
.nc-row-dice { flex: none; margin-inline: 0; }
.nc-pads-dice svg { width: calc(var(--nc-ui-target-min) / 3); height: calc(var(--nc-ui-target-min) / 3); display: block; margin: auto; }
.nc-fill { padding-inline: var(--nc-ui-module-gap); touch-action: none; user-select: none; -webkit-user-select: none; }
.nc-fill[aria-pressed="true"] { background: var(--nc-ui-text); border-color: var(--nc-ui-text); color: var(--nc-ui-surface-page); }
.nc-pads-step, .nc-pads-play, .nc-fill {
  flex: none;
  min-width: var(--nc-ui-target-min);
  min-height: var(--nc-ui-target-min);
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  border-radius: var(--nc-ui-slot-radius);
  background: var(--nc-ui-surface-page);
  color: var(--nc-ui-text);
  font-family: var(--nc-ui-font-ui);
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-title-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition: none;
}
.nc-pads-play { padding-inline: var(--nc-ui-module-gap); }
.nc-pads-play[aria-pressed="true"] { background: var(--nc-ui-text); border-color: var(--nc-ui-text); color: var(--nc-ui-surface-page); }
.nc-pads-step:focus-visible, .nc-pads-play:focus-visible, .nc-fill:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-pad {
  position: relative;
  overflow: hidden;
  min-height: calc(var(--nc-ui-target-min) * 1.25);
  border: var(--nc-ui-hairline) solid var(--nc-ui-text-sub);
  border-radius: var(--nc-ui-slot-radius);
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  text-align: start;
  vertical-align: top;
  padding: var(--nc-ui-control-gap) var(--nc-ui-module-gap);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  transition: none;
}
/* Pads show the selected lane's steps, so they follow the same rules: fill = velocity, accent = the paper mark,
   chance below 100% = dashed outline. */
.nc-pad[aria-pressed="true"] {
  background: var(--nc-ui-velocity-fill);
  border-color: var(--nc-ui-velocity-fill);
  color: var(--nc-rhythm-step-cell-ink);
}
.nc-pad[aria-pressed="true"][data-accent="true"] {
  box-shadow: inset 0 calc(-1 * var(--nc-rhythm-accent-mark-size)) 0 0 var(--nc-rhythm-accent-mark);
}
.nc-pad[data-playhead="true"] {
  outline: var(--nc-ui-playhead-width) solid var(--nc-rhythm-playhead);
  outline-offset: var(--nc-ui-playhead-offset);
}
.nc-pad[data-dim="true"] { border-style: dashed; background-clip: padding-box; }
.nc-pads[data-silent="true"] .nc-pad { border-color: var(--nc-ui-divider); color: var(--nc-ui-text-sub); }
.nc-pads[data-silent="true"] .nc-pad[aria-pressed="true"] { background: var(--nc-ui-text-sub); border-color: var(--nc-ui-text-sub); color: var(--nc-ui-surface-page); }
.nc-pad:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-step:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
/* A focused step or pad that is also playing keeps the playhead ring (focus comes later at the same specificity and
   would thin it to focus-width; both are the accent). */
.nc-step[data-playhead="true"]:focus-visible, .nc-pad[data-playhead="true"]:focus-visible {
  outline-width: var(--nc-ui-playhead-width);
  outline-offset: var(--nc-ui-playhead-offset);
}
.nc-ui-fx {
  margin-inline: calc(var(--nc-ui-module-pad) * -1);
  padding: var(--nc-ui-stack-card-pad-y) var(--nc-ui-module-pad);
  min-width: 0;
  transition: none;
}
.nc-ui-fx-name {
  margin: 0 0 var(--nc-ui-module-gap) 0;
  font-size: var(--nc-ui-body-size);
  font-weight: var(--nc-ui-fx-name-weight);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* FX card header: the effect's name and its switch on one row of at least a target's height. When the switch is
   off the card dims by colour ([data-nc-dim]). "More" holds the rarely used rows (fx-blocks' <details>). */
.nc-ui-fx-hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--nc-ui-module-gap);
  margin-bottom: var(--nc-ui-module-gap);
  min-width: 0;
}
.nc-ui-fx-hd > .nc-ui-fx-name { margin: 0; }
.nc-ui-fx-visual { display: block; width: 100%; height: var(--nc-ui-display-height); }
.nc-ui-more > summary {
  display: flex;
  align-items: center;
  padding-block: var(--nc-ui-control-gap);
  cursor: pointer;
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  color: var(--nc-ui-text-sub);
}
.nc-ui-more > summary:hover { color: var(--nc-ui-text); }
.nc-ui-more > summary:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: calc(var(--nc-ui-focus-width) * -1); }
/* On/off (ASTRID's ghost On / Off, Peter 2026-10): role="switch", the word alone, no track. Off is text-sub; on is
   text with an accent hairline under it; hover takes the word and the line to text. Both words share one grid cell,
   so the control never changes width when it flips. */
.nc-ui-switch {
  display: inline-flex;
  align-items: baseline;
  flex: none;
  margin: 0;
  padding: 0 0 var(--nc-ui-control-gap);
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid transparent;
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-control-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  color: var(--nc-ui-text-sub);
  transition-property: color, border-color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-ui-switch[aria-checked="true"] { color: var(--nc-ui-text); border-bottom-color: var(--nc-ui-accent); }
.nc-ui-switch:hover { color: var(--nc-ui-text); border-bottom-color: var(--nc-ui-text); }
.nc-ui-switch:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-control-gap); }
.nc-ui-switch-text { display: inline-grid; }
.nc-ui-switch-text > span { grid-area: 1 / 1; }
.nc-ui-switch[aria-checked="true"] [data-nc-off], .nc-ui-switch[aria-checked="false"] [data-nc-on] { visibility: hidden; }
/* Touch (ASTRID's coarse-pointer rule): text controls are drawn small and an invisible pad grows each to target-min,
   centred on it. A select cannot carry a pad, so it grows itself. */
@media (pointer: coarse) {
  :is(.nc-hide, .nc-slim, .nc-toggle, .nc-ui-switch, .nc-seg > button, .nc-ui-more > summary, .nc-page-action) { position: relative; }
  :is(.nc-hide, .nc-slim, .nc-toggle, .nc-ui-switch, .nc-seg > button, .nc-ui-more > summary, .nc-page-action)::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: max(100%, var(--nc-ui-target-min));
    height: max(100%, var(--nc-ui-target-min));
    transform: translate(-50%, -50%);
  }
  .nc-toggle { overflow: visible; text-overflow: clip; }
  .nc-select { min-height: var(--nc-ui-target-min); }
}
/* A panel (Rhythm's Parameters, under the grid): a page-coloured area, full bleed to the module's sides and
   bottom, a hairline above, a title and what it edits, and its controls in columns from 1024 px. */
.nc-section[data-nc-panel="true"] {
  flex: 1 0 auto;
  margin-inline: calc(var(--nc-ui-module-pad) * -1);
  margin-bottom: calc(var(--nc-ui-module-pad) * -1);
  padding: var(--nc-ui-module-pad);
  background: var(--nc-ui-surface-page);
  border-top: var(--nc-ui-hairline) solid var(--nc-ui-divider);
}
.nc-panel-hd {
  display: flex;
  align-items: baseline;
  gap: var(--nc-ui-module-gap);
  min-width: 0;
}
.nc-panel-title {
  margin: 0;
  font-size: var(--nc-ui-title-size);
  font-weight: var(--nc-ui-title-weight);
  letter-spacing: var(--nc-ui-title-tracking);
  white-space: nowrap;
}
.nc-panel-subject {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  color: var(--nc-ui-text-sub);
}
.nc-section[data-nc-lane="1"] .nc-panel-subject { color: var(--nc-rhythm-lane-1); }
.nc-section[data-nc-lane="2"] .nc-panel-subject { color: var(--nc-rhythm-lane-2); }
.nc-section[data-nc-lane="3"] .nc-panel-subject { color: var(--nc-rhythm-lane-3); }
.nc-section[data-nc-lane="4"] .nc-panel-subject { color: var(--nc-rhythm-lane-4); }
.nc-panel-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--nc-ui-module-pad);
  min-width: 0;
}
.nc-canvas {
  width: 100%;
  height: var(--nc-ui-display-height);
  display: block;
  background: transparent;
}
.nc-note {
  /* The containing block for its absolute token probe, so overflow: hidden clips the probe after a long note. */
  position: relative;
  margin: 0;
  min-width: 0;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nc-knob {
  width: var(--nc-ui-knob-size);
  height: var(--nc-ui-knob-size);
  flex: none;
  border-radius: 50%;
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  background: var(--nc-ui-surface-page);
  position: relative;
  padding: 0;
  touch-action: none;
  cursor: pointer;
  transition: none;
}
.nc-knob-mark {
  position: absolute;
  left: 50%;
  top: var(--nc-ui-control-gap);
  width: var(--nc-ui-hairline);
  height: var(--nc-ui-control-gap);
  background: var(--nc-ui-text);
  transform-origin: center var(--nc-ui-module-gap);
  transform: rotate(calc(var(--knob-turn, 0) * 1deg));
  transition: none;
}
.nc-knob:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
/* Tabs stay on one line (no height jump); a tab that does not fit gives way with an ellipsis, and its full text stays
   its accessible name. */
.nc-choice-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--nc-ui-control-gap) var(--nc-ui-header-gap);
  min-width: 0;
}
.nc-choice {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid transparent;
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  padding: var(--nc-ui-control-gap) 0;
  cursor: pointer;
  transition: none;
}
/* On touch a tab cut to an ellipsis is still a full target: never narrower or shorter than target-min. */
@media (pointer: coarse) {
  .nc-choice { min-width: var(--nc-ui-target-min); min-height: var(--nc-ui-target-min); }
  /* Tabs that cannot shrink below target-min scroll within their row (no visible scrollbar), never the page. */
  .nc-choice-row { overflow-x: auto; scrollbar-width: none; }
  .nc-choice-row::-webkit-scrollbar { display: none; }
}
.nc-choice[aria-selected="true"] {
  color: var(--nc-ui-text);
  border-bottom-color: var(--nc-ui-accent);
}
.nc-choice:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
.nc-slot-row { position: relative; }
.nc-slot-menu {
  position: absolute;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--nc-ui-control-gap);
  min-width: var(--nc-ui-name-width);
  padding: var(--nc-ui-control-gap);
  background: var(--nc-ui-surface-page);
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  color: var(--nc-ui-text);
}
.nc-menu-btn {
  display: flex;
  align-items: center;
  min-height: var(--nc-ui-target-min);
  border: 0;
  background: transparent;
  color: var(--nc-ui-text);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size-small);
  text-align: left;
  padding: 0;
  cursor: pointer;
  transition: none;
}
/* 44 px on every pointer (desktop too): a touch band drawn at the 20 px slider pitch; the extra height overlaps the
   gaps, not the rows. */
.nc-field[data-nc-slider] .nc-range {
  height: var(--nc-ui-target-min);
  margin-block: calc((var(--nc-ui-slider-pitch) - var(--nc-ui-target-min)) / 2);
}
/* M and S on touch: each a full target-min box (the button paints smaller inside), touching, never overlapping.
   Only on a coarse pointer: on every pointer it made each lane target-min tall on desktop (Rhythm #40). */
@media (pointer: coarse) {
  .nc-ms-wrap { flex-basis: var(--nc-ui-target-min); height: var(--nc-ui-target-min); }
  .nc-ms-wrap + .nc-ms-wrap { margin-inline-start: calc(var(--nc-ui-module-gap) * -1); }
  .nc-ms {
    inset: calc((var(--nc-ui-target-min) - var(--nc-ui-slider-pitch)) / 2);
    width: auto;
    height: auto;
  }
}
.nc-slot-scrim {
  position: fixed;
  inset: 0;
  z-index: 2;
  background: transparent;
  touch-action: none;
}
.nc-menu-btn:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring);
  outline-offset: var(--nc-ui-hairline);
}
/* A hit pad grows a control that cannot grow its look to target-min, on every pointer. */
.nc-hit {
  display: block;
  position: absolute;
  pointer-events: auto;
  left: 50%;
  top: 50%;
  width: var(--nc-ui-target-min);
  height: var(--nc-ui-target-min);
  transform: translate(-50%, -50%);
}
@media (pointer: coarse) {
  .nc-hit { width: var(--nc-ui-target-min-coarse); height: var(--nc-ui-target-min-coarse); }
}
/* nc-ui step editor (openStepEditor): long-press a step for velocity and chance. Sits under the step;
   a bottom sheet at phone widths. Rows are 44 px so the sliders are thumb-sized. */
.nc-step-editor {
  position: fixed;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: var(--nc-ui-module-gap);
  width: calc(var(--nc-ui-name-width) * 6);
  max-width: calc(100vw - 2 * var(--nc-ui-module-gap));
  padding: var(--nc-ui-module-gap);
  background: var(--nc-ui-surface-page);
  border: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  color: var(--nc-ui-text);
}
/* The step being edited: a dark ring (as Bass marks its selected pad), full strength, fill unchanged. */
.nc-pad[data-editing="true"], .nc-step-wrap[data-editing="true"] .nc-step {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-text);
  outline-offset: var(--nc-ui-hairline);
}
.nc-step-editor-scrim[data-placement="sheet"] { z-index: 4; background: var(--nc-ui-dialog-scrim); }
.nc-step-editor[data-placement="sheet"] { z-index: 5; }
.nc-step-editor-head { display: flex; align-items: center; justify-content: space-between; gap: var(--nc-ui-module-gap); }
.nc-step-editor-row {
  display: flex;
  align-items: center;
  gap: var(--nc-ui-module-gap);
  min-height: var(--nc-ui-target-min);
}
.nc-step-editor-row .nc-label { flex: none; min-width: var(--nc-ui-name-width); }
.nc-step-editor-row .nc-range { flex: 1 1 0; min-width: 0; height: var(--nc-ui-target-min); }
.nc-step-editor-row .nc-readout { flex: none; min-width: var(--nc-ui-name-width); text-align: right; }
.nc-step-editor-done {
  min-width: var(--nc-ui-target-min);
  min-height: var(--nc-ui-target-min);
  border: 0;
  background: none;
  color: var(--nc-ui-text);
  font-family: var(--nc-ui-font-ui);
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-title-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition: none;
}
.nc-step-editor-done:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
.nc-step-editor[data-placement="sheet"] {
  left: 0;
  right: 0;
  bottom: 0;
  width: auto;
  max-width: none;
  padding-bottom: calc(var(--nc-ui-module-gap) + env(safe-area-inset-bottom));
  border-width: var(--nc-ui-hairline) 0 0;
}
/* nc-ui toast (createToast): ASTRID's small dark chip with an uppercase, letter-spaced action.
   Opacity only: in with motion-fade, out with motion-fade-out. Only the chip takes taps. */
.nc-ui-toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: var(--nc-ui-toast-gap);
  max-width: calc(100vw - 2 * var(--nc-ui-toast-offset));
  min-height: var(--nc-ui-toast-target);
  padding: 0 0 0 var(--nc-ui-toast-pad-x);
  border-radius: var(--nc-ui-toast-radius);
  background: var(--nc-ui-toast-bg);
  color: var(--nc-ui-toast-text);
  font-family: var(--nc-ui-font-ui);
  font-size: var(--nc-ui-toast-font-size);
  line-height: var(--nc-ui-label-leading);
  white-space: nowrap;
  pointer-events: auto;
  opacity: 0;
  transition: opacity var(--nc-ui-motion-fade) var(--nc-ui-motion-fade-easing);
}
.nc-ui-toast[data-placement="bottom"] { bottom: calc(var(--nc-ui-toast-offset) + env(safe-area-inset-bottom)); }
.nc-ui-toast[data-placement="top"] { top: calc(var(--nc-ui-toast-offset) + env(safe-area-inset-top)); }
.nc-ui-toast[data-placement="anchor"] { position: absolute; transform: none; }
.nc-ui-toast[data-state="open"] { opacity: 1; }
.nc-ui-toast[data-state="closing"] {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--nc-ui-motion-fade-out) var(--nc-ui-motion-fade-out-easing);
}
.nc-ui-toast-message { overflow: hidden; text-overflow: ellipsis; }
.nc-ui-toast-action {
  min-width: var(--nc-ui-toast-target);
  min-height: var(--nc-ui-toast-target);
  padding: 0 var(--nc-ui-toast-pad-x);
  border: 0;
  background: none;
  color: var(--nc-ui-toast-action);
  font: inherit;
  font-weight: var(--nc-ui-title-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition: none;
}
.nc-ui-toast-action:focus-visible {
  outline: var(--nc-ui-focus-width) solid var(--nc-ui-toast-action);
  outline-offset: calc(-2 * var(--nc-ui-focus-width));
}
.nc-ui-toast-live {
  position: absolute;
  width: var(--nc-ui-hairline);
  height: var(--nc-ui-hairline);
  overflow: hidden;
  clip-path: inset(50%);
  pointer-events: none;
  white-space: nowrap;
}
/* Console (the Studio's Mix): channel strips, the FX cards, then the master strip, on one row. The body bleeds to the
   module's sides and bottom so each area is a shade block: strips on the module, the FX cards one adjacent shade
   darker each, and the master darkest (stack-1), so the row reads as the signal path ending on the right. */
.nc-module-body[data-nc-layout="console"] {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "strips fx master";
  align-items: stretch;
  gap: 0;
  margin-inline: calc(var(--nc-ui-module-pad) * -1);
  margin-bottom: calc(var(--nc-ui-module-pad) * -1);
  border-top: var(--nc-ui-hairline) solid var(--nc-ui-divider);
}
.nc-module-body[data-nc-layout="console"] > .nc-section { gap: 0; padding-top: var(--nc-ui-stack-card-pad-y); }
.nc-module-body[data-nc-layout="console"] > [data-nc-area="strips"] {
  grid-area: strips;
  flex-direction: row;
  align-items: flex-start;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  padding-inline: var(--nc-ui-module-pad) var(--nc-ui-control-gap);
  padding-bottom: var(--nc-ui-module-pad);
  /* The channel strips sit on the master's shade (Peter, 2026-10-30): the lightest step of the stack. */
  background: var(--nc-ui-module-bg-stack-1);
  --nc-ui-text-sub: var(--nc-ui-module-sub-stack-1);
  --nc-ui-divider: var(--nc-ui-module-div-stack-1);
  --nc-ui-slider-track: var(--nc-ui-module-div-stack-1);
}
.nc-module-body[data-nc-layout="console"] > [data-nc-area="fx"] {
  grid-area: fx;
  display: grid;
  grid-template-columns: repeat(3, var(--nc-ui-fx-card-width));
  align-items: stretch;
  padding-top: 0;
}
.nc-module-body[data-nc-layout="console"] > [data-nc-area="master"] {
  grid-area: master;
  align-items: center;
  padding-inline: var(--nc-ui-control-gap) var(--nc-ui-module-pad);
  padding-bottom: var(--nc-ui-module-pad);
  background: var(--nc-ui-module-bg-stack-1);
  --nc-ui-text-sub: var(--nc-ui-module-sub-stack-1);
  --nc-ui-divider: var(--nc-ui-module-div-stack-1);
  --nc-ui-slider-track: var(--nc-ui-module-div-stack-1);
}
.nc-module-body[data-nc-layout="console"] .nc-ui-fx {
  margin: 0;
  padding: var(--nc-ui-stack-card-pad-y) var(--nc-ui-module-pad) var(--nc-ui-module-pad);
  --nc-ui-text-sub: inherit;
  --nc-ui-divider: inherit;
  --nc-ui-slider-track: inherit;
}
.nc-module-body[data-nc-layout="console"] .nc-ui-fx[data-nc-depth="1"] { background: var(--nc-ui-module-bg-adjacent-2); }
.nc-module-body[data-nc-layout="console"] .nc-ui-fx[data-nc-depth="2"] { background: var(--nc-ui-module-bg-adjacent-3); }
.nc-module-body[data-nc-layout="console"] .nc-ui-fx[data-nc-depth="3"] { background: var(--nc-ui-module-bg-adjacent-4); }
/* In the console a card is a column: a select row gets the same space under it as a slider row. */
.nc-module-body[data-nc-layout="console"] .nc-ui-fx { display: flex; flex-direction: column; gap: var(--nc-ui-module-gap); }
.nc-module-body[data-nc-layout="console"] .nc-ui-fx > .nc-field:not([data-nc-slider]) { padding-bottom: var(--nc-ui-module-gap); }
/* One channel strip: name, M and S, sends, then the fader with its scale and meter, then the readout. Every strip
   (the master too, with empty M/S and send rows) keeps the same row heights, so faders and ticks line up. */
.nc-strip {
  position: relative;
  flex: none;
  width: var(--nc-ui-strip-width);
  display: grid;
  grid-template-rows: auto var(--nc-ui-slider-pitch) calc(var(--nc-ui-knob-size) + var(--nc-ui-control-gap) + var(--nc-ui-label-size) * var(--nc-ui-label-leading)) auto auto;
  justify-items: center;
  row-gap: var(--nc-ui-module-gap);
  min-width: 0;
  padding-inline: var(--nc-ui-control-gap);
}
.nc-strip + .nc-strip { border-inline-start: var(--nc-ui-hairline) solid var(--nc-ui-divider); }
.nc-strip[data-nc-master] { width: var(--nc-ui-strip-width-master); }
/* Name row: the name, and the remove × when the strip can be removed. */
.nc-strip-hd { display: flex; align-items: baseline; justify-content: center; gap: var(--nc-ui-control-gap); max-width: 100%; min-width: 0; }
.nc-strip-remove {
  position: relative;
  flex: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--nc-ui-text-sub);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-label-size);
  line-height: 1;
  cursor: pointer;
  transition-property: color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-strip-remove::before { content: ""; position: absolute; inset: calc(var(--nc-ui-control-gap) * -1); }
.nc-strip-remove:hover { color: var(--nc-ui-danger); }
.nc-strip-remove:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
.nc-strip-name {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
  color: var(--nc-ui-text);
}
.nc-strip[data-silent="true"] .nc-strip-name, .nc-strip[data-silent="true"] .nc-strip-db { color: var(--nc-ui-text-sub); }
.nc-strip-ms { display: flex; gap: var(--nc-ui-control-gap); height: var(--nc-ui-slider-pitch); }
.nc-strip-sends { display: flex; align-items: flex-start; gap: var(--nc-ui-module-gap); }
.nc-field[data-nc-compact] {
  flex-direction: column-reverse;
  align-items: center;
  gap: var(--nc-ui-control-gap);
}
.nc-field[data-nc-compact] .nc-label { min-width: 0; line-height: var(--nc-ui-label-leading); }
.nc-field[data-nc-compact] .nc-readout { display: none; }
/* A compact knob draws its amount: a ring over its 270° travel, filled in the meter blue up to the value. */
.nc-field[data-nc-compact] .nc-knob {
  border: 0;
  background:
    radial-gradient(closest-side, var(--nc-ui-surface-page) 70%, transparent 72%),
    conic-gradient(from 225deg, var(--nc-ui-meter-fill) calc(var(--knob-turn, 0) * 1deg), var(--nc-ui-meter-track) 0 270deg, transparent 0);
}
/* Its mark starts at the bottom of the travel (7:30) and turns 270° to 4:30, along the ring. */
.nc-field[data-nc-compact] .nc-knob-mark { transform: rotate(calc((var(--knob-turn, 0) - 135) * 1deg)); }
.nc-strip-body {
  display: grid;
  grid-template-columns: var(--nc-ui-fader-cap-width) auto auto;
  grid-template-rows: var(--nc-ui-clip-size) var(--nc-ui-fader-height);
  justify-content: center;
  column-gap: var(--nc-ui-control-gap);
  row-gap: var(--nc-ui-control-gap);
  padding-block: calc(var(--nc-ui-fader-cap-height) / 2);
}
.nc-strip-body > .nc-fader { grid-column: 1; grid-row: 2; }
.nc-strip-body > .nc-scale { grid-column: 2; grid-row: 2; }
.nc-strip-body > .nc-meter { grid-column: 3; grid-row: 1 / span 2; }
/* The dB scale between fader and meter: faint mono labels, each centred on its level. */
.nc-scale {
  position: relative;
  width: 3ch;
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-scale-size);
  font-variant-numeric: tabular-nums;
  color: var(--nc-ui-text-sub);
}
.nc-scale-tick {
  position: absolute;
  right: 0;
  top: calc((1 - var(--tick-pos, 0)) * 100%);
  transform: translateY(-50%);
  line-height: 1;
  white-space: nowrap;
}
/* The console fader: a slot and a flat cap with a line across its centre. The cap follows the hand: no transition. */
.nc-fader {
  position: relative;
  width: var(--nc-ui-fader-cap-width);
  height: 100%;
  cursor: ns-resize;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  transition: none;
}
.nc-fader-track {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: var(--nc-ui-rule-strong);
  transform: translateX(-50%);
  background: var(--nc-ui-fader-track);
}
.nc-fader-cap {
  position: absolute;
  left: 0;
  width: 100%;
  height: var(--nc-ui-fader-cap-height);
  top: calc((1 - var(--fader-pos, 0)) * 100%);
  transform: translateY(-50%);
  background: var(--nc-ui-fader-cap);
  transition: none;
}
.nc-fader-cap::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--nc-ui-hairline);
  transform: translateY(-50%);
  background: var(--nc-ui-fader-cap-line);
}
.nc-fader[data-dragging="true"] .nc-fader-cap { background: var(--nc-ui-accent); }
/* The master's cap in Prussian blue (Peter, 2026-10-30): the master reads apart from the channels at a glance. */
.nc-module-body[data-nc-layout="console"] > [data-nc-area="master"] .nc-fader-cap { background: var(--nc-ui-fader-cap-master); }
.nc-fader:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-control-gap); }
/* The level meter: peak over RMS in the lighter Prussian blue, a hold line, a clip light on top. It follows the audio
   every frame (transforms written by the meter's own ballistics), so nothing here transitions. */
.nc-meter {
  display: grid;
  grid-template-rows: subgrid;
  row-gap: var(--nc-ui-control-gap);
  justify-items: stretch;
}
.nc-meter-clip {
  position: relative;
  display: block;
  height: var(--nc-ui-clip-size);
  padding: 0;
  border: 0;
  background: var(--nc-ui-meter-track);
  cursor: pointer;
  transition: none;
}
.nc-meter-clip::before {
  content: "";
  position: absolute;
  inset: calc(var(--nc-ui-control-gap) * -1);
}
.nc-meter-clip[data-lit="true"] { background: var(--nc-ui-meter-clip); }
.nc-meter-clip:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
.nc-meter-bars { display: flex; gap: var(--nc-ui-hairline); height: 100%; }
.nc-meter-bar {
  position: relative;
  width: var(--nc-ui-meter-width);
  height: 100%;
  overflow: hidden;
  background: var(--nc-ui-meter-track);
}
.nc-meter-peak, .nc-meter-rms {
  position: absolute;
  inset: 0;
  transform-origin: bottom;
  transform: scaleY(0);
  transition: none;
}
.nc-meter-peak { background: var(--nc-ui-meter-peak); }
.nc-meter-rms { background: var(--nc-ui-meter-fill); }
.nc-meter-hold {
  position: absolute;
  inset: 0;
  border-top: var(--nc-ui-rule-strong) solid var(--nc-ui-meter-hold-mark);
  transform: translateY(100%);
  transition: none;
}
.nc-meter-hold[data-off="true"] { visibility: hidden; }
.nc-strip-db {
  min-width: 0;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size);
  font-variant-numeric: tabular-nums;
  color: var(--nc-ui-text);
  white-space: nowrap;
  cursor: default;
  transition: none;
}
.nc-strip-db:not(:disabled) { cursor: text; }
.nc-strip-db:hover { text-decoration: underline; text-decoration-color: var(--nc-ui-divider); text-underline-offset: var(--nc-ui-control-gap); }
/* The type-in: the readout opened as a field, the same size and font, an accent hairline under it. */
.nc-strip-db-input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-accent);
  border-radius: 0;
  background: transparent;
  color: var(--nc-ui-text);
  font-family: var(--nc-ui-font-readout);
  font-size: var(--nc-ui-readout-size);
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.nc-strip-db-input:focus-visible { outline: none; }
/* The add slot: a ghost strip after the last channel, "+ Add" over a select of what can be added. */
.nc-strip-add {
  position: relative;
  flex: none;
  align-self: stretch;
  width: var(--nc-ui-strip-width);
  margin-inline-start: var(--nc-ui-module-gap);
  border: var(--nc-ui-hairline) dashed var(--nc-ui-divider);
  color: var(--nc-ui-text-sub);
  transition-property: color, border-color;
  transition-duration: var(--nc-ui-transition-feedback);
}
.nc-strip-add:hover, .nc-strip-add:focus-within { color: var(--nc-ui-text); border-color: var(--nc-ui-text-sub); }
.nc-strip-add-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--nc-ui-control-gap);
  pointer-events: none;
}
.nc-strip-add-plus { font-family: var(--nc-ui-font-readout); font-size: var(--nc-ui-title-size-slim); line-height: 1; }
.nc-strip-add-label {
  font-size: var(--nc-ui-label-size);
  font-weight: var(--nc-ui-label-weight);
  letter-spacing: var(--nc-ui-label-tracking);
  text-transform: uppercase;
}
/* The select covers the slot (fully transparent, not dimmed), so a click anywhere on it opens the list. */
.nc-strip-add-select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  font-size: var(--nc-ui-body-size);
}
.nc-strip-add:has(.nc-strip-add-select:focus-visible) { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
.nc-strip-db:focus-visible { outline: var(--nc-ui-focus-width) solid var(--nc-ui-focus-ring); outline-offset: var(--nc-ui-hairline); }
/* Phones and tablets: the strips scroll in their row with the master pinned at the right; the FX cards go under them
   (three across on tablets, stacked on phones). */
@media (max-width: 1023px) {
  .nc-module-body[data-nc-layout="console"] {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "strips master" "fx fx";
  }
}
@media (max-width: 1023px) {
  .nc-module-body[data-nc-layout="console"] > [data-nc-area="fx"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 768px) {
  .nc-module-body[data-nc-layout="console"] > [data-nc-area="fx"] { grid-template-columns: minmax(0, 1fr); }
  /* Phones: the master as narrow as a channel strip, so the strips keep the room. */
  .nc-strip[data-nc-master] { width: var(--nc-ui-strip-width); }
  .nc-module-body[data-nc-layout="console"] > [data-nc-area="master"] { padding-inline: 0; }
}
@media (min-width: 1024px) {
  .nc-module-body[data-nc-layout="console"] {
    margin-inline: calc(var(--nc-ui-module-pad-x-desktop) * -1);
    margin-bottom: calc(var(--nc-ui-module-pad-y-desktop) * -1);
  }
  .nc-module-body[data-nc-layout="console"] > [data-nc-area="strips"] {
    padding-inline-start: var(--nc-ui-module-pad-x-desktop);
    padding-bottom: var(--nc-ui-module-pad-y-desktop);
  }
  .nc-module-body[data-nc-layout="console"] > [data-nc-area="master"] {
    padding-inline-end: var(--nc-ui-module-pad-x-desktop);
    padding-bottom: var(--nc-ui-module-pad-y-desktop);
  }
  .nc-module-body[data-nc-layout="console"] .nc-ui-fx {
    margin: 0;
    padding: var(--nc-ui-stack-card-pad-y) var(--nc-ui-module-pad-x-desktop) var(--nc-ui-module-pad-y-desktop);
  }
}
/* Pinned to its containing block's corner at zero size, so wherever it sits in a control (after a long label or
   note, in an unpositioned box) it can never reach past the page edge. It is empty and never shown; it only carries
   the accent and the UI font for token reads. */
.nc-token-probe {
  position: absolute;
  inset: 0 auto auto 0;
  width: 0;
  height: 0;
  overflow: hidden;
  background: var(--nc-ui-accent);
  font-family: var(--nc-ui-font-ui);
  pointer-events: none;
}
@media (min-width: 768px) {
  .nc-page { padding: var(--nc-ui-page-pad-y-md) var(--nc-ui-page-pad-x-md); }
  .nc-page-hd { flex-direction: row; align-items: flex-end; justify-content: space-between; padding-bottom: var(--nc-ui-page-head-gap-md); }
  .nc-page-hd::before { top: calc(var(--nc-ui-page-pad-y-md) * -1); left: calc(var(--nc-ui-page-pad-x-md) * -1); right: calc(var(--nc-ui-page-pad-x-md) * -1); }
}
/* A minimized full-width module (compact, e.g. the Studio's Mix): one slim bar at every width, title, then the summary
   on one line (cut with an ellipsis), then the index. Overrides the column-wise slim of side-by-side modules. */
.nc-module[data-nc-compact][data-nc-slim] {
  display: flex !important;
  flex-direction: row;
  align-items: center;
  gap: var(--nc-ui-header-gap);
  padding-inline: var(--nc-ui-module-pad);
}
.nc-module[data-nc-compact][data-nc-slim] .nc-module-hd { display: contents !important; }
/* A full-width module's row is its own: minimized it keeps the whole width, not the slim side column. */
.nc-stack:has(> .nc-module[data-nc-compact]) { grid-template-columns: minmax(0, 1fr) !important; }
.nc-module[data-nc-compact][data-nc-slim] .nc-title { flex: none; }
.nc-module[data-nc-compact][data-nc-slim] .nc-slim {
  flex: 1 1 auto;
  min-width: 0;
  margin-top: 0 !important;
  flex-direction: row !important;
  align-items: center !important;
  justify-content: flex-start;
  text-align: left;
}
.nc-module[data-nc-compact][data-nc-slim] .nc-slim-lines {
  white-space: nowrap !important;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Hosted (an instrument inside the Studio, html[data-nc-hosted]): the Studio already names it on its tab, so the
   title block and its band go; the header keeps only its controls (Master, Save, Load...) on one short row. */
html[data-nc-hosted] .nc-page { padding-top: var(--nc-ui-module-gap); min-height: 0; }
html[data-nc-hosted] .nc-page-hd {
  flex-direction: row;
  align-items: center;
  justify-content: flex-end;
  padding-bottom: var(--nc-ui-module-gap);
}
html[data-nc-hosted] .nc-page-hd::before { display: none; }
html[data-nc-hosted] .nc-page-hd > :first-child { display: none; }
html[data-nc-hosted] .nc-page-body { padding-top: var(--nc-ui-module-gap); }
/* Tablets (769-1023 px): the same 2 x 5 slot grid as phones and desktop; one row of 10 drew 14 px slots here. */
@media (min-width: 769px) and (max-width: 1023px) {
  .nc-slot-line { flex-wrap: wrap; }
  .nc-snap-row {
    flex: 1 0 100%;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--nc-ui-control-gap);
  }
  .nc-snap-wrap { width: 100%; max-width: none; height: var(--nc-ui-target-min); }
  .nc-snap { font-size: var(--nc-ui-readout-size); }
  .nc-snap-wrap > .nc-hit { display: none; }
}
@media (min-width: 1024px) {
  .nc-page-body { padding-top: var(--nc-ui-page-body-gap-lg); }
}
@media (min-width: 1280px) {
  .nc-page { padding-inline: var(--nc-ui-page-pad-x-xl); }
  .nc-page-hd::before { left: calc(var(--nc-ui-page-pad-x-xl) * -1); right: calc(var(--nc-ui-page-pad-x-xl) * -1); }
}
@media (min-width: 1024px) {
  .nc-stack[data-nc-layout="adjacent"] {
    display: grid;
    grid-template-columns: var(--astrid-cols);
    align-items: stretch;
  }
  .nc-stack[data-nc-layout="adjacent"] > .nc-module {
    border-bottom: 0;
    border-inline-end: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  }
  .nc-stack[data-nc-layout="adjacent"] > .nc-module:last-child { border-inline-end: 0; }
  .nc-module { padding: var(--nc-ui-module-pad-y-desktop) var(--nc-ui-module-pad-x-desktop); }
  /* Desktop slots (item C): Bass's 2 x 5 grid across the column, each slot as tall as the Pattern buttons
     (target-min). One row of 10 left each slot 19 px wide at 1280 and 16 px at 1024. */
  .nc-slot-line { flex-wrap: wrap; }
  .nc-snap-row {
    flex: 1 0 100%;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--nc-ui-control-gap);
  }
  .nc-snap-wrap {
    width: 100%;
    max-width: none;
    height: var(--nc-ui-target-min);
  }
  .nc-snap { font-size: var(--nc-ui-readout-size); }
  .nc-snap-wrap > .nc-hit { display: none; }
  .nc-section[data-nc-inset="true"] {
    margin-inline: calc(var(--nc-ui-module-pad-x-desktop) * -1);
    margin-bottom: calc(var(--nc-ui-module-pad-y-desktop) * -1);
    padding: var(--nc-ui-module-pad-y-desktop) var(--nc-ui-module-pad-x-desktop);
  }
  .nc-section[data-nc-panel="true"] {
    margin-inline: calc(var(--nc-ui-module-pad-x-desktop) * -1);
    margin-bottom: calc(var(--nc-ui-module-pad-y-desktop) * -1);
    padding: var(--nc-ui-module-pad-y-desktop) var(--nc-ui-module-pad-x-desktop);
  }
  .nc-panel-body {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: var(--nc-ui-module-pad-x-desktop);
  }
  .nc-module[data-nc-slim] {
    display: block;
    padding-inline: var(--nc-ui-module-pad-x-slim);
  }
  .nc-module[data-nc-slim] .nc-module-hd { display: flex; }
  .nc-module[data-nc-slim] .nc-module-hd,
  .nc-module[data-nc-slim] .nc-slim {
    flex-direction: column;
    align-items: flex-start;
  }
  .nc-module[data-nc-slim] .nc-slim { margin-top: var(--nc-ui-module-gap); }
  .nc-module[data-nc-slim] .nc-slim-lines { white-space: normal; }
  .nc-ui-fx {
    margin-inline: calc(var(--nc-ui-module-pad-x-desktop) * -1);
    padding-inline: var(--nc-ui-module-pad-x-desktop);
  }
}
/* 1024-1279 px (item C): four open columns left the lead about 240 px (3.5 px step cells). With a lead and three
   open modules, the last two share the last column (stacked), so the lead is 53fr against 23.333fr and every lane
   stays on one row with 18 px+ cells; the outer columns keep their width. */
@media (min-width: 1024px) and (not (min-width: 1280px)) {
  /* Three open columns (Rhythm: Transport, Pattern, Filter) get the same 53fr lead. */
  .nc-stack[data-nc-layout="adjacent"] { --astrid-lead-fr: 53fr; }
  .nc-stack[data-nc-layout="adjacent"][data-nc-stack-last="true"] {
    grid-template-columns: minmax(0, 23.333fr) minmax(0, 53fr) minmax(0, 23.333fr);
  }
  .nc-stack[data-nc-stack-last="true"] > .nc-module { grid-row: 1 / span 2; }
  .nc-stack[data-nc-stack-last="true"] > .nc-module:nth-last-child(2) {
    grid-column: 3;
    grid-row: 1;
    border-inline-end: 0;
    border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  }
  .nc-stack[data-nc-stack-last="true"] > .nc-module:last-child { grid-column: 3; grid-row: 2; }
}
/* From 1280 px the lead (Rhythm's step grid) widens from ASTRID's 30fr to 48fr so its 16 cells are 18 px+ on one row. */
@media (min-width: 1280px) {
  .nc-stack[data-nc-layout="adjacent"] {
    --astrid-lead-fr: 48fr;
    --astrid-rest-fr: 21.333fr;
  }
}
@media (max-width: 768px) {
  /* Phones: rows are the overview and lane picker; the selected lane edits on 4x4 pads (one row = one beat). */
  .nc-row-dice { display: none; }
  .nc-pads-head {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: var(--nc-ui-module-gap);
    padding-block: var(--nc-ui-control-gap);
    background: var(--nc-ui-surface-page);
    border-bottom: var(--nc-ui-hairline) solid var(--nc-ui-divider);
  }
  .nc-pads {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--nc-ui-module-gap);
    touch-action: pan-y;
  }
  .nc-steps { pointer-events: none; }
  .nc-steps .nc-hit { display: none; }
  .nc-row { cursor: pointer; }
  .nc-slot-line { flex-wrap: wrap; }
  .nc-snap-row {
    flex: 1 0 100%;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
  .nc-snap-wrap {
    width: 100%;
    max-width: var(--nc-ui-slot-span);
    height: var(--nc-ui-slot-block);
    justify-self: center;
  }
  .nc-snap { font-size: var(--nc-ui-readout-size); }
  .nc-snap-wrap > .nc-hit { display: none; }
}
@media (max-width: 360px) {
  .nc-label, .nc-name, .nc-note, .nc-title { text-overflow: ellipsis; }
}
@media (prefers-reduced-motion: reduce) {
  .nc-btn, .nc-btn:active, .nc-toggle, .nc-seg > button, .nc-sparkle, .nc-sparkle-btn, .nc-sparkle-btn:active,
  .nc-ui-toast, .nc-ui-toast[data-state="closing"], .nc-ui-switch, .nc-select,
  .nc-meter, .nc-meter-fill, .nc-step[data-playhead="true"], .nc-fader-cap, .nc-meter-clip {
    transition: none;
    animation: none;
  }
  .nc-snap[data-queued="true"][data-pulse="true"] {
    outline-color: var(--nc-ui-accent-faint);
    background: transparent;
    box-shadow: inset 0 calc(-1 * var(--nc-ui-focus-width) * 2) 0 var(--nc-ui-accent-faint);
  }
}

/* confirm.css */
/* nc-ui confirm (confirm.js links this file once per document; no kit.js needed). One question over a dimmed,
   inert page. Cancel is an outlined button like .nc-btn; the action fills with danger when it is destructive. The
   layer fades in with motion-fade and out with motion-fade-out, the box scales in with motion-slide.
   Semantic tokens only. Every var() carries the token's current value as its fallback, so the dialog looks the same
   in an app without nc-ui tokens (Bass); test/confirm.test.mjs checks each fallback against dist/tokens.js. */
.nc-ui-confirm-layer,
.nc-ui-confirm-layer * {
  box-sizing: border-box;
}
.nc-ui-confirm-layer {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  padding: var(--nc-ui-dialog-pad, 16px);
  background: var(--nc-ui-dialog-scrim, rgba(36,36,36,0.35));
  opacity: 0;
  touch-action: none;
  transition: opacity var(--nc-ui-motion-fade, .2s) var(--nc-ui-motion-fade-easing, ease);
}
.nc-ui-confirm-layer[data-state="open"] {
  opacity: 1;
}
.nc-ui-confirm-layer[data-state="closing"] {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--nc-ui-motion-fade-out, .25s) var(--nc-ui-motion-fade-out-easing, ease-out);
}
.nc-ui-confirm {
  display: flex;
  flex-direction: column;
  gap: var(--nc-ui-dialog-gap, 12px);
  width: min(var(--nc-ui-dialog-width, 320px), 100%);
  padding: var(--nc-ui-dialog-pad, 16px);
  border: var(--nc-ui-hairline, 1px) solid var(--nc-ui-divider, #DDDDDD);
  border-radius: var(--nc-ui-dialog-radius, 2px);
  background: var(--nc-ui-surface-page, #F5F5F5);
  color: var(--nc-ui-text, #242424);
  font-family: var(--nc-ui-font-ui, 'Inter', 'Geist', sans-serif);
  font-size: var(--nc-ui-body-size, 13px);
  font-weight: var(--nc-ui-title-weight, 400);
  line-height: var(--nc-ui-dialog-leading, 1.35);
  transform: scale(0.96);
  transition: transform var(--nc-ui-motion-slide, .22s) var(--nc-ui-motion-slide-easing, ease-out);
}
.nc-ui-confirm-layer[data-state="open"] .nc-ui-confirm {
  transform: none;
}
.nc-ui-confirm-title {
  margin: 0;
  font-size: var(--nc-ui-title-size-slim, 18px);
  font-weight: var(--nc-ui-title-weight, 400);
  letter-spacing: var(--nc-ui-title-tracking, -.01em);
}
.nc-ui-confirm-body {
  margin: 0;
  font-size: var(--nc-ui-body-size, 13px);
  color: var(--nc-ui-text-sub, #595959);
}
.nc-ui-confirm-actions {
  display: flex;
  gap: var(--nc-ui-dialog-button-gap, 8px);
}
button.nc-ui-confirm-btn {
  flex: 1 1 0;
  min-width: 0;
  min-height: var(--nc-ui-target-min, 44px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: var(--nc-ui-hairline, 1px) solid var(--nc-ui-text, #242424);
  border-radius: 0;
  background: transparent;
  color: var(--nc-ui-text, #242424);
  font: inherit;
  font-size: var(--nc-ui-readout-size, 12px);
  letter-spacing: var(--nc-ui-label-tracking, .14em);
  text-transform: uppercase;
  cursor: pointer;
  transition-property: color, background-color, border-color;
  transition-duration: var(--nc-ui-transition-feedback, .15s);
}
button.nc-ui-confirm-btn:hover {
  background: var(--nc-ui-surface-raised, #EAEAEA);
}
button.nc-ui-confirm-btn[data-danger="true"] {
  border-color: var(--nc-ui-danger, hsl(8 55% 44%));
  background: var(--nc-ui-danger, hsl(8 55% 44%));
  color: var(--nc-ui-on-danger, #F5F5F5);
}
button.nc-ui-confirm-btn:focus {
  outline: var(--nc-ui-focus-width-strong, 2px) solid var(--nc-ui-focus-ring, #003153);
  outline-offset: var(--nc-ui-focus-width-strong, 2px);
}
@media (prefers-reduced-motion: reduce) {
  .nc-ui-confirm-layer,
  .nc-ui-confirm-layer[data-state="closing"],
  .nc-ui-confirm,
  button.nc-ui-confirm-btn {
    transition: none;
    animation: none;
  }
}
