steake commited on
Commit
ca7232a
·
verified ·
1 Parent(s): eca9216

improve prompt engineering for images

Browse files
components/image-gallery.js ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Image Gallery Web Component
3
+ * Displays a gallery of pharmaceutical products with lightbox functionality
4
+ */
5
+ class ImageGallery extends HTMLElement {
6
+ constructor() {
7
+ super();
8
+ this.attachShadow({ mode: 'open' });
9
+ this.images = [];
10
+ this.currentIndex = 0;
11
+ }
12
+
13
+ connectedCallback() {
14
+ // Parse images from data attribute or children
15
+ const imagesData = this.getAttribute('data-images');
16
+ if (imagesData) {
17
+ try {
18
+ this.images = JSON.parse(imagesData);
19
+ } catch (e) {
20
+ console.error('Failed to parse images data', e);
21
+ }
22
+ }
23
+
24
+ // If no images data attribute, look for child elements
25
+ if (this.images.length === 0) {
26
+ this.querySelectorAll('img').forEach(img => {
27
+ this.images.push({
28
+ src: img.src,
29
+ alt: img.alt,
30
+ title: img.title || img.alt
31
+ });
32
+ });
33
+ }
34
+
35
+ this.render();
36
+ }
37
+
38
+ render() {
39
+ const columns = this.getAttribute('columns') || '4';
40
+ const gap = this.getAttribute('gap') || '4';
41
+ const showCaptions = this.hasAttribute('show-captions');
42
+
43
+ this.shadowRoot.innerHTML = `
44
+ <style>
45
+ :host {
46
+ display: block;
47
+ width: 100%;
48
+ }
49
+
50
+ .gallery-container {
51
+ display: grid;
52
+ grid-template-columns: repeat(${columns}, 1fr);
53
+ gap: ${gap}px;
54
+ margin: 0 auto;
55
+ }
56
+
57
+ @media (max-width: 1024px) {
58
+ .gallery-container {
59
+ grid-template-columns: repeat(3, 1fr);
60
+ }
61
+ }
62
+
63
+ @media (max-width: 768px) {
64
+ .gallery-container {
65
+ grid-template-columns: repeat(2, 1fr);
66
+ }
67
+ }
68
+
69
+ @media (max-width: 480px) {
70
+ .gallery-container {
71
+ grid-template-columns: 1fr;
72
+ }
73
+ }
74
+
75
+ .gallery-item {
76
+ position: relative;
77
+ cursor: pointer;
78
+ border-radius: 8px;
79
+ overflow: hidden;
80
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
81
+ }
82
+
83
+ .gallery-item:hover {
84
+ transform: translateY(-4px);
85
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
86
+ }
87
+
88
+ .gallery-image {
89
+ width: 100%;
90
+ height: 200px;
91
+ object-fit: cover;
92
+ display: block;
93
+ }
94
+
95
+ .image-caption {
96
+ padding: 12px;
97
+ background: white;
98
+ text-align: center;
99
+ font-size: 14px;
100
+ color: #333;
101
+ }
102
+
103
+ /* Lightbox styles */
104
+ .lightbox {
105
+ display: none;
106
+ position: fixed;
107
+ top: 0;
108
+ left: 0;
109
+ width: 100%;
110
+ height: 100%;
111
+ background: rgba(0, 0, 0, 0.9);
112
+ z-index: 1000;
113
+ align-items: center;
114
+ justify-content: center;
115
+ }
116
+
117
+ .lightbox.active {
118
+ display: flex;
119
+ }
120
+
121
+ .lightbox-content {
122
+ position: relative;
123
+ max-width: 90%;
124
+ max-height: 90%;
125
+ }
126
+
127
+ .lightbox-image {
128
+ max-width: 100%;
129
+ max-height: 80vh;
130
+ object-fit: contain;
131
+ }
132
+
133
+ .lightbox-caption {
134
+ color: white;
135
+ text-align: center;
136
+ padding: 15px;
137
+ font-size: 18px;
138
+ }
139
+
140
+ .lightbox-close {
141
+ position: absolute;
142
+ top: 20px;
143
+ right: 20px;
144
+ background: none;
145
+ border: none;
146
+ color: white;
147
+ font-size: 30px;
148
+ cursor: pointer;
149
+ z-index: 1001;
150
+ }
151
+
152
+ .lightbox-nav {
153
+ position: absolute;
154
+ top: 50%;
155
+ width: 100%;
156
+ display: flex;
157
+ justify-content: space-between;
158
+ transform: translateY(-50%);
159
+ padding: 0 20px;
160
+ }
161
+
162
+ .lightbox-prev,
163
+ .lightbox-next {
164
+ background: rgba(255, 255, 255, 0.2);
165
+ border: none;
166
+ color: white;
167
+ width: 50px;
168
+ height: 50px;
169
+ border-radius: 50%;
170
+ font-size: 24px;
171
+ cursor: pointer;
172
+ transition: background 0.3s;
173
+ }
174
+
175
+ .lightbox-prev:hover,
176
+ .lightbox-next:hover {
177
+ background: rgba(255, 255, 255, 0.4);
178
+ }
179
+ </style>
180
+
181
+ <div class="gallery-container">
182
+ ${this.images.map((image, index) => `
183
+ <div class="gallery-item" data-index="${index}">
184
+ <optimized-image
185
+ src="${image.src}"
186
+ alt="${image.alt}"
187
+ height="200px"
188
+ lazy
189
+ class="gallery-image"
190
+ ></optimized-image>
191
+ ${showCaptions ? `<div class="image-caption">${image.title || image.alt}</div>` : ''}
192
+ </div>
193
+ `).join('')}
194
+ </div>
195
+
196
+ <!-- Lightbox -->
197
+ <div class="lightbox">
198
+ <button class="lightbox-close">&times;</button>
199
+ <div class="lightbox-nav">
200
+ <button class="lightbox-prev">&#10094;</button>
201
+ <button class="lightbox-next">&#10095;</button>
202
+ </div>
203
+ <div class="lightbox-content">
204
+ <img class="lightbox-image" src="" alt="">
205
+ <div class="lightbox-caption"></div>
206
+ </div>
207
+ </div>
208
+ `;
209
+
210
+ // Add event listeners
211
+ this.addEventListeners();
212
+ }
213
+
214
+ addEventListeners() {
215
+ const lightbox = this.shadowRoot.querySelector('.lightbox');
216
+ const lightboxImage = this.shadowRoot.querySelector('.lightbox-image');
217
+ const lightboxCaption = this.shadowRoot.querySelector('.lightbox-caption');
218
+ const closeBtn = this.shadowRoot.querySelector('.lightbox-close');
219
+ const prevBtn = this.shadowRoot.querySelector('.lightbox-prev');
220
+ const nextBtn = this.shadowRoot.querySelector('.lightbox-next');
221
+ const galleryItems = this.shadowRoot.querySelectorAll('.gallery-item');
222
+
223
+ // Open lightbox on image click
224
+ galleryItems.forEach(item => {
225
+ item.addEventListener('click', () => {
226
+ this.currentIndex = parseInt(item.dataset.index);
227
+ this.updateLightbox();
228
+ lightbox.classList.add('active');
229
+ document.body.style.overflow = 'hidden';
230
+ });
231
+ });
232
+
233
+ // Close lightbox
234
+ closeBtn.addEventListener('click', () => {
235
+ lightbox.classList.remove('active');
236
+ document.body.style.overflow = 'auto';
237
+ });
238
+
239
+ // Lightbox navigation
240
+ prevBtn.addEventListener('click', () => {
241
+ this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
242
+ this.updateLightbox();
243
+ });
244
+
245
+ nextBtn.addEventListener('click', () => {
246
+ this.currentIndex = (this.currentIndex + 1) % this.images.length;
247
+ this.updateLightbox();
248
+ });
249
+
250
+ // Keyboard navigation
251
+ document.addEventListener('keydown', (e) => {
252
+ if (!lightbox.classList.contains('active')) return;
253
+
254
+ switch (e.key) {
255
+ case 'Escape':
256
+ lightbox.classList.remove('active');
257
+ document.body.style.overflow = 'auto';
258
+ break;
259
+ case 'ArrowLeft':
260
+ this.currentIndex = (this.currentIndex - 1 + this.images.length) % this.images.length;
261
+ this.updateLightbox();
262
+ break;
263
+ case 'ArrowRight':
264
+ this.currentIndex = (this.currentIndex + 1) % this.images.length;
265
+ this.updateLightbox();
266
+ break;
267
+ }
268
+ });
269
+
270
+ // Close on background click
271
+ lightbox.addEventListener('click', (e) => {
272
+ if (e.target === lightbox) {
273
+ lightbox.classList.remove('active');
274
+ document.body.style.overflow = 'auto';
275
+ }
276
+ });
277
+ }
278
+
279
+ updateLightbox() {
280
+ const lightboxImage = this.shadowRoot.querySelector('.lightbox-image');
281
+ const lightboxCaption = this.shadowRoot.querySelector('.lightbox-caption');
282
+ const image = this.images[this.currentIndex];
283
+
284
+ lightboxImage.src = image.src;
285
+ lightboxImage.alt = image.alt;
286
+ lightboxCaption.textContent = image.title || image.alt;
287
+ }
288
+ }
289
+
290
+ customElements.define('image-gallery', ImageGallery);
components/image-optimizer.js ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Image Optimizer Web Component
3
+ * Automatically optimizes image loading with lazy loading, placeholders, and responsive images
4
+ */
5
+ class ImageOptimizer extends HTMLElement {
6
+ constructor() {
7
+ super();
8
+ this.attachShadow({ mode: 'open' });
9
+ }
10
+
11
+ connectedCallback() {
12
+ const src = this.getAttribute('src') || '';
13
+ const alt = this.getAttribute('alt') || '';
14
+ const width = this.getAttribute('width') || '100%';
15
+ const height = this.getAttribute('height') || 'auto';
16
+ const lazy = this.hasAttribute('lazy');
17
+ const placeholder = this.getAttribute('placeholder') || 'https://static.photos/abstract/100x100';
18
+ const category = this.getAttribute('category') || 'general';
19
+
20
+ // Generate optimized image URL based on static.photos API
21
+ const optimizeURL = (url) => {
22
+ // If it's already a static.photos URL, keep it
23
+ if (url.includes('static.photos')) return url;
24
+
25
+ // For other URLs, we could add resize parameters if needed
26
+ // For now, just return the original
27
+ return url;
28
+ };
29
+
30
+ // Create responsive image sets for different screen sizes
31
+ const generateSrcSet = (baseUrl) => {
32
+ if (!baseUrl.includes('static.photos')) return '';
33
+
34
+ // Extract dimensions if present
35
+ const dimMatch = baseUrl.match(/\/(\d+)x(\d+)\//);
36
+ if (!dimMatch) return '';
37
+
38
+ const [_, width, height] = dimMatch;
39
+ const base = baseUrl.replace(`/${width}x${height}/`, '');
40
+
41
+ // Generate srcset for common breakpoints
42
+ const sizes = [
43
+ { width: 320, height: Math.round(320 * height / width) },
44
+ { width: 640, height: Math.round(640 * height / width) },
45
+ { width: 768, height: Math.round(768 * height / width) },
46
+ { width: 1024, height: Math.round(1024 * height / width) },
47
+ { width: 1280, height: Math.round(1280 * height / width) }
48
+ ];
49
+
50
+ return sizes.map(size =>
51
+ `${base.replace(/\/\d+x\d+\//, `/${size.width}x${size.height}/`)} ${size.width}w`
52
+ ).join(', ');
53
+ };
54
+
55
+ const optimizedSrc = optimizeURL(src);
56
+ const srcset = generateSrcSet(optimizedSrc);
57
+
58
+ this.shadowRoot.innerHTML = `
59
+ <style>
60
+ :host {
61
+ display: block;
62
+ position: relative;
63
+ width: ${width};
64
+ height: ${height};
65
+ overflow: hidden;
66
+ }
67
+
68
+ .image-container {
69
+ position: relative;
70
+ width: 100%;
71
+ height: 100%;
72
+ }
73
+
74
+ .optimized-image {
75
+ width: 100%;
76
+ height: 100%;
77
+ object-fit: cover;
78
+ transition: opacity 0.3s ease;
79
+ opacity: 0;
80
+ }
81
+
82
+ .optimized-image.loaded {
83
+ opacity: 1;
84
+ }
85
+
86
+ .placeholder {
87
+ position: absolute;
88
+ top: 0;
89
+ left: 0;
90
+ width: 100%;
91
+ height: 100%;
92
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
93
+ background-size: 200% 100%;
94
+ animation: loading 1.5s infinite;
95
+ border-radius: inherit;
96
+ }
97
+
98
+ @keyframes loading {
99
+ 0% { background-position: 200% 0; }
100
+ 100% { background-position: -200% 0; }
101
+ }
102
+
103
+ .error-fallback {
104
+ position: absolute;
105
+ top: 0;
106
+ left: 0;
107
+ width: 100%;
108
+ height: 100%;
109
+ background: #f8f9fa;
110
+ display: flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ color: #6c757d;
114
+ font-size: 14px;
115
+ border-radius: inherit;
116
+ }
117
+
118
+ .error-fallback i {
119
+ font-size: 24px;
120
+ margin-bottom: 8px;
121
+ }
122
+ </style>
123
+
124
+ <div class="image-container">
125
+ <div class="placeholder"></div>
126
+ <img
127
+ class="optimized-image"
128
+ src="${optimizedSrc}"
129
+ ${srcset ? `srcset="${srcset}"` : ''}
130
+ sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
131
+ alt="${alt}"
132
+ ${lazy ? 'loading="lazy"' : ''}
133
+ onload="this.classList.add('loaded')"
134
+ onerror="this.style.display='none'; this.parentNode.querySelector('.error-fallback').style.display='flex';"
135
+ >
136
+ <div class="error-fallback" style="display: none;">
137
+ <div style="text-align: center;">
138
+ <i class="fas fa-image"></i>
139
+ <div>${alt || 'Image'}</div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ `;
144
+ }
145
+
146
+ static get observedAttributes() {
147
+ return ['src', 'alt', 'width', 'height'];
148
+ }
149
+
150
+ attributeChangedCallback(name, oldValue, newValue) {
151
+ if (oldValue !== newValue) {
152
+ this.connectedCallback();
153
+ }
154
+ }
155
+ }
156
+
157
+ customElements.define('optimized-image', ImageOptimizer);
index.html CHANGED
@@ -162,9 +162,9 @@
162
  <a href="#about" class="border-2 border-white text-white hover:bg-white hover:text-[#5d9245] font-bold py-3 px-6 rounded-full text-center transition duration-300">Learn More</a>
163
  </div>
164
  </div>
165
- <div class="md:w-1/2 flex justify-center">
166
- <img src="https://placeholders.io/800/600/medical?style=photographic" alt="Pharmaceutical products" class="rounded-xl shadow-2xl max-w-md w-full floating">
167
- </div>
168
  </div>
169
  </section>
170
 
@@ -209,7 +209,7 @@
209
  <!-- Product 1 -->
210
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
211
  <div class="relative">
212
- <img src="https://placeholders.io/400/300/pills?style=photographic&seed=1" alt="Xanax" class="w-full h-48 object-contain bg-gray-100 p-4">
213
  <span class="absolute top-2 right-2 bg-blue-500 text-white text-xs font-bold px-2 py-1 rounded-full">BESTSELLER</span>
214
  </div>
215
  <div class="p-6">
@@ -227,7 +227,7 @@
227
  <!-- Product 2 -->
228
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
229
  <div class="relative">
230
- <img src="https://placeholders.io/400/300/pills?style=photographic&seed=2" alt="Valium" class="w-full h-48 object-contain bg-gray-100 p-4">
231
  </div>
232
  <div class="p-6">
233
  <h3 class="text-xl font-bold mb-2">Valium (Diazepam) 10mg</h3>
@@ -244,7 +244,7 @@
244
  <!-- Product 3 -->
245
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
246
  <div class="relative">
247
- <img src="https://placeholders.io/400/300/pills?style=photographic&seed=3" alt="Viagra" class="w-full h-48 object-contain bg-gray-100 p-4">
248
  <span class="absolute top-2 right-2 bg-blue-500 text-white text-xs font-bold px-2 py-1 rounded-full">NEW</span>
249
  </div>
250
  <div class="p-6">
@@ -262,7 +262,7 @@
262
  <!-- Product 4 -->
263
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
264
  <div class="relative">
265
- <img src="https://placeholders.io/400/300/pills?style=photographic&seed=4" alt="Codeine" class="w-full h-48 object-contain bg-gray-100 p-4">
266
  </div>
267
  <div class="p-6">
268
  <h3 class="text-xl font-bold mb-2">Codeine 30mg</h3>
@@ -290,8 +290,8 @@
290
  <div class="container mx-auto px-4">
291
  <div class="flex flex-col md:flex-row items-center">
292
  <div class="md:w-1/2 mb-10 md:mb-0 md:pr-10">
293
- <img src="https://placeholders.io/800/600/lab?style=photographic&seed=12345" alt="Our lab" class="rounded-xl shadow-lg w-full">
294
- </div>
295
  <div class="md:w-1/2">
296
  <h2 class="text-3xl font-bold mb-6">Our Pharmaceutical Expertise</h2>
297
  <p class="text-gray-600 mb-4">At PharmaCare, we are committed to providing high-quality medications that meet strict safety and efficacy standards.</p>
@@ -342,7 +342,7 @@
342
  <!-- Testimonial 1 -->
343
  <div class="bg-white p-6 rounded-xl shadow-sm testimonial-card">
344
  <div class="flex items-center mb-4">
345
- <img src="https://placeholders.io/48/48/person?style=photographic&seed=44" alt="Sarah J." class="w-12 h-12 rounded-full mr-4">
346
  <div>
347
  <h4 class="font-bold">Sarah J.</h4>
348
  <div class="flex text-yellow-400">
@@ -360,7 +360,7 @@
360
  <!-- Testimonial 2 -->
361
  <div class="bg-white p-6 rounded-xl shadow-sm testimonial-card">
362
  <div class="flex items-center mb-4">
363
- <img src="https://placeholders.io/48/48/person?style=photographic&seed=32" alt="Michael T." class="w-12 h-12 rounded-full mr-4">
364
  <div>
365
  <h4 class="font-bold">Michael T.</h4>
366
  <div class="flex text-yellow-400">
@@ -378,7 +378,7 @@
378
  <!-- Testimonial 3 -->
379
  <div class="bg-white p-6 rounded-xl shadow-sm testimonial-card">
380
  <div class="flex items-center mb-4">
381
- <img src="https://placeholders.io/48/48/person?style=photographic&seed=68" alt="Priya K." class="w-12 h-12 rounded-full mr-4">
382
  <div>
383
  <h4 class="font-bold">Priya K.</h4>
384
  <div class="flex text-yellow-400">
@@ -657,7 +657,10 @@
657
  </div>
658
  </div>
659
  </div>
660
-
 
 
 
661
  <script>
662
  // Mobile menu toggle
663
  const mobileMenuButton = document.getElementById('mobileMenuButton');
@@ -792,7 +795,7 @@
792
  <div class="flex justify-between items-center py-4 border-b">
793
  <div>
794
  <h4 class="font-medium">${item.name}</h4>
795
- <p class="text-gray-600 text-sm">$${item.price.toFixed(2)}</p>
796
  </div>
797
  <div class="flex items-center">
798
  <button class="decrease-quantity text-gray-500 hover:text-blue-600 px-2" data-id="${item.id}">
@@ -811,7 +814,7 @@
811
  });
