{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "decision-matrix-table",
  "title": "Decision Matrix Table",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/decision-matrix-table/DecisionMatrixTable.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport {\n  AlertCircle,\n  Award,\n  BarChart3,\n  Check,\n  CheckCircle2,\n  ChevronDown,\n  ChevronUp,\n  FileCode2,\n  HelpCircle,\n  Info,\n  Plus,\n  RefreshCw,\n  Scale,\n  ShieldCheck,\n  SlidersHorizontal,\n  Trash2,\n  XCircle,\n  PlusCircle,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Separator } from '@/components/ui/separator'\nimport { Slider } from '@/components/ui/slider'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport type FrameworkType = 'weighted-matrix' | 'rice'\n\ninterface Props {\n  class?: HTMLAttributes['class']\n  title?: string\n  subtitle?: string\n  defaultFramework?: FrameworkType\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  title: 'Architectural Decision Matrix (RICE / Weighted Scoring)',\n  subtitle: 'Evaluate technical options against weighted business and engineering criteria.',\n  defaultFramework: 'weighted-matrix',\n})\n\nexport interface CriterionDef {\n  key: 'impact' | 'confidence' | 'effort' | 'dx' | 'maintenance'\n  label: string\n  shortLabel: string\n  description: string\n  defaultWeight: number\n  isInverted?: boolean\n}\n\nexport interface MatrixOption {\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: {\n    impact: number // 1 to 5 (Engineering Impact)\n    confidence: number // 1 to 5 (Confidence / Feasibility)\n    effort: number // 1 to 5 (Implementation Simplicity / Low Effort)\n    dx: number // 1 to 5 (DX & Consumer Ownership)\n    maintenance: number // 1 to 5 (Low Maintenance Overhead)\n  }\n  rice: {\n    reach: number // 0 to 100 (% of engineers / services)\n    impact: number // 1 to 5 multiplier\n    confidence: number // 50 to 100 (%)\n    effort: number // 1 to 5 person-sprints\n  }\n  isCustom?: boolean\n}\n\nconst activeFramework = ref<FrameworkType>(props.defaultFramework)\nconst showWeightEditor = ref(false)\nconst showAddOptionForm = ref(false)\nconst selectedOptionId = ref<string>('opt-a')\n\nconst criteriaList: CriterionDef[] = [\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 criterionWeights = ref<Record<string, number>>({\n  impact: 25,\n  confidence: 25,\n  effort: 15,\n  dx: 20,\n  maintenance: 15,\n})\n\nconst defaultOptions: MatrixOption[] = [\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: {\n      impact: 4.8,\n      confidence: 4.7,\n      effort: 4.5,\n      dx: 5.0,\n      maintenance: 4.4,\n    },\n    rice: {\n      reach: 96,\n      impact: 5.0,\n      confidence: 95,\n      effort: 1.8,\n    },\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: {\n      impact: 3.2,\n      confidence: 4.1,\n      effort: 3.8,\n      dx: 2.3,\n      maintenance: 2.6,\n    },\n    rice: {\n      reach: 82,\n      impact: 3.0,\n      confidence: 85,\n      effort: 3.6,\n    },\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: {\n      impact: 3.7,\n      confidence: 3.4,\n      effort: 2.8,\n      dx: 3.1,\n      maintenance: 3.5,\n    },\n    rice: {\n      reach: 90,\n      impact: 3.5,\n      confidence: 70,\n      effort: 3.2,\n    },\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: {\n      impact: 3.0,\n      confidence: 2.5,\n      effort: 1.8,\n      dx: 2.6,\n      maintenance: 1.6,\n    },\n    rice: {\n      reach: 58,\n      impact: 3.0,\n      confidence: 55,\n      effort: 4.6,\n    },\n  },\n]\n\nconst options = ref<MatrixOption[]>([...defaultOptions])\n\n// Add option form state\nconst newOptionName = ref('')\nconst newOptionParadigm = ref('')\nconst newOptionSummary = ref('')\nconst newOptionScores = ref({\n  impact: 4.0,\n  confidence: 4.0,\n  effort: 3.5,\n  dx: 4.0,\n  maintenance: 3.5,\n})\n\nconst totalWeight = computed(() => {\n  return Object.values(criterionWeights.value).reduce((sum, w) => sum + (Number(w) || 0), 0)\n})\n\nfunction resetWeights() {\n  criteriaList.forEach((c) => {\n    criterionWeights.value[c.key] = c.defaultWeight\n  })\n}\n\nfunction resetOptions() {\n  options.value = [...defaultOptions]\n  selectedOptionId.value = 'opt-a'\n}\n\nfunction handleAddOption() {\n  if (!newOptionName.value.trim()) return\n\n  const newId = `opt-custom-${Date.now()}`\n  const created: MatrixOption = {\n    id: newId,\n    name: newOptionName.value.trim(),\n    architecture: newOptionParadigm.value.trim() || 'Custom Technical Architecture',\n    summary: newOptionSummary.value.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: { ...newOptionScores.value },\n    rice: {\n      reach: 75,\n      impact: newOptionScores.value.impact,\n      confidence: Number((newOptionScores.value.confidence * 20).toFixed(0)),\n      effort: Number((6 - newOptionScores.value.effort).toFixed(1)),\n    },\n    isCustom: true,\n  }\n\n  options.value.push(created)\n  selectedOptionId.value = newId\n  newOptionName.value = ''\n  newOptionParadigm.value = ''\n  newOptionSummary.value = ''\n  showAddOptionForm.value = false\n}\n\nfunction removeOption(id: string) {\n  options.value = options.value.filter((opt) => opt.id !== id)\n  if (selectedOptionId.value === id) {\n    selectedOptionId.value = options.value[0]?.id || ''\n  }\n}\n\n// Calculations\ninterface ScoredOption extends MatrixOption {\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 scoredOptions = computed<ScoredOption[]>(() => {\n  const sumW = totalWeight.value || 100\n\n  // 1. Calculate raw scores\n  const calculated = options.value.map((opt) => {\n    // Weighted score out of 100\n    const weightedSum =\n      opt.scores.impact * criterionWeights.value.impact +\n      opt.scores.confidence * criterionWeights.value.confidence +\n      opt.scores.effort * criterionWeights.value.effort +\n      opt.scores.dx * criterionWeights.value.dx +\n      opt.scores.maintenance * criterionWeights.value.maintenance\n\n    const weightedScore = Number(((weightedSum / (5 * sumW)) * 100).toFixed(1))\n\n    // RICE calculation: (Reach * Impact * (Confidence / 100)) / Effort\n    const reachFactor = opt.rice.reach\n    const impactFactor = opt.rice.impact\n    const confidenceFactor = opt.rice.confidence / 100\n    const effortFactor = Math.max(0.5, opt.rice.effort)\n    const riceScore = Number(((reachFactor * impactFactor * confidenceFactor) / effortFactor).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\n  // 2. Sort depending on active framework\n  calculated.sort((a, b) => {\n    if (activeFramework.value === 'rice') {\n      return b.riceScore - a.riceScore\n    }\n    return b.weightedScore - a.weightedScore\n  })\n\n  // 3. Assign ranks and verdicts\n  return calculated.map((item, index) => {\n    const rank = index + 1\n    let verdict: ScoredOption['verdict'] = 'Discarded'\n    let verdictVariant: ScoredOption['verdictVariant'] = 'destructive'\n\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    } else {\n      verdict = 'Discarded'\n      verdictVariant = 'destructive'\n    }\n\n    return {\n      ...item,\n      rank,\n      verdict,\n      verdictVariant,\n    }\n  })\n})\n\nconst winningOption = computed(() => {\n  return scoredOptions.value[0] || options.value[0]\n})\n\nconst activeSelectedOption = computed(() => {\n  return scoredOptions.value.find((opt) => opt.id === selectedOptionId.value) || winningOption.value\n})\n\n// Radar chart SVG geometry\nconst radarCenter = { x: 170, y: 155 }\nconst radarRadius = 95\nconst radarAxesCount = 5\n\nfunction getRadarPoint(axisIndex: number, scoreValue: number, maxVal = 5) {\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  const x = radarCenter.x + r * Math.cos(angle)\n  const y = radarCenter.y + r * Math.sin(angle)\n  return { x, y }\n}\n\nfunction getRadarPolygon(scores: {\n  impact: number\n  confidence: number\n  effort: number\n  dx: number\n  maintenance: number\n}) {\n  const values = [scores.impact, scores.confidence, scores.effort, scores.dx, scores.maintenance]\n  return values\n    .map((val, idx) => {\n      const pt = getRadarPoint(idx, val)\n      return `${pt.x.toFixed(1)},${pt.y.toFixed(1)}`\n    })\n    .join(' ')\n}\n\nfunction getRingPolygon(ratio: number) {\n  return Array.from({ length: radarAxesCount })\n    .map((_, idx) => {\n      const pt = getRadarPoint(idx, ratio * 5)\n      return `${pt.x.toFixed(1)},${pt.y.toFixed(1)}`\n    })\n    .join(' ')\n}\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\nfunction getScoreBadgeVariant(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</script>\n\n<template>\n  <div data-slot=\"decision-matrix-table\" :class=\"cn('bg-background text-foreground w-full space-y-6', props.class)\">\n    <!-- Header: Title, Framework Selector & Action Toolbar -->\n    <Card class=\"border-border bg-card shadow-xs\">\n      <CardHeader 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              <Badge variant=\"outline\" class=\"gap-1 text-xs font-semibold tracking-wide uppercase\">\n                <Scale class=\"text-primary size-3.5\" />\n                ADR-042 Evaluation\n              </Badge>\n              <Badge variant=\"secondary\" class=\"text-xs\"> Updated Aug 2026 </Badge>\n            </div>\n            <CardTitle class=\"text-xl font-semibold tracking-tight sm:text-2xl\">\n              {{ title }}\n            </CardTitle>\n            <CardDescription class=\"text-sm\">\n              {{ subtitle }}\n            </CardDescription>\n          </div>\n\n          <!-- Framework Switcher & Quick Actions -->\n          <div class=\"flex flex-wrap items-center gap-2.5\">\n            <!-- Framework Selector -->\n            <div class=\"bg-muted border-border inline-flex items-center rounded-lg border p-1\">\n              <button\n                type=\"button\"\n                :class=\"\n                  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                    activeFramework === 'weighted-matrix'\n                      ? 'bg-background text-foreground font-semibold shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"activeFramework = 'weighted-matrix'\"\n              >\n                Weighted Value-Risk Matrix\n              </button>\n              <button\n                type=\"button\"\n                :class=\"\n                  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                    activeFramework === 'rice'\n                      ? 'bg-background text-foreground font-semibold shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )\n                \"\n                @click=\"activeFramework = 'rice'\"\n              >\n                RICE Framework\n              </button>\n            </div>\n\n            <!-- Weight Adjustment Toggle -->\n            <Button\n              v-if=\"activeFramework === 'weighted-matrix'\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"gap-1.5 text-xs\"\n              @click=\"showWeightEditor = !showWeightEditor\"\n            >\n              <SlidersHorizontal class=\"text-muted-foreground size-3.5\" />\n              <span>Criterion Weights</span>\n              <Badge\n                variant=\"secondary\"\n                :class=\"\n                  cn(\n                    'ml-0.5 px-1.5 py-0 text-xs tabular-nums',\n                    totalWeight === 100 ? 'text-foreground' : 'bg-warning/20 text-warning font-semibold',\n                  )\n                \"\n              >\n                {{ totalWeight }}%\n              </Badge>\n              <ChevronDown v-if=\"!showWeightEditor\" class=\"text-muted-foreground size-3\" />\n              <ChevronUp v-else class=\"text-muted-foreground size-3\" />\n            </Button>\n\n            <!-- Add Option Button -->\n            <Button size=\"sm\" class=\"gap-1.5 text-xs font-medium\" @click=\"showAddOptionForm = !showAddOptionForm\">\n              <Plus class=\"size-3.5\" />\n              <span>Add Option</span>\n            </Button>\n          </div>\n        </div>\n      </CardHeader>\n\n      <!-- Expandable Criterion Weights Adjuster -->\n      <div\n        v-if=\"showWeightEditor && activeFramework === 'weighted-matrix'\"\n        class=\"border-border bg-muted/20 border-t px-6 py-5\"\n      >\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\n                :class=\"\n                  cn(\n                    'inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-xs font-semibold tabular-nums',\n                    totalWeight === 100 ? 'bg-success/10 text-success' : 'bg-warning/15 text-warning font-bold',\n                  )\n                \"\n              >\n                <CheckCircle2 v-if=\"totalWeight === 100\" class=\"size-3\" />\n                <AlertCircle v-else class=\"size-3\" />\n                Total Weight: {{ totalWeight }}%\n              </span>\n              <Button variant=\"ghost\" size=\"xs\" class=\"text-muted-foreground gap-1 text-xs\" @click=\"resetWeights\">\n                <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            <div\n              v-for=\"criterion in criteriaList\"\n              :key=\"criterion.key\"\n              class=\"border-border bg-card space-y-2.5 rounded-lg border p-3.5 shadow-2xs\"\n            >\n              <div class=\"flex items-center justify-between gap-1\">\n                <span class=\"text-foreground truncate text-xs font-semibold\" :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] }}%\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                <Slider v-model=\"criterionWeights[criterion.key]\" :min=\"0\" :max=\"50\" :step=\"5\" size=\"small\" />\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <!-- Expandable Add Custom Proposal Form -->\n      <div v-if=\"showAddOptionForm\" 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              <PlusCircle class=\"text-primary size-4\" />\n              Add Technical Architecture Option to Matrix\n            </h4>\n            <Button variant=\"ghost\" size=\"xs\" @click=\"showAddOptionForm = 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              <Input v-model=\"newOptionName\" placeholder=\"e.g. Option E: Shared UI Submodule\" size=\"small\" />\n            </div>\n            <div class=\"space-y-1\">\n              <label class=\"text-foreground text-xs font-medium\">Architectural architecture</label>\n              <Input v-model=\"newOptionParadigm\" placeholder=\"e.g. Git Submodule & Monorepo Link\" size=\"small\" />\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            <Input\n              v-model=\"newOptionSummary\"\n              placeholder=\"Brief summary of distribution mechanics, bundle characteristics, and DX impact...\"\n              size=\"small\"\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              <div\n                v-for=\"criterion in criteriaList\"\n                :key=\"criterion.key\"\n                class=\"border-border bg-card rounded-md border p-2 text-center\"\n              >\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                  <Slider v-model=\"newOptionScores[criterion.key]\" :min=\"1\" :max=\"5\" :step=\"0.5\" size=\"small\" />\n                </div>\n              </div>\n            </div>\n          </div>\n\n          <div class=\"flex items-center justify-end gap-2 pt-2\">\n            <Button variant=\"outline\" size=\"sm\" @click=\"showAddOptionForm = false\">Cancel</Button>\n            <Button size=\"sm\" :disabled=\"!newOptionName.trim()\" @click=\"handleAddOption\"> Add to Matrix </Button>\n          </div>\n        </div>\n      </div>\n    </Card>\n\n    <!-- Main Scoring Matrix Table -->\n    <Card class=\"border-border bg-card overflow-hidden shadow-xs\">\n      <div class=\"overflow-x-auto\">\n        <Table>\n          <TableHeader class=\"bg-muted/50\">\n            <TableRow class=\"hover:bg-transparent\">\n              <TableHead class=\"text-muted-foreground w-[42px] px-3 text-center text-xs font-semibold\">\n                Rank\n              </TableHead>\n              <TableHead class=\"text-foreground min-w-[240px] text-xs font-semibold\">\n                Technical Option & architecture\n              </TableHead>\n\n              <!-- Dynamic Headers for Weighted Matrix vs RICE -->\n              <template v-if=\"activeFramework === 'weighted-matrix'\">\n                <TableHead\n                  v-for=\"criterion in criteriaList\"\n                  :key=\"criterion.key\"\n                  class=\"text-foreground min-w-[130px] text-center text-xs font-semibold\"\n                >\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] }}% wt\n                    </span>\n                  </div>\n                </TableHead>\n                <TableHead class=\"text-foreground min-w-[140px] text-center text-xs font-semibold\">\n                  Weighted Score\n                </TableHead>\n              </template>\n\n              <template v-else>\n                <TableHead class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                  <div class=\"flex flex-col items-center\">\n                    <span>Reach</span>\n                    <span class=\"text-muted-foreground text-xs font-normal\">Dev Scale %</span>\n                  </div>\n                </TableHead>\n                <TableHead class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                  <div class=\"flex flex-col items-center\">\n                    <span>Impact</span>\n                    <span class=\"text-muted-foreground text-xs font-normal\">Multiplier (1-5)</span>\n                  </div>\n                </TableHead>\n                <TableHead class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                  <div class=\"flex flex-col items-center\">\n                    <span>Confidence</span>\n                    <span class=\"text-muted-foreground text-xs font-normal\">% Certainty</span>\n                  </div>\n                </TableHead>\n                <TableHead class=\"text-foreground min-w-[110px] text-center text-xs font-semibold\">\n                  <div class=\"flex flex-col items-center\">\n                    <span>Effort</span>\n                    <span class=\"text-muted-foreground text-xs font-normal\">Sprints (1-5)</span>\n                  </div>\n                </TableHead>\n                <TableHead class=\"text-foreground min-w-[130px] text-center text-xs font-semibold\">\n                  RICE Score\n                </TableHead>\n              </template>\n\n              <TableHead class=\"text-foreground min-w-[160px] text-center text-xs font-semibold\">\n                ADR Verdict\n              </TableHead>\n              <TableHead class=\"text-muted-foreground w-[80px] text-center text-xs font-semibold\"> Inspect </TableHead>\n            </TableRow>\n          </TableHeader>\n\n          <TableBody>\n            <TableRow\n              v-for=\"opt in scoredOptions\"\n              :key=\"opt.id\"\n              :class=\"\n                cn(\n                  'cursor-pointer transition-colors duration-150',\n                  opt.id === selectedOptionId ? 'bg-primary/5 dark:bg-primary/10' : 'hover:bg-muted/40',\n                  opt.rank === 1 && 'font-medium',\n                )\n              \"\n              @click=\"selectedOptionId = opt.id\"\n            >\n              <!-- Rank Column -->\n              <TableCell class=\"px-3 text-center\">\n                <span\n                  :class=\"\n                    cn(\n                      'inline-flex size-6 items-center justify-center rounded-full text-xs font-semibold tabular-nums',\n                      opt.rank === 1\n                        ? 'bg-success text-white shadow-xs'\n                        : opt.rank === 2\n                          ? 'bg-info/15 text-info font-semibold'\n                          : 'bg-muted text-muted-foreground font-normal',\n                    )\n                  \"\n                >\n                  {{ opt.rank }}\n                </span>\n              </TableCell>\n\n              <!-- Proposal Name, architecture & Description -->\n              <TableCell>\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\">\n                      {{ opt.name }}\n                    </span>\n                    <span\n                      class=\"size-2 shrink-0 rounded-full\"\n                      :style=\"{ backgroundColor: opt.color }\"\n                      :title=\"opt.name\"\n                    />\n                    <Badge v-if=\"opt.isCustom\" variant=\"outline\" class=\"text-xs\">Custom</Badge>\n                  </div>\n                  <div class=\"text-muted-foreground text-xs font-medium\">\n                    {{ opt.architecture }}\n                  </div>\n                  <p class=\"text-muted-foreground/80 line-clamp-1 max-w-[220px] text-xs\">\n                    {{ opt.summary }}\n                  </p>\n                </div>\n              </TableCell>\n\n              <!-- Weighted Matrix Criteria Columns -->\n              <template v-if=\"activeFramework === 'weighted-matrix'\">\n                <TableCell v-for=\"criterion in criteriaList\" :key=\"criterion.key\" class=\"text-center\">\n                  <div class=\"inline-flex flex-col items-center gap-0.5\">\n                    <Badge\n                      :variant=\"getScoreBadgeVariant(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                    </Badge>\n                    <!-- Mini visual rating meter (5 segments) -->\n                    <div class=\"mt-1 flex items-center gap-0.5\">\n                      <span\n                        v-for=\"seg in 5\"\n                        :key=\"seg\"\n                        :class=\"\n                          cn(\n                            'size-1 rounded-full',\n                            seg <= Math.round(opt.scores[criterion.key]) ? 'bg-primary' : 'bg-muted-foreground/20',\n                          )\n                        \"\n                      />\n                    </div>\n                  </div>\n                </TableCell>\n\n                <!-- Weighted Total Score Column -->\n                <TableCell class=\"text-center\">\n                  <div class=\"inline-flex flex-col items-center gap-1\">\n                    <span\n                      :class=\"\n                        cn(\n                          'text-base font-semibold tracking-tight tabular-nums',\n                          opt.rank === 1\n                            ? 'text-success'\n                            : opt.weightedScore >= 70\n                              ? 'text-foreground'\n                              : 'text-muted-foreground',\n                        )\n                      \"\n                    >\n                      {{ opt.weightedScore }}\n                      <span class=\"text-muted-foreground text-xs font-normal\">/ 100</span>\n                    </span>\n                    <div class=\"bg-muted h-1.5 w-20 overflow-hidden rounded-full\">\n                      <div\n                        class=\"h-full rounded-full transition-[width,background-color] duration-300\"\n                        :class=\"\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                        :style=\"{ width: `${opt.weightedScore}%` }\"\n                      />\n                    </div>\n                  </div>\n                </TableCell>\n              </template>\n\n              <!-- RICE Framework Columns -->\n              <template v-else>\n                <TableCell class=\"text-center text-xs font-semibold tabular-nums\"> {{ opt.rice.reach }}% </TableCell>\n                <TableCell class=\"text-center text-xs font-semibold tabular-nums\">\n                  {{ opt.rice.impact.toFixed(1) }}x\n                </TableCell>\n                <TableCell class=\"text-center text-xs font-semibold tabular-nums\">\n                  {{ opt.rice.confidence }}%\n                </TableCell>\n                <TableCell class=\"text-center text-xs font-semibold tabular-nums\">\n                  {{ opt.rice.effort.toFixed(1) }} sprints\n                </TableCell>\n                <TableCell class=\"text-center\">\n                  <div class=\"inline-flex flex-col items-center\">\n                    <span class=\"text-primary text-base font-semibold tabular-nums\">\n                      {{ opt.riceScore }}\n                    </span>\n                    <span class=\"text-muted-foreground text-xs font-medium\">RICE Pts</span>\n                  </div>\n                </TableCell>\n              </template>\n\n              <!-- Verdict Column -->\n              <TableCell class=\"text-center\">\n                <span\n                  v-if=\"opt.rank === 1\"\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                  <Award class=\"size-3.5\" />\n                  Recommended Winner\n                </span>\n                <span\n                  v-else-if=\"opt.rank === 2\"\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                  <CheckCircle2 class=\"size-3.5\" />\n                  Second Choice\n                </span>\n                <span\n                  v-else-if=\"opt.rank === 3\"\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                  <HelpCircle class=\"size-3.5\" />\n                  Alternative\n                </span>\n                <span\n                  v-else\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                  <XCircle class=\"size-3.5\" />\n                  Discarded\n                </span>\n              </TableCell>\n\n              <!-- Action / Remove Column -->\n              <TableCell class=\"text-center\" @click.stop>\n                <Button\n                  v-if=\"opt.isCustom\"\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)\"\n                >\n                  <Trash2 class=\"size-3.5\" />\n                </Button>\n                <Button\n                  v-else\n                  variant=\"ghost\"\n                  size=\"icon-sm\"\n                  class=\"text-muted-foreground hover:text-foreground\"\n                  :title=\"`Inspect ${opt.name}`\"\n                  @click=\"selectedOptionId = opt.id\"\n                >\n                  <Info class=\"size-3.5\" />\n                </Button>\n              </TableCell>\n            </TableRow>\n          </TableBody>\n        </Table>\n      </div>\n\n      <CardFooter\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\" />\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 variant=\"ghost\" size=\"xs\" class=\"text-muted-foreground gap-1 text-xs\" @click=\"resetOptions\">\n            <RefreshCw class=\"size-3\" />\n            Reset Matrix Options\n          </Button>\n        </div>\n      </CardFooter>\n    </Card>\n\n    <!-- Tradeoff Visualizer & ADR Recommendation Section -->\n    <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-12\">\n      <!-- Radar Chart: Multi-Option Criteria Comparison -->\n      <Card class=\"border-border bg-card flex flex-col shadow-xs lg:col-span-6\">\n        <CardHeader class=\"pb-2\">\n          <div class=\"flex items-center justify-between gap-x-2\">\n            <div class=\"space-y-0.5\">\n              <CardTitle class=\"flex items-center gap-2 text-base font-semibold tracking-tight\">\n                <BarChart3 class=\"text-primary size-4\" />\n                Decision Tradeoff Radar\n              </CardTitle>\n              <CardDescription class=\"text-xs\">\n                Multi-dimensional polygon overlay comparing architectural options.\n              </CardDescription>\n            </div>\n            <Badge variant=\"outline\" class=\"text-xs font-normal\">5 Axes (1-5)</Badge>\n          </div>\n        </CardHeader>\n\n        <CardContent class=\"flex flex-1 flex-col items-center justify-center p-4\">\n          <!-- SVG Radar Canvas -->\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              <!-- Background Concentric Grid Rings -->\n              <polygon\n                v-for=\"ring in [0.2, 0.4, 0.6, 0.8, 1.0]\"\n                :key=\"ring\"\n                :points=\"getRingPolygon(ring)\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                stroke-width=\"1\"\n                class=\"text-border/50\"\n                :stroke-dasharray=\"ring === 1.0 ? 'none' : '2,2'\"\n              />\n\n              <!-- Radial Axes Lines -->\n              <line\n                v-for=\"(_, idx) in Array.from({ length: radarAxesCount })\"\n                :key=\"idx\"\n                :x1=\"radarCenter.x\"\n                :y1=\"radarCenter.y\"\n                :x2=\"getRadarPoint(idx, 5).x\"\n                :y2=\"getRadarPoint(idx, 5).y\"\n                stroke=\"currentColor\"\n                stroke-width=\"1\"\n                class=\"text-border\"\n              />\n\n              <!-- Polygons for Non-selected options (subtle) -->\n              <template v-for=\"opt in scoredOptions\" :key=\"opt.id\">\n                <polygon\n                  v-if=\"opt.id !== activeSelectedOption.id\"\n                  :points=\"getRadarPolygon(opt.scores)\"\n                  :fill=\"opt.color\"\n                  fill-opacity=\"0.08\"\n                  :stroke=\"opt.color\"\n                  stroke-width=\"1.5\"\n                  stroke-opacity=\"0.45\"\n                  class=\"cursor-pointer transition-colors duration-300\"\n                  @click=\"selectedOptionId = opt.id\"\n                />\n              </template>\n\n              <!-- Polygon for Selected Option (Prominent Highlight) -->\n              <polygon\n                :points=\"getRadarPolygon(activeSelectedOption.scores)\"\n                :fill=\"activeSelectedOption.color\"\n                fill-opacity=\"0.25\"\n                :stroke=\"activeSelectedOption.color\"\n                stroke-width=\"2.5\"\n                class=\"transition-colors duration-300\"\n              />\n\n              <!-- Vertex Dots for Selected Option -->\n              <circle\n                v-for=\"(val, idx) in [\n                  activeSelectedOption.scores.impact,\n                  activeSelectedOption.scores.confidence,\n                  activeSelectedOption.scores.effort,\n                  activeSelectedOption.scores.dx,\n                  activeSelectedOption.scores.maintenance,\n                ]\"\n                :key=\"idx\"\n                :cx=\"getRadarPoint(idx, val).x\"\n                :cy=\"getRadarPoint(idx, val).y\"\n                r=\"4\"\n                :fill=\"activeSelectedOption.color\"\n                class=\"stroke-background stroke-2 transition-colors duration-300\"\n              />\n\n              <!-- Axis Labels -->\n              <text\n                v-for=\"axis in radarAxisLabels\"\n                :key=\"axis.index\"\n                :x=\"axis.x\"\n                :y=\"axis.y\"\n                :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            </svg>\n          </div>\n\n          <!-- Radar Chart Legend -->\n          <div class=\"border-border flex w-full flex-wrap items-center justify-center gap-3 border-t pt-3\">\n            <button\n              v-for=\"opt in scoredOptions\"\n              :key=\"opt.id\"\n              type=\"button\"\n              :class=\"\n                cn(\n                  'inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs transition-colors',\n                  opt.id === 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              @click=\"selectedOptionId = opt.id\"\n            >\n              <span class=\"size-2.5 shrink-0 rounded-full\" :style=\"{ backgroundColor: opt.color }\" />\n              <span class=\"max-w-[120px] truncate\">{{ opt.name.split(':')[0] }}</span>\n            </button>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Architectural Consensus & Tradeoff Detail Card -->\n      <Card class=\"border-border bg-card flex flex-col justify-between shadow-xs lg:col-span-6\">\n        <CardHeader 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                <Badge variant=\"outline\" class=\"text-xs\">Selected Option Details</Badge>\n                <Badge\n                  :variant=\"activeSelectedOption.verdictVariant === 'success' ? 'success' : 'secondary'\"\n                  class=\"text-xs font-semibold\"\n                >\n                  {{ activeSelectedOption.verdict }}\n                </Badge>\n              </div>\n              <CardTitle class=\"text-foreground text-lg font-semibold tracking-tight\">\n                {{ activeSelectedOption.name }}\n              </CardTitle>\n              <CardDescription class=\"text-primary text-xs font-medium\">\n                {{ activeSelectedOption.architecture }}\n              </CardDescription>\n            </div>\n            <div class=\"shrink-0 text-right\">\n              <div class=\"text-foreground text-2xl font-semibold tabular-nums\">\n                {{ activeFramework === 'rice' ? activeSelectedOption.riceScore : activeSelectedOption.weightedScore }}\n              </div>\n              <div class=\"text-muted-foreground text-xs\">\n                {{ activeFramework === 'rice' ? 'RICE Score' : 'Weighted Total' }}\n              </div>\n            </div>\n          </div>\n        </CardHeader>\n\n        <CardContent class=\"space-y-4 text-xs\">\n          <!-- Summary paragraph -->\n          <p class=\"text-muted-foreground text-sm leading-relaxed\">\n            {{ activeSelectedOption.summary }}\n          </p>\n\n          <Separator />\n\n          <!-- Pros & Cons Grid -->\n          <div class=\"grid grid-cols-1 gap-3.5 sm:grid-cols-2\">\n            <!-- Architectural Pros -->\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                <Check class=\"size-3.5\" />\n                Strategic Advantages\n              </span>\n              <ul class=\"text-muted-foreground space-y-1.5\">\n                <li v-for=\"(pro, idx) in activeSelectedOption.pros\" :key=\"idx\" class=\"flex items-start gap-1.5\">\n                  <span class=\"text-success mt-0.5\">•</span>\n                  <span>{{ pro }}</span>\n                </li>\n              </ul>\n            </div>\n\n            <!-- Architectural Cons & Risks -->\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                <AlertCircle class=\"size-3.5\" />\n                Compromises & Friction\n              </span>\n              <ul class=\"text-muted-foreground space-y-1.5\">\n                <li v-for=\"(con, idx) in activeSelectedOption.cons\" :key=\"idx\" class=\"flex items-start gap-1.5\">\n                  <span class=\"text-destructive mt-0.5\">•</span>\n                  <span>{{ con }}</span>\n                </li>\n              </ul>\n            </div>\n          </div>\n\n          <!-- Risk Mitigation -->\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              <ShieldCheck class=\"text-primary size-3.5\" />\n              Risk Mitigation & Governance Policy:\n            </span>\n            <p class=\"text-muted-foreground\">\n              {{ activeSelectedOption.keyRisk }}\n            </p>\n          </div>\n        </CardContent>\n\n        <CardFooter class=\"border-border bg-muted/20 flex items-center justify-between gap-x-2 border-t px-6 py-3\">\n          <div class=\"flex items-center gap-2\">\n            <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\">{{\n              winningOption.name.split(':')[1] || winningOption.name\n            }}</span>\n          </div>\n          <Badge variant=\"outline\" class=\"gap-1 text-xs\">\n            <Award class=\"text-success size-3\" />\n            Rank #{{ activeSelectedOption.rank }}\n          </Badge>\n        </CardFooter>\n      </Card>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/DecisionMatrixTable.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/slider.json",
    "https://uipkge.dev/r/vue/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"
  ]
}