import React from 'react';
import {
  AlphaDisplay,
  Arc,
  DreamknobProvider,
  Fader,
  FlatKnob,
  Gauge,
  ImageKnob,
  Knob,
  KnobValue,
  IndicatorLamp,
  LabeledField,
  LampRow,
  LEDFader,
  LEDKnob,
  MetalKnob,
  Meter,
  MeterBridge,
  NeonKnob,
  Pointer,
  PushButton,
  Rack,
  RubberKnob,
  ScrubField,
  SegmentSwitch,
  SegmentDisplay,
  SteppedKnob,
  Ticks,
  ToggleSwitch,
  TransportButton,
  VintageKnob,
  XYPad,
  logTaper,
} from 'dreamknob';

const PRESETS = [
  { name: 'INIT PATCH', cutoff: 50 },
  { name: 'WARM PAD', cutoff: 22 },
  { name: 'ACID 303', cutoff: 84 },
];

const PresetDemo: React.FC = () => {
  const [preset, setPreset] = React.useState(0);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14 }}>
      <div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
        <FlatKnob
          size={84}
          value={PRESETS[preset].cutoff}
          onChange={() => undefined}
          readOnly
          animateChanges={{ duration: 350 }}
          color="#3df2ad"
          label="Cutoff"
          aria-label="Preset cutoff"
        />
        <AlphaDisplay value={PRESETS[preset].name} chars={10} height={16} color="#3df2ad" />
      </div>
      <div style={{ display: 'flex', gap: 8 }}>
        {PRESETS.map((p, i) => (
          <PushButton
            key={p.name}
            pressed={preset === i}
            onChange={on => on && setPreset(i)}
            color="#3df2ad"
            size={34}
            aria-label={`Preset ${p.name}`}
          >
            {String.fromCharCode(65 + i)}
          </PushButton>
        ))}
      </div>
    </div>
  );
};

/** Draw a film-strip of a simple hardware knob at runtime (stand-in for a KnobMan PNG). */
const useGeneratedStrip = (frames = 31, fs = 120): string | null => {
  const [src, setSrc] = React.useState<string | null>(null);
  React.useEffect(() => {
    const canvas = document.createElement('canvas');
    canvas.width = fs;
    canvas.height = fs * frames;
    const g = canvas.getContext('2d');
    if (!g) return;
    for (let i = 0; i < frames; i++) {
      const cx = fs / 2;
      const cy = i * fs + fs / 2;
      const angle = ((225 + (i / (frames - 1)) * 270) * Math.PI) / 180;
      const grad = g.createRadialGradient(cx - fs * 0.15, cy - fs * 0.18, fs * 0.05, cx, cy, fs * 0.45);
      grad.addColorStop(0, '#5c5f69');
      grad.addColorStop(0.65, '#26282e');
      grad.addColorStop(1, '#0e0f12');
      g.fillStyle = grad;
      g.beginPath();
      g.arc(cx, cy, fs * 0.4, 0, Math.PI * 2);
      g.fill();
      g.strokeStyle = 'rgba(0,0,0,0.65)';
      g.lineWidth = fs * 0.025;
      g.stroke();
      g.strokeStyle = '#ffd23e';
      g.lineWidth = fs * 0.05;
      g.lineCap = 'round';
      g.beginPath();
      g.moveTo(cx + Math.sin(angle) * fs * 0.16, cy - Math.cos(angle) * fs * 0.16);
      g.lineTo(cx + Math.sin(angle) * fs * 0.33, cy - Math.cos(angle) * fs * 0.33);
      g.stroke();
    }
    setSrc(canvas.toDataURL('image/png'));
  }, [frames, fs]);
  return src;
};

const MeterDemo: React.FC = () => {
  const [levels, setLevels] = React.useState<[number, number]>([-18, -20]);
  React.useEffect(() => {
    let t = 0;
    const id = setInterval(() => {
      t += 0.09;
      // Occasional hot transient so the clip LED gets to do its job.
      const spike = Math.random() < 0.04 ? 9 : 0;
      setLevels([
        -13 + Math.sin(t) * 6 + Math.random() * 7 + spike,
        -14 + Math.sin(t * 1.3 + 1) * 6 + Math.random() * 7 + spike,
      ]);
    }, 90);
    return () => clearInterval(id);
  }, []);
  return (
    <div style={{ display: 'flex', gap: 22, alignItems: 'flex-end' }}>
      <Meter
        value={levels}
        min={-60}
        max={6}
        length={132}
        peakColor="#fff"
        label="L / R"
        aria-label="Stereo level"
      />
      <MeterBridge
        channels={[
          { label: 'L', value: levels[0] },
          { label: 'R', value: levels[1] },
          { label: 'M', value: (levels[0] + levels[1]) / 2 },
          { label: 'S', value: (levels[0] - levels[1]) / 2 - 20 },
        ]}
        min={-60}
        max={6}
        length={132}
        breadth={20}
        peakTextDecimals={0}
        label="Bridge"
        aria-label="Meter bridge"
      />
    </div>
  );
};

