Virtual Tour Creator
Run ID: 69cd05493e7fb09ff16a735b2026-04-01Real Estate
PantheraHive BOS
BOS Dashboard

Virtual Tour Generation Complete: Your Immersive Property Experience is Ready!

We are delighted to inform you that your professional 360° virtual tour has been successfully generated. This comprehensive tour is designed to provide an immersive and interactive experience for potential buyers, significantly enhancing your real estate listings.


Your Virtual Tour Overview

Your newly created virtual tour is a powerful tool, leveraging advanced technology to showcase properties in an engaging and detailed manner. It combines high-quality 360° imagery with interactive elements to create a seamless browsing experience.


Key Features of Your Virtual Tour

Here's a breakdown of the robust features integrated into your virtual tour:

  1. Immersive 360° Viewing Experience

* Full Pan & Tilt: Viewers can freely explore every angle of a room, panning horizontally (360°) and tilting vertically, creating a true sense of being present in the space.

* High-Resolution Imagery: Each panorama is composed of high-resolution stitched photographs, ensuring crisp details and vibrant colors that accurately represent the property.

* User-Friendly Interface: The tour features an intuitive interface, making it easy for anyone to navigate and enjoy the immersive experience across various devices (desktop, tablet, mobile).

  1. Seamless Photo Stitching Technology

* Automated Precision: Our advanced algorithms have meticulously stitched together multiple individual photographs to create flawless, distortion-free 360° panoramas for each designated area.

* Elimination of Seams: This process ensures there are no visible lines or breaks, providing a smooth and continuous visual flow throughout the tour.

  1. Interactive Hotspot Annotations

* Engaging Information Points: Strategically placed "hotspots" act as clickable markers within the tour, revealing additional details about specific features or areas.

* Rich Content Integration: Hotspots can contain:

* Text Descriptions: Highlight unique selling points (e.g., "Granite Countertops," "Hardwood Flooring").

* Image Overlays: Showcase close-ups of features or specific details.

* Video Clips: Embed short videos demonstrating appliances or unique architectural elements.

* External Links: Direct viewers to floor plans, property brochures, or community information.

* Enhanced Viewer Engagement: These interactive elements encourage deeper exploration and provide valuable information on demand.

  1. Intuitive Room-by-Room Navigation

* Structured Flow: The tour is organized logically, allowing viewers to easily transition between different rooms and areas of the property.

* Navigation Menu: A clear navigation menu (e.g., "Living Room," "Kitchen," "Master Bedroom") provides quick access to any part of the tour.

* Directional Arrows: Within each panorama, directional arrows guide viewers to adjacent rooms, simulating a physical walk-through.

* Mini-Map Integration (Optional): If provided, a small floor plan overlay helps viewers orient themselves within the property layout.

  1. Integrated Lead Capture (Embedded Contact Forms)

* Direct Inquiry Path: Strategically placed contact forms are embedded directly within the virtual tour, allowing interested viewers to submit inquiries without leaving the tour experience.

* Customizable Fields: Forms can be customized to capture essential information such as name, email, phone number, and specific questions or viewing requests.

* Instant Notifications: All submitted inquiries are immediately forwarded to your designated contact email, ensuring prompt follow-up.

* Streamlined Lead Generation: This feature transforms passive viewing into active lead generation, directly connecting you with potential buyers.

  1. Optimized for Real Estate Listings

* Showcase Every Detail: Ideal for properties of all sizes, allowing you to highlight architectural nuances, room dimensions, and key amenities.

* Increased Online Engagement: Virtual tours have been proven to significantly increase viewer engagement, dwell time on listings, and lead generation compared to traditional photos alone.

* 24/7 Open House: Potential buyers can "tour" the property at their convenience, from anywhere in the world, reducing the need for preliminary physical viewings.

* Competitive Advantage: Differentiate your listings and attract more serious buyers by offering a superior online viewing experience.


How to Access Your Virtual Tour

Your virtual tour is now live and ready for deployment!

Please click this link to view your complete virtual tour.*

html • 133 chars
    <iframe src="[Insert Unique Tour URL Here]?embed=true" width="100%" height="500px" frameborder="0" allowfullscreen></iframe>
    
Sandboxed live preview

This document outlines the first critical step in creating your professional 360-degree virtual tour: AI Image Preparation & Ingestion. This phase focuses on intelligently receiving, analyzing, and optimizing your source images to ensure the highest quality output for the subsequent stitching process and the overall virtual tour experience.


Step 1: AI Image Preparation & Ingestion

This initial step leverages advanced Artificial Intelligence to process your raw images, preparing them for seamless 360° panoramic stitching and ensuring optimal visual quality throughout your virtual tour. Our system will guide you through uploading your photos, perform automated enhancements, and intelligently group them for easy navigation.

1.1 Purpose & Overview

