{
  "version": 3,
  "sources": ["/cdn/shop/t/2/assets/aspect-configurator-3d.js?cb=20251203v3"],
  "sourcesContent": ["/**\n * Product Configurator 3D Viewer\n * Reusable 3D viewer wrapper for step-by-step configurator.\n * Works with any product that has 3D model configuration.\n */\nimport { SceneManager } from './SceneManager.js';\nimport { ModelLoader } from './ModelLoader.js';\nimport { MaterialManager } from './MaterialManager.js';\nimport { CameraControls } from './CameraControls.js';\n\n/** Extract mesh groups array from various formats */\nconst getMeshGroups = (mg) => {\n  if (!mg) return [];\n  if (Array.isArray(mg)) return mg;\n  if (mg.enabled) return mg.enabled;\n  return [];\n};\n\n/** Extract disabled mesh groups */\nconst getDisabledMeshGroups = (mg) => mg?.disabled || [];\n\nclass ProductConfigurator3D {\n  static DEFAULT_TEXTURE_BASE_URL = 'https://cdn.shopify.com/s/files/1/0969/5304/1190/files/';\n  static DEFAULT_FLOOR_TEXTURES = [\n    'ashlar-oak', 'sandcastle-oak', 'fawn-chestnut', 'knotted-chestnut',\n    'natural-hickory', 'fumed-hickory', 'ice-fog', 'stone-grey', 'gothic-arch'\n  ];\n\n  // Siding texture configurations\n  static SIDING_CONFIGS = {\n    'lap': {\n      hasTexture: true,\n      textureUrl: 'https://cdn.shopify.com/s/files/1/0969/5304/1190/files/base_lap.png',\n      textureScale: { uScale: 1, vScale: 0.142 },\n      usesSidingColor: true\n    },\n    'cedar-plank': {\n      hasTexture: true,\n      textureUrl: 'https://cdn.shopify.com/s/files/1/0969/5304/1190/files/cedar-plank.jpg',\n      textureScale: { uScale: 0.0075, vScale: 0.05 },\n      usesSidingColor: false,\n      baseColor: '#FFFFFF'\n    },\n    'cedar-shake': {\n      hasTexture: true,\n      textureUrl: 'https://cdn.shopify.com/s/files/1/0969/5304/1190/files/cedar-shake.jpg?v=1764337343',\n      textureScale: { uScale: 0.05, vScale: 0.035 },\n      usesSidingColor: false,\n      baseColor: '#FFFFFF'\n    },\n    'block': { hasTexture: false, usesSidingColor: true },\n    'plank': { hasTexture: false, usesSidingColor: true }\n  };\n\n  // Mesh patterns for siding and accent\n  static SIDING_MESH_GROUPS = [\n    'wood_texture', 'wood_texture_metal',\n    'plank_siding', 'plank_siding_metal',\n    'plank_siding_color', 'plank_siding_metal_color',\n    'block_siding_color', 'block_siding_metal_color',\n    'siding', 'siding_color', 'exterior_siding'\n  ];\n\n  static ACCENT_MESH_GROUPS = [\n    'accent_color', 'accent_siding', 'accent',\n    'siding_accent', 'exterior_accent'\n  ];\n\n  constructor(container, configData) {\n    if (!container) {\n      throw new Error('ProductConfigurator3D: Container element is required');\n    }\n    \n    this.container = container;\n    this.configData = configData || {};\n    this.sceneManager = null;\n    this.modelLoader = null;\n    this.materialManager = null;\n    this.cameraControls = null;\n    this.currentOrientation = 'left';\n    this.currentStep = 1;\n    this.isInitialized = false;\n    this.isLoading = false;\n    this.currentLayout = configData?.defaultConfiguration?.layout || 'more-living';\n    this.currentFloorConfig = null;\n    this.floorMeshCache = {};\n    \n    // Track current roof type\n    this.currentRoofType = configData?.defaultConfiguration?.roof || 'standard';\n    \n    // Track current siding state\n    this.currentSidingType = configData?.defaultConfiguration?.siding || \n                             configData?.defaultConfiguration?.sidingType || 'lap';\n    this.currentSidingColor = configData?.defaultConfiguration?.sidingColor || 'iron-gray';\n    this.currentSidingHex = '#525654';\n    \n    // Track accent color state\n    this.currentAccentColor = configData?.defaultConfiguration?.['sidingColor.accent'] ||\n                              configData?.defaultConfiguration?.accentColor || 'iron-gray';\n    this.currentAccentHex = '#525654';\n    \n    // Build texture fallbacks map\n    this.textureFallbacks = this._buildTextureFallbacks();\n  }\n\n  _buildTextureFallbacks() {\n    const fallbacks = {};\n    const baseUrl = this.configData?.textureBaseUrl || ProductConfigurator3D.DEFAULT_TEXTURE_BASE_URL;\n    const textures = this.configData?.textureFallbacks || ProductConfigurator3D.DEFAULT_FLOOR_TEXTURES;\n    \n    textures.forEach(texture => {\n      if (typeof texture === 'string') {\n        fallbacks[texture] = `${baseUrl}${texture}.jpg`;\n      } else if (texture.name && texture.url) {\n        fallbacks[texture.name] = texture.url;\n      }\n    });\n    \n    return fallbacks;\n  }\n\n  init() {\n    if (this.isInitialized) return this;\n    if (!this.container) {\n      console.error('ProductConfigurator3D: Cannot initialize without container');\n      return this;\n    }\n\n    try {\n      this.sceneManager = new SceneManager(this.container);\n      \n      // Aspect-specific: Adjust camera near/far planes to reduce z-fighting (shimmering)\n      // on mobile Safari when viewing from above. The default 1:5000 ratio causes\n      // depth buffer precision issues on mobile devices.\n      const camera = this.sceneManager.getCamera();\n      if (camera) {\n        camera.near = 10;   // Increased from 1 - better depth precision\n        camera.far = 1500;  // Decreased from 5000 - tighter range for Aspect model size\n        camera.updateProjectionMatrix();\n      }\n      \n      this.modelLoader = new ModelLoader(this.sceneManager, this.configData);\n      this.materialManager = new MaterialManager(this.modelLoader, this.configData, this.sceneManager);\n      this.cameraControls = new CameraControls(this.sceneManager);\n      this.isInitialized = true;\n    } catch (error) {\n      console.error('Failed to initialize 3D viewer:', error);\n      this.isInitialized = false;\n      this._dispatchError('initialization', error);\n    }\n    \n    return this;\n  }\n\n  _dispatchError(type, error) {\n    this.container?.dispatchEvent(new CustomEvent('configurator:error', {\n      detail: { type, error: error.message || error, timestamp: Date.now() }\n    }));\n  }\n\n  async loadModel(orientation = 'left') {\n    if (!this.isInitialized || this.isLoading) return;\n\n    this.isLoading = true;\n    this.currentOrientation = orientation;\n\n    try {\n      const modelKey = this.configData.models ? Object.keys(this.configData.models)[0] : 'aspect-1';\n      \n      this.modelLoader.clearModels();\n      this.floorMeshCache = {};\n      \n      await this.modelLoader.loadModel(modelKey, orientation);\n\n      // Load roof\n      const roofType = this.currentRoofType || this.configData.defaultConfiguration?.roof || 'standard';\n      const isExtendedRoof = roofType === '4-front-eaves' || roofType === 'extended';\n      try {\n        await this.modelLoader.loadRoof(modelKey, orientation, isExtendedRoof);\n      } catch (e) { /* Roof loading is optional */ }\n\n      // Initialize materials\n      try {\n        await this.materialManager.initializeDefaultMaterials();\n      } catch (e) { /* Continue without default materials */ }\n\n      // Apply default siding texture and accent color\n      try {\n        await this._applyDefaultSidingTexture();\n      } catch (e) { /* Continue without siding texture */ }\n\n      this.setViewForStep(this.currentStep);\n      this._onModelLoaded(orientation);\n    } catch (error) {\n      console.error('Error loading model:', error);\n      this._dispatchError('loading', error);\n    } finally {\n      this.isLoading = false;\n    }\n  }\n\n  setViewForStep(step) {\n    this.currentStep = step;\n    const isTopDown = step === 1;\n    \n    this.modelLoader.setRoofVisible(!isTopDown);\n    \n    if (isTopDown) {\n      this.cameraControls.setTopDownView().catch(() => {});\n    } else {\n      this.cameraControls.setFrontView().catch(() => {});\n    }\n  }\n\n  focusOnMeshGroups(meshGroups, animate = true) {\n    if (!meshGroups?.length) return;\n    \n    const meshes = meshGroups.flatMap(group => this.modelLoader?.getMeshesByGroup(group) || []);\n    if (meshes.length && this.sceneManager?.focusOnMeshes) {\n      this.sceneManager.focusOnMeshes(meshes, animate);\n    }\n  }\n\n  updateConfiguration(config) {\n    if (!this.isInitialized) return;\n\n    const sectionBase = config.section?.includes('.') ? config.section.split('.')[0] : config.section;\n\n    // Handle orientation change\n    if (sectionBase === 'orientation') {\n      if (config.value && config.value !== this.currentOrientation && !this.isLoading) {\n        this.container.dispatchEvent(new CustomEvent('configurator:modelLoading', { detail: { orientation: config.value } }));\n        this.loadModel(config.value);\n      }\n      return;\n    }\n\n    // Route to handlers\n    const handlers = {\n      layout: () => this._handleVisibilityChange(config),\n      kitchen: () => this._handleVisibilityChange(config),\n      exterior: () => this._handleVisibilityChange(config),\n      elevations: () => this._handleVisibilityChange(config),\n      siding: () => this._handleSidingTypeChange(config),\n      sidingOptions: () => this._handleSidingTypeChange(config),\n      sidingType: () => this._handleSidingTypeChange(config),\n      sidingColor: () => this._handleColorChange(config),\n      'sidingColor.main': () => this._handleColorChange(config),\n      'sidingColor.accent': () => this._handleAccentColorChange(config),\n      accentColor: () => this._handleAccentColorChange(config),\n      trimColor: () => this._handleColorChange(config),\n      doorColor: () => this._handleColorChange(config),\n      soffitColor: () => this._handleColorChange(config),\n      fasciaColor: () => this._handleColorChange(config),\n      eavesColor: () => this._handleColorChange(config),\n      mainFloorFinish: () => this._handleFloorFinishChange(config),\n      flooring: () => this._handleFloorFinishChange(config),\n      'flooring.main': () => this._handleFloorFinishChange(config),\n      bathFloorFinish: () => this._handleTextureChange(config),\n      'flooring.bath': () => this._handleTextureChange(config),\n      fixtureFinish: () => this._handleMetalFinishChange(config),\n      'finishes.fixture': () => this._handleMetalFinishChange(config),\n      counterFinish: () => this._handleTextureChange(config),\n      countertop: () => this._handleTextureChange(config),\n      'finishes.countertop': () => this._handleTextureChange(config),\n      cabinetFinish: () => this._handleCabinetChange(config),\n      cabinets: () => this._handleCabinetChange(config),\n      'finishes.cabinets': () => this._handleCabinetChange(config),\n      roof: () => this._handleRoofChange(config),\n      roofEaves: () => this._handleRoofChange(config)\n    };\n\n    const handler = handlers[sectionBase] || handlers[config.section];\n    if (handler) {\n      handler();\n    } else {\n      this._handleGenericChange(config);\n    }\n\n    this._onConfigChange({ key: config.section, value: config.value });\n  }\n\n  // ============================================================================\n  // INTERNAL HANDLERS\n  // ============================================================================\n\n  _handleVisibilityChange(config) {\n    const selectedOption = config.allOptions?.find(opt => opt.value === config.value);\n\n    if (selectedOption?.meshGroups?.disabled) {\n      selectedOption.meshGroups.disabled.forEach(group => {\n        this.modelLoader.setGroupVisibility(group, false);\n      });\n    } else if (config.allOptions) {\n      config.allOptions.forEach(option => {\n        if (option.value !== config.value) {\n          getMeshGroups(option.meshGroups).forEach(group => {\n            this.modelLoader.setGroupVisibility(group, false);\n          });\n        }\n      });\n    }\n\n    let groupsToShow = selectedOption?.meshGroups?.enabled || getMeshGroups(config.meshGroups);\n\n    // Layout-aware exterior switching: when exterior groups contain layout-specific\n    // variants (e.g., \"b_more_glass_more_living\" and \"b_more_glass_more_storage\"),\n    // only enable the variant matching the current layout. This mirrors the Bliss/Harp\n    // behavior that checked which layout was active before enabling exterior meshes.\n    if (config.section === 'exterior' && this.currentLayout && groupsToShow.length > 1) {\n      const layoutFiltered = groupsToShow.filter(g => {\n        const gLower = g.toLowerCase();\n        if (gLower.includes('more_living') || gLower.includes('more_storage')) {\n          return gLower.includes(this.currentLayout.replace(/-/g, '_'));\n        }\n        return true; // non-layout-specific groups (like c_most_glass) always show\n      });\n      if (layoutFiltered.length > 0) {\n        // Also explicitly hide the non-matching layout variants\n        groupsToShow.forEach(g => {\n          if (!layoutFiltered.includes(g)) {\n            this.modelLoader.setGroupVisibility(g, false);\n          }\n        });\n        groupsToShow = layoutFiltered;\n      }\n    }\n\n    groupsToShow.forEach(group => {\n      this.modelLoader.setGroupVisibility(group, true);\n    });\n\n    if (config.section === 'layout') {\n      this.currentLayout = config.value || this.currentLayout;\n      this.floorMeshCache = {};\n\n      if (this.currentFloorConfig) {\n        this._applyFloorTexture(this.currentFloorConfig);\n      }\n    }\n  }\n\n  _handleColorChange(config) {\n    const sectionBase = config.section?.includes('.') ? config.section.split('.')[0] : config.section;\n    \n    if (sectionBase === 'sidingColor') {\n      this.currentSidingColor = config.value;\n      this.currentSidingHex = config.hex || this.currentSidingHex;\n      this._applySidingMaterial(this.currentSidingType, config.value, config.hex);\n      return;\n    }\n    \n    let meshGroups = getMeshGroups(config.meshGroups);\n    \n    // Comprehensive fallback mesh groups for roof colors\n    // The extended roof model may have different mesh naming than standard roof\n    // Always merge with fallbacks for soffit/fascia/eaves to ensure we find meshes\n    const fallbackMeshGroups = {\n      doorColor: ['door_color', 'door_slab', 'door'],\n      trimColor: ['trim_color', 'trim'],\n      fasciaColor: ['roof_fascia', 'fascia_color', 'fascia'],\n      soffitColor: ['roof_soffit', 'soffit_color', 'soffit', 'roof_eave', 'eave'],\n      eavesColor: ['roof_eave', 'eaves_color', 'eave', 'eaves']\n    };\n    \n    const sectionKey = config.section || sectionBase;\n    const fallbackForSection = fallbackMeshGroups[sectionKey] || fallbackMeshGroups[sectionBase];\n    \n    // For roof-related color options (soffit, fascia, eaves), always merge with fallbacks\n    // because the extended roof model may have different mesh naming conventions\n    if (fallbackForSection && ['fasciaColor', 'soffitColor', 'eavesColor'].includes(sectionKey)) {\n      // Merge: start with config meshGroups, add any fallback entries not already present\n      const mergedGroups = [...meshGroups];\n      fallbackForSection.forEach(group => {\n        if (!mergedGroups.includes(group)) {\n          mergedGroups.push(group);\n        }\n      });\n      meshGroups = mergedGroups;\n    } else if (meshGroups.length === 0 && fallbackForSection) {\n      // Standard fallback: only use if no meshGroups provided\n      meshGroups = fallbackForSection;\n    }\n    \n    // Safari fix: Try multiple sources for hex color\n    let hexColor = config.hex || config.rgb;\n    if (!hexColor && config.allOptions?.length > 0) {\n      const matchingOption = config.allOptions.find(o => o.value === config.value);\n      hexColor = matchingOption?.hex || matchingOption?.rgb;\n    }\n    \n    if (meshGroups.length && hexColor) {\n      this.materialManager.applyColorToGroups(meshGroups, hexColor);\n    }\n\n    // Window casement color \u2014 derived from trim color selection.\n    // Aspect is bronze-only.\n    if (sectionBase === 'trimColor') {\n      const WINDOW_CASEMENT_MAP = {\n        'studio-shed-bronze': '#202021',  // Ebony \u2014 near-black for bronze trim\n      };\n      const casementColor = WINDOW_CASEMENT_MAP[config.value];\n      if (casementColor && this.materialManager) {\n        this.materialManager.applyColorToGroups(['window_exterior'], casementColor, { roughness: 0.45, metalness: 0.35 });\n      }\n    }\n  }\n\n  _handleAccentColorChange(config) {\n    this.currentAccentColor = config.value;\n    this.currentAccentHex = config.hex || this.currentAccentHex;\n    this._applyAccentColor(config.hex);\n  }\n\n  _handleTextureChange(config) {\n    if (config.texture && config.meshGroups?.length) {\n      this.materialManager.applyTextureToGroups(config.meshGroups, config.texture, {\n        textureScale: config.textureScale\n      });\n    }\n  }\n\n  _handleMetalFinishChange(config) {\n    if (config.hex && config.meshGroups?.length) {\n      this.materialManager.applyColorToGroups(config.meshGroups, config.hex, {\n        metalness: config.metalness ?? 0.8,\n        roughness: config.roughness ?? 0.2\n      });\n    } else if (this.materialManager.applyFixtureFinish) {\n      this.materialManager.applyFixtureFinish(config.value);\n    }\n  }\n\n  _handleCabinetChange(config) {\n    if (config.hex && config.meshGroups?.length) {\n      this.materialManager.applyColorToGroups(config.meshGroups, config.hex);\n    } else if (config.texture && config.meshGroups?.length) {\n      this.materialManager.applyTextureToGroups(config.meshGroups, config.texture, {\n        textureScale: config.textureScale\n      });\n    } else if (this.materialManager.applyCabinetFinish) {\n      this.materialManager.applyCabinetFinish(config.value);\n    }\n  }\n\n  _handleSidingTypeChange(config) {\n    this.currentSidingType = config.value;\n    \n    let hexColor = this.currentSidingHex;\n    if (!hexColor || hexColor === '#525654') {\n      const sidingColorConfig = this.configData.configurationOptions?.sidingColor;\n      const colorOption = sidingColorConfig?.options?.find(opt => opt.value === this.currentSidingColor);\n      hexColor = colorOption?.hex || colorOption?.color?.hex || this.currentSidingHex || '#525654';\n    }\n\n    this._applySidingMaterial(config.value, this.currentSidingColor, hexColor);\n  }\n\n  _handleRoofChange(config) {\n    const newRoofType = config.value;\n    \n    if (newRoofType && newRoofType !== this.currentRoofType && !this.isLoading) {\n      this.currentRoofType = newRoofType;\n      this.container.dispatchEvent(new CustomEvent('configurator:modelLoading', { \n        detail: { roofType: newRoofType } \n      }));\n      this.loadModel(this.currentOrientation);\n    }\n  }\n\n  _handleFloorFinishChange(config) {\n    const textureUrl = this._getFloorTextureUrl(config.value, config.texture);\n    if (!textureUrl) {\n      if (this.materialManager.applyMainFloorFinish) {\n        this.materialManager.applyMainFloorFinish(config.value);\n      }\n      return;\n    }\n\n    this._applyFloorTextureToGroundPlane(textureUrl, config.textureScale);\n    this.currentFloorConfig = { ...config, texture: textureUrl };\n    this._applyFloorTexture(this.currentFloorConfig);\n  }\n\n  _handleGenericChange(config) {\n    const meshGroups = getMeshGroups(config.meshGroups);\n    const hasColor = config.hex || config.rgb;\n    const hasTexture = config.texture;\n\n    if (hasColor && meshGroups.length) {\n      this.materialManager.applyColorToGroups(meshGroups, config.hex || config.rgb);\n    } else if (hasTexture && meshGroups.length) {\n      this.materialManager.applyTextureToGroups(meshGroups, config.texture, { textureScale: config.textureScale });\n    } else if (meshGroups.length) {\n      meshGroups.forEach(group => this.modelLoader.setGroupVisibility(group, true));\n      \n      if (config.allOptions) {\n        config.allOptions.forEach(option => {\n          if (option.value !== config.value) {\n            [...getMeshGroups(option.meshGroups), ...getDisabledMeshGroups(option.meshGroups)]\n              .forEach(group => this.modelLoader.setGroupVisibility(group, false));\n          }\n        });\n      }\n    }\n  }\n\n  // ============================================================================\n  // SIDING & ACCENT MATERIAL APPLICATION\n  // ============================================================================\n\n  async _applyDefaultSidingTexture() {\n    const defaults = this.configData?.defaultConfiguration || {};\n    const sidingType = defaults.siding || defaults.sidingType || 'lap';\n    const sidingColorValue = defaults.sidingColor || 'iron-gray';\n    \n    const sidingColorConfig = this.configData?.configurationOptions?.sidingColor;\n    const colorOption = sidingColorConfig?.options?.find(opt => opt.value === sidingColorValue);\n    const hexColor = colorOption?.hex || colorOption?.color?.hex || '#525654';\n    \n    this.currentSidingType = sidingType;\n    this.currentSidingColor = sidingColorValue;\n    this.currentSidingHex = hexColor;\n    \n    await this._applySidingMaterial(sidingType, sidingColorValue, hexColor);\n    await this._applyDefaultAccentColor();\n  }\n\n  async _applyDefaultAccentColor() {\n    const defaults = this.configData?.defaultConfiguration || {};\n    \n    const accentColorValue = defaults['sidingColor.accent'] || \n                             defaults.accentColor ||\n                             (typeof defaults.sidingColor === 'object' ? defaults.sidingColor?.accent : null) ||\n                             'iron-gray';\n    \n    let accentHex = '#525654';\n    \n    const accentConfig = this.configData?.configurationOptions?.['sidingColor.accent'] ||\n                         this.configData?.configurationOptions?.accentColor;\n    if (accentConfig?.options) {\n      const accentOption = accentConfig.options.find(opt => opt.value === accentColorValue);\n      accentHex = accentOption?.hex || accentOption?.color?.hex || accentHex;\n    }\n    \n    if (accentHex === '#525654') {\n      const sidingColorConfig = this.configData?.configurationOptions?.sidingColor;\n      if (sidingColorConfig?.accent?.options) {\n        const accentOption = sidingColorConfig.accent.options.find(opt => opt.value === accentColorValue);\n        accentHex = accentOption?.hex || accentOption?.color?.hex || accentHex;\n      }\n    }\n    \n    this.currentAccentColor = accentColorValue;\n    this.currentAccentHex = accentHex;\n    \n    this._applyAccentColor(accentHex);\n  }\n\n  async _applySidingMaterial(sidingType, colorValue, hexColor) {\n    const config = ProductConfigurator3D.SIDING_CONFIGS[sidingType] || ProductConfigurator3D.SIDING_CONFIGS['lap'];\n    \n    const meshes = this._findMeshesByPatterns(ProductConfigurator3D.SIDING_MESH_GROUPS);\n    \n    if (meshes.length === 0) {\n      if (this.materialManager?.applySidingMaterial) {\n        this.materialManager.applySidingMaterial(sidingType, colorValue, hexColor);\n      }\n      return;\n    }\n\n    const colorToUse = config.usesSidingColor ? hexColor : (config.baseColor || '#FFFFFF');\n    \n    if (config.hasTexture && config.textureUrl) {\n      try {\n        const material = await this.materialManager.createTintedTextureMaterial(\n          config.textureUrl,\n          colorToUse,\n          { textureScale: config.textureScale }\n        );\n        \n        meshes.forEach(mesh => {\n          mesh.material = material.clone();\n          mesh.material.needsUpdate = true;\n        });\n      } catch (error) {\n        const fallbackMaterial = this.materialManager.createColorMaterial(colorToUse);\n        meshes.forEach(mesh => {\n          mesh.material = fallbackMaterial.clone();\n        });\n      }\n    } else {\n      const material = this.materialManager.createColorMaterial(colorToUse);\n      meshes.forEach(mesh => {\n        mesh.material = material.clone();\n        mesh.material.needsUpdate = true;\n      });\n    }\n  }\n\n  _applyAccentColor(hexColor) {\n    if (!hexColor) return;\n    \n    const meshes = this._findMeshesByPatterns(ProductConfigurator3D.ACCENT_MESH_GROUPS);\n    \n    if (meshes.length === 0) {\n      const configMeshGroups = this.configData?.configurationOptions?.['sidingColor.accent']?.meshGroups ||\n                               this.configData?.configurationOptions?.accentColor?.meshGroups ||\n                               ProductConfigurator3D.ACCENT_MESH_GROUPS;\n      if (configMeshGroups.length) {\n        this.materialManager.applyColorToGroups(configMeshGroups, hexColor);\n      }\n      return;\n    }\n\n    const material = this.materialManager.createColorMaterial(hexColor);\n    meshes.forEach(mesh => {\n      mesh.material = material.clone();\n      mesh.material.needsUpdate = true;\n    });\n  }\n\n  _findMeshesByPatterns(patterns) {\n    const meshes = [];\n    if (this.modelLoader?.loadedModel) {\n      this.modelLoader.loadedModel.traverse(child => {\n        if (child.isMesh && child.name) {\n          const nameLower = child.name.toLowerCase();\n          const matches = patterns.some(pattern => nameLower.includes(pattern.toLowerCase()));\n          if (matches) {\n            meshes.push(child);\n          }\n        }\n      });\n    }\n    return meshes;\n  }\n\n  // ============================================================================\n  // FLOOR TEXTURE HELPERS\n  // ============================================================================\n\n  _getFloorTextureUrl(finishValue, providedTexture) {\n    if (providedTexture) return providedTexture;\n    if (this.configData?.textures?.[finishValue]) return this.configData.textures[finishValue];\n    return this.textureFallbacks[finishValue] || null;\n  }\n\n  async _applyFloorTextureToGroundPlane(textureUrl, textureScale) {\n    const ground = this.sceneManager?.getGround?.();\n    if (!ground) return;\n\n    try {\n      const material = await this.materialManager.createTexturedMaterial(textureUrl, {\n        roughness: 0.7,\n        metalness: 0.0,\n        textureScale: textureScale || { uScale: 10, vScale: 10 }\n      });\n      this.sceneManager.setGroundMaterial(material);\n    } catch (error) {\n      console.error('Failed to apply floor texture to ground:', error);\n    }\n  }\n\n  async _applyFloorTexture(config) {\n    if (!config?.texture) return false;\n\n    const layout = this.currentLayout || this.configData.defaultConfiguration?.layout || 'more-living';\n    \n    let floorMeshes = this._getFloorMeshesForLayout(layout);\n    \n    if (!floorMeshes?.length) {\n      floorMeshes = this._findFloorMeshesByGeometry(layout);\n      if (floorMeshes?.length) {\n        this.floorMeshCache[layout] = floorMeshes;\n      }\n    }\n\n    if (!floorMeshes?.length) return false;\n\n    const filtered = floorMeshes.filter(m => !/bathroom/i.test(m.name || ''));\n    if (!filtered.length) return false;\n\n    const textureScale = this._calculateFloorTextureScale(filtered, config.textureScale);\n\n    try {\n      if (typeof this.materialManager.applyTextureToMeshes === 'function') {\n        return (await this.materialManager.applyTextureToMeshes(filtered, config.texture, { textureScale })) > 0;\n      }\n\n      const material = await this.materialManager.createTexturedMaterial(config.texture, { textureScale });\n      filtered.forEach(mesh => { mesh.material = material.clone(); });\n      return true;\n    } catch (error) {\n      console.error('Failed to apply floor texture:', error);\n      return false;\n    }\n  }\n\n  _calculateFloorTextureScale(floorMeshes, configScale) {\n    if (configScale && (configScale.uScale || configScale.vScale)) {\n      return configScale;\n    }\n\n    const TEXTURE_COVERAGE_FEET = 4;\n\n    const configWidth = this.configData?.width || this.configData?.length;\n    const configDepth = this.configData?.depth;\n    \n    if (configWidth && configDepth) {\n      return { \n        uScale: parseFloat(configWidth) / TEXTURE_COVERAGE_FEET,\n        vScale: parseFloat(configDepth) / TEXTURE_COVERAGE_FEET \n      };\n    }\n\n    let maxArea = 0;\n    let largestMesh = null;\n    \n    floorMeshes.forEach(mesh => {\n      if (!mesh.geometry) return;\n      if (!mesh.geometry.boundingBox) mesh.geometry.computeBoundingBox();\n      const bbox = mesh.geometry.boundingBox;\n      const area = Math.abs(bbox.max.x - bbox.min.x) * Math.abs(bbox.max.z - bbox.min.z);\n      if (area > maxArea) {\n        maxArea = area;\n        largestMesh = mesh;\n      }\n    });\n\n    if (!largestMesh?.geometry?.boundingBox) {\n      return { uScale: 8, vScale: 8 };\n    }\n\n    const bbox = largestMesh.geometry.boundingBox;\n    const TEXTURE_COVERAGE_INCHES = TEXTURE_COVERAGE_FEET * 12;\n    const uScale = Math.max(1, Math.min(20, Math.abs(bbox.max.x - bbox.min.x) / TEXTURE_COVERAGE_INCHES));\n    const vScale = Math.max(1, Math.min(20, Math.abs(bbox.max.z - bbox.min.z) / TEXTURE_COVERAGE_INCHES));\n\n    return { uScale, vScale };\n  }\n\n  _getFloorMeshesForLayout(layout) {\n    const normalized = layout || 'more-living';\n    \n    if (this.floorMeshCache[normalized]) {\n      return this.floorMeshCache[normalized];\n    }\n\n    if (this.modelLoader?.getFloorMeshesForLayout) {\n      const meshes = this.modelLoader.getFloorMeshesForLayout(normalized);\n      this.floorMeshCache[normalized] = meshes;\n      return meshes;\n    }\n\n    return this._findFloorMeshesByGeometry(normalized);\n  }\n\n  _findFloorMeshesByGeometry(layout) {\n    const allMeshes = [];\n    if (this.modelLoader?.loadedModel) {\n      this.modelLoader.loadedModel.traverse(child => {\n        if (child.isMesh) allMeshes.push(child);\n      });\n    }\n\n    const potentialFloors = [];\n    const excludePattern = /bathroom|chair|sofa|bed|appliance|fixture|cabinet|door|window|glass|roof|rafter|eave|fascia|shower|sink|toilet|baseboard/i;\n\n    allMeshes.forEach(mesh => {\n      if (!mesh.geometry) return;\n      \n      const name = (mesh.name || '').toLowerCase();\n      if (excludePattern.test(name)) return;\n\n      if (!mesh.geometry.boundingBox) mesh.geometry.computeBoundingBox();\n      const bbox = mesh.geometry.boundingBox;\n      \n      const height = bbox.max.y - bbox.min.y;\n      const minY = bbox.min.y;\n      const length = bbox.max.x - bbox.min.x;\n      const width = bbox.max.z - bbox.min.z;\n      const area = Math.abs(length * width);\n\n      const isThin = height <= Math.min(length / 3, width / 3) || height <= 5;\n      const isNearGround = minY <= 5;\n      const hasLargeArea = area >= 50;\n      const isHorizontal = length > 0 && width > 0 && height < Math.max(length, width);\n      const hasFloorKeyword = /floor|flooring|plane|ground/i.test(name) && !/baseboard|bathroom/i.test(name);\n\n      if (hasFloorKeyword || (isThin && isNearGround && hasLargeArea && isHorizontal)) {\n        potentialFloors.push({ mesh, area });\n      }\n    });\n\n    potentialFloors.sort((a, b) => b.area - a.area);\n    \n    const result = potentialFloors.map(f => f.mesh);\n    this.floorMeshCache[layout] = result;\n    return result;\n  }\n\n  // ============================================================================\n  // EVENT DISPATCHING\n  // ============================================================================\n\n  _onConfigChange(data) {\n    this.container.dispatchEvent(new CustomEvent('configurator:change', { detail: data }));\n  }\n\n  _onModelLoaded(orientation) {\n    this.container.dispatchEvent(new CustomEvent('configurator:modelLoaded', { detail: { orientation } }));\n  }\n\n  // ============================================================================\n  // PUBLIC API\n  // ============================================================================\n\n  setMeshGroupsVisibility(meshGroups, visible) {\n    meshGroups?.forEach(group => this.modelLoader?.setGroupVisibility(group, visible));\n  }\n\n  applyColorToMeshGroups(meshGroups, color) {\n    this.materialManager?.applyColorToGroups(meshGroups, color);\n  }\n\n  applyTextureToMeshGroups(meshGroups, textureUrl, textureScale) {\n    this.materialManager?.applyTextureToGroups(meshGroups, textureUrl, { textureScale });\n  }\n\n  resetCamera() {\n    this.cameraControls?.reset();\n  }\n\n  rotateCamera(degrees) {\n    this.cameraControls?.rotateBy(degrees);\n  }\n\n  setInteriorView(enabled) {\n    if (enabled) {\n      this.modelLoader?.setRoofVisible(false);\n      this.cameraControls?.setTopDownView();\n    } else {\n      this.modelLoader?.setRoofVisible(true);\n      this.cameraControls?.restoreExteriorView();\n    }\n  }\n\n  getState() {\n    return { \n      orientation: this.currentOrientation, \n      step: this.currentStep,\n      sidingType: this.currentSidingType,\n      sidingColor: this.currentSidingColor,\n      accentColor: this.currentAccentColor\n    };\n  }\n\n  getAllMeshNames() {\n    return this.modelLoader?.getAllMeshNames() || [];\n  }\n\n  isReady() {\n    return this.isInitialized && !this.isLoading;\n  }\n\n  dispose() {\n    try {\n      this.materialManager?.clearCache?.();\n      this.floorMeshCache = {};\n      this.currentFloorConfig = null;\n      \n      this.cameraControls?.dispose?.();\n      this.modelLoader?.dispose?.();\n      this.sceneManager?.dispose?.();\n      \n      this.sceneManager = null;\n      this.modelLoader = null;\n      this.materialManager = null;\n      this.cameraControls = null;\n      this.configData = null;\n      this.textureFallbacks = null;\n      \n      this.isInitialized = false;\n      this.isLoading = false;\n    } catch (error) {\n      console.error('Error disposing ProductConfigurator3D:', error);\n    }\n  }\n}\n\n// Export for both module and non-module usage\nwindow.ProductConfigurator3D = ProductConfigurator3D;\nwindow.AspectConfigurator3D = ProductConfigurator3D;\n\nexport { ProductConfigurator3D, ProductConfigurator3D as AspectConfigurator3D };\n"],
  "mappings": "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",
  "names": ["bbox"]
}