812
 
813
  cartItems.innerHTML = itemsHTML;
814
- cartSubtotal.textContent = `$${subtotal.toFixed(2)}`;
815
 
816
  // Add event listeners to quantity buttons
817
  document.querySelectorAll('.decrease-quantity').forEach(button => {
@@ -898,6 +901,27 @@
898
  behavior: 'smooth'
899
  });
900
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
901
  </script>
902
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=steake/pharma-see" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
903
  </html>
 
162
  <a href="#about" class="border-2 border-white text-white hover:bg-white hover:text-[#5d9245] font-bold py-3 px-6 rounded-full text-center transition duration-300">Learn More</a>
163
  </div>
164
  </div>
165
+ <div class="md:w-1/2 flex justify-center">
166
+ <img src="https://static.photos/medical/800x600/1" alt="Pharmaceutical products" class="rounded-xl shadow-2xl max-w-md w-full floating">
167
+ </div>
168
  </div>
169
  </section>
170
 
 
209
  <!-- Product 1 -->
210
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
211
  <div class="relative">
212
+ <img src="https://static.photos/medical/400x300/101" alt="Xanax" class="w-full h-48 object-contain bg-gray-100 p-4">
213
  <span class="absolute top-2 right-2 bg-blue-500 text-white text-xs font-bold px-2 py-1 rounded-full">BESTSELLER</span>
