{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "floor-plan-explorer",
  "title": "Floor Plan Explorer",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/floor-plan-explorer/floor-plan-explorer.component.ts",
      "content": "// Architectural unit floor plan inspector and residential layout explorer with a 2D\n// CAD-styled blueprint canvas, interactive room highlight pins, dimensional callouts,\n// room breakdown specs, and a building unit availability table. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, DestroyRef, Input, computed, inject, signal } from '@angular/core'\nimport {\n  Bath,\n  Bed,\n  Building2,\n  Calendar,\n  Check,\n  CheckCircle2,\n  Download,\n  FileText,\n  Home,\n  Layers,\n  LucideAngularModule,\n  MapPin,\n  Ruler,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardFooterComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\nimport { UiTabsComponent, UiTabsListComponent, UiTabsTriggerComponent } from '@/ui/tabs/tabs.component'\n\nexport interface RoomSpec {\n  id: string\n  name: string\n  shortLabel: string\n  dimensionsImperial: string\n  dimensionsMetric: string\n  areaSqFt: number\n  areaSqM: number\n  flooring: string\n  features: string[]\n  pinX: number\n  pinY: number\n  rect: { x: number; y: number; w: number; h: number }\n}\n\nexport interface AvailableUnit {\n  unitNumber: string\n  floor: number\n  view: string\n  monthlyRent: number\n  sqFt: number\n  status: 'available-now' | 'available-soon' | 'leased' | 'under-contract'\n  statusLabel: string\n  moveInDate: string\n  exposure: string\n}\n\nexport interface FloorPlanData {\n  id: string\n  tabKey: string\n  tabLabel: string\n  marketingName: string\n  tier: string\n  beds: number\n  baths: number\n  totalAreaSqFt: number\n  totalAreaSqM: number\n  interiorSqFt: number\n  exteriorSqFt: number\n  ceilingHeight: string\n  exposure: string\n  startingRent: number\n  description: string\n  highlights: string[]\n  rooms: RoomSpec[]\n  availableUnits: AvailableUnit[]\n}\n\nconst floorPlans: Record<string, FloorPlanData> = {\n  'plan-a': {\n    id: 'plan-a',\n    tabKey: 'plan-a',\n    tabLabel: 'Plan A - 1 Bed / 1 Bath',\n    marketingName: 'Plan A - The Urban Haven',\n    tier: 'Urban Gallery Residence',\n    beds: 1,\n    baths: 1,\n    totalAreaSqFt: 780,\n    totalAreaSqM: 72.5,\n    interiorSqFt: 735,\n    exteriorSqFt: 45,\n    ceilingHeight: `10' 0\" Finished`,\n    exposure: 'East · Garden & Sunrise',\n    startingRent: 3450,\n    description:\n      'Artfully designed open-concept layout featuring oversized east-facing windows, gourmet galley kitchen with quartz surfaces, secluded bedroom suite with walk-in closet, and a private sunrise terrace.',\n    highlights: [\n      'Floor-to-ceiling glass wall',\n      'European quartz kitchen island',\n      'Deep soaking tub & frameless shower',\n      'Private sunrise terrace',\n    ],\n    rooms: [\n      {\n        id: 'living',\n        name: 'Living & Dining Room',\n        shortLabel: 'Living / Dining',\n        dimensionsImperial: `16' × 12'`,\n        dimensionsMetric: '4.9m × 3.7m',\n        areaSqFt: 192,\n        areaSqM: 17.8,\n        flooring: 'Wide Plank Natural White Oak',\n        features: ['East Sunrise Exposure', '9-Foot Glazing Wall', 'Concealed Media Wiring'],\n        pinX: 280,\n        pinY: 175,\n        rect: { x: 170, y: 90, w: 230, h: 170 },\n      },\n      {\n        id: 'master-bed',\n        name: 'Master Bedroom',\n        shortLabel: 'Master Bed',\n        dimensionsImperial: `13' × 11'`,\n        dimensionsMetric: '4.0m × 3.4m',\n        areaSqFt: 143,\n        areaSqM: 13.3,\n        flooring: 'Plush Organic Wool Loop',\n        features: ['Acoustic Insulation', 'Custom Closet Built-ins', 'Blackout Shade Pocket'],\n        pinX: 505,\n        pinY: 175,\n        rect: { x: 410, y: 90, w: 190, h: 170 },\n      },\n      {\n        id: 'kitchen',\n        name: 'Gourmet Galley Kitchen',\n        shortLabel: 'Kitchen',\n        dimensionsImperial: `11' × 9'`,\n        dimensionsMetric: '3.4m × 2.7m',\n        areaSqFt: 99,\n        areaSqM: 9.2,\n        flooring: 'Calacatta Honed Quartzite',\n        features: ['Integrated Bosch Appliances', 'Undermount LED Lights', 'Soft-Close Walnut Joinery'],\n        pinX: 280,\n        pinY: 330,\n        rect: { x: 170, y: 270, w: 230, h: 120 },\n      },\n      {\n        id: 'master-bath',\n        name: 'Primary Full Bath',\n        shortLabel: 'Full Bath',\n        dimensionsImperial: `9' × 6'`,\n        dimensionsMetric: '2.7m × 1.8m',\n        areaSqFt: 54,\n        areaSqM: 5.0,\n        flooring: 'Matte Slate & Terrazzo',\n        features: ['Kohler Undermount Sink', 'Frameless Glass Shower', 'Backlit Anti-Fog Vanity'],\n        pinX: 505,\n        pinY: 330,\n        rect: { x: 410, y: 270, w: 190, h: 120 },\n      },\n      {\n        id: 'balcony',\n        name: 'Private Terrace',\n        shortLabel: 'Terrace',\n        dimensionsImperial: `9' × 5'`,\n        dimensionsMetric: '2.7m × 1.5m',\n        areaSqFt: 45,\n        areaSqM: 4.2,\n        flooring: 'Weathered Teak Decking',\n        features: ['Architectural Steel Railing', 'Exterior Power Outlet', 'Garden Courtyard Vistas'],\n        pinX: 105,\n        pinY: 175,\n        rect: { x: 50, y: 90, w: 110, h: 170 },\n      },\n    ],\n    availableUnits: [\n      {\n        unitNumber: '304',\n        floor: 3,\n        view: 'Courtyard & Garden',\n        monthlyRent: 3450,\n        sqFt: 780,\n        status: 'available-now',\n        statusLabel: 'Available Now',\n        moveInDate: 'Immediate',\n        exposure: 'East',\n      },\n      {\n        unitNumber: '604',\n        floor: 6,\n        view: 'Skyline Sunrise View',\n        monthlyRent: 3650,\n        sqFt: 780,\n        status: 'available-soon',\n        statusLabel: 'Available Oct 15',\n        moveInDate: 'Oct 15, 2026',\n        exposure: 'East / North',\n      },\n      {\n        unitNumber: '904',\n        floor: 9,\n        view: 'High-Floor Park View',\n        monthlyRent: 3800,\n        sqFt: 780,\n        status: 'leased',\n        statusLabel: 'Leased',\n        moveInDate: 'Occupied',\n        exposure: 'East',\n      },\n    ],\n  },\n  'plan-b': {\n    id: 'plan-b',\n    tabKey: 'plan-b',\n    tabLabel: 'Plan B - 2 Bed / 2 Bath',\n    marketingName: 'Plan B - The Skyline Suite',\n    tier: 'Signature Corner Residence',\n    beds: 2,\n    baths: 2,\n    totalAreaSqFt: 1420,\n    totalAreaSqM: 132.0,\n    interiorSqFt: 1360,\n    exteriorSqFt: 60,\n    ceilingHeight: `10' 6\" Finished`,\n    exposure: 'Southwest · Bay & City Skyline',\n    startingRent: 4850,\n    description:\n      'Expansive dual-exposure residence centered around a dramatic living and entertaining salon with floor-to-ceiling panoramic glass, chef-grade kitchen island, split master and guest wings, and a sheltered private terrace.',\n    highlights: [\n      'Dual-aspect corner positioning with 270° light',\n      'Chef island with 10-foot marble waterfall',\n      'Primary wing with dual walk-in closets',\n      'Dedicated foyer vestibule & utility pantry',\n    ],\n    rooms: [\n      {\n        id: 'living',\n        name: 'Living Room',\n        shortLabel: 'Living Room',\n        dimensionsImperial: `18' × 14'`,\n        dimensionsMetric: '5.5m × 4.3m',\n        areaSqFt: 252,\n        areaSqM: 23.4,\n        flooring: 'Wide Plank European White Oak',\n        features: ['Floor-to-Ceiling Corner Glazing', 'Motorized Solar Shades', 'Recessed Architectural Lighting'],\n        pinX: 255,\n        pinY: 160,\n        rect: { x: 150, y: 75, w: 220, h: 175 },\n      },\n      {\n        id: 'master-bed',\n        name: 'Master Bedroom',\n        shortLabel: 'Master Bed',\n        dimensionsImperial: `15' × 12'`,\n        dimensionsMetric: '4.6m × 3.7m',\n        areaSqFt: 180,\n        areaSqM: 16.7,\n        flooring: 'New Zealand Wool Weave',\n        features: ['South Bay Views', 'Direct En-Suite Access', 'Custom Millwork Wardrobe'],\n        pinX: 455,\n        pinY: 145,\n        rect: { x: 380, y: 75, w: 155, h: 150 },\n      },\n      {\n        id: 'kitchen',\n        name: 'Chef Kitchen & Dining',\n        shortLabel: 'Kitchen',\n        dimensionsImperial: `12' × 10'`,\n        dimensionsMetric: '3.7m × 3.0m',\n        areaSqFt: 120,\n        areaSqM: 11.1,\n        flooring: 'Calacatta Honed Quartzite',\n        features: ['Waterfall Marble Island', 'Sub-Zero & Wolf Appliances', 'Pantry Cabinetry'],\n        pinX: 255,\n        pinY: 325,\n        rect: { x: 150, y: 260, w: 220, h: 135 },\n      },\n      {\n        id: 'master-bath',\n        name: 'Master Bath',\n        shortLabel: 'Master Bath',\n        dimensionsImperial: `10' × 8'`,\n        dimensionsMetric: '3.0m × 2.4m',\n        areaSqFt: 80,\n        areaSqM: 7.4,\n        flooring: 'Bianco Carrara Marble',\n        features: ['Dual Floating Vanities', 'Walk-in Rain Shower', 'Acoustic Privacy Door'],\n        pinX: 590,\n        pinY: 145,\n        rect: { x: 545, y: 75, w: 90, h: 150 },\n      },\n      {\n        id: 'guest-bed',\n        name: 'Guest Bedroom / Study',\n        shortLabel: 'Guest Bed',\n        dimensionsImperial: `13' × 11'`,\n        dimensionsMetric: '4.0m × 3.4m',\n        areaSqFt: 143,\n        areaSqM: 13.3,\n        flooring: 'Wide Plank European White Oak',\n        features: ['Multi-Function Home Office', 'South Window Exposure', 'Built-in Closet System'],\n        pinX: 565,\n        pinY: 320,\n        rect: { x: 490, y: 245, w: 145, h: 150 },\n      },\n      {\n        id: 'guest-bath',\n        name: 'Guest Full Bath',\n        shortLabel: 'Guest Bath',\n        dimensionsImperial: `8' × 6'`,\n        dimensionsMetric: '2.4m × 1.8m',\n        areaSqFt: 48,\n        areaSqM: 4.5,\n        flooring: 'Smoked Gray Terrazzo',\n        features: ['Full Soaking Tub', 'Modern Matte Black Fixtures', 'Linen Storage'],\n        pinX: 430,\n        pinY: 320,\n        rect: { x: 380, y: 245, w: 100, h: 150 },\n      },\n      {\n        id: 'balcony',\n        name: 'Private Terrace',\n        shortLabel: 'Terrace',\n        dimensionsImperial: `10' × 6'`,\n        dimensionsMetric: '3.0m × 1.8m',\n        areaSqFt: 60,\n        areaSqM: 5.6,\n        flooring: 'Architectural Ipe Wood',\n        features: ['Panoramic Bay Overlook', 'Weatherproof Recessed Sconces', 'Glass Wind Guard'],\n        pinX: 90,\n        pinY: 160,\n        rect: { x: 40, y: 75, w: 100, h: 175 },\n      },\n    ],\n    availableUnits: [\n      {\n        unitNumber: '402',\n        floor: 4,\n        view: 'South City View',\n        monthlyRent: 4850,\n        sqFt: 1420,\n        status: 'available-now',\n        statusLabel: 'Available Now',\n        moveInDate: 'Immediate',\n        exposure: 'South / West',\n      },\n      {\n        unitNumber: '708',\n        floor: 7,\n        view: 'Bay & Marina View',\n        monthlyRent: 5200,\n        sqFt: 1420,\n        status: 'available-soon',\n        statusLabel: 'Available Sep 1',\n        moveInDate: 'Sep 1, 2026',\n        exposure: 'Bay View / South',\n      },\n      {\n        unitNumber: '1102',\n        floor: 11,\n        view: 'Penthouse Level Panoramic',\n        monthlyRent: 5600,\n        sqFt: 1420,\n        status: 'leased',\n        statusLabel: 'Leased',\n        moveInDate: 'Occupied',\n        exposure: 'Panoramic South',\n      },\n    ],\n  },\n  'plan-c': {\n    id: 'plan-c',\n    tabKey: 'plan-c',\n    tabLabel: 'Plan C - 3 Bed Penthouse',\n    marketingName: 'Plan C - The Grandview Penthouse',\n    tier: 'Crown Estate Penthouse',\n    beds: 3,\n    baths: 3.5,\n    totalAreaSqFt: 2250,\n    totalAreaSqM: 209.0,\n    interiorSqFt: 2090,\n    exteriorSqFt: 160,\n    ceilingHeight: `11' 8\" Finished`,\n    exposure: '360° Panoramic · Harbor, Bay & Bridges',\n    startingRent: 9400,\n    description:\n      'A true architectural masterpiece occupying the top levels of the tower. Direct key-lock private elevator access opens into a sweeping grand salon with 11.5-foot ceilings, full culinary kitchen with butler pantry, spa sanctuary primary suite, and wraparound sky terrace.',\n    highlights: [\n      'Private elevator vestibule with secure biometric access',\n      'Wraparound sky terrace with built-in gas fire table',\n      'Primary retreat with double walk-in dressing galleries',\n      'Butler service pantry with climate-controlled wine vault',\n    ],\n    rooms: [\n      {\n        id: 'grand-salon',\n        name: 'Grand Salon & Living',\n        shortLabel: 'Grand Salon',\n        dimensionsImperial: `24' × 16'`,\n        dimensionsMetric: '7.3m × 4.9m',\n        areaSqFt: 384,\n        areaSqM: 35.7,\n        flooring: 'Herringbone European Oak',\n        features: ['360° Bay Vista Glazing', 'Gas Linear Fireplace', 'Custom Architectural Coving'],\n        pinX: 275,\n        pinY: 155,\n        rect: { x: 160, y: 85, w: 240, h: 150 },\n      },\n      {\n        id: 'primary-suite',\n        name: 'Primary Penthouse Suite',\n        shortLabel: 'Primary Suite',\n        dimensionsImperial: `18' × 14'`,\n        dimensionsMetric: '5.5m × 4.3m',\n        areaSqFt: 252,\n        areaSqM: 23.4,\n        flooring: 'Custom Silk-Wool Blend Weave',\n        features: ['Harbor Sunrise Exposure', 'Sitting Lounge Area', 'Dual Walk-in Closets'],\n        pinX: 480,\n        pinY: 155,\n        rect: { x: 410, y: 85, w: 140, h: 150 },\n      },\n      {\n        id: 'spa-bath',\n        name: 'Spa Sanctuary Primary Bath',\n        shortLabel: 'Spa Bath',\n        dimensionsImperial: `12' × 9'`,\n        dimensionsMetric: '3.7m × 2.7m',\n        areaSqFt: 108,\n        areaSqM: 10.0,\n        flooring: 'Bookmatched Calacatta Marble',\n        features: ['Freestanding Oval Soaking Tub', 'Dual Steam Shower', 'Radiant Heated Flooring'],\n        pinX: 595,\n        pinY: 155,\n        rect: { x: 560, y: 85, w: 80, h: 150 },\n      },\n      {\n        id: 'dining',\n        name: 'Formal Dining Gallery',\n        shortLabel: 'Dining Room',\n        dimensionsImperial: `15' × 12'`,\n        dimensionsMetric: '4.6m × 3.7m',\n        areaSqFt: 180,\n        areaSqM: 16.7,\n        flooring: 'Herringbone European Oak',\n        features: ['Seating for 10-12 Guests', 'Integrated Bar Cabinetry', 'Designer Chandelier Anchor'],\n        pinX: 235,\n        pinY: 315,\n        rect: { x: 160, y: 245, w: 150, h: 145 },\n      },\n      {\n        id: 'kitchen',\n        name: 'Culinary Kitchen & Pantry',\n        shortLabel: 'Kitchen',\n        dimensionsImperial: `16' × 11'`,\n        dimensionsMetric: '4.9m × 3.4m',\n        areaSqFt: 176,\n        areaSqM: 16.3,\n        flooring: 'Taj Mahal Quartzite',\n        features: ['12-Foot Monolithic Island', 'Gaggenau 400 Series Suite', 'Butler Prep Scullery'],\n        pinX: 95,\n        pinY: 315,\n        rect: { x: 40, y: 245, w: 110, h: 145 },\n      },\n      {\n        id: 'bed-2',\n        name: 'Bedroom Suite 2',\n        shortLabel: 'Bed 2 Suite',\n        dimensionsImperial: `14' × 12'`,\n        dimensionsMetric: '4.3m × 3.7m',\n        areaSqFt: 168,\n        areaSqM: 15.6,\n        flooring: 'Wide Plank European Oak',\n        features: ['En-Suite Private Bath', 'South Window Bank', 'Deep Built-in Wardrobe'],\n        pinX: 395,\n        pinY: 315,\n        rect: { x: 320, y: 245, w: 150, h: 145 },\n      },\n      {\n        id: 'bed-3',\n        name: 'Bedroom 3 / Executive Study',\n        shortLabel: 'Bed 3 / Study',\n        dimensionsImperial: `13' × 11'`,\n        dimensionsMetric: '4.0m × 3.4m',\n        areaSqFt: 143,\n        areaSqM: 13.3,\n        flooring: 'Custom Walnut Parquetry',\n        features: ['Integrated Library Shelving', 'Acoustic Pocket Doors', 'Corner View Light'],\n        pinX: 560,\n        pinY: 315,\n        rect: { x: 480, y: 245, w: 160, h: 145 },\n      },\n      {\n        id: 'sky-terrace',\n        name: 'Wraparound Sky Terrace',\n        shortLabel: 'Sky Terrace',\n        dimensionsImperial: `20' × 8'`,\n        dimensionsMetric: '6.1m × 2.4m',\n        areaSqFt: 160,\n        areaSqM: 14.9,\n        flooring: 'Porcelain Pavers & Teak',\n        features: ['Integrated Linear Gas Hearth', 'Outdoor Audio Pre-Wire', 'Frameless Wind Barrier'],\n        pinX: 340,\n        pinY: 45,\n        rect: { x: 160, y: 25, w: 360, h: 50 },\n      },\n    ],\n    availableUnits: [\n      {\n        unitNumber: 'PH-01',\n        floor: 14,\n        view: '360° Bay & City Skyline',\n        monthlyRent: 9400,\n        sqFt: 2250,\n        status: 'available-now',\n        statusLabel: 'Available Now',\n        moveInDate: 'Immediate',\n        exposure: '360° Panoramic',\n      },\n      {\n        unitNumber: 'PH-02',\n        floor: 14,\n        view: 'Harbor Sunrise & Marina',\n        monthlyRent: 9100,\n        sqFt: 2250,\n        status: 'under-contract',\n        statusLabel: 'Under Contract',\n        moveInDate: 'Pending',\n        exposure: 'East / South',\n      },\n      {\n        unitNumber: 'PH-03',\n        floor: 15,\n        view: 'Crown Sky Penthouse with Spa',\n        monthlyRent: 10500,\n        sqFt: 2250,\n        status: 'available-soon',\n        statusLabel: 'Available Nov 1',\n        moveInDate: 'Nov 1, 2026',\n        exposure: 'Crown Panoramic',\n      },\n    ],\n  },\n}\n\nconst planKeys = ['plan-a', 'plan-b', 'plan-c']\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-floor-plan-explorer, [ui-floor-plan-explorer]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardFooterComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n    UiTabsComponent,\n    UiTabsListComponent,\n    UiTabsTriggerComponent,\n  ],\n  template: `\n    <div data-slot=\"floor-plan-explorer\" [class]=\"rootClass\">\n      <!-- Header: Building Title, Plan Switcher Tabs, Action Button -->\n      <header class=\"border-border flex flex-col gap-4 border-b pb-6 lg:flex-row lg:items-center lg:justify-between\">\n        <div class=\"space-y-1.5\">\n          <div class=\"flex items-center gap-2\">\n            <span ui-badge variant=\"outline\" class=\"text-muted-foreground gap-1 px-2 py-0.5 font-mono text-xs\">\n              <lucide-icon [img]=\"Building2\" class=\"text-primary size-3\" />\n              The Grandview Collection\n            </span>\n            <span class=\"text-muted-foreground text-xs\">Tower West · Residences</span>\n          </div>\n          <h1 class=\"text-xl font-semibold tracking-tight sm:text-2xl\">\n            The Grandview Penthouse Collection · Floor Plan Explorer\n          </h1>\n          <p class=\"text-muted-foreground text-xs sm:text-sm\">\n            Interactive architectural layout inspector, dimensional specifications, and real-time residential unit\n            availability.\n          </p>\n        </div>\n\n        <div class=\"flex flex-wrap items-center gap-3\">\n          <button\n            ui-button\n            aria-label=\"Download attachment\"\n            variant=\"outline\"\n            size=\"sm\"\n            class=\"h-9 gap-2 text-xs\"\n            [disabled]=\"isDownloadingPdf()\"\n            (click)=\"downloadPdf()\"\n          >\n            @if (!downloadSuccess()) {\n              <lucide-icon [img]=\"Download\" class=\"text-muted-foreground size-3.5\" />\n            } @else {\n              <lucide-icon [img]=\"Check\" class=\"text-success size-3.5\" />\n            }\n            <span>{{ downloadLabel() }}</span>\n          </button>\n        </div>\n      </header>\n\n      <!-- Plan Selection Tabs Bar -->\n      <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <ui-tabs [value]=\"activeTab()\" (valueChange)=\"selectTab($event)\" class=\"w-full sm:w-auto\">\n          <ui-tabs-list class=\"bg-muted/60 grid h-10 w-full grid-cols-3 gap-1 p-1 sm:w-auto\">\n            <button\n              ui-tabs-trigger\n              value=\"plan-a\"\n              class=\"data-[state=active]:bg-background px-3 text-xs font-medium data-[state=active]:shadow-xs sm:px-4 sm:text-sm\"\n            >\n              Plan A - 1 Bed / 1 Bath\n            </button>\n            <button\n              ui-tabs-trigger\n              value=\"plan-b\"\n              class=\"data-[state=active]:bg-background px-3 text-xs font-medium data-[state=active]:shadow-xs sm:px-4 sm:text-sm\"\n            >\n              Plan B - 2 Bed / 2 Bath\n            </button>\n            <button\n              ui-tabs-trigger\n              value=\"plan-c\"\n              class=\"data-[state=active]:bg-background px-3 text-xs font-medium data-[state=active]:shadow-xs sm:px-4 sm:text-sm\"\n            >\n              Plan C - 3 Bed Penthouse\n            </button>\n          </ui-tabs-list>\n        </ui-tabs>\n\n        <div class=\"flex items-center gap-2\">\n          <span class=\"text-muted-foreground text-xs\">Units:</span>\n          <div class=\"border-border bg-muted/30 inline-flex rounded-md border p-0.5\">\n            <button type=\"button\" [class]=\"unitToggleClass('imperial')\" (click)=\"unitSystem.set('imperial')\">\n              Sq Ft / ft\n            </button>\n            <button type=\"button\" [class]=\"unitToggleClass('metric')\" (click)=\"unitSystem.set('metric')\">m² / m</button>\n          </div>\n        </div>\n      </div>\n\n      <!-- 2-Column Inspector: Left 2D CAD Blueprint Canvas, Right Specs & Availability -->\n      <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-12\">\n        <!-- Left Column: 2D Architectural Layout Canvas (7 cols) -->\n        <div class=\"space-y-4 lg:col-span-7\">\n          <div ui-card class=\"border-border bg-card overflow-hidden shadow-xs\">\n            <!-- Canvas Toolbar Header -->\n            <div class=\"border-border bg-muted/30 flex flex-wrap items-center justify-between gap-3 border-b px-4 py-3\">\n              <div class=\"flex items-center gap-2.5\">\n                <span class=\"relative flex size-2\">\n                  <span class=\"bg-primary/60 absolute inline-flex size-full rounded-full opacity-75\"></span>\n                  <span class=\"bg-primary relative inline-flex size-2 rounded-full\"></span>\n                </span>\n                <div>\n                  <p class=\"text-foreground text-xs font-medium\">2D Architectural CAD Schematic</p>\n                  <p class=\"text-muted-foreground text-xs\">Interactive room layout & dimensional spans</p>\n                </div>\n              </div>\n\n              <!-- Canvas View Options -->\n              <div class=\"flex items-center gap-1.5\">\n                <button\n                  ui-button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  [class]=\"canvasToggleClass(showDimensions())\"\n                  (click)=\"showDimensions.set(!showDimensions())\"\n                >\n                  <lucide-icon [img]=\"Ruler\" class=\"text-muted-foreground size-3\" />\n                  <span>Dimensions</span>\n                </button>\n                <button\n                  ui-button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  [class]=\"canvasToggleClass(showFurniture())\"\n                  (click)=\"showFurniture.set(!showFurniture())\"\n                >\n                  <lucide-icon [img]=\"Layers\" class=\"text-muted-foreground size-3\" />\n                  <span>Fixtures</span>\n                </button>\n                <button\n                  ui-button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  [class]=\"canvasToggleClass(showPins())\"\n                  (click)=\"showPins.set(!showPins())\"\n                >\n                  <lucide-icon [img]=\"MapPin\" class=\"text-muted-foreground size-3\" />\n                  <span>Pins</span>\n                </button>\n              </div>\n            </div>\n\n            <!-- Canvas Drawing Surface -->\n            <div class=\"bg-card/95 relative p-3 sm:p-5\">\n              <svg\n                viewBox=\"0 0 680 430\"\n                class=\"border-border/70 bg-card w-full rounded border select-none\"\n                xmlns=\"http://www.w3.org/2000/svg\"\n              >\n                <defs>\n                  <!-- Blueprint Architectural Grid Pattern -->\n                  <pattern id=\"cad-grid-pattern\" width=\"20\" height=\"20\" patternUnits=\"userSpaceOnUse\">\n                    <path d=\"M 20 0 L 0 0 0 20\" fill=\"none\" class=\"stroke-muted-foreground/10\" stroke-width=\"0.75\" />\n                  </pattern>\n                  <pattern id=\"cad-grid-major\" width=\"100\" height=\"100\" patternUnits=\"userSpaceOnUse\">\n                    <rect width=\"100\" height=\"100\" fill=\"url(#cad-grid-pattern)\" />\n                    <path d=\"M 100 0 L 0 0 0 100\" fill=\"none\" class=\"stroke-muted-foreground/20\" stroke-width=\"1.25\" />\n                  </pattern>\n                  <!-- Balcony / Terrace Wood Decking Pattern -->\n                  <pattern\n                    id=\"deck-slats\"\n                    width=\"8\"\n                    height=\"8\"\n                    patternUnits=\"userSpaceOnUse\"\n                    patternTransform=\"rotate(45)\"\n                  >\n                    <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"8\" class=\"stroke-muted-foreground/25\" stroke-width=\"1.5\" />\n                  </pattern>\n                </defs>\n\n                <!-- Blueprint Grid Background -->\n                <rect width=\"680\" height=\"430\" fill=\"url(#cad-grid-major)\" />\n\n                <!-- North Arrow Compass Widget -->\n                <g transform=\"translate(635, 38)\" class=\"text-muted-foreground\">\n                  <circle cx=\"0\" cy=\"0\" r=\"18\" fill=\"none\" class=\"stroke-border\" stroke-width=\"1.2\" />\n                  <path d=\"M 0 -13 L 4 4 L 0 1 L -4 4 Z\" class=\"fill-primary\" />\n                  <path d=\"M 0 1 L 4 4 L 0 13 L -4 4 Z\" class=\"fill-muted-foreground/30\" />\n                  <text x=\"0\" y=\"-15\" text-anchor=\"middle\" class=\"fill-foreground font-mono text-xs font-bold\">N</text>\n                </g>\n\n                <!-- Scale Indicator Bar -->\n                <g transform=\"translate(25, 412)\" class=\"text-muted-foreground\">\n                  <line x1=\"0\" y1=\"0\" x2=\"100\" y2=\"0\" class=\"stroke-foreground\" stroke-width=\"2\" />\n                  <line x1=\"0\" y1=\"-4\" x2=\"0\" y2=\"4\" class=\"stroke-foreground\" stroke-width=\"2\" />\n                  <line x1=\"50\" y1=\"-3\" x2=\"50\" y2=\"3\" class=\"stroke-foreground\" stroke-width=\"1.5\" />\n                  <line x1=\"100\" y1=\"-4\" x2=\"100\" y2=\"4\" class=\"stroke-foreground\" stroke-width=\"2\" />\n                  <text x=\"0\" y=\"-7\" class=\"fill-muted-foreground font-mono text-xs\">0</text>\n                  <text x=\"46\" y=\"-7\" class=\"fill-muted-foreground font-mono text-xs\">10'</text>\n                  <text x=\"94\" y=\"-7\" class=\"fill-muted-foreground font-mono text-xs\">20'</text>\n                  <text x=\"115\" y=\"3\" class=\"fill-muted-foreground font-mono text-xs\">Scale 1/4\" = 1'0\"</text>\n                </g>\n\n                <!-- Architectural Rooms Layout Polygons -->\n                <g>\n                  @for (room of currentPlan().rooms; track room.id) {\n                    <g\n                      class=\"cursor-pointer transition-colors duration-200\"\n                      (mouseenter)=\"hoverRoom(room.id)\"\n                      (mouseleave)=\"hoverRoom(null)\"\n                      (click)=\"selectRoom(room.id)\"\n                    >\n                      <!-- Room Floor Fill -->\n                      <rect\n                        [attr.x]=\"room.rect.x\"\n                        [attr.y]=\"room.rect.y\"\n                        [attr.width]=\"room.rect.w\"\n                        [attr.height]=\"room.rect.h\"\n                        [attr.fill]=\"isTerrace(room.id) ? 'url(#deck-slats)' : 'currentColor'\"\n                        [class]=\"roomFillClass(room.id)\"\n                      />\n\n                      <!-- Room Border Perimeter -->\n                      <rect\n                        [attr.x]=\"room.rect.x\"\n                        [attr.y]=\"room.rect.y\"\n                        [attr.width]=\"room.rect.w\"\n                        [attr.height]=\"room.rect.h\"\n                        fill=\"none\"\n                        [class]=\"roomBorderClass(room.id)\"\n                      />\n\n                      <!-- Architectural Fixtures Silhouette Layer -->\n                      @if (showFurniture()) {\n                        <g class=\"stroke-muted-foreground/35 text-muted-foreground/20 pointer-events-none fill-none\">\n                          <!-- Living Room: Sofa & Coffee Table -->\n                          @if (room.id === 'living' || room.id === 'grand-salon') {\n                            <rect\n                              [attr.x]=\"room.rect.x + 24\"\n                              [attr.y]=\"room.rect.y + 24\"\n                              width=\"75\"\n                              height=\"40\"\n                              rx=\"4\"\n                              stroke-width=\"1.2\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                            <rect\n                              [attr.x]=\"room.rect.x + 38\"\n                              [attr.y]=\"room.rect.y + 72\"\n                              width=\"46\"\n                              height=\"24\"\n                              rx=\"2\"\n                              stroke-width=\"1.2\"\n                              class=\"stroke-muted-foreground/30\"\n                            />\n                            <line\n                              [attr.x1]=\"room.rect.x + 130\"\n                              [attr.y1]=\"room.rect.y + 20\"\n                              [attr.x2]=\"room.rect.x + 130\"\n                              [attr.y2]=\"room.rect.y + 110\"\n                              stroke-dasharray=\"3 3\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/20\"\n                            />\n                          }\n\n                          <!-- Bedroom: Bed Silhouette & Pillows -->\n                          @if (\n                            room.id === 'master-bed' ||\n                            room.id === 'guest-bed' ||\n                            room.id === 'primary-suite' ||\n                            room.id === 'bed-2'\n                          ) {\n                            <rect\n                              [attr.x]=\"room.rect.x + 20\"\n                              [attr.y]=\"room.rect.y + 25\"\n                              width=\"60\"\n                              height=\"75\"\n                              rx=\"3\"\n                              stroke-width=\"1.2\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                            <rect\n                              [attr.x]=\"room.rect.x + 26\"\n                              [attr.y]=\"room.rect.y + 30\"\n                              width=\"20\"\n                              height=\"14\"\n                              rx=\"2\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/30\"\n                            />\n                            <rect\n                              [attr.x]=\"room.rect.x + 54\"\n                              [attr.y]=\"room.rect.y + 30\"\n                              width=\"20\"\n                              height=\"14\"\n                              rx=\"2\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/30\"\n                            />\n                            <line\n                              [attr.x1]=\"room.rect.x + 20\"\n                              [attr.y1]=\"room.rect.y + 55\"\n                              [attr.x2]=\"room.rect.x + 80\"\n                              [attr.y2]=\"room.rect.y + 55\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/20\"\n                            />\n                          }\n\n                          <!-- Kitchen: Island & Cooktop / Prep Sink -->\n                          @if (room.id === 'kitchen') {\n                            <rect\n                              [attr.x]=\"room.rect.x + 18\"\n                              [attr.y]=\"room.rect.y + 20\"\n                              width=\"85\"\n                              height=\"36\"\n                              rx=\"2\"\n                              stroke-width=\"1.2\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                            <circle\n                              [attr.cx]=\"room.rect.x + 38\"\n                              [attr.cy]=\"room.rect.y + 38\"\n                              r=\"6\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                            <circle\n                              [attr.cx]=\"room.rect.x + 56\"\n                              [attr.cy]=\"room.rect.y + 38\"\n                              r=\"6\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                            <rect\n                              [attr.x]=\"room.rect.x + 72\"\n                              [attr.y]=\"room.rect.y + 30\"\n                              width=\"18\"\n                              height=\"16\"\n                              rx=\"1\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/30\"\n                            />\n                          }\n\n                          <!-- Bathrooms: Tub / Shower & Vanity -->\n                          @if (room.id === 'master-bath' || room.id === 'guest-bath' || room.id === 'spa-bath') {\n                            <rect\n                              [attr.x]=\"room.rect.x + 12\"\n                              [attr.y]=\"room.rect.y + 15\"\n                              width=\"38\"\n                              height=\"50\"\n                              rx=\"6\"\n                              stroke-width=\"1.2\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                            <circle\n                              [attr.cx]=\"room.rect.x + 31\"\n                              [attr.cy]=\"room.rect.y + 40\"\n                              r=\"3\"\n                              stroke-width=\"1\"\n                              class=\"stroke-muted-foreground/40\"\n                            />\n                          }\n\n                          <!-- Balcony: Railing Post Accents -->\n                          @if (room.id === 'balcony' || room.id === 'sky-terrace') {\n                            <line\n                              [attr.x1]=\"room.rect.x\"\n                              [attr.y1]=\"room.rect.y\"\n                              [attr.x2]=\"room.rect.x\"\n                              [attr.y2]=\"room.rect.y + room.rect.h\"\n                              stroke-width=\"3\"\n                              class=\"stroke-primary/50\"\n                            />\n                          }\n                        </g>\n                      }\n\n                      <!-- Dimension Leader Line Callouts -->\n                      @if (showDimensions()) {\n                        <g class=\"pointer-events-none select-none\">\n                          <!-- Room Dimension Text -->\n                          <text\n                            [attr.x]=\"room.pinX\"\n                            [attr.y]=\"room.pinY + 16\"\n                            text-anchor=\"middle\"\n                            class=\"fill-muted-foreground font-mono text-xs font-medium\"\n                          >\n                            {{ unitSystem() === 'imperial' ? room.dimensionsImperial : room.dimensionsMetric }}\n                          </text>\n                        </g>\n                      }\n                    </g>\n                  }\n                </g>\n\n                <!-- Outer Perimeter Heavy Structural Walls -->\n                <g class=\"pointer-events-none\">\n                  <!-- Windows with Glass Double Thin Lines -->\n                  <line\n                    x1=\"160\"\n                    y1=\"75\"\n                    x2=\"380\"\n                    y2=\"75\"\n                    class=\"stroke-sky-400 dark:stroke-sky-300\"\n                    stroke-width=\"2.5\"\n                  />\n                  <line\n                    x1=\"390\"\n                    y1=\"75\"\n                    x2=\"540\"\n                    y2=\"75\"\n                    class=\"stroke-sky-400 dark:stroke-sky-300\"\n                    stroke-width=\"2.5\"\n                  />\n                  <line\n                    x1=\"550\"\n                    y1=\"75\"\n                    x2=\"635\"\n                    y2=\"75\"\n                    class=\"stroke-sky-400 dark:stroke-sky-300\"\n                    stroke-width=\"2.5\"\n                  />\n                </g>\n\n                <!-- Interactive Room Highlight Pins -->\n                @if (showPins()) {\n                  <g>\n                    @for (room of currentPlan().rooms; track 'pin-' + room.id) {\n                      <g\n                        [attr.transform]=\"'translate(' + room.pinX + ', ' + (room.pinY - 8) + ')'\"\n                        class=\"cursor-pointer transition-transform duration-150\"\n                        (mouseenter)=\"hoverRoom(room.id)\"\n                        (mouseleave)=\"hoverRoom(null)\"\n                        (click)=\"selectRoom(room.id)\"\n                      >\n                        <!-- Pulsing Halo on Selected -->\n                        @if (selectedRoomId() === room.id || hoveredRoomId() === room.id) {\n                          <circle cx=\"0\" cy=\"0\" r=\"16\" class=\"fill-primary/30\" />\n                        }\n\n                        <!-- Pin Badge Background Pill -->\n                        <rect x=\"-48\" y=\"-12\" width=\"96\" height=\"24\" rx=\"12\" [class]=\"pinBadgeClass(room.id)\" />\n\n                        <!-- Pin Label Text -->\n                        <text x=\"0\" y=\"4\" text-anchor=\"middle\" [class]=\"pinLabelClass(room.id)\">\n                          {{ room.shortLabel }}\n                        </text>\n                      </g>\n                    }\n                  </g>\n                }\n              </svg>\n            </div>\n\n            <!-- Canvas Footer Status / Active Room Info -->\n            <div class=\"border-border bg-muted/20 flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3\">\n              <div class=\"flex items-center gap-2\">\n                <span ui-badge variant=\"outline\" class=\"gap-1 font-mono text-xs font-normal\">\n                  <lucide-icon [img]=\"Home\" class=\"text-primary size-3\" />\n                  Active Focus: {{ activeRoom()?.name || 'Overview' }}\n                </span>\n                <span class=\"text-muted-foreground text-xs\">\n                  {{\n                    unitSystem() === 'imperial' ? activeRoom()?.dimensionsImperial : activeRoom()?.dimensionsMetric\n                  }}\n                  ·\n                  <span class=\"text-foreground font-mono font-medium tabular-nums\">\n                    {{\n                      unitSystem() === 'imperial' ? activeRoom()?.areaSqFt + ' Sq Ft' : activeRoom()?.areaSqM + ' m²'\n                    }}\n                  </span>\n                </span>\n              </div>\n\n              <div class=\"text-muted-foreground flex items-center gap-2 text-xs\">\n                <span class=\"hidden sm:inline\">Finish:</span>\n                <span class=\"text-foreground font-medium\">{{ activeRoom()?.flooring }}</span>\n              </div>\n            </div>\n          </div>\n\n          <!-- Floor Plan Features / Highlights Strip -->\n          <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2 md:grid-cols-4\">\n            <div class=\"border-border bg-card rounded-lg border p-3 shadow-xs\">\n              <p class=\"text-muted-foreground text-xs\">Ceiling Height</p>\n              <p class=\"text-foreground mt-0.5 font-mono text-sm font-semibold tabular-nums\">\n                {{ currentPlan().ceilingHeight }}\n              </p>\n            </div>\n            <div class=\"border-border bg-card rounded-lg border p-3 shadow-xs\">\n              <p class=\"text-muted-foreground text-xs\">Outdoor Space</p>\n              <p class=\"text-foreground mt-0.5 font-mono text-sm font-semibold tabular-nums\">\n                {{\n                  unitSystem() === 'imperial'\n                    ? currentPlan().exteriorSqFt + ' Sq Ft'\n                    : (currentPlan().exteriorSqFt * 0.0929).toFixed(1) + ' m²'\n                }}\n              </p>\n            </div>\n            <div class=\"border-border bg-card rounded-lg border p-3 shadow-xs\">\n              <p class=\"text-muted-foreground text-xs\">Exposure</p>\n              <p class=\"text-foreground mt-0.5 text-xs font-medium\">{{ currentPlan().exposure }}</p>\n            </div>\n            <div class=\"border-border bg-card rounded-lg border p-3 shadow-xs\">\n              <p class=\"text-muted-foreground text-xs\">Starting Rent</p>\n              <p class=\"text-foreground mt-0.5 font-mono text-sm font-semibold tabular-nums\">\n                \\${{ currentPlan().startingRent.toLocaleString()\n                }}<span class=\"text-muted-foreground text-xs font-normal\">/mo</span>\n              </p>\n            </div>\n          </div>\n        </div>\n\n        <!-- Right Column: Unit Specs, Room Breakdown & Available Units Table (5 cols) -->\n        <div class=\"space-y-6 lg:col-span-5\">\n          <!-- Selected Plan Header Card with Total Area -->\n          <div ui-card class=\"border-border bg-card shadow-xs\">\n            <div ui-card-header class=\"pb-3\">\n              <div class=\"flex flex-wrap items-center justify-between\">\n                <span ui-badge variant=\"secondary\" class=\"font-mono text-xs\">\n                  {{ currentPlan().tier }}\n                </span>\n                <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n                  <lucide-icon [img]=\"Bed\" class=\"size-3.5\" />\n                  <span>{{ currentPlan().beds }} Bed</span>\n                  <span>·</span>\n                  <lucide-icon [img]=\"Bath\" class=\"size-3.5\" />\n                  <span>{{ currentPlan().baths }} Bath</span>\n                </div>\n              </div>\n              <h3 ui-card-title class=\"mt-1 text-lg font-semibold tracking-tight sm:text-xl\">\n                {{ currentPlan().marketingName }}\n              </h3>\n              <p ui-card-description class=\"text-xs leading-relaxed sm:text-sm\">\n                {{ currentPlan().description }}\n              </p>\n            </div>\n\n            <div ui-card-content class=\"space-y-4\">\n              <!-- Total Area Hero Metric Box -->\n              <div class=\"border-border bg-muted/40 rounded-lg border p-4\">\n                <p class=\"text-muted-foreground text-xs font-medium\">Total Architectural Living Area</p>\n                <div class=\"mt-1 flex items-baseline gap-2\">\n                  <span class=\"text-foreground font-mono text-2xl font-bold tracking-tight tabular-nums sm:text-3xl\">\n                    {{ currentPlan().totalAreaSqFt.toLocaleString() }}\n                  </span>\n                  <span class=\"text-muted-foreground text-sm font-medium\">Sq Ft</span>\n                  <span class=\"text-muted-foreground/60\">/</span>\n                  <span class=\"text-muted-foreground font-mono text-lg font-semibold tabular-nums\">\n                    {{ currentPlan().totalAreaSqM.toFixed(1) }}\n                  </span>\n                  <span class=\"text-muted-foreground text-xs font-medium\">m²</span>\n                </div>\n                <div\n                  class=\"border-border/60 text-muted-foreground mt-2 flex flex-wrap items-center justify-between border-t pt-2 text-xs\"\n                >\n                  <span>\n                    Interior:\n                    <strong class=\"text-foreground font-mono tabular-nums\"\n                      >{{ currentPlan().interiorSqFt }} sq ft</strong\n                    >\n                  </span>\n                  <span>\n                    Terrace:\n                    <strong class=\"text-foreground font-mono tabular-nums\"\n                      >{{ currentPlan().exteriorSqFt }} sq ft</strong\n                    >\n                  </span>\n                </div>\n              </div>\n\n              <!-- Room Breakdown List with Interactive Highlights -->\n              <div>\n                <div class=\"mb-2 flex flex-wrap items-center justify-between\">\n                  <h4 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                    Room Breakdown & Dimensions\n                  </h4>\n                  <span class=\"text-muted-foreground text-xs\">{{ currentPlan().rooms.length }} Spaces</span>\n                </div>\n\n                <div class=\"space-y-1.5\">\n                  @for (room of currentPlan().rooms; track room.id) {\n                    <div\n                      [class]=\"roomRowClass(room.id)\"\n                      (mouseenter)=\"hoverRoom(room.id)\"\n                      (mouseleave)=\"hoverRoom(null)\"\n                      (click)=\"selectRoom(room.id)\"\n                    >\n                      <div class=\"flex min-w-0 items-center gap-2\">\n                        <span [class]=\"roomDotClass(room.id)\"></span>\n                        <div>\n                          <p class=\"text-foreground text-xs font-medium\">{{ room.name }}</p>\n                          <p class=\"text-muted-foreground text-xs\">{{ room.flooring }}</p>\n                        </div>\n                      </div>\n\n                      <div class=\"shrink-0 text-right\">\n                        <p class=\"text-foreground font-mono text-xs font-semibold tabular-nums\">\n                          {{ unitSystem() === 'imperial' ? room.dimensionsImperial : room.dimensionsMetric }}\n                        </p>\n                        <p class=\"text-muted-foreground font-mono text-xs tabular-nums\">\n                          {{ unitSystem() === 'imperial' ? room.areaSqFt + ' sq ft' : room.areaSqM + ' m²' }}\n                        </p>\n                      </div>\n                    </div>\n                  }\n                </div>\n              </div>\n            </div>\n          </div>\n\n          <!-- Available Units in Building Table -->\n          <div ui-card class=\"border-border bg-card shadow-xs\">\n            <div ui-card-header class=\"pb-3\">\n              <div class=\"flex flex-wrap items-center justify-between\">\n                <div>\n                  <h3 ui-card-title class=\"text-sm font-semibold tracking-tight sm:text-base\">\n                    Available Units in Building\n                  </h3>\n                  <p ui-card-description class=\"text-xs\">\n                    Real-time occupancy and lease rates for {{ currentPlan().tabLabel }}\n                  </p>\n                </div>\n                <span ui-badge variant=\"outline\" class=\"font-mono text-xs\"> {{ availableCount() }} Available </span>\n              </div>\n            </div>\n\n            <div ui-card-content class=\"p-0\">\n              <div class=\"overflow-x-auto\">\n                <table ui-table>\n                  <thead ui-table-header>\n                    <tr ui-table-row class=\"hover:bg-transparent\">\n                      <th ui-table-head class=\"w-[80px] text-xs font-medium\">Unit</th>\n                      <th ui-table-head class=\"text-xs font-medium\">Floor & View</th>\n                      <th ui-table-head class=\"text-right text-xs font-medium\">Monthly Rent</th>\n                      <th ui-table-head class=\"text-right text-xs font-medium\">Status</th>\n                    </tr>\n                  </thead>\n                  <tbody ui-table-body>\n                    @for (unit of currentPlan().availableUnits; track unit.unitNumber) {\n                      <tr ui-table-row [class]=\"unitRowClass(unit.unitNumber)\" (click)=\"selectUnit(unit.unitNumber)\">\n                        <td ui-table-cell class=\"text-foreground font-mono font-semibold tabular-nums\">\n                          Unit {{ unit.unitNumber }}\n                        </td>\n                        <td ui-table-cell>\n                          <div class=\"text-foreground text-xs\">{{ unit.view }}</div>\n                          <div class=\"text-muted-foreground text-xs\">Floor {{ unit.floor }} · {{ unit.exposure }}</div>\n                        </td>\n                        <td ui-table-cell class=\"text-foreground text-right font-mono font-semibold tabular-nums\">\n                          \\${{ unit.monthlyRent.toLocaleString() }}\n                          <span class=\"text-muted-foreground font-normal\">/mo</span>\n                        </td>\n                        <td ui-table-cell class=\"text-right\">\n                          <span\n                            ui-badge\n                            [variant]=\"unit.status === 'leased' ? 'secondary' : 'default'\"\n                            [class]=\"unitStatusClass(unit.status)\"\n                          >\n                            {{ unit.statusLabel }}\n                          </span>\n                        </td>\n                      </tr>\n                    }\n                  </tbody>\n                </table>\n              </div>\n            </div>\n\n            <div ui-card-footer class=\"border-border flex flex-col gap-2.5 border-t pt-4\">\n              <div class=\"flex w-full flex-col gap-2 sm:flex-row\">\n                <button ui-button class=\"w-full gap-2 text-xs sm:flex-1\" (click)=\"scheduleTour()\">\n                  <lucide-icon [img]=\"Calendar\" class=\"size-3.5\" />\n                  <span>Schedule Private Showing</span>\n                </button>\n                <button ui-button variant=\"outline\" class=\"w-full gap-2 text-xs sm:flex-1\" (click)=\"scheduleTour()\">\n                  <lucide-icon [img]=\"FileText\" class=\"size-3.5\" />\n                  <span>Apply for Unit</span>\n                </button>\n              </div>\n\n              @if (showTourSuccess()) {\n                <div class=\"bg-success/10 text-success flex w-full items-center gap-2 rounded-md p-2.5 text-xs\">\n                  <lucide-icon [img]=\"CheckCircle2\" class=\"size-4 shrink-0\" />\n                  <span>\n                    Tour request received for Unit {{ selectedUnitNumber() }}. Leasing agent will contact you within 15\n                    minutes.\n                  </span>\n                </div>\n              }\n\n              <p class=\"text-muted-foreground text-center text-xs\">\n                Self-guided tours and agent-accompanied showings available daily 9:00 AM – 7:00 PM.\n              </p>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiFloorPlanExplorerComponent {\n  protected readonly Bath = Bath\n  protected readonly Bed = Bed\n  protected readonly Building2 = Building2\n  protected readonly Calendar = Calendar\n  protected readonly Check = Check\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Download = Download\n  protected readonly FileText = FileText\n  protected readonly Home = Home\n  protected readonly Layers = Layers\n  protected readonly MapPin = MapPin\n  protected readonly Ruler = Ruler\n\n  protected readonly planList = planKeys.map((key) => floorPlans[key]!)\n\n  @Input() set initialPlan(plan: string) {\n    if (plan && floorPlans[plan]) this.selectTab(plan)\n  }\n  @Input() set initialUnitSystem(system: 'imperial' | 'metric') {\n    if (system === 'imperial' || system === 'metric') this.unitSystem.set(system)\n  }\n  @Input('class') className?: string\n\n  readonly activeTab = signal('plan-b')\n  readonly selectedRoomId = signal<string | null>('living')\n  readonly hoveredRoomId = signal<string | null>(null)\n  readonly selectedUnitNumber = signal('402')\n  readonly showDimensions = signal(true)\n  readonly showFurniture = signal(true)\n  readonly showPins = signal(true)\n  readonly unitSystem = signal<'imperial' | 'metric'>('imperial')\n  readonly isDownloadingPdf = signal(false)\n  readonly downloadSuccess = signal(false)\n  readonly showTourSuccess = signal(false)\n\n  private timers: ReturnType<typeof setTimeout>[] = []\n\n  constructor() {\n    inject(DestroyRef).onDestroy(() => this.timers.forEach((t) => clearTimeout(t)))\n  }\n\n  readonly currentPlan = computed(() => floorPlans[this.activeTab()] ?? floorPlans['plan-b']!)\n\n  readonly activeRoom = computed<RoomSpec | null>(() => {\n    const plan = this.currentPlan()\n    const hovered = this.hoveredRoomId()\n    if (hovered) return plan.rooms.find((r) => r.id === hovered) ?? null\n    const selected = this.selectedRoomId()\n    if (selected) return plan.rooms.find((r) => r.id === selected) ?? null\n    return plan.rooms[0] ?? null\n  })\n\n  readonly availableCount = computed(\n    () => this.currentPlan().availableUnits.filter((u) => u.status !== 'leased').length,\n  )\n\n  readonly downloadLabel = computed(() =>\n    this.isDownloadingPdf()\n      ? 'Generating PDF...'\n      : this.downloadSuccess()\n        ? 'PDF Downloaded'\n        : 'Download PDF Floor Plan',\n  )\n\n  get rootClass(): string {\n    return cn('bg-background text-foreground w-full space-y-6', this.className)\n  }\n\n  selectTab(key: string): void {\n    this.activeTab.set(key)\n    const plan = floorPlans[key]\n    if (plan) {\n      this.selectedRoomId.set(plan.rooms[0]?.id ?? null)\n      this.hoveredRoomId.set(null)\n      this.selectedUnitNumber.set(plan.availableUnits[0]?.unitNumber ?? '')\n    }\n  }\n\n  selectRoom(roomId: string): void {\n    this.selectedRoomId.update((prev) => (prev === roomId ? null : roomId))\n  }\n\n  hoverRoom(roomId: string | null): void {\n    this.hoveredRoomId.set(roomId)\n  }\n\n  selectUnit(unitNumber: string): void {\n    this.selectedUnitNumber.set(unitNumber)\n  }\n\n  isTerrace(roomId: string): boolean {\n    return roomId === 'balcony' || roomId === 'sky-terrace'\n  }\n\n  unitToggleClass(system: 'imperial' | 'metric'): string {\n    return cn(\n      'focus-visible:ring-ring rounded px-2.5 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none',\n      this.unitSystem() === system\n        ? 'bg-background text-foreground shadow-xs'\n        : 'text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  canvasToggleClass(active: boolean): string {\n    return cn('h-7 gap-1 px-2 text-xs', active && 'bg-muted text-foreground')\n  }\n\n  roomFillClass(roomId: string): string {\n    return cn(\n      'transition-colors duration-150',\n      this.selectedRoomId() === roomId || this.hoveredRoomId() === roomId\n        ? 'text-primary/15'\n        : this.isTerrace(roomId)\n          ? 'text-muted/60'\n          : 'text-card',\n    )\n  }\n\n  roomBorderClass(roomId: string): string {\n    return cn(\n      'transition-colors duration-150',\n      this.selectedRoomId() === roomId\n        ? 'stroke-primary stroke-[2.5]'\n        : this.hoveredRoomId() === roomId\n          ? 'stroke-primary/70 stroke-[2]'\n          : 'stroke-border/90 stroke-[1.5]',\n    )\n  }\n\n  roomRowClass(roomId: string): string {\n    return cn(\n      'flex cursor-pointer items-center justify-between rounded-md border p-2.5 transition-colors duration-150',\n      this.selectedRoomId() === roomId\n        ? 'border-primary bg-primary/5 shadow-xs'\n        : this.hoveredRoomId() === roomId\n          ? 'border-border bg-muted/60'\n          : 'border-border/60 bg-card hover:bg-muted/30',\n    )\n  }\n\n  roomDotClass(roomId: string): string {\n    return cn(\n      'size-2 rounded-full transition-colors',\n      this.selectedRoomId() === roomId\n        ? 'bg-primary'\n        : this.hoveredRoomId() === roomId\n          ? 'bg-primary/70'\n          : 'bg-muted-foreground/40',\n    )\n  }\n\n  pinBadgeClass(roomId: string): string {\n    return cn(\n      'transition-colors duration-150',\n      this.selectedRoomId() === roomId\n        ? 'fill-primary stroke-primary-foreground stroke-1 shadow-md'\n        : this.hoveredRoomId() === roomId\n          ? 'fill-foreground stroke-background stroke-1'\n          : 'fill-card/90 stroke-border stroke-1 shadow-xs backdrop-blur-xs',\n    )\n  }\n\n  pinLabelClass(roomId: string): string {\n    return cn(\n      'font-mono text-xs font-semibold select-none',\n      this.selectedRoomId() === roomId\n        ? 'fill-primary-foreground'\n        : this.hoveredRoomId() === roomId\n          ? 'fill-background'\n          : 'fill-foreground',\n    )\n  }\n\n  unitRowClass(unitNumber: string): string {\n    return cn(\n      'cursor-pointer text-xs transition-colors',\n      this.selectedUnitNumber() === unitNumber ? 'bg-muted/80 font-medium' : 'hover:bg-muted/40',\n    )\n  }\n\n  unitStatusClass(status: AvailableUnit['status']): string {\n    switch (status) {\n      case 'available-now':\n        return 'border-success/20 bg-success/10 text-success text-xs font-normal'\n      case 'available-soon':\n        return 'border-info/20 bg-info/10 text-info text-xs font-normal'\n      case 'under-contract':\n        return 'border-warning/20 bg-warning/10 text-warning text-xs font-normal'\n      default:\n        return 'text-muted-foreground text-xs font-normal'\n    }\n  }\n\n  downloadPdf(): void {\n    if (this.isDownloadingPdf()) return\n    this.isDownloadingPdf.set(true)\n    this.downloadSuccess.set(false)\n    this.timers.push(\n      setTimeout(() => {\n        this.isDownloadingPdf.set(false)\n        this.downloadSuccess.set(true)\n        this.timers.push(setTimeout(() => this.downloadSuccess.set(false), 4000))\n      }, 900),\n    )\n  }\n\n  scheduleTour(): void {\n    this.showTourSuccess.set(true)\n    this.timers.push(setTimeout(() => this.showTourSuccess.set(false), 4500))\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/floor-plan-explorer/floor-plan-explorer.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/floor-plan-explorer/index.ts",
      "content": "export {\n  UiFloorPlanExplorerComponent,\n  type AvailableUnit,\n  type FloorPlanData,\n  type RoomSpec,\n} from './floor-plan-explorer.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/floor-plan-explorer/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/table.json",
    "https://uipkge.dev/r/angular/tabs.json"
  ],
  "description": "Architectural unit floor plan inspector and residential layout explorer with 2D CAD-styled blueprint canvas, interactive room highlight pins, dimensional callouts, room breakdown specs, and building unit availability table.",
  "categories": [
    "real-estate",
    "app",
    "hospitality",
    "dashboard"
  ]
}