{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "data-catalog-lineage",
  "title": "Data Catalog Lineage",
  "type": "registry:page",
  "files": [
    {
      "path": "packages/registry-angular/blocks/data-catalog-lineage/data-catalog-lineage.component.ts",
      "content": "// Alation and Monte Carlo style enterprise data catalog lineage map and table documentation\n// explorer with interactive upstream source DAGs, dbt transform models, downstream BI consumer\n// traces, schema column definitions with types and constraints, automated data quality\n// assertions, and SQL console query runner. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport {\n  Activity,\n  ArrowRightLeft,\n  BarChart3,\n  Check,\n  CheckCircle2,\n  Clock,\n  Coins,\n  Copy,\n  CreditCard,\n  Database,\n  FileCode2,\n  GitFork,\n  Key,\n  Landmark,\n  Layers,\n  LineChart,\n  LucideAngularModule,\n  RefreshCw,\n  Search,\n  ShieldCheck,\n  Table2,\n  Terminal,\n  Users,\n  Workflow,\n  X,\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 { UiInputComponent } from '@/ui/input/input.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\nimport {\n  UiTabsComponent,\n  UiTabsContentComponent,\n  UiTabsListComponent,\n  UiTabsTriggerComponent,\n} from '@/ui/tabs/tabs.component'\n\nexport interface ColumnDef {\n  name: string\n  type: string\n  nullable: boolean\n  isPrimaryKey?: boolean\n  description: string\n  sampleValue: string\n  distinctPct: string\n  constraints?: string\n}\n\nexport interface QualityAssertion {\n  id: string\n  name: string\n  type: string\n  targetColumn: string\n  description: string\n  executionTime: string\n  lastRun: string\n  status: 'passed' | 'warning' | 'failed'\n  ruleDefinition: string\n}\n\nexport interface LineageSourceNode {\n  id: string\n  name: string\n  schema: string\n  connector: string\n  type: string\n  rowCount: string\n  latency: string\n  status: 'fresh' | 'syncing' | 'delayed'\n  iconName: 'CreditCard' | 'Users' | 'Landmark'\n  description: string\n}\n\nexport interface LineageTransformNode {\n  id: string\n  name: string\n  modelType: string\n  engine: string\n  runtime: string\n  lastRun: string\n  testsPassed: string\n  status: 'passed' | 'running' | 'failed'\n  iconName: 'Layers' | 'Coins'\n  description: string\n}\n\nexport interface LineageConsumerNode {\n  id: string\n  name: string\n  category: string\n  tool: string\n  frequency: string\n  audience: string\n  status: 'active' | 'syncing'\n  iconName: 'BarChart3' | 'ArrowRightLeft' | 'LineChart'\n  description: string\n}\n\nconst sourceNodes: LineageSourceNode[] = [\n  {\n    id: 'src-stripe',\n    name: 'raw_stripe.charges',\n    schema: 'raw_stripe',\n    connector: 'Fivetran CDC',\n    type: 'PostgreSQL Raw',\n    rowCount: '1.42M rows',\n    latency: '~5m sync',\n    status: 'fresh',\n    iconName: 'CreditCard',\n    description: 'Direct transactional charge events, currency conversions, refunds, and card processing fees.',\n  },\n  {\n    id: 'src-salesforce',\n    name: 'raw_salesforce.accounts',\n    schema: 'raw_salesforce',\n    connector: 'Airbyte Cloud',\n    type: 'CRM Extract',\n    rowCount: '84.5k rows',\n    latency: '~15m sync',\n    status: 'fresh',\n    iconName: 'Users',\n    description: 'Enterprise accounts, contract values, billing contacts, and subscription tier assignments.',\n  },\n  {\n    id: 'src-bank',\n    name: 'raw_bank.transfers',\n    schema: 'raw_bank',\n    connector: 'Kafka Stream',\n    type: 'Banking API',\n    rowCount: '620k rows',\n    latency: '<1m latency',\n    status: 'fresh',\n    iconName: 'Landmark',\n    description: 'Direct bank wire settlement entries, ACH clearances, and treasury reconciliation logs.',\n  },\n]\n\nconst transformNodes: LineageTransformNode[] = [\n  {\n    id: 'tr-daily-revenue',\n    name: 'dbt.int_daily_revenue',\n    modelType: 'dbt Incremental',\n    engine: 'dbt Core 1.8',\n    runtime: '1m 24s',\n    lastRun: '22m ago',\n    testsPassed: '14/14 Passed',\n    status: 'passed',\n    iconName: 'Layers',\n    description: 'Aggregates daily charge events into standardized GAAP revenue recognized per customer.',\n  },\n  {\n    id: 'tr-fx-rates',\n    name: 'dbt.int_fx_normalized_rates',\n    modelType: 'dbt View',\n    engine: 'dbt Core 1.8',\n    runtime: '18s',\n    lastRun: '25m ago',\n    testsPassed: '6/6 Passed',\n    status: 'passed',\n    iconName: 'Coins',\n    description: 'Normalized exchange rate matrix cross-referencing European Central Bank & Federal Reserve feeds.',\n  },\n]\n\nconst consumerNodes: LineageConsumerNode[] = [\n  {\n    id: 'cons-metabase',\n    name: 'Executive Board Metabase Dashboard',\n    category: 'BI Dashboard',\n    tool: 'Metabase Enterprise',\n    frequency: 'Hourly auto-refresh',\n    audience: '42 active executives',\n    status: 'active',\n    iconName: 'BarChart3',\n    description: 'C-Suite executive dashboard tracking recurring revenue, net burn rate, and board deck slide metrics.',\n  },\n  {\n    id: 'cons-netsuite',\n    name: 'Finance NetSuite Sync',\n    category: 'Reverse ETL',\n    tool: 'Census Reverse ETL',\n    frequency: 'Hourly batch',\n    audience: 'Accounting ERP Ledger',\n    status: 'active',\n    iconName: 'ArrowRightLeft',\n    description: 'Automated journal entry creation and revenue recognition schedules into NetSuite ERP.',\n  },\n  {\n    id: 'cons-looker',\n    name: 'Looker ARR Report',\n    category: 'Looker Model',\n    tool: 'Looker Explore',\n    frequency: 'Live semantic model',\n    audience: '18 connected reports',\n    status: 'active',\n    iconName: 'LineChart',\n    description: 'Self-service exploration model for RevOps, cohort retention, contraction, and expansion ARR.',\n  },\n]\n\nconst columns: ColumnDef[] = [\n  {\n    name: 'month_id',\n    type: 'varchar(7)',\n    nullable: false,\n    isPrimaryKey: true,\n    description: 'YYYY-MM billing calendar interval identifier (e.g. 2026-03) representing fiscal calendar close.',\n    sampleValue: \"'2026-03'\",\n    distinctPct: '100% Unique',\n    constraints: 'PRIMARY KEY, ISO-8601',\n  },\n  {\n    name: 'gross_revenue',\n    type: 'decimal(18,2)',\n    nullable: false,\n    description:\n      'Total unadjusted transaction volume processed across all payment gateways before churn and discounts.',\n    sampleValue: '$1,842,500.00',\n    distinctPct: '99.8% Distinct',\n    constraints: 'CHECK (gross_revenue >= 0)',\n  },\n  {\n    name: 'net_arr',\n    type: 'decimal(18,2)',\n    nullable: false,\n    description:\n      'Annualized recurring revenue normalized across all active multi-year and monthly enterprise contracts.',\n    sampleValue: '$14,680,240.00',\n    distinctPct: '98.9% Distinct',\n    constraints: 'CHECK (net_arr >= 0)',\n  },\n  {\n    name: 'churned_mrr',\n    type: 'decimal(18,2)',\n    nullable: true,\n    description:\n      'Monthly recurring revenue lost in the period due to voluntary cancellations or involuntary card downgrades.',\n    sampleValue: '-$12,450.00',\n    distinctPct: '42.1% Distinct',\n    constraints: 'CHECK (churned_mrr <= 0)',\n  },\n  {\n    name: 'active_subscriptions',\n    type: 'integer',\n    nullable: false,\n    description: 'Total count of distinct active paying enterprise accounts and self-serve team workspaces.',\n    sampleValue: '3,842',\n    distinctPct: '100% Integer',\n    constraints: 'CHECK (active_subscriptions > 0)',\n  },\n]\n\nconst qualityAssertions: QualityAssertion[] = [\n  {\n    id: 'test-1',\n    name: 'assert_unique_month_id',\n    type: 'Primary Key Uniqueness',\n    targetColumn: 'month_id',\n    description: 'Verifies that every monthly fiscal partition key is strictly unique with 0 duplicate rows.',\n    executionTime: '420ms',\n    lastRun: '18m ago',\n    status: 'passed',\n    ruleDefinition: 'dbt_expectations.expect_compound_columns_to_be_unique(month_id)',\n  },\n  {\n    id: 'test-2',\n    name: 'assert_positive_gross_revenue',\n    type: 'Value Range Check',\n    targetColumn: 'gross_revenue',\n    description: 'Ensures that processed monthly gross revenue cannot be negative under GAAP rules.',\n    executionTime: '380ms',\n    lastRun: '18m ago',\n    status: 'passed',\n    ruleDefinition: 'dbt_expectations.expect_column_values_to_be_between(min_value=0)',\n  },\n  {\n    id: 'test-3',\n    name: 'assert_foreign_key_accounts_integrity',\n    type: 'Referential Integrity',\n    targetColumn: 'account_id (upstream join)',\n    description: 'Validates that 100% of underlying subscription revenue lines match valid accounts in Salesforce CRM.',\n    executionTime: '890ms',\n    lastRun: '18m ago',\n    status: 'passed',\n    ruleDefinition: \"dbt_utils.relationships(to=ref('raw_salesforce_accounts'), field='id')\",\n  },\n  {\n    id: 'test-4',\n    name: 'assert_not_null_critical_metrics',\n    type: 'Completeness / Non-Null',\n    targetColumn: 'month_id, gross_revenue, net_arr',\n    description: 'Guarantees zero null occurrences across high-priority C-Suite revenue and ARR metrics.',\n    executionTime: '310ms',\n    lastRun: '18m ago',\n    status: 'passed',\n    ruleDefinition: 'dbt.test_not_null_composite(columns=[month_id, gross_revenue, net_arr])',\n  },\n  {\n    id: 'test-5',\n    name: 'assert_valid_iso_month_format',\n    type: 'Regex Format Validation',\n    targetColumn: 'month_id',\n    description: 'Asserts all month partition tokens adhere to standard ISO format regex `^\\\\d{4}-(0[1-9]|1[0-2])$`.',\n    executionTime: '240ms',\n    lastRun: '18m ago',\n    status: 'passed',\n    ruleDefinition: 'dbt_expectations.expect_column_values_to_match_regex(pattern=\"^\\\\\\\\d{4}-(0[1-9]|1[0-2])$\")',\n  },\n  {\n    id: 'test-6',\n    name: 'assert_monotonic_active_subscriptions',\n    type: 'Anomaly Detection (3-Sigma)',\n    targetColumn: 'active_subscriptions',\n    description:\n      'Monte Carlo ML rule checking month-over-month subscription volatility is within 3-sigma confidence bounds.',\n    executionTime: '610ms',\n    lastRun: '18m ago',\n    status: 'passed',\n    ruleDefinition: 'monte_carlo.metric_anomaly_detector(threshold_sigma=3.0, sensitivity=0.95)',\n  },\n]\n\nconst dbtModelSnippet = `{{ config(\n    materialized='incremental',\n    unique_key='month_id',\n    schema='production_dw',\n    tags=['finance', 'tier_1_gold', 'executive_kpi']\n) }}\n\nWITH daily_rev AS (\n    SELECT * FROM {{ ref('int_daily_revenue') }}\n    {% if is_incremental() %}\n    WHERE event_date >= dateadd(day, -3, current_date)\n    {% endif %}\n),\n\nfx_rates AS (\n    SELECT * FROM {{ ref('int_fx_normalized_rates') }}\n),\n\nmonthly_aggregates AS (\n    SELECT\n        TO_CHAR(d.event_date, 'YYYY-MM') AS month_id,\n        SUM(d.gross_amount_usd) AS gross_revenue,\n        SUM(d.annualized_contract_val) AS net_arr,\n        SUM(CASE WHEN d.is_churned THEN d.mrr_impact ELSE 0 END) AS churned_mrr,\n        COUNT(DISTINCT d.customer_account_id) AS active_subscriptions\n    FROM daily_rev d\n    LEFT JOIN fx_rates fx ON d.currency = fx.currency AND d.event_date = fx.rate_date\n    GROUP BY 1\n)\n\nSELECT\n    month_id,\n    ROUND(gross_revenue, 2) AS gross_revenue,\n    ROUND(net_arr, 2) AS net_arr,\n    ROUND(churned_mrr, 2) AS churned_mrr,\n    active_subscriptions\nFROM monthly_aggregates\nORDER BY month_id DESC;`\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-data-catalog-lineage, [ui-data-catalog-lineage]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiInputComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n    UiTabsComponent,\n    UiTabsContentComponent,\n    UiTabsListComponent,\n    UiTabsTriggerComponent,\n  ],\n  template: `\n    <div data-slot=\"data-catalog-lineage\" [class]=\"rootClass\">\n      <!-- Header Section -->\n      <header class=\"border-border bg-card/60 rounded-xl border p-4 sm:p-5\">\n        <div class=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n          <div class=\"space-y-2.5\">\n            <div class=\"flex flex-wrap items-center gap-2 text-xs\">\n              <div class=\"bg-primary/10 text-primary flex size-6 items-center justify-center rounded-md\">\n                <lucide-icon [img]=\"Database\" class=\"size-3.5\" />\n              </div>\n              <span class=\"text-muted-foreground font-mono\">snowflake-dw-production.us-east-1</span>\n              <span class=\"text-muted-foreground\">/</span>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs font-normal\"> schema: production_dw </span>\n              <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\"> Tier 1 Core Mart </span>\n            </div>\n\n            <div class=\"flex flex-wrap items-center gap-3\">\n              <h1 class=\"text-foreground font-mono text-xl font-bold tracking-tight break-all sm:text-2xl\">\n                analytics.fct_monthly_financials\n              </h1>\n              <button\n                ui-button\n                variant=\"ghost\"\n                size=\"sm\"\n                class=\"h-7 gap-1 px-2 text-xs\"\n                (click)=\"copyRef('analytics.fct_monthly_financials')\"\n              >\n                @if (copiedRef()) {\n                  <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                } @else {\n                  <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                }\n                <span class=\"font-mono\">{{ copiedRef() ? 'Copied Ref!' : 'Copy Name' }}</span>\n              </button>\n            </div>\n\n            <div class=\"flex flex-wrap items-center gap-2 pt-0.5 text-xs\">\n              <div class=\"border-border bg-background inline-flex items-center gap-2 rounded-md border px-2.5 py-1\">\n                <span class=\"relative flex size-2\">\n                  <span class=\"bg-success absolute inline-flex size-full rounded-full opacity-75\"></span>\n                  <span class=\"bg-success relative inline-flex size-2 rounded-full\"></span>\n                </span>\n                <span class=\"text-muted-foreground\">Freshness:</span>\n                <span class=\"text-foreground font-medium\">Updated 18m ago</span>\n                <span class=\"text-success font-medium\">SLA: Healthy</span>\n              </div>\n\n              <div class=\"border-border bg-background inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1\">\n                <lucide-icon [img]=\"Users\" class=\"text-muted-foreground size-3.5\" />\n                <span class=\"text-muted-foreground\">Owner:</span>\n                <span class=\"text-foreground font-medium\">Data Platform Squad</span>\n                <span ui-badge variant=\"secondary\" class=\"h-4.5 px-1 font-mono text-xs\">#data-eng-core</span>\n              </div>\n\n              <div class=\"border-border bg-background inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1\">\n                <lucide-icon [img]=\"Table2\" class=\"text-muted-foreground size-3.5\" />\n                <span class=\"text-muted-foreground\">Rows:</span>\n                <span class=\"text-foreground font-mono font-medium\">240,000</span>\n                <span class=\"text-foreground font-mono font-medium\">5 columns</span>\n              </div>\n            </div>\n          </div>\n\n          <div class=\"flex flex-wrap items-center gap-2.5 pt-1 lg:pt-0\">\n            <button ui-button variant=\"outline\" size=\"sm\" class=\"h-9 gap-1.5 text-xs\" (click)=\"resetLineageFocus()\">\n              <lucide-icon [img]=\"GitFork\" class=\"text-info size-3.5\" />\n              <span>View Upstream Lineage</span>\n            </button>\n\n            <button\n              ui-button\n              aria-label=\"Close query modal\"\n              variant=\"default\"\n              size=\"sm\"\n              class=\"h-9 gap-1.5 text-xs font-medium\"\n              (click)=\"isQueryModalOpen.set(!isQueryModalOpen())\"\n            >\n              <lucide-icon [img]=\"Terminal\" class=\"size-3.5\" />\n              <span>Query Table</span>\n            </button>\n          </div>\n        </div>\n      </header>\n\n      <!-- Interactive SQL Query Drawer / Bar -->\n      @if (isQueryModalOpen()) {\n        <div class=\"border-border bg-muted/30 overflow-hidden rounded-xl border transition-colors\">\n          <div class=\"border-border bg-card flex items-center justify-between border-b px-4 py-2.5\">\n            <div class=\"flex items-center gap-2\">\n              <lucide-icon [img]=\"Terminal\" class=\"text-primary size-4\" />\n              <span class=\"text-foreground font-mono text-xs font-semibold\"\n                >Snowflake SQL Console · Interactive Query Runner</span\n              >\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">Snowflake XS Warehouse</span>\n            </div>\n            <div class=\"flex items-center gap-2\">\n              <button ui-button variant=\"ghost\" size=\"sm\" class=\"h-7 text-xs\" (click)=\"copyCompiledSQL()\">\n                @if (copiedQuery()) {\n                  <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                } @else {\n                  <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                }\n                <span>{{ copiedQuery() ? 'Copied' : 'Copy SQL' }}</span>\n              </button>\n              <button\n                ui-button\n                variant=\"ghost\"\n                size=\"sm\"\n                class=\"size-7 p-0\"\n                aria-label=\"Close query modal\"\n                (click)=\"isQueryModalOpen.set(false)\"\n              >\n                <lucide-icon [img]=\"X\" class=\"size-4\" />\n              </button>\n            </div>\n          </div>\n          <div class=\"space-y-3 p-4\">\n            <div\n              class=\"overflow-x-auto rounded-lg bg-neutral-950 p-3 font-mono text-xs text-neutral-100 dark:bg-neutral-950\"\n            >\n              <pre class=\"leading-relaxed whitespace-pre\"><code>SELECT\n  month_id,\n  gross_revenue,\n  net_arr,\n  churned_mrr,\n  active_subscriptions\nFROM production_dw.analytics.fct_monthly_financials\nORDER BY month_id DESC\nLIMIT 5;</code></pre>\n            </div>\n            <div class=\"border-border bg-card overflow-hidden rounded-lg border\">\n              <div class=\"overflow-x-auto\">\n                <table ui-table>\n                  <thead ui-table-header>\n                    <tr ui-table-row class=\"bg-muted/50 hover:bg-muted/50\">\n                      <th ui-table-head class=\"font-mono text-xs\">month_id (varchar)</th>\n                      <th ui-table-head class=\"text-right font-mono text-xs\">gross_revenue (decimal)</th>\n                      <th ui-table-head class=\"text-right font-mono text-xs\">net_arr (decimal)</th>\n                      <th ui-table-head class=\"text-right font-mono text-xs\">churned_mrr (decimal)</th>\n                      <th ui-table-head class=\"text-right font-mono text-xs\">active_subscriptions (int)</th>\n                    </tr>\n                  </thead>\n                  <tbody ui-table-body>\n                    <tr ui-table-row class=\"font-mono text-xs\">\n                      <td ui-table-cell class=\"text-warning font-semibold\">2026-03</td>\n                      <td ui-table-cell class=\"text-right\">$1,842,500.00</td>\n                      <td ui-table-cell class=\"text-success text-right font-medium\">$14,680,240.00</td>\n                      <td ui-table-cell class=\"text-destructive text-right\">-$12,450.00</td>\n                      <td ui-table-cell class=\"text-right\">3,842</td>\n                    </tr>\n                    <tr ui-table-row class=\"font-mono text-xs\">\n                      <td ui-table-cell class=\"text-warning font-semibold\">2026-02</td>\n                      <td ui-table-cell class=\"text-right\">$1,798,200.00</td>\n                      <td ui-table-cell class=\"text-success text-right font-medium\">$14,350,100.00</td>\n                      <td ui-table-cell class=\"text-destructive text-right\">-$14,100.00</td>\n                      <td ui-table-cell class=\"text-right\">3,780</td>\n                    </tr>\n                    <tr ui-table-row class=\"font-mono text-xs\">\n                      <td ui-table-cell class=\"text-warning font-semibold\">2026-01</td>\n                      <td ui-table-cell class=\"text-right\">$1,720,000.00</td>\n                      <td ui-table-cell class=\"text-success text-right font-medium\">$13,920,400.00</td>\n                      <td ui-table-cell class=\"text-destructive text-right\">-$9,800.00</td>\n                      <td ui-table-cell class=\"text-right\">3,712</td>\n                    </tr>\n                  </tbody>\n                </table>\n              </div>\n            </div>\n          </div>\n        </div>\n      }\n\n      <!-- 3-Column Lineage Pipeline Map Section -->\n      <section class=\"border-border bg-card/40 space-y-4 rounded-xl border p-4 sm:p-5\">\n        <div class=\"border-border/80 flex flex-col gap-2 border-b pb-3 sm:flex-row sm:items-center sm:justify-between\">\n          <div class=\"space-y-0.5\">\n            <div class=\"flex items-center gap-2\">\n              <lucide-icon [img]=\"Workflow\" class=\"text-primary size-4\" />\n              <h2 class=\"text-foreground text-sm font-semibold tracking-tight\">End-to-End Data Lineage Graph</h2>\n              <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">DAG Depth: 3 Tiers</span>\n            </div>\n            <p class=\"text-muted-foreground text-xs\">\n              Interactive trace of upstream ingest sources, dbt intermediate transformations, and active downstream BI\n              consumers.\n            </p>\n          </div>\n\n          <div class=\"flex items-center gap-2\">\n            <div\n              class=\"border-border bg-background inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-xs\"\n            >\n              <span class=\"bg-success size-2 rounded-full\"></span>\n              <span class=\"text-muted-foreground\">Pipeline State:</span>\n              <span class=\"text-foreground font-medium\">All 3 Tiers Fresh</span>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"grid grid-cols-1 gap-4 lg:grid-cols-3\">\n          <!-- COLUMN 1: Source Tables -->\n          <div class=\"space-y-3\">\n            <div class=\"flex items-center justify-between px-1\">\n              <div class=\"flex items-center gap-1.5\">\n                <lucide-icon [img]=\"Database\" class=\"text-muted-foreground size-3.5\" />\n                <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                  1. Source Tables (3)\n                </span>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">Upstream Raw</span>\n            </div>\n\n            <div class=\"space-y-2.5\">\n              @for (source of sources; track source.id) {\n                <button\n                  type=\"button\"\n                  [class]=\"nodeCardClass(selectedNodeId() === source.id)\"\n                  [attr.aria-pressed]=\"selectedNodeId() === source.id\"\n                  (click)=\"selectedNodeId.set(source.id)\"\n                >\n                  <div class=\"flex items-start justify-between gap-2\">\n                    <div class=\"flex items-center gap-2\">\n                      <div\n                        class=\"bg-muted text-foreground border-border/60 flex size-7 shrink-0 items-center justify-center rounded-md border\"\n                      >\n                        @if (source.iconName === 'CreditCard') {\n                          <lucide-icon [img]=\"CreditCard\" class=\"text-chart-1 size-3.5\" />\n                        } @else if (source.iconName === 'Users') {\n                          <lucide-icon [img]=\"Users\" class=\"text-info size-3.5\" />\n                        } @else {\n                          <lucide-icon [img]=\"Landmark\" class=\"text-warning size-3.5\" />\n                        }\n                      </div>\n                      <div class=\"min-w-0\">\n                        <span class=\"text-foreground block truncate font-mono font-semibold\">{{ source.name }}</span>\n                        <span class=\"text-muted-foreground text-xs\">{{ source.connector }}</span>\n                      </div>\n                    </div>\n                    <span ui-badge class=\"border-success/20 bg-success/10 text-success shrink-0 font-mono text-xs\">\n                      {{ source.status }}\n                    </span>\n                  </div>\n\n                  <div\n                    class=\"border-border/50 text-muted-foreground mt-2.5 flex items-center justify-between border-t pt-2\"\n                  >\n                    <span class=\"font-mono\">{{ source.rowCount }}</span>\n                    <span class=\"flex items-center gap-1 font-mono\">\n                      <lucide-icon [img]=\"Clock\" class=\"size-3\" />\n                      {{ source.latency }}\n                    </span>\n                  </div>\n                </button>\n              }\n            </div>\n          </div>\n\n          <!-- COLUMN 2: Transform Models -->\n          <div class=\"space-y-3\">\n            <div class=\"flex items-center justify-between px-1\">\n              <div class=\"flex items-center gap-1.5\">\n                <lucide-icon [img]=\"Layers\" class=\"text-muted-foreground size-3.5\" />\n                <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                  2. Transform Models (2)\n                </span>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">dbt Models</span>\n            </div>\n\n            <div class=\"space-y-2.5\">\n              @for (transform of transforms; track transform.id) {\n                <button\n                  type=\"button\"\n                  [class]=\"nodeCardClass(selectedNodeId() === transform.id)\"\n                  [attr.aria-pressed]=\"selectedNodeId() === transform.id\"\n                  (click)=\"selectedNodeId.set(transform.id)\"\n                >\n                  <div class=\"flex items-start justify-between gap-2\">\n                    <div class=\"flex items-center gap-2\">\n                      <div\n                        class=\"bg-primary/10 text-primary border-primary/20 flex size-7 shrink-0 items-center justify-center rounded-md border\"\n                      >\n                        @if (transform.iconName === 'Layers') {\n                          <lucide-icon [img]=\"Layers\" class=\"size-3.5\" />\n                        } @else {\n                          <lucide-icon [img]=\"Coins\" class=\"size-3.5\" />\n                        }\n                      </div>\n                      <div class=\"min-w-0\">\n                        <span class=\"text-foreground block truncate font-mono font-semibold\">{{ transform.name }}</span>\n                        <span class=\"text-muted-foreground text-xs\">{{ transform.modelType }}</span>\n                      </div>\n                    </div>\n                    <span ui-badge variant=\"secondary\" class=\"shrink-0 font-mono text-xs\">\n                      {{ transform.runtime }}\n                    </span>\n                  </div>\n\n                  <div\n                    class=\"border-border/50 text-muted-foreground mt-2.5 flex items-center justify-between border-t pt-2\"\n                  >\n                    <span class=\"text-success flex items-center gap-1 font-medium\">\n                      <lucide-icon [img]=\"CheckCircle2\" class=\"size-3\" />\n                      {{ transform.testsPassed }}\n                    </span>\n                    <span class=\"font-mono\">{{ transform.lastRun }}</span>\n                  </div>\n                </button>\n              }\n            </div>\n          </div>\n\n          <!-- COLUMN 3: Downstream Consumers & Active Target -->\n          <div class=\"space-y-3\">\n            <div class=\"flex items-center justify-between px-1\">\n              <div class=\"flex items-center gap-1.5\">\n                <lucide-icon [img]=\"BarChart3\" class=\"text-muted-foreground size-3.5\" />\n                <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                  3. Downstream & Target\n                </span>\n              </div>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">Marts & Consumers</span>\n            </div>\n\n            <div class=\"space-y-2.5\">\n              <button\n                type=\"button\"\n                [class]=\"targetCardClass\"\n                [attr.aria-pressed]=\"selectedNodeId() === 'target-table'\"\n                (click)=\"selectedNodeId.set('target-table')\"\n              >\n                <div class=\"flex items-start justify-between gap-2\">\n                  <div class=\"flex items-center gap-2\">\n                    <div\n                      class=\"bg-primary text-primary-foreground flex size-7 shrink-0 items-center justify-center rounded-md\"\n                    >\n                      <lucide-icon [img]=\"Table2\" class=\"size-3.5\" />\n                    </div>\n                    <div class=\"min-w-0\">\n                      <div class=\"flex items-center gap-1.5\">\n                        <span class=\"text-foreground truncate font-mono font-bold\">fct_monthly_financials</span>\n                      </div>\n                      <span class=\"text-primary text-xs font-medium\">Active Catalog Target</span>\n                    </div>\n                  </div>\n                  <span ui-badge class=\"bg-primary text-primary-foreground shrink-0 text-xs font-medium\">\n                    Current\n                  </span>\n                </div>\n              </button>\n\n              @for (consumer of consumers; track consumer.id) {\n                <button\n                  type=\"button\"\n                  [class]=\"nodeCardClass(selectedNodeId() === consumer.id)\"\n                  [attr.aria-pressed]=\"selectedNodeId() === consumer.id\"\n                  (click)=\"selectedNodeId.set(consumer.id)\"\n                >\n                  <div class=\"flex items-start justify-between gap-2\">\n                    <div class=\"flex items-center gap-2\">\n                      <div\n                        class=\"bg-muted text-foreground border-border/60 flex size-7 shrink-0 items-center justify-center rounded-md border\"\n                      >\n                        @if (consumer.iconName === 'BarChart3') {\n                          <lucide-icon [img]=\"BarChart3\" class=\"text-info size-3.5\" />\n                        } @else if (consumer.iconName === 'ArrowRightLeft') {\n                          <lucide-icon [img]=\"ArrowRightLeft\" class=\"text-chart-2 size-3.5\" />\n                        } @else {\n                          <lucide-icon [img]=\"LineChart\" class=\"text-success size-3.5\" />\n                        }\n                      </div>\n                      <div class=\"min-w-0\">\n                        <span class=\"text-foreground block truncate font-medium\">{{ consumer.name }}</span>\n                        <span class=\"text-muted-foreground text-xs\">{{ consumer.category }} · {{ consumer.tool }}</span>\n                      </div>\n                    </div>\n                    <span ui-badge variant=\"secondary\" class=\"shrink-0 text-xs\">\n                      {{ consumer.status }}\n                    </span>\n                  </div>\n\n                  <div\n                    class=\"border-border/50 text-muted-foreground mt-2.5 flex items-center justify-between border-t pt-2\"\n                  >\n                    <span class=\"truncate\">{{ consumer.audience }}</span>\n                    <span class=\"shrink-0 font-mono text-xs\">{{ consumer.frequency }}</span>\n                  </div>\n                </button>\n              }\n            </div>\n          </div>\n        </div>\n\n        @if (selectedNodeDetails(); as details) {\n          <div class=\"border-border/80 bg-muted/40 rounded-lg border p-3.5 text-xs\">\n            <div\n              class=\"border-border/60 flex flex-col gap-2 border-b pb-2 sm:flex-row sm:items-center sm:justify-between\"\n            >\n              <div class=\"flex items-center gap-2\">\n                <span class=\"text-foreground font-mono font-bold\">{{ details.title }}</span>\n                <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">{{ details.badge }}</span>\n              </div>\n              <span class=\"text-muted-foreground text-xs\">Node Inspector</span>\n            </div>\n            <p class=\"text-muted-foreground mt-2\">{{ details.description }}</p>\n            <div class=\"mt-3 grid grid-cols-2 gap-2 sm:grid-cols-4\">\n              @for (item of details.metadata; track item.label) {\n                <div class=\"border-border/60 bg-card rounded-md border px-2.5 py-1.5\">\n                  <span class=\"text-muted-foreground block text-xs\">{{ item.label }}:</span>\n                  <span class=\"text-foreground block truncate font-mono font-medium\">{{ item.value }}</span>\n                </div>\n              }\n            </div>\n          </div>\n        }\n      </section>\n\n      <!-- Table Schema, Quality Tests & Governance Tabs -->\n      <ui-tabs [value]=\"activeTab()\" (valueChange)=\"activeTab.set($event)\" class=\"w-full\">\n        <ui-tabs-list class=\"grid h-10 w-full grid-cols-2 p-1 sm:grid-cols-4\">\n          <button ui-tabs-trigger value=\"schema\" class=\"gap-1.5 text-xs\">\n            <lucide-icon [img]=\"Table2\" class=\"size-3.5\" />\n            <span>Schema & Columns</span>\n            <span class=\"bg-muted rounded-full px-1.5 font-mono text-xs\">{{ columnCount }}</span>\n          </button>\n\n          <button ui-tabs-trigger value=\"tests\" class=\"gap-1.5 text-xs\">\n            <lucide-icon [img]=\"ShieldCheck\" class=\"text-success size-3.5\" />\n            <span>Quality Tests</span>\n            <span class=\"bg-success/10 text-success rounded-full px-1.5 font-mono text-xs font-semibold\"> 6/6 </span>\n          </button>\n\n          <button ui-tabs-trigger value=\"sql\" class=\"gap-1.5 text-xs\">\n            <lucide-icon [img]=\"FileCode2\" class=\"size-3.5\" />\n            <span>dbt Model SQL</span>\n          </button>\n\n          <button ui-tabs-trigger value=\"governance\" class=\"gap-1.5 text-xs\">\n            <lucide-icon [img]=\"Activity\" class=\"size-3.5\" />\n            <span>SLA & Governance</span>\n          </button>\n        </ui-tabs-list>\n\n        <ui-tabs-content value=\"schema\" class=\"mt-4 space-y-4\">\n          <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n            <div class=\"relative w-full sm:w-72\">\n              <lucide-icon\n                [img]=\"Search\"\n                class=\"text-muted-foreground absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2\"\n              />\n              <ui-input\n                [value]=\"searchQuery()\"\n                (valueChange)=\"searchQuery.set($event)\"\n                placeholder=\"Search columns, types, or terms...\"\n                class=\"h-8.5 pl-8 text-xs\"\n              />\n            </div>\n\n            <div class=\"flex items-center gap-2\">\n              <div class=\"text-muted-foreground text-xs\">\n                Showing <span class=\"text-foreground font-mono font-medium\">{{ filteredColumns().length }}</span> of\n                {{ columnCount }} columns\n              </div>\n              <button ui-button variant=\"outline\" size=\"sm\" class=\"h-8.5 gap-1.5 text-xs\" (click)=\"copyColumnNames()\">\n                <lucide-icon [img]=\"Copy\" class=\"size-3.5\" />\n                <span>Copy Columns</span>\n              </button>\n            </div>\n          </div>\n\n          <div ui-card class=\"border-border overflow-hidden border shadow-none\">\n            <div class=\"overflow-x-auto\">\n              <table ui-table>\n                <thead ui-table-header>\n                  <tr ui-table-row class=\"bg-muted/40 hover:bg-muted/40\">\n                    <th ui-table-head class=\"text-xs font-semibold\">Column Name</th>\n                    <th ui-table-head class=\"text-xs font-semibold\">Data Type</th>\n                    <th ui-table-head class=\"text-xs font-semibold\">Nullability</th>\n                    <th ui-table-head class=\"text-xs font-semibold\">Key / Constraint</th>\n                    <th ui-table-head class=\"text-xs font-semibold\">Sample Value</th>\n                    <th ui-table-head class=\"text-xs font-semibold\">Description</th>\n                  </tr>\n                </thead>\n                <tbody ui-table-body>\n                  @for (col of filteredColumns(); track col.name) {\n                    <tr ui-table-row class=\"text-xs\">\n                      <td ui-table-cell class=\"font-mono font-medium\">\n                        <div class=\"flex items-center gap-1.5\">\n                          @if (col.isPrimaryKey) {\n                            <lucide-icon [img]=\"Key\" class=\"text-warning size-3.5 shrink-0\" />\n                          }\n                          <span [class]=\"col.isPrimaryKey ? 'text-warning font-bold' : ''\">\n                            {{ col.name }}\n                          </span>\n                        </div>\n                      </td>\n\n                      <td ui-table-cell>\n                        <span ui-badge variant=\"secondary\" class=\"font-mono text-xs font-normal\">\n                          {{ col.type }}\n                        </span>\n                      </td>\n\n                      <td ui-table-cell>\n                        @if (!col.nullable) {\n                          <span ui-badge variant=\"outline\" class=\"text-muted-foreground font-mono text-xs font-normal\">\n                            NOT NULL\n                          </span>\n                        } @else {\n                          <span class=\"text-muted-foreground font-mono\">NULLABLE</span>\n                        }\n                      </td>\n\n                      <td ui-table-cell>\n                        <div class=\"flex flex-wrap items-center gap-1\">\n                          @if (col.isPrimaryKey) {\n                            <span ui-badge class=\"border-warning/30 bg-warning/15 text-warning text-xs font-semibold\">\n                              PRIMARY KEY\n                            </span>\n                          } @else if (col.constraints) {\n                            <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">\n                              {{ col.constraints }}\n                            </span>\n                          } @else {\n                            <span class=\"text-muted-foreground\">—</span>\n                          }\n                        </div>\n                      </td>\n\n                      <td ui-table-cell class=\"text-muted-foreground font-mono\">\n                        {{ col.sampleValue }}\n                      </td>\n\n                      <td ui-table-cell class=\"text-muted-foreground max-w-sm\">\n                        {{ col.description }}\n                      </td>\n                    </tr>\n                  }\n                </tbody>\n              </table>\n            </div>\n          </div>\n\n          <div class=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n            <div class=\"border-border bg-card space-y-1 rounded-lg border p-3 text-xs\">\n              <span class=\"text-muted-foreground\">Total Schema Columns</span>\n              <span class=\"text-foreground block font-mono text-base font-bold\">5</span>\n              <span class=\"text-muted-foreground text-xs\">1 Primary Key, 4 Measures</span>\n            </div>\n\n            <div class=\"border-border bg-card space-y-1 rounded-lg border p-3 text-xs\">\n              <span class=\"text-muted-foreground\">Completeness Score</span>\n              <span class=\"text-success block font-mono text-base font-bold\">97.5%</span>\n              <span class=\"text-muted-foreground text-xs\">4/5 Non-Nullable fields</span>\n            </div>\n\n            <div class=\"border-border bg-card space-y-1 rounded-lg border p-3 text-xs\">\n              <span class=\"text-muted-foreground\">Table Storage Volume</span>\n              <span class=\"text-foreground block font-mono text-base font-bold\">48.6 MB</span>\n              <span class=\"text-muted-foreground text-xs\">Micro-partition compressed</span>\n            </div>\n\n            <div class=\"border-border bg-card space-y-1 rounded-lg border p-3 text-xs\">\n              <span class=\"text-muted-foreground\">Governance Tier</span>\n              <span class=\"text-primary block font-mono text-base font-bold\">Gold Tier 1</span>\n              <span class=\"text-muted-foreground text-xs\">Certified Financial Source</span>\n            </div>\n          </div>\n        </ui-tabs-content>\n\n        <ui-tabs-content value=\"tests\" class=\"mt-4 space-y-4\">\n          <div ui-card class=\"border-border bg-card overflow-hidden border shadow-none\">\n            <div ui-card-header class=\"border-border/80 border-b p-4 sm:p-5\">\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 items-center gap-2\">\n                    <lucide-icon [img]=\"ShieldCheck\" class=\"text-success size-5\" />\n                    <h3 ui-card-title class=\"text-base font-semibold\">Data Quality & Integrity Assertions</h3>\n                    <span ui-badge class=\"border-success/20 bg-success/10 text-success font-mono text-xs\">\n                      100% Passing (6/6)\n                    </span>\n                  </div>\n                  <p ui-card-description class=\"text-xs\">\n                    Automated dbt-expectations, Monte Carlo ML anomaly detection, and referential integrity test suite.\n                  </p>\n                </div>\n\n                <button\n                  ui-button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  class=\"h-8.5 shrink-0 gap-1.5 self-start text-xs sm:self-auto\"\n                  [disabled]=\"isRunningTests()\"\n                  (click)=\"runSimulatedTests()\"\n                >\n                  <lucide-icon [img]=\"RefreshCw\" class=\"size-3.5\" [class]=\"spinClass\" />\n                  <span>{{ isRunningTests() ? 'Running 6 Tests...' : 'Re-run Test Suite' }}</span>\n                </button>\n              </div>\n            </div>\n\n            <div ui-card-content class=\"space-y-4 p-4 sm:p-5\">\n              <div class=\"flex flex-wrap items-center gap-2\">\n                <button\n                  ui-button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  [class]=\"severityPillClass('all')\"\n                  (click)=\"filterSeverity.set('all')\"\n                >\n                  All Assertions (6)\n                </button>\n                <button\n                  ui-button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  [class]=\"severityPillClass('critical')\"\n                  (click)=\"filterSeverity.set('critical')\"\n                >\n                  Primary Key & Referential (2)\n                </button>\n                <button\n                  ui-button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  [class]=\"severityPillClass('schema')\"\n                  (click)=\"filterSeverity.set('schema')\"\n                >\n                  Format & Completeness (2)\n                </button>\n              </div>\n\n              <div class=\"space-y-2.5\">\n                @for (assertion of filteredQualityTests(); track assertion.id) {\n                  <div class=\"border-border bg-muted/20 hover:bg-muted/40 rounded-lg border p-3.5 transition-colors\">\n                    <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n                      <div class=\"flex items-start gap-2.5\">\n                        <div\n                          class=\"bg-success/15 text-success mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-full\"\n                        >\n                          <lucide-icon [img]=\"Check\" class=\"size-3.5\" />\n                        </div>\n                        <div class=\"space-y-1\">\n                          <div class=\"flex flex-wrap items-center gap-2\">\n                            <span class=\"text-foreground font-mono text-xs font-bold\">{{ assertion.name }}</span>\n                            <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">{{ assertion.type }}</span>\n                            <span class=\"text-muted-foreground text-xs\"\n                              >target: <code class=\"text-foreground font-mono\">{{ assertion.targetColumn }}</code></span\n                            >\n                          </div>\n                          <p class=\"text-muted-foreground text-xs\">{{ assertion.description }}</p>\n                          <div\n                            class=\"text-muted-foreground bg-background/80 border-border/50 inline-block rounded border px-2 py-0.5 font-mono text-xs\"\n                          >\n                            {{ assertion.ruleDefinition }}\n                          </div>\n                        </div>\n                      </div>\n\n                      <div class=\"flex shrink-0 items-center gap-3 self-end text-xs sm:self-center\">\n                        <div class=\"text-right\">\n                          <span class=\"text-muted-foreground block text-xs\">Duration</span>\n                          <span class=\"text-foreground font-mono font-medium\">{{ assertion.executionTime }}</span>\n                        </div>\n                        <span ui-badge class=\"border-success/20 bg-success/10 text-success font-mono text-xs\">\n                          Passed\n                        </span>\n                      </div>\n                    </div>\n                  </div>\n                }\n              </div>\n            </div>\n          </div>\n        </ui-tabs-content>\n\n        <ui-tabs-content value=\"sql\" class=\"mt-4\">\n          <div class=\"border-border bg-muted/40 overflow-hidden rounded-xl border\">\n            <div class=\"border-border bg-card flex items-center justify-between border-b px-4 py-2.5\">\n              <div class=\"flex items-center gap-2\">\n                <lucide-icon [img]=\"FileCode2\" class=\"text-primary size-4\" />\n                <span class=\"text-foreground font-mono text-xs font-semibold\"\n                  >models/marts/finance/fct_monthly_financials.sql</span\n                >\n                <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">dbt v1.8 Incremental</span>\n              </div>\n              <button ui-button variant=\"ghost\" size=\"sm\" class=\"h-7 gap-1 text-xs\" (click)=\"copyCompiledSQL()\">\n                @if (copiedQuery()) {\n                  <lucide-icon [img]=\"Check\" class=\"text-success size-3\" />\n                } @else {\n                  <lucide-icon [img]=\"Copy\" class=\"size-3\" />\n                }\n                <span>{{ copiedQuery() ? 'Copied Model' : 'Copy dbt Code' }}</span>\n              </button>\n            </div>\n\n            <div\n              class=\"overflow-x-auto bg-neutral-950 p-4 font-mono text-xs leading-relaxed text-neutral-100 dark:bg-neutral-950\"\n            >\n              <pre class=\"whitespace-pre\"><code>{{ modelSnippet }}</code></pre>\n            </div>\n          </div>\n        </ui-tabs-content>\n\n        <ui-tabs-content value=\"governance\" class=\"mt-4 space-y-4\">\n          <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n            <div ui-card class=\"border-border space-y-3 border p-4 shadow-none\">\n              <div class=\"border-border/80 flex items-center gap-2 border-b pb-2\">\n                <lucide-icon [img]=\"Users\" class=\"text-primary size-4\" />\n                <h3 class=\"text-foreground text-sm font-semibold\">Table Ownership & Escalation</h3>\n              </div>\n              <div class=\"space-y-2 text-xs\">\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Owning Team:</span>\n                  <span class=\"text-foreground font-semibold\">Data Platform Squad</span>\n                </div>\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Technical Lead:</span>\n                  <span class=\"text-foreground font-mono\">&#64;sarah.lin (Principal Data Eng)</span>\n                </div>\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Slack Channel:</span>\n                  <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">#data-platform-alerts</span>\n                </div>\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">On-Call Rotation:</span>\n                  <span class=\"text-foreground\">PagerDuty · Tier 1 High Severity</span>\n                </div>\n              </div>\n            </div>\n\n            <div ui-card class=\"border-border space-y-3 border p-4 shadow-none\">\n              <div class=\"border-border/80 flex items-center gap-2 border-b pb-2\">\n                <lucide-icon [img]=\"Clock\" class=\"text-success size-4\" />\n                <h3 class=\"text-foreground text-sm font-semibold\">Freshness SLA & Cadence</h3>\n              </div>\n              <div class=\"space-y-2 text-xs\">\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Target SLA Threshold:</span>\n                  <span class=\"text-foreground font-mono font-medium\">&lt; 60 minutes</span>\n                </div>\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Current Latency:</span>\n                  <span class=\"text-success font-mono font-bold\">18 minutes (Compliant)</span>\n                </div>\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Cron Schedule:</span>\n                  <code class=\"text-foreground bg-muted rounded px-1.5 py-0.5 font-mono text-xs\"\n                    >0 * * * * (Hourly)</code\n                  >\n                </div>\n                <div class=\"flex items-center justify-between\">\n                  <span class=\"text-muted-foreground\">Historical Uptime:</span>\n                  <span class=\"text-foreground font-mono font-medium\">99.98% (Last 90 days)</span>\n                </div>\n              </div>\n            </div>\n          </div>\n        </ui-tabs-content>\n      </ui-tabs>\n    </div>\n  `,\n})\nexport class UiDataCatalogLineageComponent {\n  protected readonly Activity = Activity\n  protected readonly ArrowRightLeft = ArrowRightLeft\n  protected readonly BarChart3 = BarChart3\n  protected readonly Check = Check\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Clock = Clock\n  protected readonly Coins = Coins\n  protected readonly Copy = Copy\n  protected readonly CreditCard = CreditCard\n  protected readonly Database = Database\n  protected readonly FileCode2 = FileCode2\n  protected readonly GitFork = GitFork\n  protected readonly Key = Key\n  protected readonly Landmark = Landmark\n  protected readonly Layers = Layers\n  protected readonly LineChart = LineChart\n  protected readonly RefreshCw = RefreshCw\n  protected readonly Search = Search\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly Table2 = Table2\n  protected readonly Terminal = Terminal\n  protected readonly Users = Users\n  protected readonly Workflow = Workflow\n  protected readonly X = X\n\n  protected readonly sources = sourceNodes\n  protected readonly transforms = transformNodes\n  protected readonly consumers = consumerNodes\n  protected readonly columnCount = columns.length\n  protected readonly modelSnippet = dbtModelSnippet\n\n  @Input('class') className?: string\n\n  readonly activeTab = signal('schema')\n  readonly searchQuery = signal('')\n  readonly copiedRef = signal(false)\n  readonly copiedQuery = signal(false)\n  readonly isRunningTests = signal(false)\n  readonly isQueryModalOpen = signal(false)\n  readonly selectedNodeId = signal<string | null>('target-table')\n  readonly filterSeverity = signal<'all' | 'critical' | 'schema'>('all')\n\n  readonly filteredColumns = computed(() => {\n    const query = this.searchQuery().trim().toLowerCase()\n    if (!query) return columns\n    return columns.filter(\n      (col) =>\n        col.name.toLowerCase().includes(query) ||\n        col.type.toLowerCase().includes(query) ||\n        col.description.toLowerCase().includes(query),\n    )\n  })\n\n  readonly filteredQualityTests = computed(() => {\n    if (this.filterSeverity() === 'critical') {\n      return qualityAssertions.filter((t) => t.type.includes('Primary') || t.type.includes('Referential'))\n    }\n    if (this.filterSeverity() === 'schema') {\n      return qualityAssertions.filter((t) => t.type.includes('Format') || t.type.includes('Completeness'))\n    }\n    return qualityAssertions\n  })\n\n  readonly selectedNodeDetails = computed(() => {\n    if (this.selectedNodeId() === 'target-table') {\n      return {\n        title: 'analytics.fct_monthly_financials',\n        badge: 'Active Target Table',\n        description:\n          'Gold-tier core financial mart consolidating Stripe billing, FX rates, and Salesforce CRM accounts for executive reporting.',\n        metadata: [\n          { label: 'Layer', value: 'Marts / Core Analytics' },\n          { label: 'Schema', value: 'production_dw' },\n          { label: 'Total Rows', value: '240,000' },\n          { label: 'Freshness SLA', value: '60 mins (Current: 18m)' },\n        ],\n      }\n    }\n\n    const src = sourceNodes.find((n) => n.id === this.selectedNodeId())\n    if (src) {\n      return {\n        title: src.name,\n        badge: 'Source Table',\n        description: src.description,\n        metadata: [\n          { label: 'Connector', value: src.connector },\n          { label: 'Ingestion Type', value: src.type },\n          { label: 'Volume', value: src.rowCount },\n          { label: 'Sync Cadence', value: src.latency },\n        ],\n      }\n    }\n\n    const tr = transformNodes.find((n) => n.id === this.selectedNodeId())\n    if (tr) {\n      return {\n        title: tr.name,\n        badge: 'dbt Intermediate Model',\n        description: tr.description,\n        metadata: [\n          { label: 'Engine', value: tr.engine },\n          { label: 'Materialization', value: tr.modelType },\n          { label: 'Build Duration', value: tr.runtime },\n          { label: 'Test Suite', value: tr.testsPassed },\n        ],\n      }\n    }\n\n    const cons = consumerNodes.find((n) => n.id === this.selectedNodeId())\n    if (cons) {\n      return {\n        title: cons.name,\n        badge: 'Downstream Consumer',\n        description: cons.description,\n        metadata: [\n          { label: 'Tool Platform', value: cons.tool },\n          { label: 'Type', value: cons.category },\n          { label: 'Audience / Usage', value: cons.audience },\n          { label: 'Sync Schedule', value: cons.frequency },\n        ],\n      }\n    }\n\n    return null\n  })\n\n  get rootClass(): string {\n    return cn(\n      'bg-background text-foreground border-border w-full space-y-6 rounded-xl border p-4 shadow-xs sm:p-6',\n      this.className,\n    )\n  }\n\n  get spinClass(): string {\n    return cn(this.isRunningTests() && 'text-primary animate-spin')\n  }\n\n  get targetCardClass(): string {\n    return cn(\n      'focus-visible:ring-ring relative w-full cursor-pointer rounded-lg border-2 p-3 text-left text-xs shadow-xs transition-[border-color,box-shadow] focus-visible:ring-2 focus-visible:outline-none',\n      this.selectedNodeId() === 'target-table'\n        ? 'border-primary bg-primary/10 ring-primary/20 ring-2'\n        : 'border-primary/60 bg-primary/5 hover:border-primary',\n    )\n  }\n\n  nodeCardClass(selected: boolean): string {\n    return cn(\n      'group focus-visible:ring-ring relative w-full cursor-pointer rounded-lg border p-3 text-left text-xs shadow-xs transition-[background-color,border-color,box-shadow] focus-visible:ring-2 focus-visible:outline-none',\n      selected\n        ? 'border-primary bg-primary/5 ring-primary/30 ring-1'\n        : 'border-border bg-card hover:border-border/80 hover:bg-muted/40',\n    )\n  }\n\n  severityPillClass(sev: 'all' | 'critical' | 'schema'): string {\n    return cn('h-7 text-xs', this.filterSeverity() === sev && 'bg-muted font-semibold')\n  }\n\n  resetLineageFocus(): void {\n    this.selectedNodeId.set('target-table')\n    this.activeTab.set('schema')\n  }\n\n  copyRef(text: string): void {\n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      void navigator.clipboard.writeText(text)\n      this.copiedRef.set(true)\n      setTimeout(() => this.copiedRef.set(false), 2000)\n    }\n  }\n\n  copyColumnNames(): void {\n    this.copyRef(columns.map((c) => c.name).join(', '))\n  }\n\n  copyCompiledSQL(): void {\n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      void navigator.clipboard.writeText(dbtModelSnippet)\n      this.copiedQuery.set(true)\n      setTimeout(() => this.copiedQuery.set(false), 2000)\n    }\n  }\n\n  runSimulatedTests(): void {\n    this.isRunningTests.set(true)\n    setTimeout(() => this.isRunningTests.set(false), 1200)\n  }\n}\n",
      "type": "registry:page",
      "target": "~/src/app/components/blocks/data-catalog-lineage/data-catalog-lineage.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/data-catalog-lineage/index.ts",
      "content": "export {\n  UiDataCatalogLineageComponent,\n  type ColumnDef,\n  type QualityAssertion,\n  type LineageSourceNode,\n  type LineageTransformNode,\n  type LineageConsumerNode,\n} from './data-catalog-lineage.component'\n",
      "type": "registry:page",
      "target": "~/src/app/components/blocks/data-catalog-lineage/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/input.json",
    "https://uipkge.dev/r/angular/table.json",
    "https://uipkge.dev/r/angular/tabs.json"
  ],
  "description": "Alation and Monte Carlo style enterprise data catalog lineage map and table documentation explorer with interactive upstream source DAGs, dbt transform models, downstream BI consumer traces, schema column definitions with types and constraints, automated data quality assertions, and SQL console query runner.",
  "categories": [
    "devops",
    "app",
    "analytics",
    "data"
  ]
}