214
  </div>
215
  <div class="p-6">
 
227
  <!-- Product 2 -->
228
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
229
  <div class="relative">
230
+ <img src="https://static.photos/medical/400x300/102" alt="Valium" class="w-full h-48 object-contain bg-gray-100 p-4">
231
  </div>
232
  <div class="p-6">
233
  <h3 class="text-xl font-bold mb-2">Valium (Diazepam) 10mg</h3>
 
244
  <!-- Product 3 -->
245
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
246
  <div class="relative">
247
+ <img src="https://static.photos/medical/400x300/103" alt="Viagra" class="w-full h-48 object-contain bg-gray-100 p-4">
248
  <span class="absolute top-2 right-2 bg-blue-500 text-white text-xs font-bold px-2 py-1 rounded-full">NEW</span>
249
  </div>
250
  <div class="p-6">
 
262
  <!-- Product 4 -->
263
  <div class="bg-white rounded-xl shadow-md overflow-hidden product-card transition duration-300">
264
  <div class="relative">
265
+ <img src="https://static.photos/medical/400x300/104" alt="Codeine" class="w-full h-48 object-contain bg-gray-100 p-4">
266
  </div>
267
  <div class="p-6">
268
  <h3 class="text-xl font-bold mb-2">Codeine 30mg</h3>
 