const LampSwitchDemo: React.FC = () => {
  const [mode, setMode] = React.useState(1);
  const [armed, setArmed] = React.useState(true);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>
      <SegmentSwitch
        options={['LP', 'BP', 'HP', 'NOTCH']}
        value={mode}
        onChange={setMode}
        color="#4cc2ff"
        aria-label="Filter type"
      />
      <div style={{ display: 'flex', gap: 18, alignItems: 'center' }}>
        <IndicatorLamp on={armed} onChange={setArmed} color="#ff4d6b" label="REC" aria-label="Record arm" />
        <IndicatorLamp on={armed} readOnly blink color="#ff4d6b" label="SIG" aria-label="Signal lamp" />
        <PushButton led="dot" size={30} color="#3df2ad" defaultPressed aria-label="Snap toggle">
          ⌗
        </PushButton>
      </div>
    </div>
  );
};

const CommitModeDemo: React.FC = () => {
  const [commits, setCommits] = React.useState(0);
  return (
    <div style={{ display: 'flex', gap: 22, alignItems: 'center' }}>
      <FlatKnob
        size={84}
        defaultValue={35}
        color="#ffd23e"
        label="Release"
        commitMode="release"
        onChange={() => setCommits(n => n + 1)}
        aria-label="Release commit demo"
      />
      <div data-commit-count={commits} style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' }}>
        <SegmentDisplay value={commits} digits={3} decimals={0} height={20} color="#ffd23e" />
        <span style={{ fontSize: 10, letterSpacing: '0.08em', color: 'rgba(232,234,240,0.45)', textTransform: 'uppercase' }}>
          onChange calls
        </span>
      </div>
    </div>
  );
};

const RESOURCE_ZONES = [
  { upTo: 0.75, color: '#3df2ad' },
  { upTo: 0.9, color: '#ffd23e' },
  { upTo: 1, color: '#ff4d6b' },
];

const GaugeDemo: React.FC = () => {
  const [load, setLoad] = React.useState<[number, number]>([38, 61]);
  React.useEffect(() => {
    let t = 0;
    const id = setInterval(() => {
      t += 0.12;
      setLoad([
        Math.max(2, Math.min(100, 45 + Math.sin(t) * 30 + Math.random() * 12)),
        Math.max(2, Math.min(100, 62 + Math.sin(t * 0.7 + 2) * 26 + Math.random() * 10)),
      ]);
    }, 140);
    return () => clearInterval(id);
  }, []);
  return (
    <div style={{ display: 'flex', gap: 18, alignItems: 'center' }}>
      <Gauge value={load[0]} min={0} max={100} size={104} unit="%" label="CPU" zones={RESOURCE_ZONES} />
      <Gauge value={load[1]} min={0} max={100} size={104} unit="%" label="GPU" zones={RESOURCE_ZONES} needle={false} />
    </div>
  );
};

const SmallReadoutDemo: React.FC = () => {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setT(v => v + 1), 1000);
    return () => clearInterval(id);
  }, []);
  const hh = String(Math.floor(t / 3600) % 100).padStart(2, '0');
  const mm = String(Math.floor(t / 60) % 60).padStart(2, '0');
  const ss = String(t % 60).padStart(2, '0');
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14, alignItems: 'center' }}>
      <div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
        <SegmentDisplay value={17.5} digits={3} decimals={1} height={13} weight={1.5} />
        <SegmentDisplay value={`${hh}:${mm}:${ss}`} height={13} weight={1.4} />
      </div>
      <div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
        <SegmentDisplay value={82} digits={3} height={16} weight={1.4} zones={[
          { upTo: 74, color: '#3df2ad' },
          { upTo: 89, color: '#ffd23e' },
          { upTo: Infinity, color: '#ff4d6b' },
        ]} />
        <AlphaDisplay value="$4.20" height={15} weight={1.3} />
        <AlphaDisplay value="47%" height={15} weight={1.3} color="#3df2ad" />
      </div>
    </div>
  );
};