The "AI Image Preparation & Ingestion" step is designed to:

  • Efficiently collect all necessary photographic data for your virtual tour.
  • Automatically assess and enhance the quality of your uploaded images (e.g., exposure, color balance, sharpness).
  • Intelligently group photos belonging to the same scene or room, streamlining the creation of room-by-room navigation.
  • Optimize images for the subsequent 360° stitching process, minimizing errors and maximizing panoramic quality.
  • Identify potential issues with image sets (e.g., insufficient overlap, blurriness) and provide feedback.

1.2 Key AI Capabilities & Processing

Our AI-powered engine performs the following operations during this phase:

  • Intelligent Image Upload & Validation:

* Batch Upload: Supports uploading multiple images simultaneously.

* Format Compatibility: Accepts common image formats (JPEG, PNG, TIFF).

* Pre-flight Checks: Validates image integrity, resolution, and basic metadata.

  • AI-Powered Quality Assessment & Enhancement:

* Exposure & White Balance Correction: Automatically adjusts lighting and color temperature for consistency across images within a scene.

* Dynamic Range Optimization: Enhances detail in both highlights and shadows.

* Noise Reduction & Sharpening: Reduces digital noise and subtly sharpens details without over-processing.

* Lens Distortion Correction: Applies profile-based or AI-estimated corrections for common lens distortions, crucial for accurate stitching.

  • Spatial Analysis & Scene Grouping:

* Feature Detection: Identifies unique visual features within images to understand their spatial relationship.

* Automatic Scene Grouping: Our AI will attempt to automatically group images that likely belong to the same room or panoramic view based on visual similarity and EXIF data.

* Overlap Analysis: Assesses the degree of overlap between sequential images, providing feedback if insufficient overlap is detected, which is vital for successful stitching.

  • Pre-Stitching Optimization:

* Image Alignment Preparation: Analyzes and pre-processes images to facilitate more accurate and faster alignment during the stitching phase.

* Ghosting & Parallax Mitigation: Identifies potential issues that could lead to "ghosting" or misalignment during stitching, allowing for pre-emptive adjustments.

1.3 User Action Required: Providing Your Source Images

To ensure the best possible virtual tour, please follow these guidelines when preparing and uploading your images:

  1. Capture Strategy:

* For each desired 360° panoramic view (e.g., each room, outdoor area): Capture a series of overlapping photos by rotating your camera around a central point (ideally, the nodal point of your lens if using a tripod).

* Overlap: Aim for 30-50% overlap between consecutive photos. This is crucial for successful stitching.

* Number of Photos: Typically, 8-12 photos taken around a full 360-degree rotation (e.g., every 30-45 degrees) will suffice for a single panorama, plus additional shots for the ceiling and floor if desired.

* Vertical Coverage: Ensure you capture enough vertical information (upwards and downwards) to cover the full sphere.

  1. Image Quality:

* Resolution: Upload high-resolution images (e.g., 12-24 megapixels or higher) for optimal detail in the final tour.

* Lighting: Maintain consistent lighting conditions throughout the capture of a single panorama. Avoid mixed lighting sources (e.g., sunlight and artificial light) if possible.

* Focus: Ensure all images are sharply in focus.

* Stability: Use a tripod whenever possible to minimize camera shake and maintain a consistent rotation axis.

  1. Upload Process:

* Drag & Drop: Use the provided interface to drag and drop your image files.

Folder Structure (Recommended): If possible, organize your photos into folders by room or scene before* uploading. Our system can often infer grouping from folder names, which will aid in the AI's scene grouping.

* Labelling (Optional but helpful): If not using folders, you may be prompted to add basic labels (e.g., "Living Room 1", "Kitchen Panorama") to sets of photos to assist the AI.

  1. Review & Confirm:

* After upload, the system will display a summary of detected image sets and proposed room groupings.

* Review these groupings: You will have the opportunity to confirm or adjust which photos belong to which room/scene. This is vital for accurate room-by-room navigation.

* Address Warnings: Pay attention to any warnings regarding potential issues (e.g., low overlap, blurry images) and consider re-uploading improved photos if necessary.

1.4 Output of This Step

Upon successful completion of "AI Image Preparation & Ingestion," you will receive:

  • Organized Image Sets: Your uploaded photos will be logically grouped by detected scene/room, ready for individual panorama creation.
  • Enhanced Image Previews: You will see previews of the AI-enhanced versions of your images, showcasing improved clarity, color, and exposure.
  • Readiness for Stitching: All images will be pre-processed and optimized, making them ideal candidates for the next step: 360° Photo Stitching.

Next Step: Once your images are successfully ingested and prepared, we will proceed to Step 2: 360° Photo Stitching, where these optimized images will be seamlessly combined into interactive panoramic views.

  • You can copy and paste this HTML code directly into your website or real estate listing platform to embed the virtual tour seamlessly.