290
  <div class="container mx-auto px-4">
291
  <div class="flex flex-col md:flex-row items-center">
292
  <div class="md:w-1/2 mb-10 md:mb-0 md:pr-10">
293
+ <img src="https://static.photos/workspace/800x600/201" alt="Our lab" class="rounded-xl shadow-lg w-full">
294
+ </div>
295
  <div class="md:w-1/2">
296
  <h2 class="text-3xl font-bold mb-6">Our Pharmaceutical Expertise</h2>
297
  <p class="text-gray-600 mb-4">At PharmaCare, we are committed to providing high-quality medications that meet strict safety and efficacy standards.</p>
 
342
  <!-- Testimonial 1 -->
343
  <div class="bg-white p-6 rounded-xl shadow-sm testimonial-card">
344
  <div class="flex items-center mb-4">
345
+ <img src="https://static.photos/people/48x48/301" alt="Sarah J." class="w-12 h-12 rounded-full mr-4">
346
  <div>
347
  <h4 class="font-bold">Sarah J.</h4>
348
  <div class="flex text-yellow-400">
 
360
  <!-- Testimonial 2 -->
361
  <div class="bg-white p-6 rounded-xl shadow-sm testimonial-card">
362
  <div class="flex items-center mb-4">
363
+ <img src="https://static.photos/people/48x48/302" alt="Michael T." class="w-12 h-12 rounded-full mr-4">
364
  <div>
