Aesthetic Advisor /* -------------------------------------------------- Basic Reset and Desktop Defaults (Large Screens) -------------------------------------------------- */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: Arial, sans-serif; background: #f8f8f8; color: #333; } .recommender-container { display: flex; flex-direction: row; max-width: 1200px; margin: 20px auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.1); } .model-column, .selection-column { flex: 1; position: relative; } .model-column { border-right: 1px solid #eee; } /* Model Wrapper & Images */ .model-wrapper { position: relative; width: 100%; height: 700px; background: #f0f0f0; overflow: hidden; } .body-model { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; display: none; } .body-model.active { display: block; } /* Gender Toggle Button */ .gender-toggle-btn { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); padding: 0.5rem 1rem; background: #333; color: #fff; border: none; border-radius: 20px; cursor: pointer; transition: all 0.3s ease; z-index: 2; /* Ensure above model, below overlay */ } .gender-toggle-btn:hover { background: #555; } /* Hotspots */ .hotspot { position: absolute; width: 30px; height: 30px; background-color: #4AC1D5; border-radius: 50%; transform: translate(-50%, -50%); cursor: pointer; box-shadow: 0 0 0 4px rgba(74, 193, 213, 0.3); /* Adjusted alpha for subtlety */ transition: transform 0.2s ease, box-shadow 0.2s ease; z-index: 1; /* Lower than the overlay */ } .hotspot::before { content: "+"; color: #fff; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: bold; font-size: 1.2em; } .hotspot:hover { transform: translate(-50%, -50%) scale(1.2); box-shadow: 0 0 0 6px rgba(74, 193, 213, 0.5); /* Enhanced hover shadow */ } /* Back Button */ .back-btn { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); padding: 0.5rem 1rem; background: #f3f4f6; border: 1px solid #e5e7eb; border-radius: 5px; cursor: pointer; font-size: 14px; transition: background 0.2s ease; z-index: 2; /* Ensure above model, below overlay */ } .back-btn:hover { background: #e5e7eb; } /* Cover Overlays */ .cover-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; z-index: 100; /* Sits above hotspots */ cursor: pointer; transition: opacity 0.5s ease, visibility 0s 0.5s; opacity: 1; visibility: visible; } .cover-overlay.left-cover { background: rgba(0, 0, 0, 0.85); } .cover-overlay.right-cover { background: #fff; color: #333; } .cover-overlay.hidden { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.5s ease, visibility 0s 0.5s; } .cover-content { text-align: center; padding: 20px; } .left-cover .cover-content { transform: translateY(-70%); } .pulsing-arrow { font-size: 2.5rem; color: #fff; position: relative; animation: pulse 1.5s infinite; z-index: 2; } @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.1); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } .pulsing-arrow:before, .pulsing-arrow:after { content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); border: 2px solid #fff; border-radius: 50%; opacity: 0.6; } .pulsing-arrow:before { width: 60px; height: 60px; z-index: -1; animation: pulse-ring 1.5s infinite ease-out; } .pulsing-arrow:after { width: 80px; height: 80px; z-index: -2; animation: pulse-ring 1.5s 0.3s infinite ease-out; } @keyframes pulse-ring { 0% { transform: translate(-50%, -50%) scale(0.8); opacity: 0.6; } 100% { transform: translate(-50%, -50%) scale(1.2); opacity: 0; } } .click-to-begin { color: #fff; margin-top: 50px; font-size: 1rem; } /* Right Cover Overlay (Desktop Version) */ .cover-overlay.right-cover .cover-content { text-align: center; } .welcome-header { font-size: 2.0rem; margin-bottom: 100px; line-height: 1.9; } .logo-placeholder { margin-bottom: 10px; } .logo-placeholder img { max-width: 100%; height: auto; transform: translateY(-40px); max-height: 140px; } .steps { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; } .step { background: #4AC1D5; padding: 10px 15px; border-radius: 50px; display: inline-flex; align-items: center; box-shadow: 0 4px 6px rgba(0,0,0,0.1); } .step-number { background: #fff; color: #4AC1D5; border-radius: 50%; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; margin-right: 10px; flex-shrink: 0; font-weight: bold; } .step-text { font-size: 1rem; color: #fff; } /* Panels and Selection Column (Desktop) */ .selection-column { display: flex; /* Default: visible on desktop */ flex-direction: column; padding: 20px; gap: 20px; background: #fff; position: relative; /* Needed for cover overlay */ } .panel { display: none; transition: opacity 0.3s ease; } .panel.active { display: block; opacity: 1;} #introPanel, #concernPanel, #planPanel { background: #fafafa; border: 1px solid #eee; border-radius: 8px; padding: 20px; } #concernAreaTitle { margin-bottom: 15px; font-size: 1.25rem; font-weight: bold; } .concern-list { display: flex; flex-direction: column; gap: 10px; max-height: 400px; /* Prevent excessive height */ overflow-y: auto; /* Add scroll if needed */ } .concern-item { padding: 12px 15px; /* Slightly more padding */ border-radius: 6px; border: 1px solid #ddd; cursor: pointer; transition: background-color 0.2s, border-color 0.2s; background-color: #fff; /* Default background */ font-size: 0.95rem; } .concern-item:hover { background-color: #f0f0f0; } .concern-item.selected { border-color: #4AC1D5; background-color: #e0f7fa; /* Lighter blue background for selected */ font-weight: 500; } .plan-panel { display: flex; flex-direction: column; } .plan-panel h3 { margin-bottom: 10px; } .treatment-plan-items { flex: 1; overflow-y: auto; margin-bottom: 15px; /* More space before buttons */ max-height: 350px; /* Limit height */ border-top: 1px solid #eee; /* Separator */ border-bottom: 1px solid #eee; /* Separator */ padding: 10px 0; /* Padding for items */ } .plan-item { display: flex; justify-content: space-between; align-items: center; background: #fff; /* border: 1px solid #ddd; */ /* Removed border for cleaner look */ border-radius: 6px; padding: 10px; margin-bottom: 5px; font-size: 0.9rem; } .plan-item:hover { background: #f9f9f9; } .remove-btn { background: none; border: none; color: #cc0000; /* Brighter red */ font-weight: bold; cursor: pointer; font-size: 1.2em; /* Make X slightly larger */ padding: 0 5px; /* Add padding for easier click */ } .remove-btn:hover { color: #990000; /* Darker red on hover */ } .empty-plan-text { color: #999; font-style: italic; text-align: center; margin-top: 20px; padding: 20px; } .plan-buttons { display: flex; justify-content: space-between; margin-top: 10px; /* Added margin */ } .primary-btn, .secondary-btn { border: none; border-radius: 20px; padding: 10px 20px; cursor: pointer; transition: background 0.3s ease, opacity 0.3s ease; font-weight: bold; } .primary-btn { background: #4AC1D5; color: #fff; } .primary-btn:hover { background: #3b9eaa; } /* Slightly darker hover */ .secondary-btn { background: #eee; color: #333; } .secondary-btn:hover { background: #ddd; } .primary-btn:disabled { background: #a0dbe4; opacity: 0.7; cursor: not-allowed; } /* Generic Modal Styles */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; /* Hidden by default */ background: rgba(0,0,0,0.6); /* Slightly darker overlay */ justify-content: center; align-items: center; z-index: 1000; /* High z-index */ padding: 15px; /* Padding for smaller screens */ } .modal.show { display: flex; } /* Use flex to center content */ .modal-content { background: #fff; padding: 25px 30px; /* More padding */ border-radius: 8px; max-width: 500px; width: 100%; position: relative; box-shadow: 0 5px 15px rgba(0,0,0,0.2); max-height: 90vh; /* Limit height */ display: flex; /* Use flex for internal layout */ flex-direction: column; } /* Form Modal Specifics */ #formModal .modal-content h2 { margin-bottom: 15px; font-size: 1.3rem; color: #333; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: bold; font-size: 0.9rem; } .form-group label span { color: red; } /* Required asterisk */ .form-group input, .form-group textarea { width: 100%; padding: 10px; /* More padding */ border: 1px solid #ccc; /* Slightly darker border */ border-radius: 4px; font-size: 1rem; } .form-group textarea { min-height: 80px; } /* Ensure textarea is usable */ .form-disclaimer { font-size: 0.85rem; color: #666; margin-bottom: 20px; line-height: 1.4;} #formModal .primary-btn { width: 100%; padding: 12px; font-size: 1rem; } /* Full width submit */ /* Generic Close Button */ .close-modal-btn { position: absolute; top: 10px; right: 15px; background: none; border: none; cursor: pointer; color: #888; /* Lighter color */ font-size: 1.8rem; /* Larger */ line-height: 1; padding: 5px; transition: color 0.3s ease; } .close-modal-btn:hover { color: #333; } /* --- NEW: Mobile Concern Modal Styles --- */ .mobile-concern-modal .modal-content { max-width: 90%; /* Use more width on mobile */ padding: 20px; } .mobile-concern-modal h2 { font-size: 1.2rem; margin-bottom: 15px; text-align: center; border-bottom: 1px solid #eee; padding-bottom: 10px; } .mobile-concern-modal .concern-list { max-height: 60vh; /* Limit height on mobile */ overflow-y: auto; margin-bottom: 15px; /* Space before close button */ } /* Re-use concern-item styles */ .mobile-concern-modal .concern-item { font-size: 1rem; /* Slightly larger text for mobile */ padding: 15px; } .mobile-concern-modal .modal-close-footer { text-align: center; margin-top: 15px; } .mobile-concern-modal .secondary-btn { /* Style a close button if needed */ padding: 8px 25px; } /* --- END NEW --- */ /* Toast Notification */ .toast { position: fixed; bottom: 20px; left: 50%; /* Center horizontally */ transform: translateX(-50%); /* Actual centering */ background: #333; color: #fff; padding: 12px 25px; border-radius: 6px; opacity: 0; /* transform: translateY(50px); */ /* Removed Y transform for simple fade */ transition: opacity 0.4s ease; z-index: 1010; /* Above modals */ pointer-events: none; /* Don't intercept clicks */ } .toast.show { opacity: 1; /* transform: translateY(0); */ } /* Back button inside concern panel */ #closeConcernsBtn { background: none; border: none; cursor: pointer; color: #555; font-size: 0.9rem; margin-bottom: 10px; /* Space below button */ display: inline-block; /* Allow margin */ padding: 5px 0; transition: color 0.2s ease; } #closeConcernsBtn:hover { color: #000; } /* --- *** CSS FIX *** --- */ /* --- Mobile Submit Button Area --- */ .mobile-submit-area { /* display: block; REMOVED THIS LINE */ padding: 15px; background-color: #f8f8f8; text-align: center; border-top: 1px solid #eee; display: none; /* HIDE BY DEFAULT (for desktop) - ADDED THIS LINE */ } .mobile-submit-area .primary-btn { width: 80%; max-width: 300px; padding: 12px 20px; font-size: 1rem; } /* --- *** END CSS FIX *** --- */ /* -------------------------------------------------- Mobile Adjustments – Reordering for Mobile Layout -------------------------------------------------- */ /* Hide mobile-specific elements on desktop */ .mobile-welcome-header, .mobile-logo-buttons { display: none; } @media (max-width: 768px) { /* Stack the overall layout vertically */ .recommender-container { flex-direction: column; margin: 0; /* Remove margin for full width */ border-radius: 0; /* Remove radius for full width */ box-shadow: none; /* Remove shadow */ } .model-column, .selection-column { width: 100%; } .model-column { border-right: none; border-bottom: 1px solid #eee; min-height: 400px; /* Ensure minimum height */ } .model-wrapper { height: auto; /* Let content determine height */ min-height: 400px; /* Match column height */ } .body-model { position: relative; /* Change positioning for natural flow */ object-fit: contain; /* Keep contain */ max-height: 400px; /* Limit image height */ } .gender-toggle-btn { bottom: 10px; } .back-btn { bottom: 10px; } /* Hide the original right cover overlay and selection column */ .cover-overlay.right-cover, .selection-column { display: none !important; } /* Keep this! */ /* Show mobile welcome header */ .mobile-welcome-header { display: block; background: #fff; padding: 1rem; text-align: center; border-bottom: 1px solid #eee; box-shadow: 0 2px 4px rgba(0,0,0,0.05); /* Subtle shadow */ } .mobile-welcome-header .welcome-header { font-size: 1.4rem; /* Adjust size */ margin: 0; line-height: 1.4; } /* Show mobile logo/buttons */ .mobile-logo-buttons { display: block; background: #fff; padding: 1.5rem 1rem; /* More padding */ text-align: center; border-top: 1px solid #eee; /* Use border instead of margin */ } .mobile-logo-buttons .logo-placeholder { margin-bottom: 1.5rem; /* More space */ } .mobile-logo-buttons .logo-placeholder img { max-width: 60%; /* Adjust logo size */ max-height: 100px; height: auto; transform: none; /* Reset desktop transform */ } .mobile-logo-buttons .steps { display: flex; flex-direction: column; gap: 0.8rem; /* Adjust gap */ align-items: flex-start; /* left align items */ text-align: left; /* ensure text is left aligned */ max-width: 400px; /* Limit width for better readability */ margin: 0 auto; /* Center the steps block */ } .mobile-logo-buttons .step { padding: 0.6rem 1rem; /* Adjust padding */ border-radius: 30px; /* Adjust radius */ background: #4AC1D5; color: #fff; display: flex; align-items: center; width: 100%; /* Make steps full width */ box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .mobile-logo-buttons .step-number { margin-right: 0.8rem; /* Adjust spacing */ width: 28px; /* Adjust size */ height: 28px; font-size: 0.9rem; } .mobile-logo-buttons .step-text { font-size: 0.9rem; /* Adjust text size */ } /* Adjust Hotspot size for mobile */ .hotspot { width: 25px; height: 25px; } .hotspot::before { font-size: 1em; } /* Make left cover content centered better on mobile */ .left-cover .cover-content { transform: none; } .pulsing-arrow { font-size: 2rem; } .pulsing-arrow:before { width: 50px; height: 50px; } .pulsing-arrow:after { width: 70px; height: 70px; } .click-to-begin { margin-top: 30px; } /* --- *** CSS FIX *** --- */ /* --- Explicitly show mobile submit area --- */ .mobile-submit-area { display: block; /* SHOW ONLY ON MOBILE */ } /* --- *** END CSS FIX *** --- */ } /* End @media (max-width: 768px) */ /* --- *** CSS FIX *** --- */ /* REMOVED the @media (min-width: 769px) rule that previously tried to hide .mobile-submit-area */ /* --- *** END CSS FIX *** --- */ Welcome to your 360 Aesthetic Advisor Switch to Male Back to Body ↖ click to begin Welcome to your 360 Aesthetic Advisor 1 Click on body parts to view concerns. 2 Select your concerns. 3 Submit & receive your personalized treatment recommendations. Welcome! Click on a body area to begin building your treatment plan. ← Back to Plan Area Concerns Your Selections (0) No selections yet. Click a body area to begin. Clear All Finish & Get Results 1 Click on body parts to view concerns. 2 Select one or multiple concerns. 3 Submit to receive personalized treatment recommendations. Finish & Get Results (0) × Area Concerns × Enter your contact information to receive your customized treatment plan! First Name * Email * Additional Information All of your information will be kept private and only shared with your provider. Submit Message goes here document.addEventListener('DOMContentLoaded', function() { // --- DOM Element References --- const toggleGenderBtn = document.getElementById('toggleGenderBtn'); const femaleModel = document.getElementById('femaleModel'); const maleModel = document.getElementById('maleModel'); const bodyModelContainer = document.getElementById('bodyModelContainer'); const faceModelContainer = document.getElementById('faceModelContainer'); const backToBodyBtn = document.getElementById('backToBodyBtn'); const leftCover = document.querySelector('.cover-overlay.left-cover'); const rightCover = document.querySelector('.cover-overlay.right-cover'); const introPanel = document.getElementById('introPanel'); const concernPanel = document.getElementById('concernPanel'); const planPanel = document.getElementById('planPanel'); const concernAreaTitle = document.getElementById('concernAreaTitle'); const concernList = document.getElementById('concernList'); const closeConcernsBtn = document.getElementById('closeConcernsBtn'); const planCountDesktop = document.getElementById('planCount'); const treatmentPlanItems = document.getElementById('treatmentPlanItems'); const clearPlanBtn = document.getElementById('clearPlanBtn'); const finishPlanBtnDesktop = document.getElementById('finishPlanBtnDesktop'); const formModal = document.getElementById('formModal'); const treatmentPlanDataInput = document.getElementById('treatment_plan_data'); const contactForm = document.getElementById('contactForm'); const toast = document.getElementById('toast'); // Mobile Specific Elements const mobileConcernModal = document.getElementById('mobileConcernModal'); const mobileConcernAreaTitle = document.getElementById('mobileConcernAreaTitle'); const mobileConcernList = document.getElementById('mobileConcernList'); const finishPlanBtnMobile = document.getElementById('finishPlanBtnMobile'); const mobilePlanCount = document.getElementById('mobilePlanCount'); let isFemale = true; let treatmentPlan = []; // Stores { area: string, id: string, label: string } // --- Data --- const AREA_CONCERNS = { face: [ { id: 'fine-lines', label: 'Fine lines & wrinkles' }, { id: 'uneven-skin-tone', label: 'Uneven skin tone' }, { id: 'dull-skin', label: 'Dull skin' }, { id: 'sagging-skin', label: 'Sagging skin' }, { id: 'enlarged-pores', label: 'Enlarged pores' } ], forehead: [ { id: 'fine-lines', label: 'Fine lines & wrinkles' }, { id: 'uneven-skin-tone', label: 'Uneven skin tone' }, { id: 'dull-skin', label: 'Dull skin' }, { id: 'sagging-skin', label: 'Sagging skin' }, { id: 'enlarged-pores', label: 'Enlarged pores' }, { id: 'hair-thinning', label: 'Hair thinning or hair loss' } ], eyes: [ { id: 'dark-circles', label: 'Dark circles' }, { id: 'fine-lines', label: 'Fine lines (crow’s feet)' }, { id: 'puffiness', label: 'Puffiness' }, { id: 'thin-skin', label: 'Thin or crepey skin' }, { id: 'lash-enhancement', label: 'Lash enhancement' } ], cheeks: [ { id: 'acne', label: 'Acne & acne scars' }, { id: 'dark-spots', label: 'Dark spots & melasma' }, { id: 'dull-skin', label: 'Dull skin' }, { id: 'redness', label: 'Redness or rosacea' }, { id: 'sensitive-skin', label: 'Sensitive skin' }, { id: 'uneven-skin-tone', label: 'Uneven skin tone' }, { id: 'enlarged-pores', label: 'Enlarged pores & blackheads' } ], nose: [ { id: 'oily-skin', label: 'Oily skin' }, { id: 'blackheads', label: 'Blackheads' }, { id: 'redness', label: 'Redness' }, { id: 'enlarged-pores', label: 'Visible/enlarged pores' } ], lips: [ { id: 'lip-shape', label: 'Lip shape or volume' }, { id: 'fine-lines', label: 'Fine lines around lips' }, { id: 'dry-lips', label: 'Dry or cracked lips' } ], jaw: [ { id: 'sagging-skin', label: 'Sagging skin' }, { id: 'jowls', label: 'Jowls' }, { id: 'jawline-definition', label: 'Jawline definition' }, { id: 'acne', label: 'Acne or breakouts' }, { id: 'enlarged-pores', label: 'Enlarged pores' } ], neck: [ { id: 'sagging-skin', label: 'Sagging / crepey skin' }, { id: 'fine-lines', label: 'Fine lines' }, { id: 'dull-skin', label: 'Dull skin' }, { id: 'dark-spots', label: 'Dark spots & sun damage' }, { id: 'uneven-skin-tone', label: 'Uneven skin tone' }, { id: 'decolletage-rejuvenation', label: 'Decolletage rejuvenation' } ], underarms: [ { id: 'excessive-sweating', label: 'Excessive sweating (hyperhidrosis)' } ], abdomen: [ { id: 'stretch-marks', label: 'Stretch marks' }, { id: 'cellulite', label: 'Cellulite' }, { id: 'sagging-skin', label: 'Sagging skin' }, { id: 'uneven-texture', label: 'Uneven skin texture' }, { id: 'medical-weight-loss', label: 'Medical weight loss' } ], hips: [ { id: 'stretch-marks', label: 'Stretch marks' }, { id: 'cellulite', label: 'Cellulite' }, { id: 'sagging-skin', label: 'Sagging or loose skin' }, { id: 'uneven-skin-tone', label: 'Uneven skin tone' } ], hands: [ { id: 'thin-skin', label: 'Thin or aging skin' }, { id: 'dry-skin', label: 'Dry skin' }, { id: 'uneven-skin-tone', label: 'Uneven skin tone' }, { id: 'volume-loss', label: 'Volume loss' }, { id: 'hands-rejuvenation', label: 'Hands rejuvenation' } ] }; // --- Utility Functions --- function capitalize(str) { return str ? str.charAt(0).toUpperCase() + str.slice(1) : ''; } function isMobileView() { // Use window.matchMedia for reliable detection based on CSS breakpoint return window.matchMedia("(max-width: 768px)").matches; } function showToast(message) { toast.textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } function openModal(modalElement) { if(modalElement) modalElement.classList.add('show'); } function closeModal(modalElement) { if(modalElement) modalElement.classList.remove('show'); } // --- Core Logic Functions --- // Updates both desktop plan panel and mobile submit button state function renderPlanItems() { const count = treatmentPlan.length; // Update Desktop Plan Panel (only if it exists) if (treatmentPlanItems && finishPlanBtnDesktop && planCountDesktop && introPanel && planPanel) { treatmentPlanItems.innerHTML = ""; // Clear previous items if (count === 0) { treatmentPlanItems.innerHTML = '