const PanelDemo: React.FC = () => {
  const [fresh, setFresh] = React.useState(true);
  const [mode, setMode] = React.useState(0);
  const [playing, setPlaying] = React.useState(false);
  const [armed, setArmed] = React.useState(false);
  return (
    <Rack orientation="column" title="Performer" accentColor="#c9a6ff">
      <div style={{ display: 'flex', gap: 16, alignItems: 'center', justifyContent: 'center' }}>
        <FlatKnob size={62} defaultValue={7} min={0} max={64} step={1} color="#c9a6ff"
          label="Seed" sublabel="world #7" labelSize={9} aria-label="Seed" />
        <FlatKnob size={62} defaultValue={40} min={0} max={100} color="#c9a6ff"
          label="Refresh" sublabel="every 40" labelSize={9} aria-label="Refresh" />
      </div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <TransportButton kind="play" active={playing} onClick={() => setPlaying(p => !p)} size={34} />
        <TransportButton kind="stop" onClick={() => setPlaying(false)} size={34} />
        <TransportButton kind="record" active={armed} onClick={() => setArmed(a => !a)} size={34} />
        <TransportButton kind="panic" onClick={() => { setPlaying(false); setArmed(false); }} size={34} />
      </div>
      <LabeledField label="Fresh seed" labelWidth={78}>
        <ToggleSwitch on={fresh} onChange={setFresh} color="#c9a6ff" showStateLabel aria-label="Fresh seed" />
      </LabeledField>
      <SegmentSwitch options={['SOLID', 'GRAD', 'NOISE']} value={mode} onChange={setMode} color="#c9a6ff" aria-label="Fill mode" />
      <LampRow
        lamps={[
          { label: 'Cue', on: playing, color: '#3df2ad' },
          { label: 'Rec', on: armed, color: '#ff4d6b' },
          { label: 'Seed', on: fresh, color: '#c9a6ff' },
        ]}
      />
    </Rack>
  );
};

const ImageKnobDemo: React.FC = () => {
  const src = useGeneratedStrip();
  if (!src) return null;
  return (
    <ImageKnob
      src={src}
      frames={31}
      size={92}
      defaultValue={40}
      step={1}
      showValue
      label="Sprite"
      aria-label="Film-strip demo"
    />
  );
};

const Card: React.FC<{
  title: string;
  desc: string;
  tag: string;
  children: React.ReactNode;
}> = ({ title, desc, tag, children }) => (
  <div className="card">
    <h3>{title}</h3>
    <div className="card-desc">{desc}</div>
    <div className="demo">{children}</div>
    <span className="tag">{tag}</span>
  </div>
);