Actionable Next Steps

  1. Review Your Tour: Please take some time to thoroughly review the entire virtual tour. Check the navigation, hotspot information, and overall visual quality.
  2. Share Widely: Integrate the tour link or embed code into all your real estate listings, social media channels, email campaigns, and property websites.
  3. Gather Feedback: Share the tour with colleagues or test users to gather initial impressions and identify any areas for potential enhancement.
  4. Monitor Leads: Keep an eye on your designated email for inquiries submitted through the embedded contact forms.

Support & Feedback

Should you have any questions, require modifications to hotspots or navigation, or need assistance with embedding the tour, please do not hesitate to contact our support team at [Support Email/Phone Number]. Your feedback is invaluable as we strive to deliver the best possible tools for your success.


We are confident that this professional virtual tour will be an invaluable asset in marketing your properties and attracting high-quality leads.

Start exploring your virtual tour now!

virtual_tour_creator.html
Download source file
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( ) "); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react' import './App.css' function App(){ return(

"+slugTitle(pn)+"

Built with PantheraHive BOS

) } export default App "); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e} .app{min-height:100vh;display:flex;flex-direction:column} .app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px} h1{font-size:2.5rem;font-weight:700} "); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` ## Open in IDE Open the project folder in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{ "name": "'+pn+'", "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview" }, "dependencies": { "vue": "^3.5.13", "vue-router": "^4.4.5", "pinia": "^2.3.0", "axios": "^1.7.9" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", "typescript": "~5.7.3", "vite": "^6.0.5", "vue-tsc": "^2.2.0" } } '); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve(__dirname,'src') } } }) "); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]} '); zip.file(folder+"tsconfig.app.json",'{ "compilerOptions":{ "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"], "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true, "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue", "strict":true,"paths":{"@/*":["./src/*"]} }, "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"] } '); zip.file(folder+"env.d.ts","/// "); zip.file(folder+"index.html"," "+slugTitle(pn)+"
"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import './assets/main.css' const app = createApp(App) app.use(createPinia()) app.mount('#app') "); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue"," "); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547} "); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` Open in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{ "name": "'+pn+'", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test" }, "dependencies": { "@angular/animations": "^19.0.0", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, "devDependencies": { "@angular-devkit/build-angular": "^19.0.0", "@angular/cli": "^19.0.0", "@angular/compiler-cli": "^19.0.0", "typescript": "~5.6.0" } } '); zip.file(folder+"angular.json",'{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "'+pn+'": { "projectType": "application", "root": "", "sourceRoot": "src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": "dist/'+pn+'", "index": "src/index.html", "browser": "src/main.ts", "tsConfig": "tsconfig.app.json", "styles": ["src/styles.css"], "scripts": [] } }, "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"} } } } } '); zip.file(folder+"tsconfig.json",'{ "compileOnSave": false, "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]}, "references":[{"path":"./tsconfig.app.json"}] } '); zip.file(folder+"tsconfig.app.json",'{ "extends":"./tsconfig.json", "compilerOptions":{"outDir":"./dist/out-tsc","types":[]}, "files":["src/main.ts"], "include":["src/**/*.d.ts"] } '); zip.file(folder+"src/index.html"," "+slugTitle(pn)+" "); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, appConfig) .catch(err => console.error(err)); "); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; } "); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = '"+pn+"'; } "); zip.file(folder+"src/app/app.component.html","

"+slugTitle(pn)+"

Built with PantheraHive BOS

"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1} "); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes) ] }; "); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router'; export const routes: Routes = []; "); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install ng serve # or: npm start ``` ## Build ```bash ng build ``` Open in VS Code with Angular Language Service extension. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local .angular/ "); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join(" "):"# add dependencies here "; zip.file(folder+"main.py",src||"# "+title+" # Generated by PantheraHive BOS print(title+" loaded") "); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Run ```bash python main.py ``` "); zip.file(folder+".gitignore",".venv/ __pycache__/ *.pyc .env .DS_Store "); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+" "; zip.file(folder+"package.json",pkgJson); var fallback="const express=require("express"); const app=express(); app.use(express.json()); app.get("/",(req,res)=>{ res.json({message:""+title+" API"}); }); const PORT=process.env.PORT||3000; app.listen(PORT,()=>console.log("Server on port "+PORT)); "; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000 "); zip.file(folder+".gitignore","node_modules/ .env .DS_Store "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash npm install ``` ## Run ```bash npm run dev ``` "); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:" "+title+" "+code+" "; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */ *{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e} "); zip.file(folder+"script.js","/* "+title+" — scripts */ "); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Open Double-click `index.html` in your browser. Or serve locally: ```bash npx serve . # or python3 -m http.server 3000 ``` "); zip.file(folder+".gitignore",".DS_Store node_modules/ .env "); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/**(.+?)**/g,"$1"); hc=hc.replace(/ {2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. Files: - "+app+".md (Markdown) - "+app+".html (styled HTML) "); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); }function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}