{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "crm-sales-call-workbench",
  "title": "Crm Sales Call Workbench",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/crm-sales-call-workbench/crm-sales-call-workbench.component.ts",
      "content": "// Edit this file to change the call, transcript, battlecard and CRM copy. State is local --\n// wire the call controls, \"End Call & Log to CRM\" and \"Log Call & Sync CRM Record\" to your\n// telephony / CRM APIs.\nimport { Component, DestroyRef, computed, effect, inject, signal, ChangeDetectionStrategy } from '@angular/core'\nimport {\n  Bot,\n  Check,\n  CheckCircle2,\n  Clock,\n  Copy,\n  Disc,\n  FileText,\n  LucideAngularModule,\n  Mic,\n  MicOff,\n  Pause,\n  Phone,\n  PhoneForwarded,\n  PhoneOff,\n  Play,\n  Plus,\n  Radio,\n  RefreshCw,\n  Save,\n  ShieldCheck,\n  Zap,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiAvatarComponent, UiAvatarFallbackComponent } from '@/ui/avatar/avatar.component'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiCheckboxComponent } from '@/ui/checkbox/checkbox.component'\nimport { UiInputComponent } from '@/ui/input/input.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport { UiTextareaComponent } from '@/ui/textarea/textarea.component'\n\nexport interface CrmSalesCallActionItem {\n  id: string\n  text: string\n  completed: boolean\n  dueDate: string\n  assignee: string\n}\n\n// 32-bar audio spectrum waveform bars\nconst waveformBars = [\n  32, 48, 65, 42, 78, 92, 84, 66, 52, 74, 96, 82, 60, 44, 58, 88, 100, 76, 62, 48, 72, 94, 80, 68, 54, 42, 68, 86, 72,\n  52, 38, 28,\n]\n\n/**\n * CrmSalesCallWorkbench -- the React block, 1:1: a live call header (status dot, running\n * timer, prospect, End Call / Reconnect), a dark audio canvas with a 32-bar waveform and\n * Mute / Hold / Transfer / Record controls, a diarized AI transcript, an objection\n * battlecard, quick deal notes with tag chips, and a next-steps checklist with an add row.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-crm-sales-call-workbench, [ui-crm-sales-call-workbench]',\n  standalone: true,\n  // React renders the root <div> itself: keep this wrapper out of the layout.\n  host: { class: 'contents' },\n  imports: [\n    LucideAngularModule,\n    UiAvatarComponent,\n    UiAvatarFallbackComponent,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiCardDescriptionComponent,\n    UiCardContentComponent,\n    UiCheckboxComponent,\n    UiInputComponent,\n    UiSeparatorComponent,\n    UiTextareaComponent,\n  ],\n  template: `\n    <div data-slot=\"crm-sales-call-workbench\" class=\"bg-background text-foreground w-full space-y-4\">\n      <!-- Top Header Bar -->\n      <header class=\"bg-card rounded-xl border p-4 shadow-xs sm:px-6 sm:py-3.5\">\n        <div class=\"flex flex-wrap items-center justify-between gap-4\">\n          <!-- Call Metadata Strip -->\n          <div class=\"flex flex-wrap items-center gap-3 sm:gap-4\">\n            <!-- Status Indicator & Timer -->\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <span class=\"relative flex size-3\">\n                @if (isLive()) {\n                  <span class=\"bg-success absolute inline-flex h-full w-full rounded-full opacity-75\"></span>\n                }\n                <span [class]=\"statusDotClass()\"></span>\n              </span>\n              <div class=\"flex items-center gap-1.5 font-mono text-sm font-semibold tracking-tight\">\n                <lucide-icon [img]=\"Clock\" class=\"text-muted-foreground size-3.5\" />\n                <span class=\"tabular-nums\">{{ statusLabel() }}</span>\n              </div>\n            </div>\n\n            <ui-separator orientation=\"vertical\" class=\"hidden h-5 sm:block\" />\n\n            <!-- Customer Name & Role -->\n            <div class=\"flex flex-wrap items-center gap-2.5\">\n              <ui-avatar class=\"size-7 border\">\n                <ui-avatar-fallback class=\"bg-primary/10 text-primary text-xs font-bold\">DC</ui-avatar-fallback>\n              </ui-avatar>\n              <div class=\"flex flex-col sm:flex-row sm:items-center sm:gap-2\">\n                <span class=\"text-foreground text-xs font-bold sm:text-sm\">David Chen</span>\n                <span class=\"text-muted-foreground text-xs\">VP of Engineering at Acme Corp</span>\n              </div>\n            </div>\n\n            <ui-separator orientation=\"vertical\" class=\"hidden h-5 md:block\" />\n\n            <!-- Phone & Carrier Strip -->\n            <div class=\"hidden items-center gap-2 md:flex\">\n              <span ui-badge variant=\"outline\" class=\"gap-1.5 font-mono text-xs font-medium\">\n                <lucide-icon [img]=\"Phone\" class=\"text-success size-3\" />\n                <span>+1 (415) 555-0192</span>\n              </span>\n              <span ui-badge variant=\"secondary\" class=\"text-xs font-normal\">Acme Corp · 500 Seats ($180k ARR)</span>\n            </div>\n          </div>\n\n          <!-- Header Actions: End Call / Sync -->\n          <div class=\"flex flex-wrap items-center gap-2.5\">\n            <div class=\"text-muted-foreground hidden items-center gap-1.5 text-xs lg:flex\">\n              <lucide-icon [img]=\"Radio\" class=\"text-success size-3.5\" />\n              <span class=\"font-mono text-xs\">Opus HD · 14ms Latency</span>\n            </div>\n\n            @if (!isCallEnded()) {\n              <button\n                ui-button\n                variant=\"destructive\"\n                size=\"sm\"\n                class=\"h-8 gap-1.5 px-3 text-xs font-semibold shadow-xs\"\n                (click)=\"endCall()\"\n              >\n                <lucide-icon [img]=\"PhoneOff\" class=\"size-3.5\" />\n                <span>End Call &amp; Log to CRM</span>\n              </button>\n            } @else {\n              <button\n                ui-button\n                variant=\"default\"\n                size=\"sm\"\n                class=\"h-8 gap-1.5 px-3 text-xs font-semibold shadow-xs\"\n                (click)=\"reconnectCall()\"\n              >\n                <lucide-icon [img]=\"RefreshCw\" class=\"size-3.5\" />\n                <span>Reconnect Call</span>\n              </button>\n            }\n          </div>\n        </div>\n      </header>\n\n      <!-- 2-Column Call Workspace Grid (60% Left / 40% Right) -->\n      <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-12\">\n        <!-- Left Panel: Live Audio Visualizer & Real-Time AI Transcript (60% -> 7 Cols) -->\n        <div class=\"space-y-4 lg:col-span-7 xl:col-span-7\">\n          <!-- Audio Dialing Canvas -->\n          <section\n            class=\"relative flex flex-col justify-between overflow-hidden rounded-xl border border-zinc-800 bg-zinc-950 p-5 text-white shadow-lg\"\n          >\n            <!-- Top Overlay: Speaker Status & WebRTC Specs -->\n            <div class=\"flex flex-wrap items-center justify-between gap-3\">\n              <!-- Active Speaker Info -->\n              <div\n                class=\"flex flex-wrap items-center gap-2.5 rounded-lg border border-zinc-800 bg-zinc-900/80 p-2 backdrop-blur-xs\"\n              >\n                <div class=\"relative\">\n                  <ui-avatar class=\"border-success/60 size-8 border\">\n                    <ui-avatar-fallback class=\"text-success bg-zinc-800 text-xs font-bold\">DC</ui-avatar-fallback>\n                  </ui-avatar>\n                  @if (isLive()) {\n                    <span\n                      class=\"bg-success absolute -right-0.5 -bottom-0.5 size-2.5 rounded-full ring-2 ring-zinc-950\"\n                    ></span>\n                  }\n                </div>\n                <div>\n                  <div class=\"flex items-center gap-1.5\">\n                    <span class=\"text-xs font-semibold text-zinc-100\">David Chen</span>\n                    <span\n                      ui-badge\n                      variant=\"outline\"\n                      class=\"border-success/40 bg-success/20 text-success px-1 py-0 text-xs\"\n                    >\n                      Speaking\n                    </span>\n                  </div>\n                  <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n                    <lucide-icon [img]=\"Mic\" class=\"text-success size-3\" />\n                    <span>Acme Corp · Audio Level: -14 dB</span>\n                  </div>\n                </div>\n              </div>\n\n              <!-- Call Encryption & Recording Status -->\n              <div class=\"flex flex-wrap items-center gap-2\">\n                @if (isRecording()) {\n                  <div\n                    class=\"border-destructive/40 bg-destructive/15 text-destructive flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs\"\n                  >\n                    <span class=\"bg-destructive size-2 animate-pulse rounded-full\"></span>\n                    <span class=\"font-mono text-xs font-semibold\">REC 08:42</span>\n                  </div>\n                }\n                <div\n                  class=\"flex items-center gap-1.5 rounded-lg border border-zinc-800 bg-zinc-900/80 px-2.5 py-1 text-xs text-zinc-300\"\n                >\n                  <lucide-icon [img]=\"ShieldCheck\" class=\"text-success size-3.5\" />\n                  <span class=\"font-mono text-xs\">WebRTC AES-256</span>\n                </div>\n              </div>\n            </div>\n\n            <!-- Live 32-Bar Audio Waveform Visualizer -->\n            <div class=\"my-6 flex flex-col items-center justify-center space-y-3\">\n              <div class=\"flex h-24 w-full items-center justify-between gap-1 px-1 sm:gap-1.5 sm:px-4\">\n                @for (bar of waveformBars; track $index) {\n                  <div [class]=\"barClass($index)\" [style]=\"barStyle(bar, $index)\"></div>\n                }\n              </div>\n\n              <!-- Frequency Scale & Stream Diagnostics -->\n              <div\n                class=\"text-muted-foreground flex w-full items-center justify-between px-2 font-mono text-xs sm:px-6\"\n              >\n                <span class=\"shrink-0 whitespace-nowrap\">-48 dB</span>\n                <span class=\"text-muted-foreground min-w-0 text-center\">\n                  32-Band AI Audio Spectrum · Real-time Voice Detection\n                </span>\n                <span class=\"shrink-0 whitespace-nowrap\">0 dB</span>\n              </div>\n            </div>\n\n            <!-- Audio Controls Bar -->\n            <div class=\"flex items-center justify-center pt-2\">\n              <div\n                class=\"flex flex-wrap items-center justify-center gap-2 rounded-full border border-zinc-800 bg-zinc-900/90 p-1.5 shadow-xl sm:px-4 sm:py-2\"\n              >\n                <!-- Mute Button -->\n                <button\n                  ui-button\n                  [variant]=\"isMuted() ? 'destructive' : 'secondary'\"\n                  size=\"sm\"\n                  class=\"h-8 gap-1.5 rounded-full px-3 text-xs font-medium\"\n                  (click)=\"isMuted.set(!isMuted())\"\n                >\n                  @if (isMuted()) {\n                    <lucide-icon [img]=\"MicOff\" class=\"size-3.5\" />\n                  } @else {\n                    <lucide-icon [img]=\"Mic\" class=\"text-success size-3.5\" />\n                  }\n                  <span>{{ isMuted() ? 'Muted' : 'Mute Mic' }}</span>\n                </button>\n\n                <!-- Hold Call Button -->\n                <button\n                  ui-button\n                  [variant]=\"isOnHold() ? 'default' : 'secondary'\"\n                  size=\"sm\"\n                  class=\"h-8 gap-1.5 rounded-full px-3 text-xs font-medium\"\n                  (click)=\"isOnHold.set(!isOnHold())\"\n                >\n                  @if (isOnHold()) {\n                    <lucide-icon [img]=\"Play\" class=\"text-warning size-3.5\" />\n                  } @else {\n                    <lucide-icon [img]=\"Pause\" class=\"size-3.5\" />\n                  }\n                  <span>{{ isOnHold() ? 'Resume Call' : 'Hold Call' }}</span>\n                </button>\n\n                <!-- Transfer Button -->\n                <button\n                  ui-button\n                  variant=\"secondary\"\n                  size=\"sm\"\n                  class=\"h-8 gap-1.5 rounded-full px-3 text-xs font-medium text-zinc-200\"\n                >\n                  <lucide-icon [img]=\"PhoneForwarded\" class=\"text-muted-foreground size-3.5\" />\n                  <span>Transfer</span>\n                </button>\n\n                <!-- Record Toggle Button -->\n                <button\n                  ui-button\n                  [variant]=\"isRecording() ? 'destructive' : 'secondary'\"\n                  size=\"sm\"\n                  class=\"h-8 gap-1.5 rounded-full px-3 text-xs font-medium\"\n                  (click)=\"isRecording.set(!isRecording())\"\n                >\n                  <!-- [class] (not class=) feeds only the svg, so the spin is not applied twice (host + svg). -->\n                  <lucide-icon [img]=\"Disc\" [class]=\"isRecording() ? 'size-3.5 animate-spin' : 'size-3.5'\" />\n                  <span>{{ isRecording() ? 'Recording' : 'Record' }}</span>\n                </button>\n              </div>\n            </div>\n          </section>\n\n          <!-- Real-Time AI Live Speech Transcript -->\n          <ui-card class=\"shadow-xs\">\n            <ui-card-header class=\"border-b px-4 py-3 sm:px-5\">\n              <div class=\"flex flex-wrap items-center justify-between gap-2\">\n                <div class=\"space-y-0.5\">\n                  <ui-card-title class=\"flex flex-wrap items-center gap-2 text-sm font-bold\">\n                    <lucide-icon [img]=\"Bot\" class=\"text-primary size-4\" />\n                    <span>Real-Time AI Live Speech Transcript</span>\n                  </ui-card-title>\n                  <ui-card-description class=\"text-xs\">\n                    Deepgram Nova-2 STT · Real-time diarization &amp; sentiment detection\n                  </ui-card-description>\n                </div>\n                <span\n                  ui-badge\n                  variant=\"outline\"\n                  class=\"border-success/30 bg-success/10 text-success gap-1.5 text-xs font-medium\"\n                >\n                  <span class=\"bg-success size-1.5 animate-pulse rounded-full\"></span>\n                  <span>Live Diarization</span>\n                </span>\n              </div>\n            </ui-card-header>\n\n            <ui-card-content class=\"space-y-4 p-4 sm:p-5\">\n              <!-- Turn 1: Elena Rostova -->\n              <div class=\"space-y-1.5\">\n                <div class=\"flex flex-wrap items-center justify-between gap-2\">\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <ui-avatar class=\"size-6\">\n                      <ui-avatar-fallback class=\"bg-primary/20 text-primary text-xs font-bold\">ER</ui-avatar-fallback>\n                    </ui-avatar>\n                    <span class=\"text-foreground text-xs font-bold\">Elena Rostova</span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">Account Executive (You)</span>\n                  </div>\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"border-info/30 bg-info/10 text-info text-xs\"\n                      >Discovery</span\n                    >\n                    <span class=\"text-muted-foreground font-mono text-xs\">08:12</span>\n                  </div>\n                </div>\n                <div class=\"bg-muted/30 text-foreground rounded-lg border p-3 text-xs leading-relaxed\">\n                  \"Thanks for walking us through your current build setup, David. You mentioned earlier that team\n                  velocity slowed down during the last framework migration. How is that impacting your Q3 delivery\n                  milestones?\"\n                </div>\n              </div>\n\n              <!-- Turn 2: David Chen (Objection) -->\n              <div class=\"space-y-1.5\">\n                <div class=\"flex flex-wrap items-center justify-between gap-2\">\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <ui-avatar class=\"size-6\">\n                      <ui-avatar-fallback class=\"bg-warning/20 text-warning text-xs font-bold\">DC</ui-avatar-fallback>\n                    </ui-avatar>\n                    <span class=\"text-foreground text-xs font-bold\">David Chen</span>\n                    <span ui-badge variant=\"secondary\" class=\"text-xs font-normal\">Prospect (Acme Corp)</span>\n                  </div>\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"border-warning/40 bg-warning/10 text-warning text-xs\">\n                      Budget Hesitation\n                    </span>\n                    <span class=\"text-muted-foreground font-mono text-xs\">08:24</span>\n                  </div>\n                </div>\n                <div class=\"bg-muted/30 text-foreground space-y-2 rounded-lg border p-3 text-xs leading-relaxed\">\n                  <p>\n                    \"Right now we're spending around 12 engineering hours a week just fixing broken dependency cascades\n                    across 40 micro-frontends whenever upstream packages release major semver bumps. We want to\n                    standardize, but leadership is wary of signing another 6-figure SaaS vendor contract this quarter.\"\n                  </p>\n                  <!-- AI Extracted Entities -->\n                  <div class=\"flex flex-wrap items-center gap-1.5 border-t pt-2 text-xs\">\n                    <span class=\"text-muted-foreground font-medium\">AI Entities:</span>\n                    <span class=\"bg-warning/10 text-warning rounded px-1.5 py-0.5 font-mono text-xs\">\n                      40 micro-frontends\n                    </span>\n                    <span class=\"bg-warning/10 text-warning rounded px-1.5 py-0.5 font-mono text-xs\">\n                      12 eng hrs/wk debt\n                    </span>\n                    <span class=\"bg-warning/10 text-warning rounded px-1.5 py-0.5 font-mono text-xs\">\n                      Objection: 6-figure SaaS cost\n                    </span>\n                  </div>\n                </div>\n              </div>\n\n              <!-- Turn 3: Elena Rostova (Value Prop) -->\n              <div class=\"space-y-1.5\">\n                <div class=\"flex flex-wrap items-center justify-between gap-2\">\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <ui-avatar class=\"size-6\">\n                      <ui-avatar-fallback class=\"bg-primary/20 text-primary text-xs font-bold\">ER</ui-avatar-fallback>\n                    </ui-avatar>\n                    <span class=\"text-foreground text-xs font-bold\">Elena Rostova</span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">Account Executive (You)</span>\n                  </div>\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"border-success/30 bg-success/10 text-success text-xs\">\n                      Value Proposition\n                    </span>\n                    <span class=\"text-muted-foreground font-mono text-xs\">08:31</span>\n                  </div>\n                </div>\n                <div class=\"bg-muted/30 text-foreground rounded-lg border p-3 text-xs leading-relaxed\">\n                  \"That makes total sense. With UIPKGE's registry distribution model, your engineers copy the exact\n                  source code directly into your own repositories. You own the code completely, eliminate runtime npm\n                  lock-in, and never deal with breaking semver upgrades again.\"\n                </div>\n              </div>\n\n              <!-- Turn 4: David Chen (Buying Signal) -->\n              <div class=\"space-y-1.5\">\n                <div class=\"flex flex-wrap items-center justify-between gap-2\">\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <ui-avatar class=\"size-6\">\n                      <ui-avatar-fallback class=\"bg-success/20 text-success text-xs font-bold\">DC</ui-avatar-fallback>\n                    </ui-avatar>\n                    <span class=\"text-foreground text-xs font-bold\">David Chen</span>\n                    <span ui-badge variant=\"secondary\" class=\"text-xs font-normal\">Prospect (Acme Corp)</span>\n                  </div>\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span\n                      ui-badge\n                      variant=\"outline\"\n                      class=\"border-success/40 bg-success/15 text-success text-xs font-medium\"\n                    >\n                      Positive Intent\n                    </span>\n                    <span class=\"text-muted-foreground font-mono text-xs\">08:42</span>\n                  </div>\n                </div>\n                <div class=\"bg-muted/30 text-foreground space-y-2 rounded-lg border p-3 text-xs leading-relaxed\">\n                  <p>\n                    \"That would honestly solve our biggest compliance and dependency audit headache. If we can verify\n                    SOC2 Type II and get our SecOps team to review your DPA, we'd be ready to proceed with a 500-seat\n                    Enterprise rollout next month.\"\n                  </p>\n                  <div class=\"flex flex-wrap items-center justify-between gap-2 border-t pt-2 text-xs\">\n                    <div class=\"text-success flex items-center gap-1.5\">\n                      <lucide-icon [img]=\"CheckCircle2\" class=\"size-3.5\" />\n                      <span class=\"font-medium\">Buying Signal: 500 seats ($180k ARR) pending SOC2 &amp; DPA</span>\n                    </div>\n                    <span class=\"text-muted-foreground text-xs\">AI Confidence: 99.4%</span>\n                  </div>\n                </div>\n              </div>\n\n              <!-- Active Live Listening Indicator -->\n              <div class=\"bg-muted/20 flex items-center justify-between rounded-lg border border-dashed p-3 text-xs\">\n                <div class=\"text-muted-foreground flex flex-wrap items-center gap-2 text-xs\">\n                  <span class=\"bg-success size-2 rounded-full\"></span>\n                  <span class=\"text-foreground font-medium\">Real-time speech stream active...</span>\n                  <span>listening to David Chen</span>\n                </div>\n                <span class=\"text-muted-foreground font-mono text-xs\">Deepgram Nova-2 STT</span>\n              </div>\n            </ui-card-content>\n          </ui-card>\n        </div>\n\n        <!-- Right Panel: AI Battlecards & CRM Note Logger (40% -> 5 Cols) -->\n        <div class=\"space-y-4 lg:col-span-5 xl:col-span-5\">\n          <!-- Real-Time AI Objection Handling Battlecard -->\n          <ui-card class=\"border-primary/40 from-primary/5 via-card to-card bg-gradient-to-br shadow-xs\">\n            <ui-card-header class=\"px-4 pt-4 pb-2 sm:px-5\">\n              <div class=\"flex items-center justify-between\">\n                <span\n                  ui-badge\n                  variant=\"outline\"\n                  class=\"border-primary/30 bg-primary/10 text-primary gap-1.5 text-xs font-semibold\"\n                >\n                  <lucide-icon [img]=\"Zap\" class=\"text-primary size-3\" />\n                  <span>AI Battlecard · Live Trigger</span>\n                </span>\n                <span class=\"text-muted-foreground font-mono text-xs\">Confidence: 98%</span>\n              </div>\n              <ui-card-title class=\"text-foreground pt-1.5 text-sm font-bold\">\n                Competitor / Pricing Objection: Legacy NPM Packages\n              </ui-card-title>\n              <ui-card-description class=\"text-xs\">\n                Triggered by mention of 6-figure SaaS vendor fatigue &amp; dependency cascades\n              </ui-card-description>\n            </ui-card-header>\n\n            <ui-card-content class=\"space-y-3 px-4 pb-4 sm:px-5\">\n              <!-- AI Counter-Points List -->\n              <div class=\"bg-card space-y-2.5 rounded-lg border p-3 text-xs\">\n                <div class=\"text-foreground flex items-center gap-1.5 font-bold\">\n                  <lucide-icon [img]=\"Zap\" class=\"text-primary size-3.5\" />\n                  <span>Recommended Response Points:</span>\n                </div>\n\n                <div class=\"space-y-2 text-xs\">\n                  <div class=\"flex items-start gap-2\">\n                    <span\n                      class=\"bg-primary/20 text-primary mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full text-xs font-bold\"\n                    >\n                      1\n                    </span>\n                    <p class=\"text-muted-foreground leading-relaxed\">\n                      <strong class=\"text-foreground font-semibold\">Zero-Dependency Ownership:</strong> Code is copied\n                      directly into Acme's repos via CLI (<code class=\"text-foreground bg-muted rounded px-1\"\n                        >npx shadcn-vue add</code\n                      >). Zero npm runtime lock-in.\n                    </p>\n                  </div>\n\n                  <div class=\"flex items-start gap-2\">\n                    <span\n                      class=\"bg-primary/20 text-primary mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full text-xs font-bold\"\n                    >\n                      2\n                    </span>\n                    <p class=\"text-muted-foreground leading-relaxed\">\n                      <strong class=\"text-foreground font-semibold\">Eliminate Upgrade Cascades:</strong> Reclaim the 12\n                      hrs/week engineering maintenance debt David mentioned.\n                    </p>\n                  </div>\n\n                  <div class=\"flex items-start gap-2\">\n                    <span\n                      class=\"bg-primary/20 text-primary mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full text-xs font-bold\"\n                    >\n                      3\n                    </span>\n                    <p class=\"text-muted-foreground leading-relaxed\">\n                      <strong class=\"text-foreground font-semibold\">Fast Enterprise ROI:</strong> Predictable team seat\n                      license pays for itself in under 3 weeks of reclaimed developer hours.\n                    </p>\n                  </div>\n                </div>\n              </div>\n\n              <!-- Copy Talking Points Button -->\n              <button\n                ui-button\n                variant=\"outline\"\n                size=\"sm\"\n                class=\"w-full gap-1.5 text-xs font-semibold\"\n                (click)=\"copyTalkingPoints()\"\n              >\n                @if (copiedTalkingPoints()) {\n                  <lucide-icon [img]=\"Check\" class=\"text-success size-3.5\" />\n                } @else {\n                  <lucide-icon [img]=\"Copy\" class=\"size-3.5\" />\n                }\n                <span>{{\n                  copiedTalkingPoints() ? 'Talking Points Copied to Clipboard!' : 'Copy Talking Points to Clipboard'\n                }}</span>\n              </button>\n            </ui-card-content>\n          </ui-card>\n\n          <!-- Quick Deal Notes Textarea -->\n          <ui-card class=\"shadow-xs\">\n            <ui-card-header class=\"px-4 pt-4 pb-2 sm:px-5\">\n              <div class=\"flex items-center justify-between\">\n                <ui-card-title class=\"flex items-center gap-1.5 text-sm font-bold\">\n                  <lucide-icon [img]=\"FileText\" class=\"text-primary size-4\" />\n                  <span>Quick Deal Notes</span>\n                </ui-card-title>\n                <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n                  <lucide-icon [img]=\"CheckCircle2\" class=\"text-success size-3.5\" />\n                  <span>Synced with Salesforce</span>\n                </div>\n              </div>\n              <ui-card-description class=\"text-xs\">\n                Live call documentation synced to Opportunity #ACME-9481\n              </ui-card-description>\n            </ui-card-header>\n\n            <ui-card-content class=\"space-y-3 px-4 pb-4 sm:px-5\">\n              <ui-textarea\n                [value]=\"dealNotes()\"\n                (valueChange)=\"dealNotes.set($event)\"\n                [rows]=\"4\"\n                class=\"resize-y text-xs leading-relaxed\"\n                placeholder=\"Enter call notes, key customer requirements, and objections...\"\n              />\n\n              <!-- Quick Append Tags -->\n              <div class=\"space-y-1.5\">\n                <span class=\"text-muted-foreground text-xs font-medium\">Quick Tags:</span>\n                <div class=\"flex flex-wrap gap-1.5\">\n                  <button\n                    ui-button\n                    variant=\"outline\"\n                    size=\"sm\"\n                    class=\"h-6 px-2 text-xs\"\n                    (click)=\"appendTag('SOC2-Security')\"\n                  >\n                    + #soc2-security\n                  </button>\n                  <button\n                    ui-button\n                    variant=\"outline\"\n                    size=\"sm\"\n                    class=\"h-6 px-2 text-xs\"\n                    (click)=\"appendTag('500-Seats')\"\n                  >\n                    + #500-seats\n                  </button>\n                  <button\n                    ui-button\n                    variant=\"outline\"\n                    size=\"sm\"\n                    class=\"h-6 px-2 text-xs\"\n                    (click)=\"appendTag('DPA-Review')\"\n                  >\n                    + #dpa-review\n                  </button>\n                  <button\n                    ui-button\n                    variant=\"outline\"\n                    size=\"sm\"\n                    class=\"h-6 px-2 text-xs\"\n                    (click)=\"appendTag('Q3-Close')\"\n                  >\n                    + #q3-close\n                  </button>\n                </div>\n              </div>\n\n              <!-- Opportunity Metrics Strip -->\n              <div class=\"bg-muted/30 grid grid-cols-3 gap-2 rounded-lg border p-2.5 text-center text-xs\">\n                <div>\n                  <span class=\"text-muted-foreground block text-xs\">Deal Value</span>\n                  <span class=\"text-foreground font-mono font-bold\">$180,000</span>\n                </div>\n                <div class=\"border-x\">\n                  <span class=\"text-muted-foreground block text-xs\">Stage</span>\n                  <span class=\"text-foreground font-semibold\">Negotiation</span>\n                </div>\n                <div>\n                  <span class=\"text-muted-foreground block text-xs\">Win Prob.</span>\n                  <span class=\"text-success font-semibold\">85%</span>\n                </div>\n              </div>\n            </ui-card-content>\n          </ui-card>\n\n          <!-- Next Steps Checklist -->\n          <ui-card class=\"shadow-xs\">\n            <ui-card-header class=\"px-4 pt-4 pb-2 sm:px-5\">\n              <div class=\"flex items-center justify-between\">\n                <ui-card-title class=\"flex items-center gap-1.5 text-sm font-bold\">\n                  <lucide-icon [img]=\"CheckCircle2\" class=\"text-primary size-4\" />\n                  <span>Next Steps Checklist</span>\n                </ui-card-title>\n                <span ui-badge variant=\"secondary\" class=\"text-xs\"\n                  >{{ completedCount() }}/{{ actionItems().length }} Done</span\n                >\n              </div>\n              <ui-card-description class=\"text-xs\">\n                Action items committed during call. Checked items auto-create CRM tasks.\n              </ui-card-description>\n            </ui-card-header>\n\n            <ui-card-content class=\"space-y-3 px-4 pb-4 sm:px-5\">\n              <div class=\"space-y-2\">\n                @for (item of actionItems(); track item.id) {\n                  <div\n                    class=\"bg-muted/20 hover:bg-muted/40 flex items-start gap-2.5 rounded-lg border p-2.5 transition-colors\"\n                  >\n                    <ui-checkbox\n                      [id]=\"item.id\"\n                      [checked]=\"item.completed\"\n                      (checkedChange)=\"toggleStep(item.id)\"\n                      class=\"mt-0.5\"\n                    />\n                    <div class=\"flex-1 space-y-0.5\">\n                      <label [attr.for]=\"item.id\" [class]=\"stepLabelClass(item.completed)\">{{ item.text }}</label>\n                      <div class=\"text-muted-foreground flex flex-wrap items-center gap-2 text-xs\">\n                        <span>{{ item.dueDate }}</span>\n                        <span>·</span>\n                        <span>{{ item.assignee }}</span>\n                      </div>\n                    </div>\n                  </div>\n                }\n              </div>\n\n              <!-- Add Item Row -->\n              <div class=\"flex flex-wrap items-center gap-2 pt-1\">\n                <ui-input\n                  [value]=\"newItemText()\"\n                  (valueChange)=\"newItemText.set($event)\"\n                  placeholder=\"Add custom action item...\"\n                  class=\"h-8 text-xs\"\n                  (keydown)=\"onNewItemKeydown($event)\"\n                />\n                <button\n                  ui-button\n                  size=\"sm\"\n                  variant=\"outline\"\n                  class=\"h-8 shrink-0 px-3 text-xs\"\n                  [disabled]=\"!newItemText().trim()\"\n                  (click)=\"addActionItem()\"\n                >\n                  <lucide-icon [img]=\"Plus\" class=\"size-3.5\" />\n                  <span>Add</span>\n                </button>\n              </div>\n\n              <!-- Sync Button -->\n              <div class=\"border-t pt-2\">\n                <button ui-button size=\"sm\" class=\"w-full gap-1.5 text-xs font-semibold shadow-xs\" (click)=\"syncCrm()\">\n                  @if (isSyncedCrm()) {\n                    <lucide-icon [img]=\"Check\" class=\"size-3.5\" />\n                  } @else {\n                    <lucide-icon [img]=\"Save\" class=\"size-3.5\" />\n                  }\n                  <span>{{\n                    isSyncedCrm() ? 'Call Summary & Tasks Logged to CRM!' : 'Log Call & Sync CRM Record'\n                  }}</span>\n                </button>\n              </div>\n            </ui-card-content>\n          </ui-card>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiCrmSalesCallWorkbenchComponent {\n  private readonly timers = new Set<ReturnType<typeof setTimeout>>()\n\n  // Interactive Call State\n  readonly isMuted = signal(false)\n  readonly isOnHold = signal(false)\n  readonly isRecording = signal(true)\n  readonly isCallEnded = signal(false)\n  readonly callDurationSeconds = signal(522) // 08m:42s\n  readonly copiedTalkingPoints = signal(false)\n  readonly isSyncedCrm = signal(false)\n  readonly newItemText = signal('')\n\n  // CRM Deal Notes State\n  readonly dealNotes = signal(\n    'David Chen (VP of Eng) confirmed Acme Corp has 40 micro-frontends facing frequent dependency breakages (~12 eng hrs/week maintenance debt). Highly receptive to UIPKGE zero-dependency registry model. Key decision factor: SOC2 Type II compliance and DPA sign-off. Deal size: 500 seats ($180k ARR). Target close: Q3 end.',\n  )\n\n  // Next Steps Checklist State\n  readonly actionItems = signal<CrmSalesCallActionItem[]>([\n    {\n      id: 'step-1',\n      text: 'Send SOC2 Type II compliance package & Security Whitepaper',\n      completed: true,\n      dueDate: 'Today · 2:00 PM',\n      assignee: 'Elena Rostova',\n    },\n    {\n      id: 'step-2',\n      text: 'Schedule DPA legal review with Acme SecOps team',\n      completed: true,\n      dueDate: 'Tomorrow · 10:00 AM',\n      assignee: 'Elena Rostova',\n    },\n    {\n      id: 'step-3',\n      text: 'Draft 500-seat Enterprise MSA & customized Order Form',\n      completed: false,\n      dueDate: 'Thu, Aug 27',\n      assignee: 'Legal Ops',\n    },\n    {\n      id: 'step-4',\n      text: 'Send post-call recap email with call recording & transcript highlights',\n      completed: false,\n      dueDate: 'Today · 5:00 PM',\n      assignee: 'Elena Rostova',\n    },\n  ])\n\n  readonly isLive = computed(() => !this.isCallEnded() && !this.isOnHold())\n  readonly completedCount = computed(() => this.actionItems().filter((i) => i.completed).length)\n\n  readonly formattedDuration = computed(() => {\n    const seconds = this.callDurationSeconds()\n    const mins = Math.floor(seconds / 60)\n    const secs = seconds % 60\n    return `${mins.toString().padStart(2, '0')}m:${secs.toString().padStart(2, '0')}s`\n  })\n\n  readonly statusLabel = computed(() =>\n    this.isCallEnded()\n      ? 'Call Ended'\n      : this.isOnHold()\n        ? 'Call On Hold'\n        : `Live Call in Progress · ${this.formattedDuration()}`,\n  )\n\n  readonly statusDotClass = computed(() =>\n    cn(\n      'relative inline-flex size-3 rounded-full',\n      this.isCallEnded() ? 'bg-zinc-400' : this.isOnHold() ? 'bg-warning' : 'bg-success',\n    ),\n  )\n\n  protected readonly waveformBars = waveformBars\n\n  constructor() {\n    // Timer: ticks while the call is live, pauses on hold, stops when the call ends.\n    effect((onCleanup) => {\n      if (this.isCallEnded() || this.isOnHold()) return\n      const interval = setInterval(() => this.callDurationSeconds.update((prev) => prev + 1), 1000)\n      onCleanup(() => clearInterval(interval))\n    })\n    inject(DestroyRef).onDestroy(() => {\n      for (const t of this.timers) clearTimeout(t)\n      this.timers.clear()\n    })\n  }\n\n  barClass(index: number): string {\n    const ended = this.isCallEnded()\n    const onHold = this.isOnHold()\n    const muted = this.isMuted()\n    const isBarMuted = muted && index % 2 === 0\n    return cn(\n      'w-full max-w-[8px] rounded-full transition-[height] duration-200',\n      ended\n        ? 'h-2 bg-zinc-800'\n        : onHold\n          ? 'bg-warning/60 h-3'\n          : isBarMuted\n            ? 'h-2 bg-zinc-700'\n            : 'bg-gradient-to-t from-emerald-500 to-teal-300',\n      !ended && !onHold && !muted ? 'animate-pulse' : '',\n    )\n  }\n\n  /** Runtime values per bar (height from the spectrum, a staggered pulse), as React's inline style. */\n  barStyle(bar: number, index: number): Record<string, string> {\n    return {\n      height: this.isCallEnded() ? '8%' : this.isOnHold() ? '16%' : `${bar}%`,\n      'animation-delay': `${(index % 8) * 120}ms`,\n      'animation-duration': '1.2s',\n    }\n  }\n\n  stepLabelClass(completed: boolean): string {\n    return cn(\n      'cursor-pointer text-xs font-medium select-none',\n      completed ? 'text-muted-foreground line-through' : 'text-foreground',\n    )\n  }\n\n  endCall(): void {\n    this.isCallEnded.set(true)\n  }\n\n  reconnectCall(): void {\n    this.isCallEnded.set(false)\n    this.callDurationSeconds.set(0)\n  }\n\n  copyTalkingPoints(): void {\n    this.copiedTalkingPoints.set(true)\n    this.later(() => this.copiedTalkingPoints.set(false), 2500)\n  }\n\n  syncCrm(): void {\n    this.isSyncedCrm.set(true)\n    this.later(() => this.isSyncedCrm.set(false), 3500)\n  }\n\n  addActionItem(): void {\n    const text = this.newItemText().trim()\n    if (!text) return\n    this.actionItems.update((prev) => [\n      ...prev,\n      {\n        id: `step-${Date.now()}`,\n        text,\n        completed: false,\n        dueDate: 'Next Week',\n        assignee: 'Elena Rostova',\n      },\n    ])\n    this.newItemText.set('')\n  }\n\n  onNewItemKeydown(event: KeyboardEvent): void {\n    if (event.key === 'Enter') {\n      event.preventDefault()\n      this.addActionItem()\n    }\n  }\n\n  toggleStep(id: string): void {\n    this.actionItems.update((prev) =>\n      prev.map((item) => (item.id === id ? { ...item, completed: !item.completed } : item)),\n    )\n  }\n\n  appendTag(tag: string): void {\n    if (!this.dealNotes().includes(tag)) {\n      this.dealNotes.update((prev) => `${prev}\\n[Tag: ${tag}]`)\n    }\n  }\n\n  private later(fn: () => void, ms: number): void {\n    const t = setTimeout(() => {\n      this.timers.delete(t)\n      fn()\n    }, ms)\n    this.timers.add(t)\n  }\n\n  protected readonly Bot = Bot\n  protected readonly Check = Check\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Clock = Clock\n  protected readonly Copy = Copy\n  protected readonly Disc = Disc\n  protected readonly FileText = FileText\n  protected readonly Mic = Mic\n  protected readonly MicOff = MicOff\n  protected readonly Pause = Pause\n  protected readonly Phone = Phone\n  protected readonly PhoneForwarded = PhoneForwarded\n  protected readonly PhoneOff = PhoneOff\n  protected readonly Play = Play\n  protected readonly Plus = Plus\n  protected readonly Radio = Radio\n  protected readonly RefreshCw = RefreshCw\n  protected readonly Save = Save\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly Zap = Zap\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/crm-sales-call-workbench/crm-sales-call-workbench.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/crm-sales-call-workbench/index.ts",
      "content": "export { UiCrmSalesCallWorkbenchComponent, type CrmSalesCallActionItem } from './crm-sales-call-workbench.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/crm-sales-call-workbench/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/avatar.json",
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/checkbox.json",
    "https://uipkge.dev/r/angular/input.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/textarea.json"
  ],
  "description": "Live CRM sales call console with audio waveform dialer, real-time AI live transcription, objection handling battlecards, and CRM note logger.",
  "categories": [
    "communication",
    "app",
    "crm"
  ]
}