{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "decision-matrix-table",
  "title": "Decision Matrix Table",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/decision-matrix-table/decision-matrix-table.component.ts",
      "content": "// Architectural decision matrix with weighted scoring (Impact, Confidence, Effort, DX,\n// Maintenance), a RICE framework toggle, interactive weight sliders, an option creator,\n// a multi-dimensional SVG tradeoff radar, and an ADR consensus breakdown.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport {\n  AlertCircle,\n  Award,\n  BarChart3,\n  Check,\n  CheckCircle2,\n  ChevronDown,\n  ChevronUp,\n  FileCode2,\n  HelpCircle,\n  Info,\n  LucideAngularModule,\n  Plus,\n  PlusCircle,\n  RefreshCw,\n  Scale,\n  ShieldCheck,\n  SlidersHorizontal,\n  Trash2,\n  XCircle,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardFooterComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiInputComponent } from '@/ui/input/input.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport { UiSliderComponent } from '@/ui/slider/slider.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport type DecisionFrameworkType = 'weighted-matrix' | 'rice'\n\nexport interface DecisionCriterionDef {\n  key: 'impact' | 'confidence' | 'effort' | 'dx' | 'maintenance'\n  label: string\n  shortLabel: string\n  description: string\n  defaultWeight: number\n}\n\nexport interface DecisionMatrixOption {\n  id: string\n  name: string\n  architecture: string\n  summary: string\n  keyRisk: string\n  color: string\n  pros: string[]\n  cons: string[]\n  scores: { impact: number; confidence: number; effort: number; dx: number; maintenance: number }\n  rice: { reach: number; impact: number; confidence: number; effort: number }\n  isCustom?: boolean\n}\n\nexport interface ScoredDecisionOption extends DecisionMatrixOption {\n  weightedScore: number\n  riceScore: number\n  rank: number\n  verdict: 'Recommended Winner' | 'Second Choice' | 'Alternative' | 'Discarded'\n  verdictVariant: 'success' | 'info' | 'warning' | 'destructive'\n}\n\nconst criteriaList: DecisionCriterionDef[] = [\n  {\n    key: 'impact',\n    label: 'Engineering Impact',\n    shortLabel: 'Impact',\n    description: 'System modularity, bundle footprint reduction, and runtime performance gains.',\n    defaultWeight: 25,\n  },\n  {\n    key: 'confidence',\n    label: 'Confidence / Feasibility',\n    shortLabel: 'Confidence',\n    description: 'Ecosystem support, library maturity, and developer team readiness.',\n    defaultWeight: 25,\n  },\n  {\n    key: 'effort',\n    label: 'Simplicity (Low Effort)',\n    shortLabel: 'Low Effort',\n    description: 'Frictionless adoption curve, zero monolith refactors, fast time to market.',\n    defaultWeight: 15,\n  },\n  {\n    key: 'dx',\n    label: 'DX & Consumer Ownership',\n    shortLabel: 'DX Ownership',\n    description: 'Full source access, effortless Tailwind styling customization, zero semver lock-in.',\n    defaultWeight: 20,\n  },\n  {\n    key: 'maintenance',\n    label: 'Low Maintenance',\n    shortLabel: 'Low Maint.',\n    description: 'Decoupled component lifecycles, zero breaking upstream transitive dependency cascades.',\n    defaultWeight: 15,\n  },\n]\n\nconst initialOptions: DecisionMatrixOption[] = [\n  {\n    id: 'opt-a',\n    name: 'Option A: Unbundled Registry architecture',\n    architecture: 'UIPKGE / shadcn Model',\n    summary:\n      'Components copy directly into consumer source tree. Zero semver locks, complete styling autonomy, and unconstrained design customization.',\n    keyRisk: 'Downstream drift from upstream patches managed through automated registry diffing.',\n    color: '#10b981',\n    pros: [\n      'Zero npm package version lock-in or dependency gridlock',\n      'Immediate Tailwind class-level and DOM customization',\n      '100% dead-code elimination and optimal bundle footprint',\n    ],\n    cons: ['Manual or CLI-assisted updates when upstream security patches land'],\n    scores: { impact: 4.8, confidence: 4.7, effort: 4.5, dx: 5.0, maintenance: 4.4 },\n    rice: { reach: 96, impact: 5.0, confidence: 95, effort: 1.8 },\n  },\n  {\n    id: 'opt-b',\n    name: 'Option B: Monolithic Multi-Framework NPM',\n    architecture: 'Centralized Monorepo Package',\n    summary:\n      'Single heavy versioned library published to private registry. Standardized tokens but painful breaking version cascades across product suites.',\n    keyRisk: 'High cross-team dependency coupling and blocked semver upgrades.',\n    color: '#f59e0b',\n    pros: [\n      'Single point of governance for security and accessibility patches',\n      'Familiar `npm install` workflow for junior developers',\n    ],\n    cons: [\n      'Massive wrapper overhead and difficult Tailwind class overrides',\n      'Breaking changes in one component delay releases for entire company',\n      'Bloated runtime JS bundle containing unused component code',\n    ],\n    scores: { impact: 3.2, confidence: 4.1, effort: 3.8, dx: 2.3, maintenance: 2.6 },\n    rice: { reach: 82, impact: 3.0, confidence: 85, effort: 3.6 },\n  },\n  {\n    id: 'opt-c',\n    name: 'Option C: Custom Web Components Wrapper',\n    architecture: 'Custom Elements v1 & Shadow DOM',\n    summary:\n      'Framework-agnostic web components encapsulated in Shadow DOM. Cross-platform runtime interoperability, but major SSR hydration and styling friction.',\n    keyRisk: 'SSR rendering latency and challenging CSS theme token propagation through shadow boundaries.',\n    color: '#6366f1',\n    pros: [\n      'Universal encapsulation across Vue, React, Angular, and vanilla HTML',\n      'Strict CSS isolation prevents accidental style collisions',\n    ],\n    cons: [\n      'Complex SSR and Declarative Shadow DOM hydration mechanics',\n      'Difficult theme token synchronization and slot styling gymnastics',\n      'Suboptimal ergonomics with React synthetic event systems',\n    ],\n    scores: { impact: 3.7, confidence: 3.4, effort: 2.8, dx: 3.1, maintenance: 3.5 },\n    rice: { reach: 90, impact: 3.5, confidence: 70, effort: 3.2 },\n  },\n  {\n    id: 'opt-d',\n    name: 'Option D: Micro-Frontend Module Federation',\n    architecture: 'Webpack / Vite Runtime Federation',\n    summary:\n      'Dynamic runtime module stitching over HTTP. Independent team deployments, but vulnerable to CSS leakage, network latency, and orchestration failures.',\n    keyRisk: 'Runtime script evaluation latency and version mismatch instability in production.',\n    color: '#ef4444',\n    pros: ['Fully decentralized team deployments without monorepo synchronization'],\n    cons: [\n      'High network overhead and cumulative layout shifts on initial load',\n      'Complex local development sandbox and shared singleton debugging',\n      'Runtime failures when remote hosts experience temporary downtime',\n    ],\n    scores: { impact: 3.0, confidence: 2.5, effort: 1.8, dx: 2.6, maintenance: 1.6 },\n    rice: { reach: 58, impact: 3.0, confidence: 55, effort: 4.6 },\n  },\n]\n\nconst radarCenter = { x: 170, y: 155 }\nconst radarRadius = 95\nconst radarAxesCount = 5\n\nconst radarAxisLabels = [\n  { index: 0, label: 'Impact', x: 170, y: 38, anchor: 'middle' },\n  { index: 1, label: 'Confidence', x: 285, y: 115, anchor: 'start' },\n  { index: 2, label: 'Simplicity', x: 245, y: 258, anchor: 'middle' },\n  { index: 3, label: 'DX & Own', x: 95, y: 258, anchor: 'middle' },\n  { index: 4, label: 'Low Maint', x: 55, y: 115, anchor: 'end' },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-decision-matrix-table, [ui-decision-matrix-table]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardFooterComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiInputComponent,\n    UiSeparatorComponent,\n    UiSliderComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <div data-slot=\"decision-matrix-table\" [class]=\"rootClass\">\n      <!-- Header Card: Controls and Metadata -->\n      <div ui-card class=\"border-border bg-card shadow-xs\">\n        <div ui-card-header class=\"pb-4\">\n          <div class=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n            <div class=\"space-y-1.5\">\n              <div class=\"flex flex-wrap items-center gap-2\">\n                <span ui-badge variant=\"outline\" class=\"gap-1 text-xs font-semibold tracking-wide uppercase\">\n                  <lucide-icon [img]=\"Scale\" class=\"text-primary size-3.5\" />\n                  ADR-042 Evaluation\n                </span>\n                <span ui-badge variant=\"secondary\" class=\"text-xs\">Updated Aug 2026</span>\n              </div>\n              <h3 ui-card-title class=\"text-xl font-semibold tracking-tight sm:text-2xl\">{{ title }}</h3>\n              <p ui-card-description class=\"text-sm\">{{ subtitle }}</p>\n            </div>\n\n            <!-- Framework Switcher & Action Toolbar -->\n            <div class=\"flex flex-wrap items-center gap-2.5\">\n              <div class=\"bg-muted border-border inline-flex items-center rounded-lg border p-1\">\n                <button\n                  type=\"button\"\n                  [class]=\"frameworkButtonClass('weighted-matrix')\"\n                  (click)=\"activeFramework.set('weighted-matrix')\"\n                >\n                  Weighted Value-Risk Matrix\n                </button>\n                <button type=\"button\" [class]=\"frameworkButtonClass('rice')\" (click)=\"activeFramework.set('rice')\">\n                  RICE Framework\n                </button>\n              </div>\n\n              @if (activeFramework() === 'weighted-matrix') {\n                <button\n                  ui-button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  class=\"gap-1.5 text-xs\"\n                  (click)=\"showWeightEditor.set(!showWeightEditor())\"\n                >\n                  <lucide-icon [img]=\"SlidersHorizontal\" class=\"text-muted-foreground size-3.5\" />\n                  <span>Criterion Weights</span>\n                  <span ui-badge variant=\"secondary\" [class]=\"weightBadgeClass\">{{ totalWeight() }}%</span>\n                  @if (!showWeightEditor()) {\n                    <lucide-icon [img]=\"ChevronDown\" class=\"text-muted-foreground size-3\" />\n                  } @else {\n                    <lucide-icon [img]=\"ChevronUp\" class=\"text-muted-foreground size-3\" />\n                  }\n                </button>\n              }\n\n              <button\n                ui-button\n                size=\"sm\"\n                class=\"gap-1.5 text-xs font-medium\"\n                (click)=\"showAddOptionForm.set(!showAddOptionForm())\"\n              >\n                <lucide-icon [img]=\"Plus\" class=\"size-3.5\" />\n                <span>Add Option</span>\n              </button>\n            </div>\n          </div>\n        </div>\n\n        <!-- Expandable Criterion Weights Adjuster -->\n        @if (showWeightEditor() && activeFramework() === 'weighted-matrix') {\n          <div class=\"border-border bg-muted/20 border-t px-6 py-5\">\n            <div class=\"space-y-4\">\n              <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n                <div>\n                  <h4 class=\"text-foreground text-sm font-semibold tracking-tight\">\n                    Calibrate Evaluation Criteria Weights\n                  </h4>\n                  <p class=\"text-muted-foreground text-xs\">\n                    Adjust criteria percentages to reflect your organization's architectural priorities.\n                  </p>\n                </div>\n                <div class=\"flex items-center gap-2\">\n                  <span [class]=\"totalWeightClass\">\n                    @if (totalWeight() === 100) {\n                      <lucide-icon [img]=\"CheckCircle2\" class=\"size-3\" />\n                    } @else {\n                      <lucide-icon [img]=\"AlertCircle\" class=\"size-3\" />\n                    }\n                    Total Weight: {{ totalWeight() }}%\n                  </span>\n                  <button\n                    ui-button\n                    variant=\"ghost\"\n                    size=\"xs\"\n                    class=\"text-muted-foreground gap-1 text-xs\"\n                    (click)=\"resetWeights()\"\n                  >\n                    <lucide-icon [img]=\"RefreshCw\" class=\"size-3\" />\n                    Reset Defaults\n                  </button>\n                </div>\n              </div>\n\n              <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5\">\n                @for (criterion of criteria; track criterion.key) {\n                  <div class=\"border-border bg-card space-y-2.5 rounded-lg border p-3.5 shadow-2xs\">\n                    <div class=\"flex items-center justify-between gap-1\">\n                      <span class=\"text-foreground truncate text-xs font-semibold\" [attr.title]=\"criterion.label\">\n                        {{ criterion.label }}\n                      </span>\n                      <span class=\"bg-primary/10 text-primary rounded px-1.5 py-0.5 text-xs font-bold tabular-nums\">\n                        {{ criterionWeights()[criterion.key] ?? criterion.defaultWeight }}%\n                      </span>\n                    </div>\n                    <p class=\"text-muted-foreground line-clamp-2 h-8 text-xs leading-tight\">\n                      {{ criterion.description }}\n                    </p>\n                    <div class=\"pt-1\">\n                      <ui-slider\n                        [value]=\"[criterionWeights()[criterion.key] ?? criterion.defaultWeight]\"\n                        [min]=\"0\"\n                        [max]=\"50\"\n                        [step]=\"5\"\n                        (valueChange)=\"setWeight(criterion.key, $event)\"\n                      />\n                    </div>\n                  </div>\n                }\n              </div>\n            </div>\n          </div>\n        }\n\n        <!-- Expandable Add Custom Proposal Form -->\n        @if (showAddOptionForm()) {\n          <div class=\"border-border bg-muted/30 border-t px-6 py-5\">\n            <div class=\"max-w-3xl space-y-4\">\n              <div class=\"flex items-center justify-between gap-x-2\">\n                <h4 class=\"text-foreground flex items-center gap-1.5 text-sm font-semibold tracking-tight\">\n                  <lucide-icon [img]=\"PlusCircle\" class=\"text-primary size-4\" />\n                  Add Technical Architecture Option to Matrix\n                </h4>\n                <button ui-button variant=\"ghost\" size=\"xs\" (click)=\"showAddOptionForm.set(false)\">Cancel</button>\n              </div>\n\n              <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n                <div class=\"space-y-1\">\n                  <label class=\"text-foreground text-xs font-medium\">Option Proposal Name</label>\n                  <ui-input\n                    [value]=\"newOptionName()\"\n                    (valueChange)=\"newOptionName.set($event)\"\n                    placeholder=\"e.g. Option E: Shared UI Submodule\"\n                  />\n                </div>\n                <div class=\"space-y-1\">\n                  <label class=\"text-foreground text-xs font-medium\">Architectural architecture</label>\n                  <ui-input\n                    [value]=\"newOptionParadigm()\"\n                    (valueChange)=\"newOptionParadigm.set($event)\"\n                    placeholder=\"e.g. Git Submodule & Monorepo Link\"\n                  />\n                </div>\n              </div>\n\n              <div class=\"space-y-1\">\n                <label class=\"text-foreground text-xs font-medium\">Executive Architectural Summary</label>\n                <ui-input\n                  [value]=\"newOptionSummary()\"\n                  (valueChange)=\"newOptionSummary.set($event)\"\n                  placeholder=\"Brief summary of distribution mechanics, bundle characteristics, and DX impact...\"\n                />\n              </div>\n\n              <div class=\"space-y-2\">\n                <label class=\"text-foreground text-xs font-medium\">Initial Scores (1.0 to 5.0)</label>\n                <div class=\"grid grid-cols-2 gap-2.5 sm:grid-cols-5\">\n                  @for (criterion of criteria; track criterion.key) {\n                    <div class=\"border-border bg-card rounded-md border p-2 text-center\">\n                      <div class=\"text-muted-foreground truncate text-xs font-medium\">{{ criterion.shortLabel }}</div>\n                      <div class=\"text-foreground mt-0.5 text-sm font-bold tabular-nums\">\n                        {{ newOptionScores()[criterion.key] }} / 5\n                      </div>\n                      <div class=\"pt-1.5\">\n                        <ui-slider\n                          [value]=\"[newOptionScores()[criterion.key]]\"\n                          [min]=\"1\"\n                          [max]=\"5\"\n                          [step]=\"0.5\"\n                          (valueChange)=\"setNewScore(criterion.key, $event)\"\n                        />\n                      </div>\n                    </div>\n                  }\n                </div>\n              </div>\n\n              <div class=\"flex items-center justify-end gap-2 pt-2\">\n                <button ui-button variant=\"outline\" size=\"sm\" (click)=\"showAddOptionForm.set(false)\">Cancel</button>\n                <button ui-button size=\"sm\" [disabled]=\"!newOptionName().trim()\" (click)=\"handleAddOption()\">\n                  Add to Matrix\n                </button>\n              </div>\n            </div>\n          </div>\n        }\n      </div>\n\n      <!-- Main Scoring Matrix Table -->\n      <div ui-card class=\"border-border bg-card overflow-hidden shadow-xs\">\n        <div class=\"overflow-x-auto\">\n          <table ui-table>\n            <thead ui-table-header class=\"bg-muted/50\">\n              <tr ui-table-row class=\"hover:bg-transparent\">\n                <th ui-table-head class=\"text-muted-foreground w-[42px] px-3 text-center text-xs font-semibold\">\n                  Rank\n                </th>\n                <th ui-table-head class=\"text-foreground min-w-[240px] text-xs font-semibold\">\n                  Technical Option & architecture\n                </th>\n                @if (activeFramework() === 'weighted-matrix') {\n                  @for (criterion of criteria; track criterion.key) {\n                    <th ui-table-head class=\"text-foreground min-w-[130px] text-center text-xs font-semibold\">\n                      <div class=\"flex flex-col items-center\">\n                        <span>{{ criterion.shortLabel }}</span>\n                        <span class=\"text-muted-foreground text-xs font-normal tabular-nums\">\n                          {{ criterionWeights()[criterion.key] ?? criterion.defaultWeight }}% wt\n                        </span>\n                      </div>\n                    </th>\n                  }\n                  <th ui-table-head class=\"text-foreground min-w-[140px] text-center text-xs font-semibold\">\n                    Weighted Score\n                  </th>\n                } @else {\n                  <th ui-table-head class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                    <div class=\"flex flex-col items-center\">\n                      <span>Reach</span><span class=\"text-muted-foreground text-xs font-normal\">Dev Scale %</span>\n                    </div>\n                  </th>\n                  <th ui-table-head class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                    <div class=\"flex flex-col items-center\">\n                      <span>Impact</span><span class=\"text-muted-foreground text-xs font-normal\">Multiplier (1-5)</span>\n                    </div>\n                  </th>\n                  <th ui-table-head class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                    <div class=\"flex flex-col items-center\">\n                      <span>Confidence</span><span class=\"text-muted-foreground text-xs font-normal\">% Certainty</span>\n                    </div>\n                  </th>\n                  <th ui-table-head class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                    <div class=\"flex flex-col items-center\">\n                      <span>Effort</span><span class=\"text-muted-foreground text-xs font-normal\">Sprints (1-5)</span>\n                    </div>\n                  </th>\n                  <th ui-table-head class=\"text-foreground min-w-[130px] text-center text-xs font-semibold\">\n                    RICE Score\n                  </th>\n                }\n                <th ui-table-head class=\"text-foreground min-w-[160px] text-center text-xs font-semibold\">\n                  ADR Verdict\n                </th>\n                <th ui-table-head class=\"text-muted-foreground w-[80px] text-center text-xs font-semibold\">Inspect</th>\n              </tr>\n            </thead>\n            <tbody ui-table-body>\n              @for (opt of scoredOptions(); track opt.id) {\n                <tr ui-table-row [class]=\"matrixRowClass(opt)\" (click)=\"selectedOptionId.set(opt.id)\">\n                  <td ui-table-cell class=\"px-3 text-center\">\n                    <span [class]=\"rankClass(opt.rank)\">{{ opt.rank }}</span>\n                  </td>\n                  <td ui-table-cell>\n                    <div class=\"space-y-1 py-1\">\n                      <div class=\"flex flex-wrap items-center gap-2\">\n                        <span class=\"text-foreground text-sm font-semibold tracking-tight\">{{ opt.name }}</span>\n                        <span\n                          class=\"size-2 shrink-0 rounded-full\"\n                          [style.background-color]=\"opt.color\"\n                          [attr.title]=\"opt.name\"\n                        ></span>\n                        @if (opt.isCustom) {\n                          <span ui-badge variant=\"outline\" class=\"text-xs\">Custom</span>\n                        }\n                      </div>\n                      <div class=\"text-muted-foreground text-xs font-medium\">{{ opt.architecture }}</div>\n                      <p class=\"text-muted-foreground/80 line-clamp-1 max-w-[220px] text-xs\">{{ opt.summary }}</p>\n                    </div>\n                  </td>\n                  @if (activeFramework() === 'weighted-matrix') {\n                    @for (criterion of criteria; track criterion.key) {\n                      <td ui-table-cell class=\"text-center\">\n                        <div class=\"inline-flex flex-col items-center gap-0.5\">\n                          <span\n                            ui-badge\n                            [variant]=\"scoreBadgeVariant(opt.scores[criterion.key])\"\n                            class=\"px-2 py-0.5 text-xs font-semibold tabular-nums\"\n                          >\n                            {{ opt.scores[criterion.key].toFixed(1) }}\n                          </span>\n                          <div class=\"mt-1 flex items-center gap-0.5\">\n                            @for (seg of [1, 2, 3, 4, 5]; track seg) {\n                              <span [class]=\"segmentClass(opt.scores[criterion.key], seg)\"></span>\n                            }\n                          </div>\n                        </div>\n                      </td>\n                    }\n                    <td ui-table-cell class=\"text-center\">\n                      <div class=\"inline-flex flex-col items-center gap-1\">\n                        <span [class]=\"weightedScoreClass(opt)\"\n                          >{{ opt.weightedScore\n                          }}<span class=\"text-muted-foreground text-xs font-normal\">/ 100</span></span\n                        >\n                        <div class=\"bg-muted h-1.5 w-20 overflow-hidden rounded-full\">\n                          <div [class]=\"weightedBarClass(opt)\" [style.width.%]=\"opt.weightedScore\"></div>\n                        </div>\n                      </div>\n                    </td>\n                  } @else {\n                    <td ui-table-cell class=\"text-center text-xs font-semibold tabular-nums\">{{ opt.rice.reach }}%</td>\n                    <td ui-table-cell class=\"text-center text-xs font-semibold tabular-nums\">\n                      {{ opt.rice.impact.toFixed(1) }}x\n                    </td>\n                    <td ui-table-cell class=\"text-center text-xs font-semibold tabular-nums\">\n                      {{ opt.rice.confidence }}%\n                    </td>\n                    <td ui-table-cell class=\"text-center text-xs font-semibold tabular-nums\">\n                      {{ opt.rice.effort.toFixed(1) }} sprints\n                    </td>\n                    <td ui-table-cell class=\"text-center\">\n                      <div class=\"inline-flex flex-col items-center\">\n                        <span class=\"text-primary text-base font-semibold tabular-nums\">{{ opt.riceScore }}</span>\n                        <span class=\"text-muted-foreground text-xs font-medium\">RICE Pts</span>\n                      </div>\n                    </td>\n                  }\n                  <td ui-table-cell class=\"text-center\">\n                    @if (opt.rank === 1) {\n                      <span\n                        class=\"border-success/30 bg-success/10 text-success inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-semibold\"\n                      >\n                        <lucide-icon [img]=\"Award\" class=\"size-3.5\" />Recommended Winner\n                      </span>\n                    } @else if (opt.rank === 2) {\n                      <span\n                        class=\"border-info/30 bg-info/10 text-info inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-semibold\"\n                      >\n                        <lucide-icon [img]=\"CheckCircle2\" class=\"size-3.5\" />Second Choice\n                      </span>\n                    } @else if (opt.rank === 3) {\n                      <span\n                        class=\"border-border bg-muted/60 text-muted-foreground inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium\"\n                      >\n                        <lucide-icon [img]=\"HelpCircle\" class=\"size-3.5\" />Alternative\n                      </span>\n                    } @else {\n                      <span\n                        class=\"border-destructive/20 bg-destructive/10 text-destructive inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium\"\n                      >\n                        <lucide-icon [img]=\"XCircle\" class=\"size-3.5\" />Discarded\n                      </span>\n                    }\n                  </td>\n                  <td ui-table-cell class=\"text-center\">\n                    @if (opt.isCustom) {\n                      <button\n                        ui-button\n                        variant=\"ghost\"\n                        size=\"icon-sm\"\n                        class=\"text-muted-foreground hover:text-destructive\"\n                        title=\"Remove Custom Option\"\n                        (click)=\"removeOption(opt.id); $event.stopPropagation()\"\n                      >\n                        <lucide-icon [img]=\"Trash2\" class=\"size-3.5\" />\n                      </button>\n                    } @else {\n                      <button\n                        ui-button\n                        variant=\"ghost\"\n                        size=\"icon-sm\"\n                        class=\"text-muted-foreground hover:text-foreground\"\n                        [attr.title]=\"'Inspect ' + opt.name\"\n                        (click)=\"selectedOptionId.set(opt.id); $event.stopPropagation()\"\n                      >\n                        <lucide-icon [img]=\"Info\" class=\"size-3.5\" />\n                      </button>\n                    }\n                  </td>\n                </tr>\n              }\n            </tbody>\n          </table>\n        </div>\n        <div\n          ui-card-footer\n          class=\"border-border bg-muted/20 text-muted-foreground flex flex-wrap items-center justify-between gap-3 border-t px-6 py-3 text-xs\"\n        >\n          <div class=\"flex items-center gap-2\">\n            <span class=\"bg-success inline-block size-2 rounded-full\"></span>\n            <span>Scores normalize dynamically to a 0–100 scale based on active criteria weights.</span>\n          </div>\n          <div class=\"flex items-center gap-3\">\n            <button\n              ui-button\n              variant=\"ghost\"\n              size=\"xs\"\n              class=\"text-muted-foreground gap-1 text-xs\"\n              (click)=\"resetOptions()\"\n            >\n              <lucide-icon [img]=\"RefreshCw\" class=\"size-3\" />Reset Matrix Options\n            </button>\n          </div>\n        </div>\n      </div>\n\n      <!-- Tradeoff Visualizer & ADR Recommendation Section -->\n      <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-12\">\n        <!-- Radar Chart -->\n        <div ui-card class=\"border-border bg-card flex flex-col shadow-xs lg:col-span-6\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <div class=\"space-y-0.5\">\n                <h3 ui-card-title class=\"flex items-center gap-2 text-base font-semibold tracking-tight\">\n                  <lucide-icon [img]=\"BarChart3\" class=\"text-primary size-4\" />Decision Tradeoff Radar\n                </h3>\n                <p ui-card-description class=\"text-xs\">\n                  Multi-dimensional polygon overlay comparing architectural options.\n                </p>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">5 Axes (1-5)</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"flex flex-1 flex-col items-center justify-center p-4\">\n            <div class=\"relative flex aspect-square w-full max-w-[340px] items-center justify-center\">\n              <svg viewBox=\"0 0 340 310\" class=\"h-full w-full overflow-visible\">\n                @for (ring of [0.2, 0.4, 0.6, 0.8, 1.0]; track ring) {\n                  <polygon\n                    [attr.points]=\"ringPolygon(ring)\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"1\"\n                    class=\"text-border/50\"\n                    [attr.stroke-dasharray]=\"ring === 1.0 ? 'none' : '2,2'\"\n                  />\n                }\n                @for (idx of [0, 1, 2, 3, 4]; track idx) {\n                  <line\n                    [attr.x1]=\"170\"\n                    [attr.y1]=\"155\"\n                    [attr.x2]=\"radarPoint(idx, 5).x\"\n                    [attr.y2]=\"radarPoint(idx, 5).y\"\n                    stroke=\"currentColor\"\n                    stroke-width=\"1\"\n                    class=\"text-border\"\n                  />\n                }\n                @for (opt of scoredOptions(); track opt.id) {\n                  @if (opt.id !== activeSelectedOption().id) {\n                    <polygon\n                      [attr.points]=\"scoresPolygon(opt.scores)\"\n                      [attr.fill]=\"opt.color\"\n                      fill-opacity=\"0.08\"\n                      [attr.stroke]=\"opt.color\"\n                      stroke-width=\"1.5\"\n                      stroke-opacity=\"0.45\"\n                      class=\"cursor-pointer transition-colors duration-300\"\n                      (click)=\"selectedOptionId.set(opt.id)\"\n                    />\n                  }\n                }\n                <polygon\n                  [attr.points]=\"scoresPolygon(activeSelectedOption().scores)\"\n                  [attr.fill]=\"activeSelectedOption().color\"\n                  fill-opacity=\"0.25\"\n                  [attr.stroke]=\"activeSelectedOption().color\"\n                  stroke-width=\"2.5\"\n                  class=\"transition-colors duration-300\"\n                />\n                @for (val of selectedScoreValues(); track $index) {\n                  <circle\n                    [attr.cx]=\"radarPoint($index, val).x\"\n                    [attr.cy]=\"radarPoint($index, val).y\"\n                    r=\"4\"\n                    [attr.fill]=\"activeSelectedOption().color\"\n                    class=\"stroke-background stroke-2 transition-colors duration-300\"\n                  />\n                }\n                @for (axis of radarLabels; track axis.index) {\n                  <text\n                    [attr.x]=\"axis.x\"\n                    [attr.y]=\"axis.y\"\n                    [attr.text-anchor]=\"axis.anchor\"\n                    class=\"fill-foreground text-xs font-semibold select-none\"\n                    style=\"font-size: 11px\"\n                  >\n                    {{ axis.label }}\n                  </text>\n                }\n              </svg>\n            </div>\n            <div class=\"border-border flex w-full flex-wrap items-center justify-center gap-3 border-t pt-3\">\n              @for (opt of scoredOptions(); track opt.id) {\n                <button type=\"button\" [class]=\"legendClass(opt.id)\" (click)=\"selectedOptionId.set(opt.id)\">\n                  <span class=\"size-2.5 shrink-0 rounded-full\" [style.background-color]=\"opt.color\"></span>\n                  <span class=\"max-w-[120px] truncate\">{{ opt.name.split(':')[0] }}</span>\n                </button>\n              }\n            </div>\n          </div>\n        </div>\n\n        <!-- Consensus & Tradeoff Detail Card -->\n        <div ui-card class=\"border-border bg-card flex flex-col justify-between shadow-xs lg:col-span-6\">\n          <div ui-card-header class=\"pb-3\">\n            <div class=\"flex flex-wrap items-start justify-between gap-3\">\n              <div class=\"min-w-0 space-y-1\">\n                <div class=\"flex flex-wrap items-center gap-2\">\n                  <span ui-badge variant=\"outline\" class=\"text-xs\">Selected Option Details</span>\n                  <span\n                    ui-badge\n                    [variant]=\"activeSelectedOption().verdictVariant === 'success' ? 'success' : 'secondary'\"\n                    class=\"text-xs font-semibold\"\n                  >\n                    {{ activeSelectedOption().verdict }}\n                  </span>\n                </div>\n                <h3 ui-card-title class=\"text-foreground text-lg font-semibold tracking-tight\">\n                  {{ activeSelectedOption().name }}\n                </h3>\n                <p ui-card-description class=\"text-primary text-xs font-medium\">\n                  {{ activeSelectedOption().architecture }}\n                </p>\n              </div>\n              <div class=\"shrink-0 text-right\">\n                <div class=\"text-foreground text-2xl font-semibold tabular-nums\">\n                  {{\n                    activeFramework() === 'rice'\n                      ? activeSelectedOption().riceScore\n                      : activeSelectedOption().weightedScore\n                  }}\n                </div>\n                <div class=\"text-muted-foreground text-xs\">\n                  {{ activeFramework() === 'rice' ? 'RICE Score' : 'Weighted Total' }}\n                </div>\n              </div>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-4 text-xs\">\n            <p class=\"text-muted-foreground text-sm leading-relaxed\">{{ activeSelectedOption().summary }}</p>\n            <ui-separator />\n            <div class=\"grid grid-cols-1 gap-3.5 sm:grid-cols-2\">\n              <div class=\"border-success/20 bg-success/5 space-y-2 rounded-lg border p-3\">\n                <span class=\"text-success flex items-center gap-1.5 text-xs font-semibold\">\n                  <lucide-icon [img]=\"Check\" class=\"size-3.5\" />Strategic Advantages\n                </span>\n                <ul class=\"text-muted-foreground space-y-1.5\">\n                  @for (pro of activeSelectedOption().pros; track pro) {\n                    <li class=\"flex items-start gap-1.5\">\n                      <span class=\"text-success mt-0.5\">•</span><span>{{ pro }}</span>\n                    </li>\n                  }\n                </ul>\n              </div>\n              <div class=\"border-destructive/20 bg-destructive/5 space-y-2 rounded-lg border p-3\">\n                <span class=\"text-destructive flex items-center gap-1.5 text-xs font-semibold\">\n                  <lucide-icon [img]=\"AlertCircle\" class=\"size-3.5\" />Compromises & Friction\n                </span>\n                <ul class=\"text-muted-foreground space-y-1.5\">\n                  @for (con of activeSelectedOption().cons; track con) {\n                    <li class=\"flex items-start gap-1.5\">\n                      <span class=\"text-destructive mt-0.5\">•</span><span>{{ con }}</span>\n                    </li>\n                  }\n                </ul>\n              </div>\n            </div>\n            <div class=\"border-border bg-muted/40 space-y-1 rounded-md border p-3\">\n              <span class=\"text-foreground flex items-center gap-1.5 font-semibold\">\n                <lucide-icon [img]=\"ShieldCheck\" class=\"text-primary size-3.5\" />Risk Mitigation & Governance Policy:\n              </span>\n              <p class=\"text-muted-foreground\">{{ activeSelectedOption().keyRisk }}</p>\n            </div>\n          </div>\n          <div\n            ui-card-footer\n            class=\"border-border bg-muted/20 flex items-center justify-between gap-x-2 border-t px-6 py-3\"\n          >\n            <div class=\"flex items-center gap-2\">\n              <lucide-icon [img]=\"FileCode2\" class=\"text-muted-foreground size-4\" />\n              <span class=\"text-muted-foreground text-xs font-medium\">ADR Record Consensus: </span>\n              <span class=\"text-foreground text-xs font-semibold\">{{ consensusName() }}</span>\n            </div>\n            <span ui-badge variant=\"outline\" class=\"gap-1 text-xs\">\n              <lucide-icon [img]=\"Award\" class=\"text-success size-3\" />Rank #{{ activeSelectedOption().rank }}\n            </span>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiDecisionMatrixTableComponent {\n  protected readonly AlertCircle = AlertCircle\n  protected readonly Award = Award\n  protected readonly BarChart3 = BarChart3\n  protected readonly Check = Check\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly ChevronDown = ChevronDown\n  protected readonly ChevronUp = ChevronUp\n  protected readonly FileCode2 = FileCode2\n  protected readonly HelpCircle = HelpCircle\n  protected readonly Info = Info\n  protected readonly Plus = Plus\n  protected readonly PlusCircle = PlusCircle\n  protected readonly RefreshCw = RefreshCw\n  protected readonly Scale = Scale\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly SlidersHorizontal = SlidersHorizontal\n  protected readonly Trash2 = Trash2\n  protected readonly XCircle = XCircle\n\n  protected readonly criteria = criteriaList\n  protected readonly radarLabels = radarAxisLabels\n\n  @Input() title = 'Architectural Decision Matrix (RICE / Weighted Scoring)'\n  @Input() subtitle = 'Evaluate technical options against weighted business and engineering criteria.'\n  @Input() set defaultFramework(v: DecisionFrameworkType) {\n    if (v) this.activeFramework.set(v)\n  }\n  @Input('class') className?: string\n\n  readonly activeFramework = signal<DecisionFrameworkType>('weighted-matrix')\n  readonly showWeightEditor = signal(false)\n  readonly showAddOptionForm = signal(false)\n  readonly selectedOptionId = signal('opt-a')\n  readonly criterionWeights = signal<Record<string, number>>({\n    impact: 25,\n    confidence: 25,\n    effort: 15,\n    dx: 20,\n    maintenance: 15,\n  })\n  readonly options = signal<DecisionMatrixOption[]>(\n    initialOptions.map((o) => ({\n      ...o,\n      scores: { ...o.scores },\n      rice: { ...o.rice },\n      pros: [...o.pros],\n      cons: [...o.cons],\n    })),\n  )\n  readonly newOptionName = signal('')\n  readonly newOptionParadigm = signal('')\n  readonly newOptionSummary = signal('')\n  readonly newOptionScores = signal({ impact: 4.0, confidence: 4.0, effort: 3.5, dx: 4.0, maintenance: 3.5 })\n\n  readonly totalWeight = computed(() =>\n    Object.values(this.criterionWeights()).reduce((sum, w) => sum + (Number(w) || 0), 0),\n  )\n\n  readonly scoredOptions = computed<ScoredDecisionOption[]>(() => {\n    const weights = this.criterionWeights()\n    const sumW = this.totalWeight() || 100\n    const framework = this.activeFramework()\n    const calculated = this.options().map((opt) => {\n      const weightedSum =\n        opt.scores.impact * (weights['impact'] ?? 25) +\n        opt.scores.confidence * (weights['confidence'] ?? 25) +\n        opt.scores.effort * (weights['effort'] ?? 15) +\n        opt.scores.dx * (weights['dx'] ?? 20) +\n        opt.scores.maintenance * (weights['maintenance'] ?? 15)\n      const weightedScore = Number(((weightedSum / (5 * sumW)) * 100).toFixed(1))\n      const riceScore = Number(\n        ((opt.rice.reach * opt.rice.impact * (opt.rice.confidence / 100)) / Math.max(0.5, opt.rice.effort)).toFixed(1),\n      )\n      return {\n        ...opt,\n        weightedScore,\n        riceScore,\n        rank: 0,\n        verdict: 'Discarded' as const,\n        verdictVariant: 'destructive' as const,\n      }\n    })\n    calculated.sort((a, b) => (framework === 'rice' ? b.riceScore - a.riceScore : b.weightedScore - a.weightedScore))\n    return calculated.map((item, index) => {\n      const rank = index + 1\n      let verdict: ScoredDecisionOption['verdict'] = 'Discarded'\n      let verdictVariant: ScoredDecisionOption['verdictVariant'] = 'destructive'\n      if (rank === 1) {\n        verdict = 'Recommended Winner'\n        verdictVariant = 'success'\n      } else if (rank === 2) {\n        verdict = 'Second Choice'\n        verdictVariant = 'info'\n      } else if (rank === 3) {\n        verdict = 'Alternative'\n        verdictVariant = 'warning'\n      }\n      return { ...item, rank, verdict, verdictVariant }\n    })\n  })\n\n  readonly winningOption = computed(() => this.scoredOptions()[0]!)\n  readonly activeSelectedOption = computed(\n    () => this.scoredOptions().find((opt) => opt.id === this.selectedOptionId()) ?? this.winningOption(),\n  )\n  readonly selectedScoreValues = computed(() => {\n    const s = this.activeSelectedOption().scores\n    return [s.impact, s.confidence, s.effort, s.dx, s.maintenance]\n  })\n  readonly consensusName = computed(() => {\n    const name = this.winningOption().name\n    return name.split(':')[1] || name\n  })\n\n  get rootClass(): string {\n    return cn('bg-background text-foreground w-full space-y-6', this.className)\n  }\n\n  get weightBadgeClass(): string {\n    return cn(\n      'ml-0.5 px-1.5 py-0 text-xs tabular-nums',\n      this.totalWeight() === 100 ? 'text-foreground' : 'bg-warning/20 text-warning font-semibold',\n    )\n  }\n\n  get totalWeightClass(): string {\n    return cn(\n      'inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-xs font-semibold tabular-nums',\n      this.totalWeight() === 100 ? 'bg-success/10 text-success' : 'bg-warning/15 text-warning font-bold',\n    )\n  }\n\n  frameworkButtonClass(framework: DecisionFrameworkType): string {\n    return cn(\n      'focus-visible:ring-ring rounded-md px-3 py-1.5 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none',\n      this.activeFramework() === framework\n        ? 'bg-background text-foreground font-semibold shadow-xs'\n        : 'text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  matrixRowClass(opt: ScoredDecisionOption): string {\n    return cn(\n      'cursor-pointer transition-colors duration-150',\n      opt.id === this.selectedOptionId() ? 'bg-primary/5 dark:bg-primary/10' : 'hover:bg-muted/40',\n      opt.rank === 1 && 'font-medium',\n    )\n  }\n\n  rankClass(rank: number): string {\n    return cn(\n      'inline-flex size-6 items-center justify-center rounded-full text-xs font-semibold tabular-nums',\n      rank === 1\n        ? 'bg-success text-white shadow-xs'\n        : rank === 2\n          ? 'bg-info/15 text-info font-semibold'\n          : 'bg-muted text-muted-foreground font-normal',\n    )\n  }\n\n  scoreBadgeVariant(score: number): 'success' | 'default' | 'secondary' | 'outline' {\n    if (score >= 4.5) return 'success'\n    if (score >= 3.5) return 'default'\n    if (score >= 2.5) return 'secondary'\n    return 'outline'\n  }\n\n  segmentClass(score: number, seg: number): string {\n    return cn('size-1 rounded-full', seg <= Math.round(score) ? 'bg-primary' : 'bg-muted-foreground/20')\n  }\n\n  weightedScoreClass(opt: ScoredDecisionOption): string {\n    return cn(\n      'text-base font-semibold tracking-tight tabular-nums',\n      opt.rank === 1 ? 'text-success' : opt.weightedScore >= 70 ? 'text-foreground' : 'text-muted-foreground',\n    )\n  }\n\n  weightedBarClass(opt: ScoredDecisionOption): string {\n    return cn(\n      'h-full rounded-full transition-[width,background-color] duration-300',\n      opt.rank === 1\n        ? 'bg-success'\n        : opt.weightedScore >= 70\n          ? 'bg-info'\n          : opt.weightedScore >= 50\n            ? 'bg-warning'\n            : 'bg-destructive',\n    )\n  }\n\n  legendClass(id: string): string {\n    return cn(\n      'inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs transition-colors',\n      id === this.activeSelectedOption().id\n        ? 'bg-muted text-foreground ring-border font-semibold ring-1'\n        : 'text-muted-foreground hover:text-foreground opacity-80',\n    )\n  }\n\n  radarPoint(axisIndex: number, scoreValue: number, maxVal = 5): { x: number; y: number } {\n    const angle = -Math.PI / 2 + (axisIndex * 2 * Math.PI) / radarAxesCount\n    const ratio = Math.min(1, Math.max(0, scoreValue / maxVal))\n    const r = radarRadius * ratio\n    return { x: radarCenter.x + r * Math.cos(angle), y: radarCenter.y + r * Math.sin(angle) }\n  }\n\n  scoresPolygon(scores: DecisionMatrixOption['scores']): string {\n    return [scores.impact, scores.confidence, scores.effort, scores.dx, scores.maintenance]\n      .map((val, idx) => {\n        const pt = this.radarPoint(idx, val)\n        return `${pt.x.toFixed(1)},${pt.y.toFixed(1)}`\n      })\n      .join(' ')\n  }\n\n  ringPolygon(ratio: number): string {\n    return Array.from({ length: radarAxesCount })\n      .map((_, idx) => {\n        const pt = this.radarPoint(idx, ratio * 5)\n        return `${pt.x.toFixed(1)},${pt.y.toFixed(1)}`\n      })\n      .join(' ')\n  }\n\n  setWeight(key: string, vals: number[]): void {\n    this.criterionWeights.update((prev) => ({ ...prev, [key]: vals[0] ?? 0 }))\n  }\n\n  setNewScore(key: keyof DecisionMatrixOption['scores'], vals: number[]): void {\n    this.newOptionScores.update((prev) => ({ ...prev, [key]: vals[0] ?? 3 }))\n  }\n\n  resetWeights(): void {\n    const fresh: Record<string, number> = {}\n    criteriaList.forEach((c) => {\n      fresh[c.key] = c.defaultWeight\n    })\n    this.criterionWeights.set(fresh)\n  }\n\n  resetOptions(): void {\n    this.options.set(\n      initialOptions.map((o) => ({\n        ...o,\n        scores: { ...o.scores },\n        rice: { ...o.rice },\n        pros: [...o.pros],\n        cons: [...o.cons],\n      })),\n    )\n    this.selectedOptionId.set('opt-a')\n  }\n\n  handleAddOption(): void {\n    const name = this.newOptionName().trim()\n    if (!name) return\n    const scores = { ...this.newOptionScores() }\n    const newId = `opt-custom-${Date.now()}`\n    const created: DecisionMatrixOption = {\n      id: newId,\n      name,\n      architecture: this.newOptionParadigm().trim() || 'Custom Technical Architecture',\n      summary: this.newOptionSummary().trim() || 'Custom evaluated technical approach for this architectural decision.',\n      keyRisk: 'Requires comprehensive proof-of-concept testing in staging environments.',\n      color: '#06b6d4',\n      pros: ['Tailored to immediate domain constraints', 'Custom architectural design'],\n      cons: ['Needs dedicated long-term ownership and testing framework'],\n      scores,\n      rice: {\n        reach: 75,\n        impact: scores.impact,\n        confidence: Number((scores.confidence * 20).toFixed(0)),\n        effort: Number((6 - scores.effort).toFixed(1)),\n      },\n      isCustom: true,\n    }\n    this.options.update((prev) => [...prev, created])\n    this.selectedOptionId.set(newId)\n    this.newOptionName.set('')\n    this.newOptionParadigm.set('')\n    this.newOptionSummary.set('')\n    this.showAddOptionForm.set(false)\n  }\n\n  removeOption(id: string): void {\n    this.options.update((prev) => prev.filter((opt) => opt.id !== id))\n    if (this.selectedOptionId() === id) {\n      this.selectedOptionId.set(this.options()[0]?.id ?? '')\n    }\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/decision-matrix-table/decision-matrix-table.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/decision-matrix-table/index.ts",
      "content": "export {\n  UiDecisionMatrixTableComponent,\n  type DecisionCriterionDef,\n  type DecisionFrameworkType,\n  type DecisionMatrixOption,\n  type ScoredDecisionOption,\n} from './decision-matrix-table.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/decision-matrix-table/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "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/input.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/slider.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Product and architectural decision matrix with dynamic weighted scoring algorithms (Impact, Confidence, Effort, Risk), RICE framework toggle, interactive weight sliders, option creator, multi-dimensional SVG tradeoff radar, and ADR consensus breakdown.",
  "categories": [
    "productivity",
    "app",
    "table"
  ]
}