365
  <h4 class="font-bold">Michael T.</h4>
366
  <div class="flex text-yellow-400">
 
378
  <!-- Testimonial 3 -->
379
  <div class="bg-white p-6 rounded-xl shadow-sm testimonial-card">
380
  <div class="flex items-center mb-4">
381
+ <img src="https://static.photos/people/48x48/303" alt="Priya K." class="w-12 h-12 rounded-full mr-4">
382
  <div>
383
  <h4 class="font-bold">Priya K.</h4>
384
  <div class="flex text-yellow-400">
 
657
  </div>
658
  </div>
659
  </div>
660
+ <!-- Image Optimizer Component -->
661
+ <script src="components/image-optimizer.js"></script>
662
+ <script src="components/image-gallery.js"></script>
663
+
664
  <script>
665
  // Mobile menu toggle
666
  const mobileMenuButton = document.getElementById('mobileMenuButton');
 
795
  <div class="flex justify-between items-center py-4 border-b">
796
  <div>
797
  <h4 class="font-medium">${item.name}</h4>
798
+ <p class="text-gray-600 text-sm">${item.price.toFixed(2)}</p>
799
  </div>
800
  <div class="flex items-center">
801
  <button class="decrease-quantity text-gray-500 hover:text-blue-600 px-2" data-id="${item.id}">
 
814
  });
815
 
816
  cartItems.innerHTML = itemsHTML;
817
+ cartSubtotal.textContent = `${subtotal.toFixed(2)}`;
818
 
819
  // Add event listeners to quantity buttons
820
  document.querySelectorAll('.decrease-quantity').forEach(button => {
 
901
  behavior: 'smooth'
902
  });
903
  });
904
+
905
+ // Image optimization initialization
906
+ document.addEventListener('DOMContentLoaded', function() {
907
+ // Replace all product images with optimized versions
908
+ const productImages = document.querySelectorAll('.product-card img');
909
+ productImages.forEach(img => {
910
+ const parent = img.parentElement;
911
+ const alt = img.alt;
912
+ const src = img.src;
913
+
914
+ // Create optimized image component
915
+ const optimizedImg = document.createElement('optimized-image');
916
+ optimizedImg.setAttribute('src', src);
917
+ optimizedImg.setAttribute('alt', alt);
918
+ optimizedImg.setAttribute('height', '200px');
919
+ optimizedImg.setAttribute('lazy', '');
920
+
921
+ // Replace the original image
922
+ img.replaceWith(optimizedImg);
923
+ });
924
+ });
925
  </script>
926
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=steake/pharma-see" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
927
  </html>