1(function () { 2 'use strict'; 3 var EXHIBITS = [ 4 { 5 id: 'bloom-pop-workshop', 6 title: 'Pop-Art Floral Masterclass', 7 date: 'June 14, 2026', 8 time: '2:00 PM \u2013 5:00 PM PHT', 9 venue: 'Bloom Studio, Lipa City', 10 price: 2500, 11 currency: '\u20B1', 12 seats: 20, 13 remaining: 8, 14 description: 'Learn hand-tied bouquet assembly techniques inspired by Warhol\u2019s bold color theory. Includes all materials, a take-home arrangement, and a signed certificate.', 15 type: 'workshop', 16 image: '/uploads/products/neon-blossom.jpg' 17 }, 18 { 19 id: 'bloom-gallery-night', 20 title: 'Ethereal Petals: A Virtual Gallery', 21 date: 'June 28, 2026', 22 time: '7:00 PM \u2013 10:00 PM PHT', 23 venue: 'Online (WebGL Experience)', 24 price: 0, 25 currency: '\u20B1', 26 seats: 200, 27 remaining: 142, 28 description: 'Explore procedurally generated 3D floral sculptures in an interactive browser gallery. Free admission. Powered by the Bloom Three.js render engine.', 29 type: 'exhibit', 30 image: '/uploads/products/velvet-midnight.jpg' 31 }, 32 { 33 id: 'bloom-dried-lab', 34 title: 'Dried & Preserved Workshop', 35 date: 'July 12, 2026', 36 time: '10:00 AM \u2013 1:00 PM PHT', 37 venue: 'Bloom Studio, Lipa City', 38 price: 1800, 39 currency: '\u20B1', 40 seats: 15, 41 remaining: 5, 42 description: 'Master the art of preserving botanicals. Create a framed dried arrangement using silica gel and glycerin techniques documented by the Smithsonian Gardens.', 43 type: 'workshop', 44 image: '/uploads/products/obsidian-rose.jpg' 45 } 46 ]; 47 48 var BAG_KEY = 'bloom_exhibit_bag'; 49 var bag = []; 50 51 function loadBag() { 52 try { bag = JSON.parse(localStorage.getItem(BAG_KEY) || '[]'); } catch (e) { bag = []; } 53 } 54 55 function saveBag() { 56 try { localStorage.setItem(BAG_KEY, JSON.stringify(bag)); } catch (e) {} 57 } 58 59 function addToBag(exhibitId) { 60 if (bag.indexOf(exhibitId) !== -1) return false; 61 bag.push(exhibitId); 62 saveBag(); 63 return true; 64 } 65 66 function removeFromBag(exhibitId) { 67 bag = bag.filter(function (id) { return id !== exhibitId; }); 68 saveBag(); 69 } 70 71 function escH(s) { 72 return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); 73 } 74 75 function money(n) { 76 return '\u20B1' + Number(n).toLocaleString('en-PH', { minimumFractionDigits: 0 }); 77 } 78 79 function renderMarquee() { 80 var el = document.getElementById('bloomExhibitMarquee'); 81 if (!el) return; 82 var items = EXHIBITS.map(function (e) { 83 return '<span class="exh-marquee-item">' + 84 '<span class="exh-marquee-type">' + e.type.toUpperCase() + '</span> ' + 85 escH(e.title) + ' \u2014 ' + escH(e.date) + 86 (e.price > 0 ? ' \u00B7 ' + money(e.price) : ' \u00B7 FREE') + 87 ' \u00B7 ' + e.remaining + ' spots left' + 88 '</span>'; 89 }).join('<span class="exh-marquee-sep">\u2726</span>'); 90 el.innerHTML = '<div class="exh-marquee-track">' + items + items + '</div>'; 91 } 92 93 function renderCards() { 94 var grid = document.getElementById('bloomExhibitGrid'); 95 if (!grid) return; 96 grid.innerHTML = EXHIBITS.map(function (e) { 97 var inBag = bag.indexOf(e.id) !== -1; 98 var soldOut = e.remaining <= 0; 99 var pctFull = Math.round(((e.seats - e.remaining) / e.seats) * 100); 100 return '<article class="exh-card glass-ethereal" data-exhibit="' + e.id + '">' + 101 '<div class="exh-card-img"><img src="' + escH(e.image) + '" alt="' + escH(e.title) + '" loading="lazy" decoding="async" onerror="this.style.display=\'none\'"></div>' + 102 '<div class="exh-card-body">' + 103 '<span class="exh-type-tag exh-type-' + e.type + '">' + e.type + '</span>' + 104 '<h3 class="exh-card-title">' + escH(e.title) + '</h3>' + 105 '<div class="exh-card-meta"><span>' + escH(e.date) + '</span><span>' + escH(e.time) + '</span></div>' + 106 '<div class="exh-card-venue">' + escH(e.venue) + '</div>' + 107 '<p class="exh-card-desc">' + escH(e.description) + '</p>' + 108 '<div class="exh-card-capacity">' + 109 '<div class="exh-bar"><div class="exh-bar-fill" style="width:' + pctFull + '%"></div></div>' + 110 '<span>' + e.remaining + ' of ' + e.seats + ' spots</span>' + 111 '</div>' + 112 '<div class="exh-card-foot">' + 113 '<span class="exh-price">' + (e.price > 0 ? money(e.price) : 'Free Admission') + '</span>' + 114 '<button class="btn btn-p exh-bag-btn' + (inBag ? ' exh-bagged' : '') + '"' + 115 (soldOut ? ' disabled' : '') + 116 ' data-id="' + e.id + '">' + 117 (soldOut ? 'Sold Out' : (inBag ? '\u2714 In Bag' : 'Bag It \u2192')) + 118 '</button>' + 119 '</div>' + 120 '</div>' + 121 '</article>'; 122 }).join(''); 123 grid.querySelectorAll('.exh-bag-btn').forEach(function (btn) { 124 btn.addEventListener('click', function () { 125 var id = btn.dataset.id; 126 if (bag.indexOf(id) !== -1) { 127 removeFromBag(id); 128 btn.classList.remove('exh-bagged'); 129 btn.textContent = 'Bag It \u2192'; 130 if (window.showToast) window.showToast('Removed from bag', 'info'); 131 } else { 132 if (addToBag(id)) { 133 btn.classList.add('exh-bagged'); 134 btn.textContent = '\u2714 In Bag'; 135 btn.style.transform = 'scale(1.1)'; 136 setTimeout(function () { btn.style.transform = ''; }, 200); 137 if (window.showToast) window.showToast('Added to exhibit bag', 'success'); 138 } 139 } 140 }); 141 }); 142 } 143 144 function injectSection() { 145 var target = document.querySelector('.subs-sec') || document.querySelector('#subs'); 146 if (!target) return; 147 if (document.getElementById('bloomExhibitSection')) return; 148 var section = document.createElement('section'); 149 section.id = 'bloomExhibitSection'; 150 section.className = 'exh-section sec-pad'; 151 section.setAttribute('aria-label', 'Floral workshops and exhibitions'); 152 section.innerHTML = 153 '<div class="exh-marquee-wrap" id="bloomExhibitMarquee" aria-hidden="true"></div>' + 154 '<div class="con">' + 155 '<div class="sec-hd" style="flex-direction:column;align-items:flex-start">' + 156 '<span class="tag tag-a">\u2726 Events</span>' + 157 '<h2 class="sec-title" style="max-width:680px">Workshops & Exhibits</h2>' + 158 '<p class="sec-sub" style="max-width:640px">Hands-on floral craft sessions and immersive gallery experiences. ' + 159 'All events are organized by the Bloom team as part of the BSIT Capstone demonstration platform. ' + 160 'Ticket availability and pricing shown are simulated for academic purposes.</p>' + 161 '</div>' + 162 '<div class="exh-grid" id="bloomExhibitGrid"></div>' + 163 '</div>'; 164 var divider = document.createElement('div'); 165 divider.className = 'p5-sec-div'; 166 divider.setAttribute('aria-hidden', 'true'); 167 target.parentNode.insertBefore(divider, target); 168 target.parentNode.insertBefore(section, divider); 169 loadBag(); 170 renderMarquee(); 171 renderCards(); 172 } 173 174 if (document.readyState === 'loading') { 175 document.addEventListener('DOMContentLoaded', injectSection); 176 } else { 177 injectSection(); 178 } 179 180 window.BloomExhibits = { addToBag: addToBag, removeFromBag: removeFromBag, getBag: function () { return bag.slice(); } }; 181})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.