No selections yet. Click a body area to begin.

'; finishPlanBtnDesktop.disabled = true; if (planPanel.classList.contains('active') && !isMobileView()) { planPanel.classList.remove('active'); introPanel.classList.add('active'); // Show intro if plan becomes empty } } else { finishPlanBtnDesktop.disabled = false; if (introPanel.classList.contains('active') && !isMobileView()) { introPanel.classList.remove('active'); planPanel.classList.add('active'); // Ensure plan panel is visible if items exist } treatmentPlan.forEach((item, index) => { const row = document.createElement("div"); row.className = "plan-item"; row.innerHTML = `
${capitalize(item.area)}: ${item.label}
`; row.querySelector('.remove-btn').addEventListener("click", function() { const itemToRemove = treatmentPlan[index]; // Get item before removing treatmentPlan.splice(index, 1); renderPlanItems(); // Update plan display // Update selection state in the currently visible concern list (if any) if (!isMobileView() && concernPanel && concernPanel.classList.contains('active')) { renderConcernSelection(itemToRemove.area, concernList); // Update desktop list } showToast(`Removed: ${itemToRemove.label}`); }); treatmentPlanItems.appendChild(row); }); } planCountDesktop.textContent = `(${count})`; } // Update Mobile Submit Button (only if it exists) if(mobilePlanCount && finishPlanBtnMobile) { mobilePlanCount.textContent = count; finishPlanBtnMobile.disabled = (count === 0); } } // Renders the selection state (highlighting) for concerns in a given list element function renderConcernSelection(area, listElement) { if (!listElement) return; // Guard against null listElement const items = listElement.querySelectorAll(".concern-item"); items.forEach(item => { const concernId = item.getAttribute('data-id'); // Use data-id for reliable matching const inPlan = treatmentPlan.some(tp => tp.area === area && tp.id === concernId); item.classList.toggle("selected", inPlan); }); } // Handles showing concerns either in Desktop Panel or Mobile Modal function showConcerns(area) { const concerns = AREA_CONCERNS[area] || []; const areaTitleText = capitalize(area) + " Concerns"; if (isMobileView()) { // --- Mobile Logic: Use Modal --- if (!mobileConcernModal || !mobileConcernAreaTitle || !mobileConcernList) return; // Guard clauses mobileConcernAreaTitle.textContent = areaTitleText; mobileConcernList.innerHTML = ""; // Clear previous items concerns.forEach(concern => { const div = document.createElement("div"); div.className = "concern-item"; div.textContent = concern.label; div.setAttribute('data-id', concern.id); // Store ID for matching div.setAttribute('data-area', area); // Store area for context // Add click listener to toggle selection and close modal div.addEventListener("click", function() { toggleConcern(area, concern); // Toggle class immediately for visual feedback before modal closes this.classList.toggle("selected", treatmentPlan.some(tp => tp.area === area && tp.id === concern.id)); // Close modal after a short delay for visual feedback setTimeout(() => closeModal(mobileConcernModal), 150); }); mobileConcernList.appendChild(div); }); // Update selection state for the newly added items renderConcernSelection(area, mobileConcernList); openModal(mobileConcernModal); } else { // --- Desktop Logic: Use Panel --- if (!concernAreaTitle || !concernList || !introPanel || !planPanel || !concernPanel) return; // Guard clauses concernAreaTitle.textContent = areaTitleText; concernList.innerHTML = ""; // Clear previous items concerns.forEach(concern => { const div = document.createElement("div"); div.className = "concern-item"; div.textContent = concern.label; div.setAttribute('data-id', concern.id); // Store ID for matching div.setAttribute('data-area', area); // Store area for context div.addEventListener("click", function() { toggleConcern(area, concern); // Re-render selection state for the desktop list after toggle renderConcernSelection(area, concernList); }); concernList.appendChild(div); }); // Update selection state for the newly added items renderConcernSelection(area, concernList); // Switch panels introPanel.classList.remove('active'); planPanel.classList.remove('active'); // Hide plan panel when showing concerns concernPanel.classList.add('active'); } } // Toggles a concern in the treatment plan function toggleConcern(area, concern) { const index = treatmentPlan.findIndex(item => item.area === area && item.id === concern.id); if (index > -1) { // Remove concern treatmentPlan.splice(index, 1); showToast(`Removed: ${concern.label}`); } else { // Add concern treatmentPlan.push({ area: area, id: concern.id, label: concern.label }); showToast(`Added: ${concern.label}`); } // Update the main plan display (both desktop and mobile button state) renderPlanItems(); } // Prepares and shows the final submission form function initiateFinishPlan() { if (treatmentPlan.length === 0) return; // Should be disabled, but double-check if (!treatmentPlanDataInput || !formModal) return; // Guard clauses // Format plan for hidden input const planText = treatmentPlan.map(item => `${capitalize(item.area)}: ${item.label}`).join('\n'); treatmentPlanDataInput.value = planText; // Show the form modal openModal(formModal); } // --- Event Listeners --- // Gender Toggle if (toggleGenderBtn) { toggleGenderBtn.addEventListener('click', () => { isFemale = !isFemale; if (femaleModel) femaleModel.classList.toggle('active', isFemale); if (maleModel) maleModel.classList.toggle('active', !isFemale); toggleGenderBtn.textContent = isFemale ? 'Switch to Male' : 'Switch to Female'; }); } // Hotspot Clicks (using event delegation on containers) if (bodyModelContainer) { bodyModelContainer.addEventListener('click', function(e) { if (e.target.classList.contains('hotspot')) { e.stopPropagation(); const area = e.target.getAttribute('data-area'); if (area === "face") { if (faceModelContainer) { bodyModelContainer.style.display = "none"; faceModelContainer.style.display = "block"; } } else { showConcerns(area); } } }); } if (faceModelContainer) { faceModelContainer.addEventListener('click', function(e) { if (e.target.classList.contains('hotspot')) { e.stopPropagation(); const area = e.target.getAttribute('data-area'); showConcerns(area); } }); } // Back from Face to Body if (backToBodyBtn) { backToBodyBtn.addEventListener('click', () => { if (faceModelContainer) faceModelContainer.style.display = "none"; if (bodyModelContainer) bodyModelContainer.style.display = "block"; // Decide if we should show intro or plan panel on desktop if (!isMobileView()) { if (concernPanel) concernPanel.classList.remove('active'); // Hide concerns if user goes back if (treatmentPlan.length > 0) { if (planPanel) planPanel.classList.add('active'); if (introPanel) introPanel.classList.remove('active'); } else { if (planPanel) planPanel.classList.remove('active'); if (introPanel) introPanel.classList.add('active'); } } }); } // Hide Cover Overlays function hideCovers() { if(leftCover) leftCover.classList.add('hidden'); if (rightCover) rightCover.classList.add('hidden'); // Only hide right if it exists // Show initial panel(s) after covers hide if (!isMobileView()) { // Desktop: show intro or plan panel based on selections if (treatmentPlan.length === 0) { if(introPanel) introPanel.classList.add('active'); if(planPanel) planPanel.classList.remove('active'); } else { if(introPanel) introPanel.classList.remove('active'); if(planPanel) planPanel.classList.add('active'); } } // No specific action needed for mobile after cover hide, interaction starts with hotspots. } if(leftCover) leftCover.addEventListener('click', hideCovers); if (rightCover) rightCover.addEventListener('click', hideCovers); // Back button inside Desktop Concern Panel if (closeConcernsBtn) { closeConcernsBtn.addEventListener('click', () => { if (concernPanel) concernPanel.classList.remove('active'); // Show plan panel if it has items, otherwise intro if (treatmentPlan.length > 0) { if (planPanel) planPanel.classList.add('active'); if (introPanel) introPanel.classList.remove('active'); } else { if (planPanel) planPanel.classList.remove('active'); if (introPanel) introPanel.classList.add('active'); } }); } // Clear All Selections Button (Desktop) if (clearPlanBtn) { clearPlanBtn.addEventListener('click', () => { if (treatmentPlan.length > 0) { treatmentPlan = []; renderPlanItems(); // Update UI // If concern panel was active, switch back to intro on desktop if (!isMobileView() && concernPanel && concernPanel.classList.contains('active')) { concernPanel.classList.remove('active'); if (introPanel) introPanel.classList.add('active'); } showToast("All selections cleared."); } }); } // Finish & Get Results Buttons (Desktop and Mobile) if(finishPlanBtnDesktop) finishPlanBtnDesktop.addEventListener('click', initiateFinishPlan); if(finishPlanBtnMobile) finishPlanBtnMobile.addEventListener('click', initiateFinishPlan); // Modal Closing (Generic Handler for Close Buttons and Backdrop) document.addEventListener('click', function(e) { // Check for close buttons with data-close-modal attribute if (e.target.matches('[data-close-modal]')) { const modalId = e.target.getAttribute('data-close-modal'); const modalToClose = document.getElementById(modalId); if (modalToClose) { closeModal(modalToClose); } } // Check for backdrop clicks (target is the modal container itself) else if (e.target.classList.contains('modal')) { closeModal(e.target); } }); // Form submission (optional: add validation or confirmation) // if(contactForm) { // contactForm.addEventListener('submit', function(e) { // // Optional: Add client-side validation here if needed // console.log("Form submitted with plan:", treatmentPlanDataInput.value); // }); // } // --- Initial Setup --- renderPlanItems(); // Initialize plan display (counts, button states) // Hide covers if they shouldn't show initially (e.g., deep link, testing) // hideCovers(); // Uncomment this line if you want covers hidden by default });