<script lang="ts">
  import '../theme/index';
  import './control-button.css';
  import { DotButton, FillButton, HardwareButton, HardwarePlainButton, StatusIndicator } from '$lib/Button';
  import { PRESET_MAPPINGS, type RoleMapping } from '$lib/Button/roleMapping';
  import { SegmentedControl } from '$lib/SegmentedControl';
  import { ValueControl } from './value-control';

  const indicatorStyles = [
    { value: 'ring', label: 'Ring' },
    { value: 'dot', label: 'Dot' },
    { value: 'edge-bottom', label: 'Edge Bottom' },
    { value: 'edge-left', label: 'Edge Left' },
    { value: 'fill', label: 'Fill' },
  ] as const;

  const indicatorColors = ['cyan', 'green', 'amber', 'red', 'orange', 'white'] as const;

  const hardwareButtons = [
    { style: 'edge-left', color: 'cyan', label: 'NB' },
    { style: 'edge-left', color: 'amber', label: 'NR' },
    { style: 'edge-bottom', color: 'green', label: 'TUNE' },
    { style: 'dot', color: 'red', label: 'VOX' },
    { style: 'dot', color: 'green', label: 'MUTE' },
    { style: 'dot', color: 'amber', label: 'MON' },
    { style: 'edge-bottom', color: 'cyan', label: 'LOCK' },
    { style: 'edge-left', color: 'orange', label: 'SPLIT' },
  ] as const;

  // Reactive toggle state for all demo buttons
  let styleActive: Record<string, boolean> = $state({});
  let dotActive: Record<string, boolean> = $state({});
  let dotLayoutActive: Record<string, boolean> = $state({});
  let hwActive: Record<string, boolean> = $state({});
  
  // Component library states
  let compDotStates: Record<string, boolean> = $state({});
  let compFillStates: Record<string, boolean> = $state({});
  let compHwStates: Record<string, boolean> = $state({});
  let compPlainStates: Record<string, boolean> = $state({});

  // action-button role — momentary commands, no sustained on/off state
  const actionButtons = [
    { label: 'CLEAR',     color: 'amber'  },
    { label: 'TUNE',      color: 'green'  },
    { label: 'AUTO TUNE', color: 'cyan'   },
    { label: 'RESET',     color: 'red'    },
    { label: 'CENTER',    color: 'orange' },
    { label: 'SCAN',      color: 'cyan'   },
  ] as const;
  let actionFlash: Record<string, boolean> = $state({});

  function fireAction(key: string) {
    actionFlash[key] = true;
    setTimeout(() => { actionFlash[key] = false; }, 180);
  }

  // StatusBadge migration reference — status-toggle role across multiple visual families
  const statusToggleButtons = [
    { label: 'NB',   color: 'orange' },
    { label: 'ATU',  color: 'green'  },
    { label: 'VOX',  color: 'orange' },
    { label: 'COMP', color: 'orange' },
    { label: 'MON',  color: 'orange' },
    { label: 'RIT',  color: 'cyan'   },
    { label: 'XIT',  color: 'orange' },
    { label: 'NR',   color: 'cyan'   },
    { label: 'LOCK', color: 'orange' },
  ] as const;
  let fillToggleStates: Record<string, boolean> = $state({});
  let fillCompactToggleStates: Record<string, boolean> = $state({});
  let dotToggleStates: Record<string, boolean> = $state({});
  let plainToggleStates: Record<string, boolean> = $state({});

  function toggle(map: Record<string, boolean>, key: string) {
    map[key] = !map[key];
  }

  // Theme mapping proof — role → family preset selector
  let activeMapping: RoleMapping = $state(PRESET_MAPPINGS[0]);
  let mappingToggleStates: Record<string, boolean> = $state({});
  let mappingActionFlash: Record<string, boolean> = $state({});

  function fireMappingAction(key: string) {
    mappingActionFlash[key] = true;
    setTimeout(() => { mappingActionFlash[key] = false; }, 180);
  }

  // ── Selector family demo ─────────────────────────────────────────────────
  // Real radio labels — same values used in production AGC / DSP / mode panels

  const AGC_OPTS = [
    { value: 0, label: 'OFF'  },
    { value: 1, label: 'FAST' },
    { value: 2, label: 'MID'  },
    { value: 3, label: 'SLOW' },
  ];

  const NOTCH_OPTS = [
    { value: 'off',    label: 'OFF'  },
    { value: 'auto',   label: 'AUTO' },
    { value: 'manual', label: 'MAN'  },
  ];

  const MODE_OPTS = [
    { value: 'LSB',  label: 'LSB'  },
    { value: 'USB',  label: 'USB'  },
    { value: 'AM',   label: 'AM'   },
    { value: 'FM',   label: 'FM'   },
    { value: 'CW',   label: 'CW'   },
    { value: 'RTTY', label: 'RTTY' },
  ];

  const NR_OPTS = [
    { value: 0, label: 'OFF' },
    { value: 1, label: 'NR1' },
    { value: 2, label: 'NR2' },
  ];

  let selectorAgcFlat = $state(0);
  let selectorAgcFill = $state(0);
  let selectorAgcHwEdge = $state(0);
  let selectorAgcHwDot = $state(0);
  let selectorNotchFlat = $state('off');
  let selectorNotchHw = $state('off');
  let selectorModeCompact = $state('USB');
  let selectorNrFlat = $state(0);

  // Grid selector (BandSelector pattern) demo
  const DEMO_BANDS = ['160m','80m','40m','30m','20m','17m','15m','12m','10m','6m','2m','70cm'];
  let gridDemoActive = $state('20m');

  // ── Value Control family demo ─────────────────────────────────────────────
  // HBar examples — real radio parameters
  let afLevel = $state(128);
  let rfGain = $state(255);
  let nrLevel = $state(64);
  let nbLevel = $state(80);
  let cwPitch = $state(600);
  let notchFreq = $state(1500);
  let micGain = $state(50);
  let txPower = $state(100);

  // HBar compact examples
  let afLevelCompact = $state(128);
  let rfGainCompact = $state(200);

  // HBar disabled example
  let afLevelDisabled = $state(80);

  // DiscreteRenderer examples — stepped controls
  let discreteNrLevel = $state(8);

  // Bipolar examples — real radio parameters
  let ritOffset = $state(0);         // RIT offset: -9999..+9999 Hz
  let xitOffset = $state(0);         // XIT offset
  let passband = $state(0);          // Passband shift: -50..+50
  let toneOffset = $state(0);        // Tone control: -50..+50

  // Knob examples
  let rfGainKnob = $state(200);
  let squelchKnob = $state(80);
  let cwPitchKnob = $state(600);
  let micGainKnob = $state(50);

  // ── #350 — Modern Accent vs Hardware family comparison ───────────────────


  // ── Hardware Illuminated demo (5-layer) ─────────────────────────────────
  let vcHwCurrentAf = $state(128);
  let vcHwCurrentRf = $state(200);
  let vcHwCurrentNr = $state(64);
  let vcHwCurrentRit = $state(1200);
  let vcHwCurrentXit = $state(-400);

  let vcIllumAf = $state(128);
  let vcIllumRf = $state(200);
  let vcIllumNr = $state(64);
  let vcIllumRit = $state(1200);

  let vcIllumXit = $state(-400);