export const Gallery: React.FC = () => (
  <section className="block" id="gallery">
    <div className="container">
      <div className="section-kicker">Gallery</div>
      <h2 className="section-title">Every style in the studio</h2>
      <p className="section-sub">
        A full rack of prebuilt controls — every color themeable per instance. All of
        them share the same interaction core: rotary or drag adjustment, scroll-wheel
        nudge, keyboard, fine control and double-click reset.
      </p>

      <div className="grid">
        <Card title="Flat" desc="Clean 2D arc knob for modern plugin UIs." tag="<FlatKnob />">
          <FlatKnob size={86} defaultValue={64} label="Level" aria-label="Flat demo" />
          <FlatKnob size={86} defaultValue={0} min={-50} max={50} arcFrom="center" color="#3df2ad" label="Pan" aria-label="Pan demo" />
          <FlatKnob size={86} defaultValue={30} color="#ffd23e" trackColor="rgba(255,210,62,0.15)" label="Send" aria-label="Send demo" />
        </Card>

        <Card title="Metal" desc="Brushed aluminum with a knurled rim — 3D hi-fi feel." tag="<MetalKnob />">
          <MetalKnob size={92} defaultValue={40} label="Input" aria-label="Metal demo" />
          <MetalKnob size={92} defaultValue={75} tone="dark" color="#ff9640" label="Drive" aria-label="Dark metal demo" />
        </Card>

        <Card title="Rubber" desc="Soft-touch synth knob with a glowing halo." tag="<RubberKnob />">
          <RubberKnob size={92} defaultValue={72} label="Cutoff" aria-label="Rubber demo" />
          <RubberKnob size={92} defaultValue={30} color="#4cc2ff" label="Res" aria-label="Rubber resonance demo" />
        </Card>

        <Card title="Vintage" desc="Chicken-head bakelite over a printed scale." tag="<VintageKnob />">
          <VintageKnob size={96} defaultValue={7} min={0} max={10} step={0.5} label="Volume" scaleLabels={['0', '', '', '', '', '5', '', '', '', '', '10']} aria-label="Vintage demo" />
          <VintageKnob size={96} defaultValue={4} min={0} max={10} bodyColor="#26221f" label="Tone" aria-label="Bakelite demo" />
        </Card>

        <Card title="LED" desc="Segmented ring + true seven-segment readout." tag="<LEDKnob />">
          <LEDKnob size={96} defaultValue={120} min={40} max={240} step={1} label="BPM" aria-label="LED demo" />
          <LEDKnob size={96} defaultValue={-12.5} min={-60} max={0} step={0.5} digits={4} color="#ff4d6b" label="Thresh" aria-label="Threshold demo" />
        </Card>

        <Card title="Neon" desc="A glowing arc for dark, futuristic interfaces." tag="<NeonKnob />">
          <NeonKnob size={90} defaultValue={35} label="Space" aria-label="Neon demo" />
          <NeonKnob size={90} defaultValue={80} color="#3df2ad" label="Shine" aria-label="Neon green demo" />
        </Card>

        <Card title="Stepped" desc="Detented selector with named or numeric positions." tag="<SteppedKnob />">
          <SteppedKnob size={92} positions={['LP', 'BP', 'HP', 'NT']} defaultValue={0} label="Filter" aria-label="Filter type demo" />
          <SteppedKnob size={92} min={-24} max={24} steps={9} color="#4cc2ff" defaultValue={0} label="Semi" aria-label="Semitones demo" />
        </Card>

        <Card title="Fader" desc="Absolute-position linear control, both orientations, custom caps." tag="<Fader />">
          <Fader length={130} defaultValue={-6} min={-60} max={12} step={0.5} unit=" dB" label="Main" aria-label="Fader demo" />
          <Fader length={130} defaultValue={20} step={1} capColor="#e8e8ec" capLength={26} color="#3df2ad" label="Aux" aria-label="White cap fader demo" />
          <Fader orientation="horizontal" length={150} defaultValue={35} step={1} color="#e44cff" label="X-Fade" aria-label="Crossfade demo" />
        </Card>

        <Card title="LED fader" desc="Segmented meter-style fader with color zones." tag="<LEDFader />">
          <LEDFader
            length={130}
            defaultValue={70}
            step={1}
            zones={[
              { upTo: 0.6, color: '#3df2ad' },
              { upTo: 0.85, color: '#ffd23e' },
              { upTo: 1, color: '#ff4d6b' },
            ]}
            label="Level"
            aria-label="LED fader demo"
          />
          <LEDFader
            orientation="horizontal"
            length={140}
            defaultValue={40}
            step={1}
            color="#4cc2ff"
            label="Pos"
            aria-label="Horizontal LED fader demo"
          />
        </Card>

        <Card title="Segment display" desc="The seven-segment engine, standalone." tag="<SegmentDisplay />">
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10, alignItems: 'center' }}>
            <SegmentDisplay value={128.5} digits={4} decimals={1} />
            <SegmentDisplay value={-42} digits={4} color="#ff4d6b" />
          </div>
        </Card>

        <Card title="Log taper" desc="Audio-true frequency sweep: equal ratios per turn." tag="taper={logTaper}">
          <FlatKnob
            size={92}
            min={20}
            max={20000}
            defaultValue={632}
            taper={logTaper}
            decimals={0}
            color="#3df2ad"
            format={v => (v >= 1000 ? `${(v / 1000).toFixed(1)}k` : `${Math.round(v)}`)}
            label="Freq"
            aria-label="Frequency demo"
          />
        </Card>

        <Card title="Film-strip" desc="Photoreal sprite knobs — any KnobMan-style PNG strip works. This one is drawn at runtime." tag="<ImageKnob />">
          <ImageKnobDemo />
        </Card>

        <Card title="Bipolar origin + detent" desc="Fill anchors at value 0 (not mid-travel) and the drag snaps magnetically at 0." tag="origin={0} detents={[0]}">
          <FlatKnob
            size={92}
            min={-60}
            max={12}
            step={0.5}
            defaultValue={0}
            origin={0}
            detents={[0]}
            arcFrom="center"
            color="#3df2ad"
            format={v => `${v > 0 ? '+' : ''}${v.toFixed(1)}`}
            label="Gain"
            aria-label="Bipolar gain demo"
          />
          <Fader
            length={130}
            min={-60}
            max={12}
            step={0.5}
            defaultValue={0}
            origin={0}
            detents={[0]}
            color="#3df2ad"
            format={v => `${v > 0 ? '+' : ''}${v.toFixed(1)} dB`}
            label="Trim"
            aria-label="Bipolar fader demo"
          />
        </Card>

        <Card title="Type-in editing" desc="Double-click the knob (or click a fader readout) and type the exact value — '1.2k' works too." tag="editable">
          <FlatKnob
            size={92}
            min={20}
            max={20000}
            taper={logTaper}
            decimals={0}
            defaultValue={440}
            editable
            color="#4cc2ff"
            format={v => (v >= 1000 ? `${(v / 1000).toFixed(1)}k` : `${Math.round(v)}`)}
            label="Freq"
            aria-label="Editable demo"
          />
          <Fader
            length={130}
            min={-60}
            max={12}
            step={0.5}
            defaultValue={-6}
            editable
            unit=" dB"
            label="Out"
            aria-label="Editable fader demo"
          />
        </Card>

        <Card title="Theming" desc="One provider restyles every control — accent, tracks, text, fonts. Light backgrounds too." tag="<DreamknobProvider />">
          <DreamknobProvider theme={{ accent: '#ff4d6b' }}>
            <FlatKnob size={70} defaultValue={62} label="A" aria-label="Themed A" />
            <RubberKnob size={70} defaultValue={35} label="B" aria-label="Themed B" />
          </DreamknobProvider>
          <div
            style={{
              background: '#eceef2',
              borderRadius: 10,
              padding: '12px 16px',
              display: 'flex',
              gap: 14,
              alignItems: 'center',
            }}
          >
            <DreamknobProvider base="light" theme={{ accent: '#0868c8' }}>
              <FlatKnob size={70} defaultValue={62} label="Light" aria-label="Light themed" />
            </DreamknobProvider>
          </div>
        </Card>

        <Card title="Meters" desc="Stereo metering from one component (value={[l, r]}), or a full labeled bridge with per-channel peak text. Click the clip LED to clear it." tag="<Meter /> · <MeterBridge />">
          <MeterDemo />
        </Card>

        <Card title="Lamps & switches" desc="A segmented option switch, pressable indicator lamps (blink included) and a corner-dot button — the whole panel family." tag="<SegmentSwitch /> · <IndicatorLamp />">
          <LampSwitchDemo />
        </Card>

        <Card title="Scrub field" desc="After-Effects-style numbers: drag the label to scrub, click to type, Shift for fine. '1.2k' parses too." tag="<ScrubField />">
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            <ScrubField label="Width" defaultValue={1280} min={0} max={4096} unit="px" aria-label="Width" />
            <ScrubField label="Scale" defaultValue={1} min={0} max={10} step={0.01} widthCh={5} unit="×" aria-label="Scale" />
          </div>
        </Card>

        <Card title="Release commit" desc="commitMode='release' previews the drag but your app hears one onChange, on pointer-up — for parameters that are expensive to apply." tag="commitMode='release'">
          <CommitModeDemo />
        </Card>

        <Card title="Gauge" desc="Read-only radial arc meter — the round sibling of Meter. Colors itself green→amber→red as load climbs." tag="<Gauge />">
          <GaugeDemo />
        </Card>

        <Card title="Small readouts" desc="Bold own-cell decimal + colon, weight to thicken strokes, and value-colored zones — legible at status-bar sizes. Colons and $/% are in the charset." tag="weight · zones · : $ %">
          <SmallReadoutDemo />
        </Card>

        <Card title="Panel: strip + switches" desc="Rack chrome, ToggleSwitch, TransportButton, SegmentSwitch and a LampRow — a console section, declarative." tag="<Rack /> · <ToggleSwitch /> · <TransportButton />">
          <PanelDemo />
        </Card>

        <Card title="Gradient arc" desc="Position-anchored gradient — the red zone stays at the top of travel." tag="<Arc gradient={...} />">
          <Knob size={96} min={-60} max={6} step={0.5} defaultValue={-8} aria-label="Gradient arc demo">
            <Arc
              thickness={7}
              trackColor="rgba(255,255,255,0.08)"
              gradient={[
                { at: 0, color: '#3df2ad' },
                { at: 0.72, color: '#3df2ad' },
                { at: 0.9, color: '#ffd23e' },
                { at: 1, color: '#ff4d6b' },
              ]}
            />
            <Pointer type="line" radius={33} length={12} width={3} color="#e8eaf0" />
            <KnobValue unit=" dB" color="#e8eaf0" fontSize={14} />
          </Knob>
        </Card>

        <Card title="Drag feel options" desc="Pickup mode never jumps on grab; acceleration makes fast vertical drags cover more range." tag="rotaryMode · dragAcceleration">
          <FlatKnob
            size={88}
            defaultValue={70}
            rotaryMode="pickup"
            color="#ffd23e"
            label="Pickup"
            aria-label="Pickup mode demo"
          />
          <RubberKnob
            size={88}
            defaultValue={40}
            interaction="vertical"
            dragAcceleration={2}
            hideCursorOnDrag
            showValue
            color="#4cc2ff"
            label="Accel"
            aria-label="Acceleration demo"
          />
        </Card>

        <Card title="Animated presets + buttons" desc="animateChanges tweens programmatic changes; PushButton latches or is momentary." tag="animateChanges · <PushButton />">
          <PresetDemo />
        </Card>

        <Card title="XY pad" desc="Two parameters at once — cutoff/resonance, vector mixing, FX morphing." tag="<XYPad />">
          <XYPad
            width={190}
            height={140}
            x={{ min: 20, max: 20000, step: 1, defaultValue: 800 }}
            y={{ min: 0, max: 100, step: 0.5, defaultValue: 30 }}
            formatX={v => (v >= 1000 ? `${(v / 1000).toFixed(1)}k` : `${Math.round(v)}`)}
            color="#e44cff"
            label="Filter"
            aria-label="Filter XY pad"
          />
        </Card>

        <Card title="Endless encoder" desc="wrap makes the value roll around min↔max — full-turn phase and offset dials." tag="wrap · angleRange={360}">
          <NeonKnob
            size={92}
            min={0}
            max={360}
            step={1}
            defaultValue={90}
            wrap
            angleOffset={0}
            angleRange={360}
            unit="°"
            color="#4cc2ff"
            label="Phase"
            aria-label="Phase encoder"
          />
        </Card>

        <Card title="Drag bubble" desc="A floating readout follows the gesture — keep the knob face clean." tag="valueBubble">
          <MetalKnob
            size={92}
            defaultValue={64}
            step={1}
            valueBubble
            bubbleFormat={v => `${v} %`}
            label="Blend"
            aria-label="Bubble demo"
          />
        </Card>

        <Card title="Alpha display" desc="Fourteen-segment alphanumeric LED — preset names, modes, messages." tag="<AlphaDisplay />">
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10, alignItems: 'center' }}>
            <AlphaDisplay value="DREAMKNOB" height={20} />
            <AlphaDisplay value="LP-24 SAT+2" height={16} color="#4cc2ff" />
          </div>
        </Card>

        <Card title="Compose your own" desc="Primitives + headless core = any design you want." tag="<Knob> + primitives">
          <Knob size={96} defaultValue={42} aria-label="Composed demo">
            <Ticks count={28} radius={47} length={5} width={1.5} color="rgba(255,255,255,0.12)" activeColor="#ffd23e" />
            <Arc radius={36} thickness={2.5} color="#ffd23e" trackColor="rgba(255,255,255,0.08)" cap="butt" />
            <Pointer type="triangle" radius={33} length={9} width={8} color="#ffd23e" />
            <KnobValue color="#fff" fontSize={15} />
          </Knob>
        </Card>

        <Card title="Vertical-drag mode" desc="Prefer the up/down plugin feel? One prop." tag="interaction='vertical'">
          <RubberKnob size={92} defaultValue={50} interaction="vertical" color="#3df2ad" label="Depth" showValue aria-label="Vertical drag demo" />
        </Card>
      </div>
    </div>
  </section>
);
