{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "column-profiling-summary",
  "title": "Column Profiling Summary",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/column-profiling-summary/column-profiling-summary.component.ts",
      "content": "import { Component, Input, signal, computed, ChangeDetectionStrategy } from '@angular/core'\nimport {\n  AlertCircle,\n  BarChart2,\n  Binary,\n  Check,\n  CheckCircle2,\n  Copy,\n  Database,\n  Download,\n  Hash,\n  LayoutGrid,\n  LucideAngularModule,\n  Search,\n  Table as TableIcon,\n  Tag,\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  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiProgressComponent } from '@/ui/progress/progress.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport type ColumnProfilingTypeFilter = 'all' | 'numeric' | 'categorical' | 'boolean'\nexport type ColumnProfilingViewMode = 'cards' | 'table'\n\nexport interface ColumnProfilingHistogramBin {\n  bin: string\n  count: number\n  pct: number\n  height: number\n}\n\nexport interface ColumnProfilingTier {\n  name: string\n  count: number\n  pct: number\n  colorClass: string\n  badgeClass: string\n}\n\nexport interface ColumnProfilingSchemaColumn {\n  name: string\n  type: string\n  category: string\n  missing: string\n  distinct: string\n  summary: string\n  status: string\n}\n\n// Column 1: monthly_spend_usd (Numeric Float64)\nconst monthlySpendStats = {\n  name: 'monthly_spend_usd',\n  type: 'Numeric Float64',\n  category: 'numeric',\n  min: '$0.00',\n  mean: '$142.50',\n  median: '$120.00',\n  max: '$2,450.00',\n  stdDev: '48.2',\n  iqr: '$115.00',\n  zerosCount: 1420,\n  zerosPct: '0.96%',\n  missingCount: 0,\n  missingPct: '0.0%',\n  distinctCount: '12,410',\n  distinctPct: '8.37%',\n  memory: '1.19 MB',\n}\n\nconst histogramBins: ColumnProfilingHistogramBin[] = [\n  { bin: '$0 - $245', count: 58400, pct: 39.4, height: 95 },\n  { bin: '$245 - $490', count: 42100, pct: 28.4, height: 68 },\n  { bin: '$490 - $735', count: 22500, pct: 15.2, height: 36 },\n  { bin: '$735 - $980', count: 12800, pct: 8.6, height: 21 },\n  { bin: '$980 - $1,225', count: 6400, pct: 4.3, height: 10 },\n  { bin: '$1,225 - $1,470', count: 3100, pct: 2.1, height: 5 },\n  { bin: '$1,470 - $1,715', count: 1650, pct: 1.1, height: 3 },\n  { bin: '$1,715 - $1,960', count: 840, pct: 0.6, height: 2 },\n  { bin: '$1,960 - $2,205', count: 380, pct: 0.3, height: 1 },\n  { bin: '$2,205 - $2,450', count: 120, pct: 0.1, height: 1 },\n]\n\n// Column 2: subscription_tier (Categorical)\nconst subscriptionTierStats = {\n  name: 'subscription_tier',\n  type: 'Categorical',\n  category: 'categorical',\n  distinctCount: 4,\n  missingCount: 0,\n  missingPct: '0.0%',\n  memory: '1.19 MB',\n  topValue: 'Starter',\n  topFreqPct: '45.0%',\n}\n\nconst subscriptionTiers: ColumnProfilingTier[] = [\n  { name: 'Starter', count: 66730, pct: 45.0, colorClass: 'bg-primary', badgeClass: 'border-primary/30 text-primary' },\n  { name: 'Pro', count: 51901, pct: 35.0, colorClass: 'bg-success', badgeClass: 'border-success/30 text-success' },\n  { name: 'Enterprise', count: 22243, pct: 15.0, colorClass: 'bg-info', badgeClass: 'border-info/30 text-info' },\n  { name: 'Custom', count: 7416, pct: 5.0, colorClass: 'bg-warning', badgeClass: 'border-warning/30 text-warning' },\n]\n\n// Column 3: account_age_days (Numeric Int32)\nconst accountAgeStats = {\n  name: 'account_age_days',\n  type: 'Numeric Int32',\n  category: 'numeric',\n  min: '1d',\n  p25: '42d',\n  p50: '180d',\n  p75: '365d',\n  p95: '580d',\n  p99: '720d',\n  max: '850d',\n  iqr: '323d',\n  mean: '214.6d',\n  stdDev: '142.1',\n  missingCount: 42,\n  missingPct: '0.03%',\n  distinctCount: '820',\n  distinctPct: '0.55%',\n  memory: '593.2 KB',\n}\n\n// Column 4: has_cancelled (Boolean)\nconst hasCancelledStats = {\n  name: 'has_cancelled',\n  type: 'Boolean',\n  category: 'boolean',\n  missingCount: 0,\n  missingPct: '0.0%',\n  distinctCount: 2,\n  memory: '144.8 KB',\n  trueCount: 21057,\n  truePct: 14.2,\n  falseCount: 127233,\n  falsePct: 85.8,\n}\n\n// Schema overview for compact table view\nconst allSchemaColumns: ColumnProfilingSchemaColumn[] = [\n  {\n    name: 'monthly_spend_usd',\n    type: 'Numeric Float64',\n    category: 'numeric',\n    missing: '0 (0.0%)',\n    distinct: '12,410 (8.4%)',\n    summary: 'Mean: $142.50 · Median: $120.00 · Max: $2,450.00',\n    status: 'Clean',\n  },\n  {\n    name: 'subscription_tier',\n    type: 'Categorical',\n    category: 'categorical',\n    missing: '0 (0.0%)',\n    distinct: '4 values',\n    summary: 'Starter (45%) > Pro (35%) > Enterprise (15%)',\n    status: 'Clean',\n  },\n  {\n    name: 'account_age_days',\n    type: 'Numeric Int32',\n    category: 'numeric',\n    missing: '42 (0.03%)',\n    distinct: '820 (0.6%)',\n    summary: 'P25: 42d · P50: 180d · P75: 365d · P99: 720d',\n    status: '99.97% Complete',\n  },\n  {\n    name: 'has_cancelled',\n    type: 'Boolean',\n    category: 'boolean',\n    missing: '0 (0.0%)',\n    distinct: '2 values',\n    summary: 'False: 85.8% (127.2k) · True: 14.2% (21.1k)',\n    status: 'Clean',\n  },\n  {\n    name: 'customer_id',\n    type: 'Categorical UUID',\n    category: 'categorical',\n    missing: '0 (0.0%)',\n    distinct: '148,290 (100%)',\n    summary: 'Primary Key · Unique identifier',\n    status: 'Unique Index',\n  },\n  {\n    name: 'support_tickets_count',\n    type: 'Numeric Int16',\n    category: 'numeric',\n    missing: '0 (0.0%)',\n    distinct: '18 values',\n    summary: 'Mean: 1.4 · Median: 1.0 · Max: 16.0',\n    status: 'Clean',\n  },\n  {\n    name: 'last_login_epoch',\n    type: 'Numeric Int64',\n    category: 'numeric',\n    missing: '112 (0.08%)',\n    distinct: '114,200',\n    summary: 'Min: 1770000000 · Max: 1787313600',\n    status: 'Clean',\n  },\n  {\n    name: 'signup_channel',\n    type: 'Categorical',\n    category: 'categorical',\n    missing: '439 (0.30%)',\n    distinct: '7 values',\n    summary: 'Organic (42%) > Google Ads (28%) > Partner (16%)',\n    status: 'Clean',\n  },\n]\n\nconst spendMetrics = [\n  { label: 'Minimum', value: monthlySpendStats.min },\n  { label: 'Mean (Avg)', value: monthlySpendStats.mean },\n  { label: 'Median (P50)', value: monthlySpendStats.median },\n  { label: 'Maximum', value: monthlySpendStats.max },\n  { label: 'Std. Deviation', value: monthlySpendStats.stdDev },\n  { label: 'Interquartile (IQR)', value: monthlySpendStats.iqr },\n]\n\nconst typeFilters: { value: ColumnProfilingTypeFilter; label: string }[] = [\n  { value: 'all', label: 'All Types (18)' },\n  { value: 'numeric', label: 'Numeric (10)' },\n  { value: 'categorical', label: 'Categorical (6)' },\n  { value: 'boolean', label: 'Boolean (2)' },\n]\n\n/**\n * ColumnProfilingSummary -- the React block, 1:1: a ydata-profiling style EDA summary with a\n * dataset header (export report), four overview KPI cards, a type filter / search / view-mode\n * toolbar, and either four column deep-dive cards (histogram, category split, box plot,\n * boolean ratio) or a compact schema table. Pass `tableName`, `totalRows`, `totalColumns`,\n * `memoryFootprint` and `datasetVersion` to relabel it; edit the data above to change the rest.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-column-profiling-summary, [ui-column-profiling-summary]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout, `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiCardDescriptionComponent,\n    UiCardContentComponent,\n    UiProgressComponent,\n    UiTableComponent,\n    UiTableHeaderComponent,\n    UiTableBodyComponent,\n    UiTableRowComponent,\n    UiTableHeadComponent,\n    UiTableCellComponent,\n  ],\n  template: `\n    <div data-slot=\"column-profiling-summary\" [class]=\"rootClass\">\n      <!-- Header Section -->\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.5\">\n            <div class=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-lg\">\n              <lucide-icon [img]=\"Database\" class=\"size-4\" />\n            </div>\n            <h1 class=\"text-foreground text-2xl font-bold tracking-tight break-all sm:text-3xl\">\n              Table: {{ tableName }}\n            </h1>\n            <span ui-badge variant=\"outline\" class=\"gap-1.5 font-mono text-xs font-normal\">\n              <span class=\"bg-success size-1.5 rounded-full\"></span>\n              <span>Apache Parquet</span>\n            </span>\n            <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">{{ datasetVersion }}</span>\n          </div>\n          <p class=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-xs\">\n            <span>Profiled: 2026-08-21 14:30 UTC</span>\n            <span>•</span>\n            <span>Snappy Compressed</span>\n            <span>•</span>\n            <span class=\"text-foreground font-medium\">EDA Engine: ydata-profiler v4.8</span>\n          </p>\n        </div>\n\n        <div class=\"flex flex-wrap items-center gap-3\">\n          <!-- Quick Meta Pills -->\n          <div class=\"bg-card border-border/80 flex items-center divide-x rounded-lg border text-xs shadow-xs\">\n            <div class=\"px-3 py-1.5\">\n              <span class=\"text-muted-foreground\">Rows: </span>\n              <span class=\"text-foreground font-semibold tabular-nums\">{{ totalRows }}</span>\n            </div>\n            <div class=\"px-3 py-1.5\">\n              <span class=\"text-muted-foreground\">Cols: </span>\n              <span class=\"text-foreground font-semibold tabular-nums\">{{ totalColumns }}</span>\n            </div>\n            <div class=\"px-3 py-1.5\">\n              <span class=\"text-muted-foreground\">Memory: </span>\n              <span class=\"text-foreground font-semibold tabular-nums\">{{ memoryFootprint }}</span>\n            </div>\n          </div>\n\n          <!-- Export EDA Report Button -->\n          <button\n            ui-button\n            type=\"button\"\n            aria-label=\"Download attachment\"\n            size=\"sm\"\n            class=\"gap-1.5 shadow-xs\"\n            [disabled]=\"isExporting()\"\n            (click)=\"handleExportReport()\"\n          >\n            @if (isExporting()) {\n              <span class=\"size-3.5 animate-spin rounded-full border-2 border-current border-t-transparent\"></span>\n            } @else {\n              <lucide-icon [img]=\"Download\" class=\"size-3.5\" />\n            }\n            <span>{{ isExporting() ? 'Generating HTML Report...' : 'Export EDA Report' }}</span>\n          </button>\n        </div>\n      </div>\n\n      <!-- Export Success Banner -->\n      @if (showExportSuccess()) {\n        <div\n          class=\"border-success/30 bg-success/10 text-foreground dark:text-foreground flex items-center justify-between rounded-lg border p-3 text-xs shadow-xs\"\n          role=\"status\"\n        >\n          <div class=\"flex items-center gap-2\">\n            <lucide-icon [img]=\"CheckCircle2\" class=\"text-success size-4 shrink-0\" />\n            <span class=\"font-medium\">\n              Exploratory Data Analysis report exported. HTML summary &amp; JSON schema bundle ready for download.\n            </span>\n          </div>\n          <button\n            type=\"button\"\n            class=\"text-success text-success cursor-pointer text-xs font-semibold hover:underline\"\n            (click)=\"showExportSuccess.set(false)\"\n          >\n            Dismiss\n          </button>\n        </div>\n      }\n\n      <!-- 4 Dataset Overview KPI Cards -->\n      <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        <!-- 1. Numeric Columns -->\n        <div ui-card class=\"flex flex-col justify-between\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex items-center gap-2\">\n                <div class=\"bg-muted text-foreground flex size-7 items-center justify-center rounded-md border\">\n                  <lucide-icon [img]=\"Hash\" class=\"text-info size-3.5\" />\n                </div>\n                <h3 ui-card-title class=\"text-sm font-medium\">Numeric Columns</h3>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs tabular-nums\">55.6%</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2 pt-1\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">10</span>\n              <span class=\"text-muted-foreground text-xs font-medium\">Columns</span>\n            </div>\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between\">\n                <span>Types Breakdown:</span>\n                <span class=\"text-foreground font-medium tabular-nums\">8 Float64 · 2 Int32</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- 2. Categorical Columns -->\n        <div ui-card class=\"flex flex-col justify-between\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex items-center gap-2\">\n                <div class=\"bg-muted text-foreground flex size-7 items-center justify-center rounded-md border\">\n                  <lucide-icon [img]=\"Tag\" class=\"text-chart-1 size-3.5\" />\n                </div>\n                <h3 ui-card-title class=\"text-sm font-medium\">Categorical Columns</h3>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs tabular-nums\">33.3%</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2 pt-1\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">6</span>\n              <span class=\"text-muted-foreground text-xs font-medium\">Columns</span>\n            </div>\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between\">\n                <span>High Cardinality:</span>\n                <span class=\"text-foreground font-medium tabular-nums\">1 (customer_id)</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- 3. Missing Values % -->\n        <div ui-card class=\"flex flex-col justify-between\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex items-center gap-2\">\n                <div class=\"bg-muted text-foreground flex size-7 items-center justify-center rounded-md border\">\n                  <lucide-icon [img]=\"AlertCircle\" class=\"text-success size-3.5\" />\n                </div>\n                <h3 ui-card-title class=\"text-sm font-medium\">Missing Values</h3>\n              </div>\n              <span ui-badge variant=\"success\" class=\"text-xs\">Clean</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2 pt-1\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">0.4%</span>\n              <span class=\"text-muted-foreground text-xs font-medium\">Missing</span>\n            </div>\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between\">\n                <span>Total Null Cells:</span>\n                <span class=\"text-foreground font-medium tabular-nums\">593 / 2,669,220</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- 4. Duplicate Rows -->\n        <div ui-card class=\"flex flex-col justify-between\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex items-center gap-2\">\n                <div class=\"bg-muted text-foreground flex size-7 items-center justify-center rounded-md border\">\n                  <lucide-icon [img]=\"CheckCircle2\" class=\"text-success size-3.5\" />\n                </div>\n                <h3 ui-card-title class=\"text-sm font-medium\">Duplicate Rows</h3>\n              </div>\n              <span ui-badge variant=\"success\" class=\"text-xs\">100% Unique</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2 pt-1\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">0</span>\n              <span class=\"text-muted-foreground text-xs font-medium\">Duplicates</span>\n            </div>\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between\">\n                <span>Primary Key Integrity:</span>\n                <span class=\"text-foreground font-medium\">100.0% Valid</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <!-- Filter & Toolbar Controls -->\n      <div ui-card class=\"border-border bg-card shadow-xs\">\n        <div ui-card-content class=\"p-3\">\n          <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n            <!-- Type Filter Tabs -->\n            <div class=\"flex flex-wrap items-center gap-1.5\">\n              @for (f of typeFilters; track f.value) {\n                <button type=\"button\" [class]=\"filterClass(f.value)\" (click)=\"activeTypeFilter.set(f.value)\">\n                  {{ f.label }}\n                </button>\n              }\n            </div>\n\n            <!-- Search & View Mode Switcher -->\n            <div class=\"flex items-center gap-2\">\n              <div class=\"relative flex items-center\">\n                <lucide-icon\n                  [img]=\"Search\"\n                  class=\"text-muted-foreground pointer-events-none absolute left-2.5 size-3.5\"\n                />\n                <input\n                  [value]=\"searchQuery()\"\n                  (input)=\"onSearch($event)\"\n                  type=\"text\"\n                  placeholder=\"Filter column name...\"\n                  class=\"border-border bg-background text-foreground focus-visible:border-ring focus-visible:ring-ring/50 h-8 w-44 rounded-md border pr-2.5 pl-8 text-xs focus-visible:ring-2 focus-visible:outline-none sm:w-56\"\n                />\n              </div>\n\n              <div class=\"bg-muted border-border flex items-center rounded-md border p-0.5 text-xs\">\n                <button\n                  type=\"button\"\n                  [class]=\"viewClass('cards')\"\n                  aria-label=\"Card deep dive view\"\n                  (click)=\"viewMode.set('cards')\"\n                >\n                  <lucide-icon [img]=\"LayoutGrid\" class=\"size-3.5\" />\n                </button>\n                <button\n                  type=\"button\"\n                  [class]=\"viewClass('table')\"\n                  aria-label=\"Compact table view\"\n                  (click)=\"viewMode.set('table')\"\n                >\n                  <lucide-icon [img]=\"TableIcon\" class=\"size-3.5\" />\n                </button>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      @if (viewMode() === 'table') {\n        <!-- Compact Table View -->\n        <div ui-card>\n          <div ui-card-header class=\"pb-3\">\n            <div class=\"flex items-center justify-between\">\n              <div>\n                <h3 ui-card-title class=\"text-base font-semibold\">Dataset Schema &amp; Profiling Matrix</h3>\n                <p ui-card-description class=\"text-xs\">\n                  Tabular view of all columns with inferred types, missingness, cardinality, and distribution summary.\n                </p>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs tabular-nums\">\n                {{ filteredColumns().length }} of 18 columns\n              </span>\n            </div>\n          </div>\n          <div ui-card-content class=\"p-0\">\n            <div class=\"overflow-x-auto\">\n              <div ui-table>\n                <thead ui-table-header>\n                  <tr ui-table-row>\n                    <th ui-table-head class=\"min-w-[180px]\">Column Name</th>\n                    <th ui-table-head class=\"min-w-[140px]\">Data Type</th>\n                    <th ui-table-head class=\"min-w-[110px]\">Missing Values</th>\n                    <th ui-table-head class=\"min-w-[120px]\">Distinct Values</th>\n                    <th ui-table-head class=\"min-w-[280px]\">Distribution / Quantiles</th>\n                    <th ui-table-head class=\"text-right\">Health Status</th>\n                  </tr>\n                </thead>\n                <tbody ui-table-body>\n                  @for (col of filteredColumns(); track col.name) {\n                    <tr ui-table-row>\n                      <td ui-table-cell class=\"font-mono text-xs font-medium\">\n                        <div class=\"flex items-center gap-1.5\">\n                          <span>{{ col.name }}</span>\n                          <button\n                            type=\"button\"\n                            class=\"text-muted-foreground hover:text-foreground cursor-pointer\"\n                            [attr.aria-label]=\"'Copy column ' + col.name\"\n                            (click)=\"handleCopy(col.name)\"\n                          >\n                            @if (copiedColumn() === col.name) {\n                              <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                            } @else {\n                              <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                            }\n                          </button>\n                        </div>\n                      </td>\n                      <td ui-table-cell class=\"text-xs\">\n                        <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">{{ col.type }}</span>\n                      </td>\n                      <td ui-table-cell class=\"text-muted-foreground font-mono text-xs tabular-nums\">\n                        {{ col.missing }}\n                      </td>\n                      <td ui-table-cell class=\"text-foreground font-mono text-xs tabular-nums\">{{ col.distinct }}</td>\n                      <td ui-table-cell class=\"text-muted-foreground text-xs\">{{ col.summary }}</td>\n                      <td ui-table-cell class=\"text-right\">\n                        <span ui-badge [variant]=\"statusVariant(col)\" class=\"text-xs font-normal\">{{\n                          col.status\n                        }}</span>\n                      </td>\n                    </tr>\n                  }\n                </tbody>\n              </div>\n            </div>\n          </div>\n        </div>\n      } @else {\n        <!-- 4 Detailed Column Deep-Dive Cards -->\n        <div class=\"space-y-6\">\n          <!-- 1. monthly_spend_usd (Numeric Float64 + 10-bar SVG Histogram) -->\n          @if (activeTypeFilter() === 'all' || activeTypeFilter() === 'numeric') {\n            <div ui-card class=\"border-border bg-card shadow-xs\">\n              <div ui-card-header class=\"pb-3\">\n                <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n                  <div class=\"space-y-1\">\n                    <div class=\"flex flex-wrap items-center gap-2\">\n                      <div class=\"bg-info/10 text-info flex size-6 items-center justify-center rounded-md\">\n                        <lucide-icon [img]=\"Hash\" class=\"size-3.5\" />\n                      </div>\n                      <h3 ui-card-title class=\"font-mono text-base font-semibold\">{{ spend.name }}</h3>\n                      <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">{{ spend.type }}</span>\n                      <button\n                        type=\"button\"\n                        class=\"text-muted-foreground hover:text-foreground cursor-pointer\"\n                        [attr.aria-label]=\"'Copy ' + spend.name\"\n                        (click)=\"handleCopy(spend.name)\"\n                      >\n                        @if (copiedColumn() === spend.name) {\n                          <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                        } @else {\n                          <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                        }\n                      </button>\n                    </div>\n                    <p ui-card-description class=\"text-xs\">\n                      Monthly billed subscription and add-on expenditure in USD. Right-skewed distribution with long\n                      tail.\n                    </p>\n                  </div>\n\n                  <!-- Meta Badges -->\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Missing:\n                      <span class=\"text-success text-success ml-1 font-semibold tabular-nums\">{{\n                        spend.missingPct\n                      }}</span>\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Distinct:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\">{{ spend.distinctCount }}</span>\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Memory:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\">{{ spend.memory }}</span>\n                    </span>\n                  </div>\n                </div>\n              </div>\n\n              <div ui-card-content class=\"space-y-6 pt-1\">\n                <!-- Summary Metrics Grid -->\n                <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6\">\n                  @for (m of spendMetrics; track m.label) {\n                    <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n                      <span class=\"text-muted-foreground text-xs\">{{ m.label }}</span>\n                      <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ m.value }}</p>\n                    </div>\n                  }\n                </div>\n\n                <!-- 10-Bar SVG Histogram -->\n                <div class=\"space-y-2\">\n                  <div class=\"flex items-center justify-between text-xs\">\n                    <div class=\"flex items-center gap-2\">\n                      <lucide-icon [img]=\"BarChart2\" class=\"text-primary size-3.5\" />\n                      <span class=\"text-foreground font-medium\">10-Bin Distribution Frequency Histogram</span>\n                    </div>\n                    @if (hoveredBin(); as b) {\n                      <span class=\"text-foreground font-mono tabular-nums\">\n                        {{ b.bin }}: <strong class=\"text-primary\">{{ fmt(b.count) }} rows</strong> ({{ b.pct }}%)\n                      </span>\n                    } @else {\n                      <span class=\"text-muted-foreground\">Hover bar to inspect bin interval</span>\n                    }\n                  </div>\n\n                  <!-- SVG Histogram Visual -->\n                  <div class=\"border-border bg-muted/20 w-full overflow-x-auto rounded-lg border p-4\">\n                    <div class=\"h-44 w-full max-w-[420px] min-w-full\">\n                      <svg\n                        class=\"h-full w-full overflow-visible\"\n                        viewBox=\"0 0 520 140\"\n                        preserveAspectRatio=\"none\"\n                        role=\"img\"\n                        aria-label=\"10-bar distribution histogram for monthly spend in USD\"\n                      >\n                        <!-- Background Grid Lines -->\n                        <line\n                          x1=\"0\"\n                          y1=\"20\"\n                          x2=\"520\"\n                          y2=\"20\"\n                          stroke=\"currentColor\"\n                          class=\"text-border/40\"\n                          stroke-dasharray=\"3 3\"\n                        />\n                        <line\n                          x1=\"0\"\n                          y1=\"65\"\n                          x2=\"520\"\n                          y2=\"65\"\n                          stroke=\"currentColor\"\n                          class=\"text-border/40\"\n                          stroke-dasharray=\"3 3\"\n                        />\n                        <line x1=\"0\" y1=\"110\" x2=\"520\" y2=\"110\" stroke=\"currentColor\" class=\"text-border\" />\n\n                        <!-- 10 Bars -->\n                        @for (bin of histogramBins; track $index; let idx = $index) {\n                          <g>\n                            <rect\n                              [attr.x]=\"idx * 52 + 6\"\n                              [attr.y]=\"110 - bin.height\"\n                              width=\"40\"\n                              [attr.height]=\"bin.height\"\n                              rx=\"3\"\n                              [attr.class]=\"barClass(idx)\"\n                              (mouseenter)=\"hoveredHistBin.set(idx)\"\n                              (mouseleave)=\"hoveredHistBin.set(null)\"\n                            />\n                            @if (bin.pct >= 5) {\n                              <text\n                                [attr.x]=\"idx * 52 + 26\"\n                                [attr.y]=\"104 - bin.height\"\n                                text-anchor=\"middle\"\n                                class=\"fill-foreground font-mono text-xs font-medium select-none\"\n                              >\n                                {{ bin.pct }}%\n                              </text>\n                            }\n                          </g>\n                        }\n                      </svg>\n                    </div>\n\n                    <!-- Bin Axis Ticks -->\n                    <div class=\"text-muted-foreground mt-2 grid grid-cols-5 text-center font-mono text-xs tabular-nums\">\n                      <span class=\"text-left\">$0.00</span>\n                      <span>$490</span>\n                      <span>$980</span>\n                      <span>$1,715</span>\n                      <span class=\"text-right\">$2,450</span>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          }\n\n          <!-- 2. subscription_tier (Categorical + Horizontal Distribution Bars) -->\n          @if (activeTypeFilter() === 'all' || activeTypeFilter() === 'categorical') {\n            <div ui-card class=\"border-border bg-card shadow-xs\">\n              <div ui-card-header class=\"pb-3\">\n                <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n                  <div class=\"space-y-1\">\n                    <div class=\"flex flex-wrap items-center gap-2\">\n                      <div class=\"bg-chart-1/10 text-chart-1 flex size-6 items-center justify-center rounded-md\">\n                        <lucide-icon [img]=\"Tag\" class=\"size-3.5\" />\n                      </div>\n                      <h3 ui-card-title class=\"font-mono text-base font-semibold\">{{ tier.name }}</h3>\n                      <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">{{ tier.type }}</span>\n                      <button\n                        type=\"button\"\n                        class=\"text-muted-foreground hover:text-foreground cursor-pointer\"\n                        [attr.aria-label]=\"'Copy ' + tier.name\"\n                        (click)=\"handleCopy(tier.name)\"\n                      >\n                        @if (copiedColumn() === tier.name) {\n                          <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                        } @else {\n                          <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                        }\n                      </button>\n                    </div>\n                    <p ui-card-description class=\"text-xs\">\n                      Active customer plan classification tier. Clean categorical distribution across 4 discrete levels.\n                    </p>\n                  </div>\n\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Missing:\n                      <span class=\"text-success text-success ml-1 font-semibold tabular-nums\">{{\n                        tier.missingPct\n                      }}</span>\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Distinct:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\"\n                        >{{ tier.distinctCount }} values</span\n                      >\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Memory:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\">{{ tier.memory }}</span>\n                    </span>\n                  </div>\n                </div>\n              </div>\n\n              <div ui-card-content class=\"space-y-6 pt-1\">\n                <!-- Segmented Composite Stacked Bar -->\n                <div class=\"space-y-2\">\n                  <div class=\"flex items-center justify-between text-xs\">\n                    <span class=\"text-foreground font-medium\">Category Proportions</span>\n                    <span class=\"text-muted-foreground font-mono tabular-nums\">148,290 total instances</span>\n                  </div>\n\n                  <div class=\"border-border flex h-4 w-full overflow-hidden rounded-full border\">\n                    @for (t of subscriptionTiers; track t.name) {\n                      <div\n                        [class]=\"t.colorClass\"\n                        [style.width.%]=\"t.pct\"\n                        [title]=\"t.name + ': ' + t.pct + '% (' + fmt(t.count) + ' rows)'\"\n                      ></div>\n                    }\n                  </div>\n                </div>\n\n                <!-- Detailed Breakdown Rows -->\n                <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4\">\n                  @for (t of subscriptionTiers; track t.name) {\n                    <div class=\"border-border bg-muted/20 flex flex-col justify-between rounded-lg border p-3.5\">\n                      <div class=\"space-y-1.5\">\n                        <div class=\"flex items-center justify-between\">\n                          <span class=\"text-foreground font-mono text-xs font-semibold\">{{ t.name }}</span>\n                          <span ui-badge variant=\"outline\" [class]=\"tierBadgeClass(t)\">{{ t.pct.toFixed(1) }}%</span>\n                        </div>\n                        <p class=\"text-muted-foreground font-mono text-xs tabular-nums\">{{ fmt(t.count) }} rows</p>\n                      </div>\n\n                      <div class=\"mt-3\">\n                        <div class=\"bg-muted relative h-1.5 w-full overflow-hidden rounded-full\">\n                          <div [class]=\"tierBarClass(t)\" [style.width.%]=\"t.pct\"></div>\n                        </div>\n                      </div>\n                    </div>\n                  }\n                </div>\n              </div>\n            </div>\n          }\n\n          <!-- 3. account_age_days (Numeric Int32 + Quantiles Box Plot) -->\n          @if (activeTypeFilter() === 'all' || activeTypeFilter() === 'numeric') {\n            <div ui-card class=\"border-border bg-card shadow-xs\">\n              <div ui-card-header class=\"pb-3\">\n                <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n                  <div class=\"space-y-1\">\n                    <div class=\"flex flex-wrap items-center gap-2\">\n                      <div class=\"bg-info/10 text-info flex size-6 items-center justify-center rounded-md\">\n                        <lucide-icon [img]=\"Hash\" class=\"size-3.5\" />\n                      </div>\n                      <h3 ui-card-title class=\"font-mono text-base font-semibold\">{{ age.name }}</h3>\n                      <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">{{ age.type }}</span>\n                      <button\n                        type=\"button\"\n                        class=\"text-muted-foreground hover:text-foreground cursor-pointer\"\n                        [attr.aria-label]=\"'Copy ' + age.name\"\n                        (click)=\"handleCopy(age.name)\"\n                      >\n                        @if (copiedColumn() === age.name) {\n                          <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                        } @else {\n                          <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                        }\n                      </button>\n                    </div>\n                    <p ui-card-description class=\"text-xs\">\n                      Total account tenure in days since initial signup. Box plot shows median at 180d with Q1-Q3\n                      interquartile band.\n                    </p>\n                  </div>\n\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Missing:\n                      <span class=\"text-success text-success ml-1 font-semibold tabular-nums\"\n                        >{{ age.missingPct }} (42 rows)</span\n                      >\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Distinct:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\">{{ age.distinctCount }}</span>\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Memory:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\">{{ age.memory }}</span>\n                    </span>\n                  </div>\n                </div>\n              </div>\n\n              <div ui-card-content class=\"space-y-6 pt-1\">\n                <!-- Quantile Stats Grid -->\n                <div class=\"grid grid-cols-2 gap-3 sm:grid-cols-4 lg:grid-cols-7\">\n                  <div class=\"border-border bg-muted/30 rounded-lg border p-2.5 text-center\">\n                    <span class=\"text-muted-foreground text-xs\">Min (0%)</span>\n                    <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ age.min }}</p>\n                  </div>\n                  <div class=\"border-border bg-muted/30 rounded-lg border p-2.5 text-center\">\n                    <span class=\"text-muted-foreground text-xs\">Q1 (P25)</span>\n                    <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ age.p25 }}</p>\n                  </div>\n                  <div class=\"border-primary/40 bg-primary/5 rounded-lg border p-2.5 text-center shadow-xs\">\n                    <span class=\"text-primary text-xs font-medium\">Median (P50)</span>\n                    <p class=\"text-primary font-mono text-sm font-bold tabular-nums\">{{ age.p50 }}</p>\n                  </div>\n                  <div class=\"border-border bg-muted/30 rounded-lg border p-2.5 text-center\">\n                    <span class=\"text-muted-foreground text-xs\">Q3 (P75)</span>\n                    <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ age.p75 }}</p>\n                  </div>\n                  <div class=\"border-border bg-muted/30 rounded-lg border p-2.5 text-center\">\n                    <span class=\"text-muted-foreground text-xs\">P95</span>\n                    <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ age.p95 }}</p>\n                  </div>\n                  <div class=\"border-border bg-muted/30 rounded-lg border p-2.5 text-center\">\n                    <span class=\"text-muted-foreground text-xs\">P99</span>\n                    <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ age.p99 }}</p>\n                  </div>\n                  <div class=\"border-border bg-muted/30 rounded-lg border p-2.5 text-center\">\n                    <span class=\"text-muted-foreground text-xs\">Max</span>\n                    <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">{{ age.max }}</p>\n                  </div>\n                </div>\n\n                <!-- Box Plot SVG Representation -->\n                <div class=\"space-y-2\">\n                  <div class=\"flex items-center justify-between text-xs\">\n                    <span class=\"text-foreground font-medium\">Quantile Box &amp; Whisker Plot</span>\n                    <span class=\"text-muted-foreground font-mono tabular-nums\">IQR = 323 days (P75 - P25)</span>\n                  </div>\n\n                  <div class=\"border-border bg-muted/20 w-full overflow-x-auto rounded-lg border p-4\">\n                    <div class=\"h-28 w-full max-w-[420px] min-w-full\">\n                      <svg\n                        class=\"h-full w-full overflow-visible\"\n                        viewBox=\"0 0 500 90\"\n                        preserveAspectRatio=\"none\"\n                        role=\"img\"\n                        aria-label=\"Box plot visualization of account age quantiles\"\n                      >\n                        <!-- Axis Baseline -->\n                        <line x1=\"30\" y1=\"72\" x2=\"470\" y2=\"72\" stroke=\"currentColor\" class=\"text-border\" />\n                        <!-- Left Whisker: Min to Q1 -->\n                        <line\n                          x1=\"31\"\n                          y1=\"36\"\n                          x2=\"51\"\n                          y2=\"36\"\n                          stroke=\"currentColor\"\n                          class=\"text-foreground\"\n                          stroke-width=\"2\"\n                        />\n                        <!-- Min Cap -->\n                        <line\n                          x1=\"31\"\n                          y1=\"24\"\n                          x2=\"31\"\n                          y2=\"48\"\n                          stroke=\"currentColor\"\n                          class=\"text-foreground\"\n                          stroke-width=\"2\"\n                        />\n                        <!-- Right Whisker: Q3 to P99 -->\n                        <line\n                          x1=\"208\"\n                          y1=\"36\"\n                          x2=\"382\"\n                          y2=\"36\"\n                          stroke=\"currentColor\"\n                          class=\"text-foreground\"\n                          stroke-width=\"2\"\n                        />\n                        <!-- P99 Cap -->\n                        <line\n                          x1=\"382\"\n                          y1=\"24\"\n                          x2=\"382\"\n                          y2=\"48\"\n                          stroke=\"currentColor\"\n                          class=\"text-foreground\"\n                          stroke-width=\"2\"\n                        />\n                        <!-- Interquartile Box (Q1 to Q3) -->\n                        <rect\n                          x=\"51\"\n                          y=\"18\"\n                          width=\"157\"\n                          height=\"36\"\n                          rx=\"3\"\n                          class=\"fill-primary/20 stroke-primary\"\n                          stroke-width=\"2\"\n                        />\n                        <!-- Median (P50) Line -->\n                        <line x1=\"118\" y1=\"18\" x2=\"118\" y2=\"54\" class=\"stroke-primary\" stroke-width=\"3\" />\n                        <!-- Outlier Points (P99 to Max: 780d, 820d, 850d) -->\n                        <circle cx=\"411\" cy=\"36\" r=\"3.5\" class=\"fill-muted-foreground/60 stroke-foreground\" />\n                        <circle cx=\"431\" cy=\"36\" r=\"3.5\" class=\"fill-muted-foreground/60 stroke-foreground\" />\n                        <circle cx=\"446\" cy=\"36\" r=\"3.5\" class=\"fill-muted-foreground/60 stroke-foreground\" />\n                        <!-- Tick Labels on Axis -->\n                        <text x=\"31\" y=\"86\" text-anchor=\"middle\" class=\"fill-muted-foreground font-mono text-xs\">\n                          1d (Min)\n                        </text>\n                        <text x=\"51\" y=\"86\" text-anchor=\"middle\" class=\"fill-muted-foreground font-mono text-xs\">\n                          42d\n                        </text>\n                        <text x=\"118\" y=\"86\" text-anchor=\"middle\" class=\"fill-primary font-mono text-xs font-bold\">\n                          180d (Med)\n                        </text>\n                        <text x=\"208\" y=\"86\" text-anchor=\"middle\" class=\"fill-muted-foreground font-mono text-xs\">\n                          365d\n                        </text>\n                        <text x=\"382\" y=\"86\" text-anchor=\"middle\" class=\"fill-muted-foreground font-mono text-xs\">\n                          720d (P99)\n                        </text>\n                        <text x=\"446\" y=\"86\" text-anchor=\"middle\" class=\"fill-muted-foreground font-mono text-xs\">\n                          850d (Max)\n                        </text>\n                      </svg>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          }\n\n          <!-- 4. has_cancelled (Boolean) -->\n          @if (activeTypeFilter() === 'all' || activeTypeFilter() === 'boolean') {\n            <div ui-card class=\"border-border bg-card shadow-xs\">\n              <div ui-card-header class=\"pb-3\">\n                <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n                  <div class=\"space-y-1\">\n                    <div class=\"flex flex-wrap items-center gap-2\">\n                      <div class=\"bg-warning/10 text-warning flex size-6 items-center justify-center rounded-md\">\n                        <lucide-icon [img]=\"Binary\" class=\"size-3.5\" />\n                      </div>\n                      <h3 ui-card-title class=\"font-mono text-base font-semibold\">{{ cancelled.name }}</h3>\n                      <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">{{\n                        cancelled.type\n                      }}</span>\n                      <button\n                        type=\"button\"\n                        class=\"text-muted-foreground hover:text-foreground cursor-pointer\"\n                        [attr.aria-label]=\"'Copy ' + cancelled.name\"\n                        (click)=\"handleCopy(cancelled.name)\"\n                      >\n                        @if (copiedColumn() === cancelled.name) {\n                          <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                        } @else {\n                          <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                        }\n                      </button>\n                    </div>\n                    <p ui-card-description class=\"text-xs\">\n                      Binary churn indicator flag. 14.2% positive cancellation rate against 85.8% retained base.\n                    </p>\n                  </div>\n\n                  <div class=\"flex flex-wrap items-center gap-2\">\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Missing:\n                      <span class=\"text-success text-success ml-1 font-semibold tabular-nums\">{{\n                        cancelled.missingPct\n                      }}</span>\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Distinct:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\"\n                        >{{ cancelled.distinctCount }} values</span\n                      >\n                    </span>\n                    <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">\n                      Memory:\n                      <span class=\"text-foreground ml-1 font-semibold tabular-nums\">{{ cancelled.memory }}</span>\n                    </span>\n                  </div>\n                </div>\n              </div>\n\n              <div ui-card-content class=\"space-y-6 pt-1\">\n                <!-- Boolean Split Bar -->\n                <div class=\"space-y-2\">\n                  <div class=\"flex items-center justify-between text-xs\">\n                    <span class=\"text-foreground font-medium\">Boolean Ratio Distribution</span>\n                    <span class=\"text-muted-foreground font-mono tabular-nums\">Class Imbalance: 1 : 6.04</span>\n                  </div>\n\n                  <div class=\"border-border flex h-4 w-full overflow-hidden rounded-full border\">\n                    <div\n                      class=\"bg-success transition-colors\"\n                      [style.width.%]=\"cancelled.falsePct\"\n                      [title]=\"'False: ' + cancelled.falsePct + '% (' + fmt(cancelled.falseCount) + ' rows)'\"\n                    ></div>\n                    <div\n                      class=\"bg-destructive transition-colors\"\n                      [style.width.%]=\"cancelled.truePct\"\n                      [title]=\"'True: ' + cancelled.truePct + '% (' + fmt(cancelled.trueCount) + ' rows)'\"\n                    ></div>\n                  </div>\n                </div>\n\n                <!-- Value Breakdown Cards -->\n                <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n                  <!-- False / Active -->\n                  <div class=\"border-border bg-muted/20 flex flex-col justify-between rounded-lg border p-4\">\n                    <div class=\"space-y-1.5\">\n                      <div class=\"flex items-center justify-between\">\n                        <div class=\"flex items-center gap-2\">\n                          <span class=\"bg-success size-2 rounded-full\"></span>\n                          <span class=\"text-foreground font-mono text-xs font-semibold\">False (Active / Retained)</span>\n                        </div>\n                        <span\n                          ui-badge\n                          variant=\"outline\"\n                          class=\"border-success/30 text-success text-success font-mono text-xs font-medium tabular-nums\"\n                        >\n                          {{ cancelled.falsePct }}%\n                        </span>\n                      </div>\n                      <p class=\"text-muted-foreground font-mono text-xs tabular-nums\">\n                        {{ fmt(cancelled.falseCount) }} instances\n                      </p>\n                    </div>\n                    <div class=\"mt-3\">\n                      <ui-progress\n                        [value]=\"cancelled.falsePct\"\n                        class=\"[&_[data-slot=progress-indicator]]:bg-success h-1.5\"\n                      />\n                    </div>\n                  </div>\n\n                  <!-- True / Cancelled -->\n                  <div class=\"border-border bg-muted/20 flex flex-col justify-between rounded-lg border p-4\">\n                    <div class=\"space-y-1.5\">\n                      <div class=\"flex items-center justify-between\">\n                        <div class=\"flex items-center gap-2\">\n                          <span class=\"bg-destructive size-2 rounded-full\"></span>\n                          <span class=\"text-foreground font-mono text-xs font-semibold\"\n                            >True (Cancelled / Churned)</span\n                          >\n                        </div>\n                        <span\n                          ui-badge\n                          variant=\"outline\"\n                          class=\"border-destructive/30 text-destructive text-destructive font-mono text-xs font-medium tabular-nums\"\n                        >\n                          {{ cancelled.truePct }}%\n                        </span>\n                      </div>\n                      <p class=\"text-muted-foreground font-mono text-xs tabular-nums\">\n                        {{ fmt(cancelled.trueCount) }} instances\n                      </p>\n                    </div>\n                    <div class=\"mt-3\">\n                      <ui-progress\n                        [value]=\"cancelled.truePct\"\n                        class=\"[&_[data-slot=progress-indicator]]:bg-destructive h-1.5\"\n                      />\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          }\n        </div>\n      }\n    </div>\n  `,\n})\nexport class UiColumnProfilingSummaryComponent {\n  @Input() tableName = 'customer_churn_features_v2'\n  @Input() totalRows = '148,290'\n  @Input() totalColumns = 18\n  @Input() memoryFootprint = '24.2 MB'\n  @Input() datasetVersion = 'v2.4.1'\n  @Input('class') className?: string\n\n  readonly activeTypeFilter = signal<ColumnProfilingTypeFilter>('all')\n  readonly searchQuery = signal('')\n  readonly viewMode = signal<ColumnProfilingViewMode>('cards')\n  readonly isExporting = signal(false)\n  readonly showExportSuccess = signal(false)\n  readonly copiedColumn = signal<string | null>(null)\n  readonly hoveredHistBin = signal<number | null>(null)\n\n  readonly filteredColumns = computed(() => {\n    const filter = this.activeTypeFilter()\n    const q = this.searchQuery().toLowerCase()\n    return allSchemaColumns.filter((col) => {\n      const matchesCategory = filter === 'all' || col.category === filter\n      const matchesSearch = col.name.toLowerCase().includes(q) || col.type.toLowerCase().includes(q)\n      return matchesCategory && matchesSearch\n    })\n  })\n\n  readonly hoveredBin = computed<ColumnProfilingHistogramBin | null>(() => {\n    const idx = this.hoveredHistBin()\n    return idx === null ? null : (histogramBins[idx] ?? null)\n  })\n\n  protected readonly spend = monthlySpendStats\n  protected readonly tier = subscriptionTierStats\n  protected readonly age = accountAgeStats\n  protected readonly cancelled = hasCancelledStats\n  protected readonly histogramBins = histogramBins\n  protected readonly subscriptionTiers = subscriptionTiers\n  protected readonly spendMetrics = spendMetrics\n  protected readonly typeFilters = typeFilters\n\n  protected readonly AlertCircle = AlertCircle\n  protected readonly BarChart2 = BarChart2\n  protected readonly Binary = Binary\n  protected readonly Check = Check\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Copy = Copy\n  protected readonly Database = Database\n  protected readonly Download = Download\n  protected readonly Hash = Hash\n  protected readonly LayoutGrid = LayoutGrid\n  protected readonly Search = Search\n  protected readonly TableIcon = TableIcon\n  protected readonly Tag = Tag\n\n  get rootClass(): string {\n    return cn('mx-auto w-full max-w-6xl space-y-6', this.className)\n  }\n\n  handleExportReport(): void {\n    if (this.isExporting()) return\n    this.isExporting.set(true)\n    setTimeout(() => {\n      this.isExporting.set(false)\n      this.showExportSuccess.set(true)\n      setTimeout(() => this.showExportSuccess.set(false), 3500)\n    }, 600)\n  }\n\n  handleCopy(name: string): void {\n    void navigator.clipboard?.writeText(name)\n    this.copiedColumn.set(name)\n    setTimeout(() => {\n      this.copiedColumn.update((prev) => (prev === name ? null : prev))\n    }, 2000)\n  }\n\n  protected onSearch(event: Event): void {\n    this.searchQuery.set((event.target as HTMLInputElement).value)\n  }\n\n  protected fmt(n: number): string {\n    return n.toLocaleString()\n  }\n\n  protected filterClass(value: ColumnProfilingTypeFilter): string {\n    return cn(\n      'cursor-pointer rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n      this.activeTypeFilter() === value\n        ? 'bg-primary text-primary-foreground shadow-xs'\n        : 'bg-muted/60 text-muted-foreground hover:bg-muted hover:text-foreground',\n    )\n  }\n\n  protected viewClass(mode: ColumnProfilingViewMode): string {\n    return cn(\n      'cursor-pointer rounded px-2 py-1 transition-colors',\n      this.viewMode() === mode\n        ? 'bg-background text-foreground shadow-xs'\n        : 'text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  protected barClass(idx: number): string {\n    return cn(\n      'cursor-pointer transition-colors duration-150',\n      this.hoveredHistBin() === idx\n        ? 'fill-primary text-primary'\n        : 'fill-primary/75 hover:fill-primary text-primary/75',\n    )\n  }\n\n  protected tierBadgeClass(t: ColumnProfilingTier): string {\n    return cn('font-mono text-xs font-medium tabular-nums', t.badgeClass)\n  }\n\n  protected tierBarClass(t: ColumnProfilingTier): string {\n    return cn('h-full rounded-full', t.colorClass)\n  }\n\n  protected statusVariant(col: ColumnProfilingSchemaColumn): 'default' | 'success' {\n    return col.status.includes('Unique') ? 'default' : 'success'\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/column-profiling-summary/column-profiling-summary.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/column-profiling-summary/index.ts",
      "content": "export {\n  UiColumnProfilingSummaryComponent,\n  type ColumnProfilingTypeFilter,\n  type ColumnProfilingViewMode,\n  type ColumnProfilingHistogramBin,\n  type ColumnProfilingTier,\n  type ColumnProfilingSchemaColumn,\n} from './column-profiling-summary.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/column-profiling-summary/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/progress.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Pandas Profiling and ydata style exploratory data analysis (EDA) column profiling summary with dataset metrics, distribution histograms, quantile box plots, and categorical frequency breakdowns.",
  "categories": [
    "devops",
    "dashboard",
    "analytics",
    "data"
  ]
}