</script>

<div class="demo-root">
  <section class="demo-card">
    <h2>Indicator Styles <span class="hint">(click to toggle)</span></h2>
    <div class="demo-grid">
      {#each indicatorStyles as style}
        <button
          type="button"
          class="v2-control-button"
          data-active={styleActive[style.value] ?? false}
          data-indicator-style={style.value}
          data-indicator-color="cyan"
          onclick={() => toggle(styleActive, style.value)}
        >
          {style.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>Dot Colors <span class="hint">(click to toggle)</span></h2>
    <div class="demo-grid">
      {#each indicatorColors as color}
        <button
          type="button"
          class="v2-control-button"
          data-active={dotActive[color] ?? false}
          data-indicator-style="dot"
          data-indicator-color={color}
          onclick={() => toggle(dotActive, color)}
        >
          {color}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>Fill Colors <span class="hint">(click to toggle)</span></h2>
    <div class="demo-grid">
      {#each hardwareButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={dotActive[`${btn.label}-fill`] ?? false}
          data-indicator-style="fill"
          data-indicator-color={btn.color}
          onclick={() => toggle(dotActive, `${btn.label}-fill`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>Hardware Surface <span class="hint">(click to toggle)</span></h2>
    <div class="demo-grid">
      {#each hardwareButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={hwActive[btn.label] ?? false}
          data-surface="hardware"
          data-indicator-style={btn.style}
          data-indicator-color={btn.color}
          onclick={() => toggle(hwActive, btn.label)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

<section class="demo-card">
    <h2>Hardware Plain + Warm Glow <span class="hint">(click to toggle)</span></h2>
    <div class="demo-grid">
      {#each hardwareButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={hwActive[`${btn.label}-plain`] ?? false}
          data-surface="hardware"
          data-glow="warm"
          onclick={() => toggle(hwActive, `${btn.label}-plain`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <section class="demo-card">
    <h2>🎨 Component Library v2 <span class="hint">(Svelte components)</span></h2>
    <p style="margin: 0 0 16px; color: var(--v2-text-subdued); font-size: 11px;">
      Same styles, cleaner API. Import from <code>$lib/Button</code>
    </p>
  </section>

  <section class="demo-card">
    <h2>DotButton <span class="hint">(component)</span></h2>
    <div class="demo-grid">
      {#each indicatorColors as color}
        <DotButton 
          active={compDotStates[color] ?? false}
          {color}
          onclick={() => compDotStates[color] = !compDotStates[color]}
        >
          {color}
        </DotButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>FillButton <span class="hint">(component)</span></h2>
    <div class="demo-grid">
      {#each hardwareButtons as btn}
        <FillButton 
          active={compFillStates[btn.label] ?? false}
          color={btn.color}
          onclick={() => compFillStates[btn.label] = !compFillStates[btn.label]}
        >
          {btn.label}
        </FillButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>HardwareButton <span class="hint">(component)</span></h2>
    <div class="demo-grid">
      {#each hardwareButtons as btn}
        <HardwareButton
          active={compHwStates[btn.label] ?? false}
          indicator={btn.style as any}
          color={btn.color}
          onclick={() => compHwStates[btn.label] = !compHwStates[btn.label]}
        >
          {btn.label}
        </HardwareButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>HardwarePlainButton <span class="hint">(component)</span></h2>
    <div class="demo-grid">
      {#each hardwareButtons as btn}
        <HardwarePlainButton
          active={compPlainStates[btn.label] ?? false}
          onclick={() => compPlainStates[btn.label] = !compPlainStates[btn.label]}
        >
          {btn.label}
        </HardwarePlainButton>
      {/each}
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── StatusBadge migration reference ─────────────────────────────────── -->

  <section class="demo-card">
    <h2>StatusBadge Migration Reference <span class="hint">(semantic split + visual candidates)</span></h2>
    <p class="lab-note">
      <code>StatusBadge</code> is legacy/transitional. It conflates two separate concerns that must split:<br/><br/>
      <strong>Display path</strong> → <code>StatusIndicator</code> — a read-only display primitive (CSS class, <code>&lt;span&gt;</code>).
      No interactivity. Use for TX state, VFO header mode/filter badges, any status that is set by the radio, not the user.<br/><br/>
      <strong>Interactive path</strong> → <code>status-toggle</code> — a <em>semantic role</em>, not a fixed visual component.
      A status-toggle may be rendered using any approved button family depending on theme/design choice:
      Fill (current default), Dot, Hardware Plain + Warm Glow, or others.
      The architecture must not assume <code>status-toggle === FillButton</code> forever.
    </p>
  </section>

  <!-- ── Interactive path: status-toggle role across visual families ── -->

  <section class="demo-card">
    <h2>status-toggle / Fill family <span class="hint">(click to toggle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> status-toggle &nbsp;·&nbsp; <strong>Visual family:</strong> FillButton<br/>
      Current recommended default for interactive StatusBadge migration.
      Proper <code>&lt;button&gt;</code> semantics, token-driven glow, no inline styles.
    </p>
    <div class="demo-grid">
      {#each statusToggleButtons as btn}
        <FillButton
          active={fillToggleStates[btn.label] ?? false}
          color={btn.color}
          onclick={() => fillToggleStates[btn.label] = !fillToggleStates[btn.label]}
        >
          {btn.label}
        </FillButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>status-toggle / Fill family compact <span class="hint">(click to toggle)</span></h2>
    <p class="lab-note">
      Same role, same visual family, <code>compact</code> sizing.
      For tighter panel rows where the current 22px badge height is more appropriate.
    </p>
    <div class="demo-grid">
      {#each statusToggleButtons as btn}
        <FillButton
          active={fillCompactToggleStates[btn.label] ?? false}
          color={btn.color}
          compact
          onclick={() => fillCompactToggleStates[btn.label] = !fillCompactToggleStates[btn.label]}
        >
          {btn.label}
        </FillButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>status-toggle / Dot family <span class="hint">(click to toggle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> status-toggle &nbsp;·&nbsp; <strong>Visual family:</strong> DotButton<br/>
      Same radio toggles, different approved visual family. Shows that the role is not locked to Fill.
      A theme could map status-toggle here instead — e.g. a more minimal or monochrome panel theme.
    </p>
    <div class="demo-grid">
      {#each statusToggleButtons as btn}
        <DotButton
          active={dotToggleStates[btn.label] ?? false}
          color={btn.color}
          onclick={() => dotToggleStates[btn.label] = !dotToggleStates[btn.label]}
        >
          {btn.label}
        </DotButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>status-toggle / HardwarePlain family <span class="hint">(click to toggle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> status-toggle &nbsp;·&nbsp; <strong>Visual family:</strong> HardwarePlainButton + Warm Glow<br/>
      Incandescent / instrument-panel feel. A vintage or hardware-skeuomorphic theme could prefer this
      over Fill for the same toggles. The role maps; the visual family changes.
    </p>
    <div class="demo-grid">
      {#each statusToggleButtons as btn}
        <HardwarePlainButton
          active={plainToggleStates[btn.label] ?? false}
          onclick={() => plainToggleStates[btn.label] = !plainToggleStates[btn.label]}
        >
          {btn.label}
        </HardwarePlainButton>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>status-toggle / Hardware Left <span class="hint">(click to toggle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> status-toggle &nbsp;·&nbsp; <strong>Visual family:</strong> Hardware + Left Edge<br/>
      Hardware surface with left-edge accent as the sustained state indicator. Good candidate for hardware themes
      where a more instrument-like active marker is preferable to fill.
    </p>
    <div class="demo-grid">
      {#each statusToggleButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={compHwStates[`status-left-${btn.label}`] ?? false}
          data-surface="hardware"
          data-indicator-style="edge-left"
          data-indicator-color={btn.color}
          onclick={() => compHwStates[`status-left-${btn.label}`] = !compHwStates[`status-left-${btn.label}`]}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>status-toggle / Hardware Bottom <span class="hint">(click to toggle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> status-toggle &nbsp;·&nbsp; <strong>Visual family:</strong> Hardware + Bottom Edge<br/>
      Hardware surface with bottom-edge accent as the sustained state indicator. Another strong candidate for
      skeuomorphic themes where the active state should read as panel illumination rather than fill.
    </p>
    <div class="demo-grid">
      {#each statusToggleButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={compHwStates[`status-bottom-${btn.label}`] ?? false}
          data-surface="hardware"
          data-indicator-style="edge-bottom"
          data-indicator-color={btn.color}
          onclick={() => compHwStates[`status-bottom-${btn.label}`] = !compHwStates[`status-bottom-${btn.label}`]}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── action-button role exploration ───────────────────────────────────── -->

  <section class="demo-card">
    <h2>Action Button Role <span class="hint">(approved semantic role reference)</span></h2>
    <p class="lab-note">
      <strong>action-button</strong> is a semantic role for momentary command-style controls.<br/><br/>
      Key distinction vs <code>status-toggle</code>: an action-button <em>does not maintain sustained on/off state</em>.
      Clicking fires a command (CLEAR, TUNE, RESET…) and the button returns to idle immediately.
      The brief press-flash below is intentional — it confirms the action fired, but the control is not "on".<br/><br/>
      Same semantic role, three approved visual families shown below. A theme may pick any family.
    </p>
  </section>

  <section class="demo-card">
    <h2>action-button / Fill <span class="hint">(momentary — press flashes, then returns to idle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> action-button &nbsp;·&nbsp; <strong>Visual family:</strong> FillButton<br/>
      Strong visual confirmation on press. Color identity helps distinguish command type at a glance.
      Recommended for prominent command controls in dense panels.
    </p>
    <div class="demo-grid">
      {#each actionButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={actionFlash[`fill-${btn.label}`] ?? false}
          data-indicator-style="fill"
          data-indicator-color={btn.color}
          onclick={() => fireAction(`fill-${btn.label}`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>action-button / Dot <span class="hint">(momentary — press flashes, then returns to idle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> action-button &nbsp;·&nbsp; <strong>Visual family:</strong> DotButton<br/>
      Dot family gives a subtle color cue without full-fill weight. Works well when action buttons
      need to coexist with status-toggle controls in the same panel row without visual competition.
    </p>
    <div class="demo-grid">
      {#each actionButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={actionFlash[`dot-${btn.label}`] ?? false}
          data-indicator-style="dot"
          data-indicator-color={btn.color}
          onclick={() => fireAction(`dot-${btn.label}`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>action-button / HardwarePlain <span class="hint">(momentary — press flashes, then returns to idle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> action-button &nbsp;·&nbsp; <strong>Visual family:</strong> HardwarePlainButton + Warm Glow<br/>
      Incandescent flash on press; returns to unlit hardware surface. Strong instrument-panel feel.
      A vintage or hardware-skeuomorphic theme could use this family for all command actions.
    </p>
    <div class="demo-grid">
      {#each actionButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={actionFlash[`plain-${btn.label}`] ?? false}
          data-surface="hardware"
          data-glow="warm"
          onclick={() => fireAction(`plain-${btn.label}`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>action-button / Hardware Left <span class="hint">(momentary — press flashes, then returns to idle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> action-button &nbsp;·&nbsp; <strong>Visual family:</strong> Hardware Surface + Left Edge Accent<br/>
      Left-edge indicator lights on press; hardware surface returns to neutral on release.
      Suits command controls sharing a panel row with left-edge status-toggles (NB, NR, SPLIT).
    </p>
    <div class="demo-grid">
      {#each actionButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={actionFlash[`hw-left-${btn.label}`] ?? false}
          data-surface="hardware"
          data-indicator-style="edge-left"
          data-indicator-color={btn.color}
          onclick={() => fireAction(`hw-left-${btn.label}`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>action-button / Hardware Bottom <span class="hint">(momentary — press flashes, then returns to idle)</span></h2>
    <p class="lab-note">
      <strong>Semantic role:</strong> action-button &nbsp;·&nbsp; <strong>Visual family:</strong> Hardware Surface + Bottom Edge Accent<br/>
      Bottom-edge indicator lights on press; hardware surface returns to neutral on release.
      Suits command controls sharing a panel row with bottom-edge status-toggles (TUNE, LOCK).
    </p>
    <div class="demo-grid">
      {#each actionButtons as btn}
        <button
          type="button"
          class="v2-control-button"
          data-active={actionFlash[`hw-bottom-${btn.label}`] ?? false}
          data-surface="hardware"
          data-indicator-style="edge-bottom"
          data-indicator-color={btn.color}
          onclick={() => fireAction(`hw-bottom-${btn.label}`)}
        >
          {btn.label}
        </button>
      {/each}
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── Display path: StatusIndicator primitive ── -->

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── Theme Mapping Proof ──────────────────────────────────────────────── -->

  <section class="demo-card">
    <h2>Theme Mapping Proof <span class="hint">(role → family preset)</span></h2>
    <p class="lab-note">
      Select a preset mapping. Both semantic roles — <code>status-toggle</code> and <code>action-button</code> —
      render via the mapped visual family. The <strong>mixed</strong> preset is most instructive:
      it assigns different families to each role, making the semantic distinction visually legible.<br/><br/>
      Mapping lives in <code>$lib/Button/roleMapping.ts</code>. No production panels changed.
    </p>
    <div style="display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px;">
      {#each PRESET_MAPPINGS as preset}
        <button
          type="button"
          class="v2-control-button"
          data-active={activeMapping.name === preset.name}
          data-indicator-style="fill"
          data-indicator-color="cyan"
          onclick={() => { activeMapping = preset; mappingToggleStates = {}; mappingActionFlash = {}; }}
        >
          {preset.name}
        </button>
      {/each}
    </div>

    <p class="lab-note" style="margin-bottom: 8px;">
      <strong>status-toggle</strong> → <code>{activeMapping.statusToggle}</code>
    </p>
    <div class="demo-grid" style="margin-bottom: 20px;">
      {#if activeMapping.statusToggle === 'fill'}
        {#each statusToggleButtons as btn}
          <FillButton
            active={mappingToggleStates[btn.label] ?? false}
            color={btn.color}
            onclick={() => toggle(mappingToggleStates, btn.label)}
          >{btn.label}</FillButton>
        {/each}
      {:else if activeMapping.statusToggle === 'dot'}
        {#each statusToggleButtons as btn}
          <DotButton
            active={mappingToggleStates[btn.label] ?? false}
            color={btn.color}
            onclick={() => toggle(mappingToggleStates, btn.label)}
          >{btn.label}</DotButton>
        {/each}
      {:else if activeMapping.statusToggle === 'hardware-plain'}
        {#each statusToggleButtons as btn}
          <HardwarePlainButton
            active={mappingToggleStates[btn.label] ?? false}
            onclick={() => toggle(mappingToggleStates, btn.label)}
          >{btn.label}</HardwarePlainButton>
        {/each}
      {:else if activeMapping.statusToggle === 'hardware'}
        {#each statusToggleButtons as btn}
          <HardwareButton
            active={mappingToggleStates[btn.label] ?? false}
            indicator="edge-left"
            color={btn.color}
            onclick={() => toggle(mappingToggleStates, btn.label)}
          >{btn.label}</HardwareButton>
        {/each}
      {/if}
    </div>

    <p class="lab-note" style="margin-bottom: 8px;">
      <strong>action-button</strong> → <code>{activeMapping.actionButton}</code>
    </p>
    <div class="demo-grid">
      {#if activeMapping.actionButton === 'fill'}
        {#each actionButtons as btn}
          <FillButton
            active={mappingActionFlash[btn.label] ?? false}
            color={btn.color}
            onclick={() => fireMappingAction(btn.label)}
          >{btn.label}</FillButton>
        {/each}
      {:else if activeMapping.actionButton === 'dot'}
        {#each actionButtons as btn}
          <DotButton
            active={mappingActionFlash[btn.label] ?? false}
            color={btn.color}
            onclick={() => fireMappingAction(btn.label)}
          >{btn.label}</DotButton>
        {/each}
      {:else if activeMapping.actionButton === 'hardware-plain'}
        {#each actionButtons as btn}
          <HardwarePlainButton
            active={mappingActionFlash[btn.label] ?? false}
            onclick={() => fireMappingAction(btn.label)}
          >{btn.label}</HardwarePlainButton>
        {/each}
      {:else if activeMapping.actionButton === 'hardware'}
        {#each actionButtons as btn}
          <HardwareButton
            active={mappingActionFlash[btn.label] ?? false}
            indicator="edge-bottom"
            color={btn.color}
            onclick={() => fireMappingAction(btn.label)}
          >{btn.label}</HardwareButton>
        {/each}
      {/if}
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── Selector Family — SegmentedControl ───────────────────────────────── -->

  <section class="demo-card">
    <h2>Selector Family — <code>SegmentedControl</code> <span class="hint">(library name candidate)</span></h2>
    <p class="lab-note">
      <strong>SegmentedControl</strong> is the intended library name for the segmented selector primitive
      (see naming taxonomy §6.2 in the control system plan). It is exported from
      <code>$lib/SegmentedControl</code> and wraps the current <code>SegmentedButton</code> implementation.<br/><br/>
      Production panels (<code>AgcPanel</code>, <code>DspPanel</code>, <code>RfFrontEnd</code>, …) still import
      <code>SegmentedButton</code> directly — migration tracked in #345. This section is the review surface
      for selector-family API and visual variants before that migration.
    </p>
  </section>

  <section class="demo-card">
    <h2>AGC selector / flat + ring <span class="hint">(default, production pattern)</span></h2>
    <p class="lab-note">
      <strong>Real labels:</strong> OFF / FAST / MID / SLOW &nbsp;·&nbsp;
      Default <code>indicatorStyle="ring"</code>, flat surface.<br/>
      This is the current production pattern in <code>AgcPanel</code> and <code>DspPanel</code>.
    </p>
    <SegmentedControl
      options={AGC_OPTS}
      selected={selectorAgcFlat}
      onchange={(v) => { selectorAgcFlat = v as number; }}
    />
  </section>

  <section class="demo-card">
    <h2>AGC selector / flat + fill <span class="hint">(fill indicator style)</span></h2>
    <p class="lab-note">
      Same real labels, <code>indicatorStyle="fill"</code> with cyan accent.<br/>
      Matches the Fill family visual language — a thematic alternative for AGC selection.
    </p>
    <SegmentedControl
      options={AGC_OPTS}
      selected={selectorAgcFill}
      indicatorStyle="fill"
      indicatorColor="cyan"
      onchange={(v) => { selectorAgcFill = v as number; }}
    />
  </section>

  <section class="demo-card">
    <h2>AGC selector / hardware surface variants <span class="hint">(side-by-side comparison)</span></h2>
    <p class="lab-note">
      Hardware surface with two accent placements. Top row: <code>edge-bottom</code> + green.
      Bottom row: <code>dot</code> + cyan. Hardware surface makes the selector feel instrument-panel-native.
    </p>
    <div style="display: flex; flex-direction: column; gap: 10px;">
      <SegmentedControl
        options={AGC_OPTS}
        selected={selectorAgcHwEdge}
        surface="hardware"
        indicatorStyle="edge-bottom"
        indicatorColor="green"
        onchange={(v) => { selectorAgcHwEdge = v as number; }}
      />
      <SegmentedControl
        options={AGC_OPTS}
        selected={selectorAgcHwDot}
        surface="hardware"
        indicatorStyle="dot"
        indicatorColor="cyan"
        onchange={(v) => { selectorAgcHwDot = v as number; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>Notch selector / flat vs hardware <span class="hint">(side-by-side)</span></h2>
    <p class="lab-note">
      <strong>Real labels:</strong> OFF / AUTO / MAN &nbsp;·&nbsp; Three-way selector from <code>DspPanel</code>.<br/>
      Top row: flat + ring (default). Bottom row: hardware + edge-left + amber.
    </p>
    <div style="display: flex; flex-direction: column; gap: 10px;">
      <SegmentedControl
        options={NOTCH_OPTS}
        selected={selectorNotchFlat}
        onchange={(v) => { selectorNotchFlat = v as string; }}
      />
      <SegmentedControl
        options={NOTCH_OPTS}
        selected={selectorNotchHw}
        surface="hardware"
        indicatorStyle="edge-left"
        indicatorColor="amber"
        onchange={(v) => { selectorNotchHw = v as string; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>NR mode selector / flat + dot <span class="hint">(three-way, orange)</span></h2>
    <p class="lab-note">
      <strong>Real labels:</strong> OFF / NR1 / NR2 &nbsp;·&nbsp;
      Noise-reduction mode selector, orange dot indicator. Demonstrates a short three-state selector
      with distinct dot-family visual weight distinct from AGC.
    </p>
    <SegmentedControl
      options={NR_OPTS}
      selected={selectorNrFlat}
      indicatorStyle="dot"
      indicatorColor="orange"
      onchange={(v) => { selectorNrFlat = v as number; }}
    />
  </section>

  <section class="demo-card">
    <h2>Mode selector / compact <span class="hint">(six-way, full mode list)</span></h2>
    <p class="lab-note">
      <strong>Real labels:</strong> LSB / USB / AM / FM / CW / RTTY &nbsp;·&nbsp;
      <code>compact</code> mode for dense panel rows. Shows the selector scales to six options
      without breaking layout.
    </p>
    <SegmentedControl
      options={MODE_OPTS}
      selected={selectorModeCompact}
      compact
      indicatorStyle="fill"
      indicatorColor="cyan"
      onchange={(v) => { selectorModeCompact = v as string; }}
    />
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── Grid Selector — BandSelector pattern ──────────────────────────────── -->

  <section class="demo-card">
    <h2>Grid Selector — <code>BandSelector</code> pattern <span class="hint">(distinct from SegmentedControl)</span></h2>
    <p class="lab-note">
      <strong>BandSelector</strong> is the <em>grid-selector</em> branch of the selector family — intentionally
      distinct from <code>SegmentedControl</code>. Key differences:<br/><br/>
      · <strong>Layout:</strong> 4-column grid (not a horizontal strip). Scales across many options.<br/>
      · <strong>Data:</strong> driven by <code>freqRanges</code> from capabilities — dynamic, not a static list.<br/>
      · <strong>Active state:</strong> <code>data-indicator-style="fill"</code> + <code>data-indicator-color="cyan"</code> —
      token-driven path, replacing the old <code>--control-accent</code> inline style hack.<br/>
      · <strong>Shortcut hints:</strong> BSR code → keyboard shortcut via <code>getShortcutHint()</code>.<br/><br/>
      The live component lives in the BAND collapsible panel in the left sidebar.
      This section shows the static visual pattern with representative band labels.
    </p>
  </section>

  <section class="demo-card">
    <h2>Grid Selector / fill + cyan <span class="hint">(BandSelector active-state pattern)</span></h2>
    <p class="lab-note">
      <strong>Real band labels.</strong> One active at a time. Fill indicator makes the selected band
      immediately legible against the grid. <code>data-indicator-style="fill"</code> + <code>data-indicator-color="cyan"</code>.
    </p>
    <div class="band-grid-demo">
      {#each DEMO_BANDS as band}
        <button
          type="button"
          class="v2-control-button"
          data-indicator-style="fill"
          data-indicator-color="cyan"
          data-active={band === gridDemoActive}
          onclick={() => { gridDemoActive = band; }}
        >
          {band}
        </button>
      {/each}
    </div>
  </section>

  <section class="demo-card">
    <h2>StatusIndicator <span class="hint">(display-only component)</span></h2>
    <p class="lab-note">
      Read-only status/mode display. No <code>onclick</code>, rendered as a dedicated primitive.
      Replaces the old <code>badgeStyleString()</code> inline style path for display cases.
      Standard size (top row) and XS for VFO header display (bottom row).
    </p>
    <div class="demo-grid" style="margin-bottom: 8px;">
      <StatusIndicator label="TX ACTIVE" active color="red" />
      <StatusIndicator label="TX IDLE" color="muted" />
      <StatusIndicator label="RX READY" active color="cyan" />
      <StatusIndicator label="ATU OK" active color="green" />
      <StatusIndicator label="AGC" />
      <StatusIndicator label="CLEAR" active color="muted" />
    </div>
    <div class="demo-grid">
      <StatusIndicator label="USB" active color="cyan" size="xs" />
      <StatusIndicator label="FIL1" active color="green" size="xs" />
      <StatusIndicator label="SPLIT" active color="orange" size="xs" />
      <StatusIndicator label="RIT" active color="orange" size="xs" />
      <StatusIndicator label="NR" size="xs" />
      <StatusIndicator label="NB" size="xs" />
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">

  <!-- ── Value Control Family ─────────────────────────────────────────────── -->

  <section class="demo-card">
    <h2>Value Control Family <span class="hint">(exploration — status: candidate)</span></h2>
    <p class="lab-note">
      <strong>ValueControl</strong> is the unified continuous/stepped-value control primitive.
      It delegates rendering to one of three renderer implementations: <code>hbar</code>, <code>bipolar</code>, or <code>knob</code>.<br/><br/>
      · <strong>hbar</strong> — horizontal bar, left-fill. 0-to-max range. Used in production for RF Gain, AF Level, NR Level, CW Pitch.<br/>
      · <strong>bipolar</strong> — center-origin bar. Symmetric +/- range. Used in production for RIT/XIT offsets, passband shift.<br/>
      · <strong>knob</strong> — SVG rotary knob. Not yet in production — demo-only exploration.<br/><br/>
      Drag to adjust · Mouse wheel to step · Shift for fine step · Double-click to reset to default.
    </p>
  </section>

  <!-- ── HBar renderer ─────────────────────────────────────────────────────── -->

  <section class="demo-card">
    <h2>HBar / standard — accent colors <span class="hint">(real radio labels)</span></h2>
    <p class="lab-note">
      Real radio parameters with per-control accent colors matching current production convention.
      <code>accentColor</code> drives thumb border, fill glow, and focus ring.
    </p>
    <div class="vc-demo-grid">
      <ValueControl
        label="AF Level"
        value={afLevel}
        min={0} max={255} step={1}
        renderer="hbar"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { afLevel = v; }}
      />
      <ValueControl
        label="RF Gain"
        value={rfGain}
        min={0} max={255} step={1}
        renderer="hbar"
        accentColor="var(--v2-accent-green)"
        onChange={(v) => { rfGain = v; }}
      />
      <ValueControl
        label="NR Level"
        value={nrLevel}
        min={0} max={255} step={1}
        renderer="hbar"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { nrLevel = v; }}
      />
      <ValueControl
        label="NB Level"
        value={nbLevel}
        min={0} max={255} step={1}
        renderer="hbar"
        accentColor="var(--v2-accent-yellow)"
        onChange={(v) => { nbLevel = v; }}
      />
      <ValueControl
        label="Mic Gain"
        value={micGain}
        min={0} max={100} step={1}
        unit="%"
        renderer="hbar"
        accentColor="var(--v2-accent-orange)"
        onChange={(v) => { micGain = v; }}
      />
      <ValueControl
        label="TX Power"
        value={txPower}
        min={0} max={100} step={1}
        unit="%"
        renderer="hbar"
        accentColor="var(--v2-accent-red)"
        onChange={(v) => { txPower = v; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>HBar / standard — with unit and displayFn <span class="hint">(CW Pitch, Notch Freq)</span></h2>
    <p class="lab-note">
      Controls with <code>unit</code> suffix and custom <code>displayFn</code>.
      CW Pitch is 300–900 Hz in production (<code>DspPanel</code>). Notch Freq is 0–3000 Hz.
    </p>
    <div class="vc-demo-grid">
      <ValueControl
        label="CW Pitch"
        value={cwPitch}
        min={300} max={900} step={1}
        unit="Hz"
        renderer="hbar"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { cwPitch = v; }}
      />
      <ValueControl
        label="Notch Freq"
        value={notchFreq}
        min={0} max={3000} step={1}
        unit="Hz"
        renderer="hbar"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { notchFreq = v; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>HBar / compact <span class="hint">(panel-row density)</span></h2>
    <p class="lab-note">
      <code>compact</code> sizing — thinner bar (3px vs 4px), smaller thumb (7px vs 10px), 9px label font.
      Useful when controls share panel rows with buttons or selectors.
    </p>
    <div class="vc-demo-grid">
      <ValueControl
        label="AF Level"
        value={afLevelCompact}
        min={0} max={255} step={1}
        renderer="hbar"
        compact
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { afLevelCompact = v; }}
      />
      <ValueControl
        label="RF Gain"
        value={rfGainCompact}
        min={0} max={255} step={1}
        renderer="hbar"
        compact
        accentColor="var(--v2-accent-green)"
        onChange={(v) => { rfGainCompact = v; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>HBar / disabled <span class="hint">(muted state)</span></h2>
    <p class="lab-note">
      <code>disabled</code> renders at 40% opacity with <code>pointer-events: none</code>.
      Used in production for AF Level when monitor mode is muted.
    </p>
    <div class="vc-demo-grid">
      <ValueControl
        label="AF Level"
        value={afLevelDisabled}
        min={0} max={255} step={1}
        renderer="hbar"
        disabled
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { afLevelDisabled = v; }}
      />
      <ValueControl
        label="RF Gain"
        value={200}
        min={0} max={255} step={1}
        renderer="hbar"
        disabled
        accentColor="var(--v2-accent-green)"
        onChange={() => {}}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>DiscreteRenderer — Tick Styles</h2>
    <p class="lab-note">
      Three ways to show discrete steps without tick marks fighting the illuminated slot glow.
      All rows share one value — drag any control to compare styles.
    </p>

    <h3 class="vc-tickstyle-sub">Style A: Ruler (ticks below track)</h3>
    <p class="lab-note">NR Level 0–15, tickStyle='ruler', hardware-illuminated</p>
    <div class="vc-demo-grid">
      <ValueControl
        label="NR Level"
        value={discreteNrLevel}
        min={0}
        max={15}
        step={1}
        defaultValue={0}
        renderer="discrete"
        variant="hardware-illuminated"
        tickStyle="ruler"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => {
          discreteNrLevel = v;
        }}
      />
    </div>

    <h3 class="vc-tickstyle-sub">Style B: LED segments</h3>
    <p class="lab-note">NR Level 0–15, tickStyle='led', hardware-illuminated</p>
    <div class="vc-demo-grid">
      <ValueControl
        label="NR Level"
        value={discreteNrLevel}
        min={0}
        max={15}
        step={1}
        defaultValue={0}
        renderer="discrete"
        variant="hardware-illuminated"
        tickStyle="led"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => {
          discreteNrLevel = v;
        }}
      />
    </div>

    <h3 class="vc-tickstyle-sub">Style C: Notch (cuts in fill)</h3>
    <p class="lab-note">NR Level 0–15, tickStyle='notch', hardware-illuminated</p>
    <div class="vc-demo-grid">
      <ValueControl
        label="NR Level"
        value={discreteNrLevel}
        min={0}
        max={15}
        step={1}
        defaultValue={0}
        renderer="discrete"
        variant="hardware-illuminated"
        tickStyle="notch"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => {
          discreteNrLevel = v;
        }}
      />
    </div>
  </section>

  <!-- ── Bipolar renderer ──────────────────────────────────────────────────── -->

  <section class="demo-card">
    <h2>Bipolar / standard — real radio parameters <span class="hint">(center-origin bar)</span></h2>
    <p class="lab-note">
      Center-origin bar with +/- axis labels. Fill extends from center toward the active side.
      Used in production for RIT and XIT offsets in <code>RitXitPanel</code>.
      Double-click resets to 0.
    </p>
    <div class="vc-demo-grid">
      <ValueControl
        label="RIT"
        value={ritOffset}
        min={-9999} max={9999} step={1}
        defaultValue={0}
        unit="Hz"
        renderer="bipolar"
        accentColor="var(--v2-accent-cyan)"
        displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
        onChange={(v) => { ritOffset = v; }}
      />
      <ValueControl
        label="XIT"
        value={xitOffset}
        min={-9999} max={9999} step={1}
        defaultValue={0}
        unit="Hz"
        renderer="bipolar"
        accentColor="var(--v2-accent-orange)"
        displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
        onChange={(v) => { xitOffset = v; }}
      />
      <ValueControl
        label="Passband"
        value={passband}
        min={-50} max={50} step={1}
        defaultValue={0}
        renderer="bipolar"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { passband = v; }}
      />
      <ValueControl
        label="Tone"
        value={toneOffset}
        min={-50} max={50} step={1}
        defaultValue={0}
        renderer="bipolar"
        accentColor="var(--v2-accent-yellow)"
        onChange={(v) => { toneOffset = v; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>Bipolar / compact <span class="hint">(same range, reduced size)</span></h2>
    <p class="lab-note">
      <code>compact</code> shrinks bar height and axis label font. Same behavior.
    </p>
    <div class="vc-demo-grid">
      <ValueControl
        label="RIT"
        value={ritOffset}
        min={-9999} max={9999} step={1}
        defaultValue={0}
        unit="Hz"
        renderer="bipolar"
        compact
        accentColor="var(--v2-accent-cyan)"
        displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
        onChange={(v) => { ritOffset = v; }}
      />
      <ValueControl
        label="XIT"
        value={xitOffset}
        min={-9999} max={9999} step={1}
        defaultValue={0}
        unit="Hz"
        renderer="bipolar"
        compact
        accentColor="var(--v2-accent-orange)"
        displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
        onChange={(v) => { xitOffset = v; }}
      />
    </div>
  </section>

  <!-- ── Knob renderer ─────────────────────────────────────────────────────── -->

  <section class="demo-card">
    <h2>Knob / standard — accent colors <span class="hint">(demo-only, not yet in production)</span></h2>
    <p class="lab-note">
      SVG rotary knob. Drag vertically to adjust (up = increase). Mouse wheel or keyboard arrows also work.
      Default <code>arcAngle=270°</code>. Fill arc + indicator line follow position.
      Not yet used in production panels — this section is the initial review surface.
    </p>
    <div class="vc-knob-row">
      <ValueControl
        label="RF Gain"
        value={rfGainKnob}
        min={0} max={255} step={1}
        renderer="knob"
        accentColor="var(--v2-accent-green)"
        onChange={(v) => { rfGainKnob = v; }}
      />
      <ValueControl
        label="Squelch"
        value={squelchKnob}
        min={0} max={255} step={1}
        renderer="knob"
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { squelchKnob = v; }}
      />
      <ValueControl
        label="CW Pitch"
        value={cwPitchKnob}
        min={300} max={900} step={1}
        unit="Hz"
        renderer="knob"
        accentColor="var(--v2-accent-yellow)"
        onChange={(v) => { cwPitchKnob = v; }}
      />
      <ValueControl
        label="Mic Gain"
        value={micGainKnob}
        min={0} max={100} step={1}
        unit="%"
        renderer="knob"
        accentColor="var(--v2-accent-orange)"
        onChange={(v) => { micGainKnob = v; }}
      />
    </div>
  </section>

  <section class="demo-card">
    <h2>Knob / compact + ticks <span class="hint">(reduced size, with tick marks)</span></h2>
    <p class="lab-note">
      <code>compact</code> reduces SVG size from 64px to 48px. <code>tickCount</code> adds radial tick marks.
      <code>tickLabels</code> adds text labels below the knob.
    </p>
    <div class="vc-knob-row">
      <ValueControl
        label="RF Gain"
        value={rfGainKnob}
        min={0} max={255} step={1}
        renderer="knob"
        compact
        tickCount={5}
        tickLabels={['0', '', '', '', 'MAX']}
        accentColor="var(--v2-accent-green)"
        onChange={(v) => { rfGainKnob = v; }}
      />
      <ValueControl
        label="Squelch"
        value={squelchKnob}
        min={0} max={255} step={1}
        renderer="knob"
        compact
        tickCount={5}
        accentColor="var(--v2-accent-cyan)"
        onChange={(v) => { squelchKnob = v; }}
      />
    </div>
  </section>

  <hr style="margin: 32px 0; border: 0; border-top: 1px solid var(--v2-border-panel);">


  <!-- ── Hardware Illuminated Slider (5-layer exploratory) ───────────────── -->

  <section class="demo-card">
    <h2>Hardware Illuminated Slider <span class="hint">(exploratory — 5-layer industrial reference)</span></h2>
    <p class="lab-note">
      <strong>Design reference:</strong> physical illuminated slider mechanism.<br/><br/>
      Five-layer model:<br/>
      1. Outer diffuser frame (backlit plastic bezel)<br/>
      2. Recessed milled channel<br/>
      3. Illuminated slot (lamp light through opening, not CSS fill)<br/>
      4. Wide raised carriage thumb (~10% width) with 3D shadows<br/>
      5. Center slit in thumb (light transmitted through)<br/><br/>
      NOT replacing current hardware variant — this is a visual exploration
      for potential future hardware-skeuomorphic theme direction.
    </p>
  </section>

  <!-- ── Hardware Illuminated Slider ──────────────────────────────────────── -->

  <section class="demo-card vc-hw-panel">
    <h2>HBar / Hardware (current)</h2>
    <p class="lab-note">Current hardware variant for comparison.</p>
    <div class="vc-demo-grid">
      <ValueControl
        label="AF Level"
        value={vcHwCurrentAf}
        min={0} max={255} step={1}
        renderer="hbar"
        variant="hardware"
        accentColor="#c8a840"
        fillColor="#b89030"
        onChange={(v) => { vcHwCurrentAf = v; }}
      />
      <ValueControl
        label="RF Gain"
        value={vcHwCurrentRf}
        min={0} max={255} step={1}
        renderer="hbar"
        variant="hardware"
        accentColor="#7aaa60"
        fillColor="#6a9a50"
        onChange={(v) => { vcHwCurrentRf = v; }}
      />
      <ValueControl
        label="NR Level"
        value={vcHwCurrentNr}
        min={0} max={255} step={1}
        renderer="hbar"
        variant="hardware"
        accentColor="#c8a840"
        fillColor="#a88030"
        onChange={(v) => { vcHwCurrentNr = v; }}
      />
    </div>
  </section>

  <section class="demo-card vc-hw-panel">
    <h2>HBar / Hardware Illuminated</h2>
      <p class="lab-note">
        New illuminated slider concept with diffuser frame and light slot.
        Drag to see brightness variation in slot and slit.
      </p>
      <div class="vc-demo-grid">
        <ValueControl
          label="AF Level"
          value={vcIllumAf}
          min={0} max={255} step={1}
          renderer="hbar"
          variant="hardware-illuminated"
          onChange={(v) => { vcIllumAf = v; }}
        />
        <ValueControl
          label="RF Gain"
          value={vcIllumRf}
          min={0} max={255} step={1}
          renderer="hbar"
          variant="hardware-illuminated"
          onChange={(v) => { vcIllumRf = v; }}
        />
        <ValueControl
          label="NR Level"
          value={vcIllumNr}
          min={0} max={255} step={1}
          renderer="hbar"
          variant="hardware-illuminated"
          onChange={(v) => { vcIllumNr = v; }}
        />
      </div>
  </section>

  <section class="demo-card vc-hw-panel">
    <h2>Bipolar / Hardware (current)</h2>
    <p class="lab-note">Current hardware variant for comparison.</p>
    <div class="vc-demo-grid">
      <ValueControl
        label="RIT"
        value={vcHwCurrentRit}
        min={-9999} max={9999} step={1}
        defaultValue={0}
        renderer="bipolar"
        variant="hardware"
        accentColor="#c8a840"
        fillColor="#a88030"
        displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
        onChange={(v) => { vcHwCurrentRit = v; }}
      />
      <ValueControl
        label="XIT"
        value={vcHwCurrentXit}
        min={-9999} max={9999} step={1}
        defaultValue={0}
        renderer="bipolar"
        variant="hardware"
        accentColor="#c87820"
        fillColor="#a06010"
        displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
        onChange={(v) => { vcHwCurrentXit = v; }}
      />
    </div>
  </section>

  <section class="demo-card vc-hw-panel">
    <h2>Bipolar / Hardware Illuminated</h2>
      <p class="lab-note">
        Center-origin illuminated slider. Slot fills from center outward.
        Slit glows regardless of direction.
      </p>
      <div class="vc-demo-grid">
        <ValueControl
          label="RIT"
          value={vcIllumRit}
          min={-9999} max={9999} step={1}
          defaultValue={0}
          renderer="bipolar"
          variant="hardware-illuminated"
          displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
          onChange={(v) => { vcIllumRit = v; }}
        />
        <ValueControl
          label="XIT"
          value={vcIllumXit}
          min={-9999} max={9999} step={1}
          defaultValue={0}
          renderer="bipolar"
          variant="hardware-illuminated"
          displayFn={(v) => (v >= 0 ? `+${v}` : `${v}`) + '\u00a0Hz'}
          onChange={(v) => { vcIllumXit = v; }}
        />
      </div>
  </section>

</div>

<style>
  .demo-root {
    min-height: 100vh;
    padding: 24px;
    display: grid;
    gap: 16px;
    background:
      radial-gradient(circle at top, rgba(0, 212, 255, 0.08), transparent 36%),
      linear-gradient(180deg, var(--v2-bg-gradient-start) 0%, var(--v2-bg-darkest) 100%);
  }

  .demo-card {
    padding: 16px;
    border: 1px solid var(--v2-border-panel);
    border-radius: 8px;
    background: linear-gradient(180deg, var(--v2-panel-bg-gradient-top) 0%, var(--v2-panel-bg-gradient-bottom) 100%);
    box-shadow: var(--v2-shadow-sm);
  }

  h2 {
    margin: 0 0 12px;
    color: var(--v2-text-bright);
    font-family: var(--v2-font-mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  h3.vc-tickstyle-sub {
    margin: 14px 0 6px;
    color: var(--v2-text-bright);
    font-family: var(--v2-font-mono);
    font-size: 10px;
    letter-spacing: 0.06em;
    font-weight: 600;
    text-transform: none;
  }

  h3.vc-tickstyle-sub:first-of-type {
    margin-top: 0;
  }

  .hint {
    color: var(--v2-text-dim);
    font-weight: 400;
    font-size: 10px;
    letter-spacing: 0.02em;
    text-transform: none;
  }

  .demo-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }

  .band-grid-demo {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 3px;
    max-width: 280px;
  }

  .lab-note {
    margin: 0 0 14px;
    color: var(--v2-text-subdued);
    font-size: 10px;
    line-height: 1.6;
  }

  .lab-note strong {
    color: var(--v2-text-bright);
    font-weight: 700;
  }

  code {
    padding: 2px 6px;
    background: var(--v2-bg-darker);
    border: 1px solid var(--v2-border-dark);
    border-radius: 3px;
    font-family: var(--v2-font-mono);
    font-size: 10px;
    color: var(--v2-accent-cyan);
  }

  hr {
    opacity: 0.3;
  }

  .vc-demo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
  }

  .vc-knob-row {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    align-items: flex-start;
  }

  /* ── #350 — Modern Accent vs Hardware comparison layout ─────────────────── */

  .vc-family-compare {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }

  /* Hardware panel background — slightly warmer/darker than standard panel */
  .vc-hw-panel {
    background: linear-gradient(
      180deg,
      #131610 0%,
      #0e1008 100%
    );
    border-color: #2a2e1a;
  }

  /* Hardware panel h2 label — olive-green tint */
  .vc-hw-panel h2 {
    color: #8a9e78;
  }

  @media (max-width: 700px) {
    .vc-family-compare {
      grid-template-columns: 1fr;
    }
  }
</style>
