1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'sha256-g5a3SrOYIecCloZ8S7M4xdT1pbYi6e7mjHrmwphRxfE=' https://static.cloudflareinsights.com; worker-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: blob: https://images.unsplash.com; manifest-src 'self'; connect-src 'self' ws: wss: https://cloudflareinsights.com https://fonts.googleapis.com https://fonts.gstatic.com https://api.groq.com https://generativelanguage.googleapis.com https://api.openai.com;"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"> 8 <meta name="apple-mobile-web-app-capable" content="yes"> 9<meta name="mobile-web-app-capable" content="yes"> 10 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> 11 <meta name="apple-mobile-web-app-title" content="Chef Popiah"> 12 <meta name="format-detection" content="telephone=no"> 13 <meta name="description" content="Chef Popiah: Your intelligent AI sous-chef and interactive kitchen companion. Cook delicious recipes step-by-step with smart timers."> 14 <meta name="keywords" content="chef popiah, ai sous chef, culinary assistant, smart kitchen timer, interactive recipe copilot, cooking clock"> 15 <meta name="author" content="popiah.dev"> 16 <meta property="og:title" content="Chef Popiah â AI Sous-Chef & Kitchen Companion"> 17 <meta property="og:type" content="website"> 18 19 <title>Chef Popiah â AI Sous-Chef & Kitchen Companion</title> 20 <link rel="icon" type="image/svg+xml" href="favicon.svg"> 21 <link rel="apple-touch-icon" href="favicon.svg"> 22 <link rel="manifest" href="manifest.json"> 23 <meta name="theme-color" content="#ff5f56"> 24 <!-- Open Graph / Social Sharing --> 25 <meta property="og:title" content="Chef Popiah â AI Sous-Chef & Kitchen Companion"> 26 <meta property="og:description" content="Chef Popiah: Your intelligent AI sous-chef and interactive kitchen companion. Cook delicious recipes step-by-step with smart timers."> 27 <meta property="og:type" content="website"> 28 <meta property="og:url" content="https://popiah.dev"> 29 <meta name="twitter:card" content="summary"> 30 <meta name="twitter:title" content="Chef Popiah â AI Sous-Chef & Kitchen Companion"> 31 <meta name="twitter:description" content="Chef Popiah: Your intelligent AI sous-chef and interactive kitchen companion. Cook delicious recipes step-by-step with smart timers."> 32 <link rel="stylesheet" href="index.css?v=2.1.0"> 33 34 35 36 <!-- Structured Data --> 37
37<script type="application/ld+json"> 38 { 39 "@context": "https://schema.org", 40 "@type": "WebApplication", 41 "name": "Chef Popiah", 42 "url": "https://popiah.dev", 43 "description": "Your intelligent AI sous-chef and interactive kitchen companion. Cook delicious recipes step-by-step with smart timers.", 44 "applicationCategory": "LifestyleApplication", 45 "operatingSystem": "Web", 46 "browserRequirements": "Requires JavaScript", 47 "author": { 48 "@type": "Organization", 49 "name": "popiah.dev" 50 } 51 } 52 </script>
52 53 54
54<script src="error-tracker.js?v=2.1.0"></script>
54 55
55<script src="mascot-init.js?v=2.1.0"></script>
55 56</head> 57<body> 58 <div id="ambient-glow" class="ambient-glow"></div> 59 60 <!-- Centered Brand Showcase --> 61 <div class="brand-showcase-container"> 62 <div class="brand-card"> 63 <svg class="brand-card-border-svg"> 64 <rect class="brand-card-border-rect" rx="16" ry="16" vector-effect="non-scaling-stroke"></rect> 65 </svg> 66 <button class="timer-settings-btn transition-transform active:scale-90" id="timer-settings-toggle" title="Settings"> 67 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 68 <circle cx="12" cy="12" r="3"></circle> 69 <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"></path> 70 </svg> 71 </button> 72 <button class="theme-toggle-btn transition-transform active:scale-90" id="theme-toggle" title="Switch Theme (âï¸ Warm Kitchen / ð Midnight Chef)"> 73 <svg class="theme-icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 74 <circle cx="12" cy="12" r="5"></circle> 75 <line x1="12" y1="1" x2="12" y2="3"></line> 76 <line x1="12" y1="21" x2="12" y2="23"></line> 77 <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> 78 <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> 79 <line x1="1" y1="12" x2="3" y2="12"></line> 80 <line x1="21" y1="12" x2="23" y2="12"></line> 81 <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> 82 <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> 83 </svg> 84 <svg class="theme-icon-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;"> 85 <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> 86 </svg> 87 </button> 88 <button class="pip-toggle-btn transition-transform active:scale-90" id="pip-toggle" title="Float Window (Always on Top)"> 89 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 90 <rect x="2" y="2" width="20" height="20" rx="2" ry="2"></rect> 91 <rect x="13" y="13" width="9" height="9" rx="1" ry="1" fill="currentColor" fill-opacity="0.25"></rect> 92 </svg> 93 </button> 94 <button class="clock-toggle-btn transition-transform active:scale-90" id="clock-toggle" title="Kitchen Timer Mode"> 95 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" 96 stroke-linecap="round" stroke-linejoin="round"> 97 <circle cx="12" cy="12" r="10"></circle> 98 <polyline points="12 6 12 12 16 14"></polyline> 99 </svg> 100 </button> 101 102 <!-- Glassmorphic Settings Overlay --> 103 <div class="timer-settings-panel" id="timer-settings-panel"> 104 <div class="settings-header"> 105 <div class="settings-header-center"> 106 <div class="settings-header-badge"> 107 <svg class="settings-header-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"> 108 <circle cx="12" cy="12" r="3"></circle> 109 <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2
1090 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> 110 </svg> 111 <span>Preferences</span> 112 </div> 113 <div class="settings-title">Settings</div> 114 </div> 115 <button type="button" class="settings-close-btn transition-all duration-150 active:scale-90" id="settings-close-btn" aria-label="Close Settings" title="Close Settings (Esc)">â</button> 116 </div> 117 118 <div class="settings-content-flow"> 119 <!-- Card 1: Appearance & Ambience --> 120 <div class="settings-section-card"> 121 <div class="settings-card-header"> 122 <span class="settings-card-icon">ð¨</span> 123 <div class="settings-subtitle">Appearance & Ambience</div> 124 </div> 125 126 <!-- Theme Row (Full-width Justified Stack) --> 127 <div class="settings-stacked-row select-row"> 128 <div class="settings-label-wrap"> 129 <label for="theme-select">Visual Theme</label> 130 <span class="settings-hint-text">Atmospheric lighting & palette</span> 131 </div> 132 <select id="theme-select" class="sr-only"> 133 <option value="warm-kitchen">âï¸ Warm Kitchen (Daylight)</option> 134 <option value="midnight">ð Midnight Chef (Dark)</option> 135 </select> 136 <div class="settings-segmented-control grid grid-cols-2 p-1 bg-black/40 rounded-xl border border-white/10 w-full" id="theme-segmented-control" role="radiogroup" aria-label="Theme selection"> 137 <button type="button" class="theme-segment-btn flex items-center justify-center gap-1.5 py-1.5 px-2 rounded-lg text-xs font-semibold transition-all" data-value="warm-kitchen"> 138 <span>âï¸</span> Warm Kitchen 139 </button> 140 <button type="button" class="theme-segment-btn flex items-center justify-center gap-1.5 py-1.5 px-2 rounded-lg text-xs font-medium transition-all" data-value="midnight"> 141 <span>ð</span> Midnight Chef 142 </button> 143 </div> 144 </div> 145 146 <div class="settings-card-divider"></div> 147 148 <!-- Mascot Row --> 149 <div class="settings-row select-row"> 150 <div class="settings-label-wrap"> 151 <label for="mascot-select">Mascot Companion</label> 152 <span class="settings-hint-text">Animated sous-chef cat</span> 153 </div> 154 <div class="settings-custom-select-wrap"> 155 <select id="mascot-select" class="settings-styled-select"> 156 <option value="abyssinian">ð¦ Red Abyssinian</option> 157 <option value="tuxedo">ðâ⬠Tuxedo Cat</option> 158 </select> 159 <svg class="select-chevron" width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 160 <polyline points="6 9 12 15 18 9"></polyline> 161 </svg> 162 </div> 163 </div> 164 </div> 165 166 <div class="settings-divider"></div> 167 168 <!-- Card 2: Kitchen Timer & Measurements --> 169 <div class="settings-section-card"> 170 <div class="settings-card-header"> 171 <span class="settings-card-icon">â±ï¸</span> 172 <div class="settings-subtitle">Kitchen Timer & Measurements</div> 173 </div> 174 175 <!-- Units Row (Full-width Justified Stack) --> 176 <div class="settings-stacked-row select-row"> 177 <div class="settings-label-wrap"> 178 <label for="units-select">Units System</label>
179 <span class="settings-hint-text">Recipe ingredient measurements</span> 180 </div> 181 <select id="units-select" class="sr-only"> 182 <option value="metric">Metric / SI (g, ml, °C)</option> 183 <option value="imperial">Imperial / US (oz, cup, °F)</option> 184 </select> 185 <div class="settings-segmented-control grid grid-cols-2 p-1 bg-black/40 rounded-xl border border-white/10 w-full" id="units-segmented-control" role="radiogroup" aria-label="Units selection"> 186 <button type="button" class="units-segment-btn flex items-center justify-center gap-1.5 py-1.5 px-2 rounded-lg text-xs font-semibold transition-all" data-value="metric"> 187 <span>âï¸</span> Metric (g/ml) 188 </button> 189 <button type="button" class="units-segment-btn flex items-center justify-center gap-1.5 py-1.5 px-2 rounded-lg text-xs font-medium transition-all" data-value="imperial"> 190 <span>ð</span> Imperial (oz/cup) 191 </button> 192 </div> 193 </div> 194 195 <div class="settings-card-divider"></div> 196 197 <!-- Default Kitchen Timer Row --> 198 <div class="settings-row number-row" id="focus-settings-row"> 199 <div class="settings-label-wrap"> 200 <label for="focus-input">Quick Timer Duration</label> 201 <span class="settings-hint-text">Default kitchen timer interval (1-180 min)</span> 202 </div> 203 <div class="settings-stepper"> 204 <button type="button" class="stepper-btn stepper-minus" data-target="focus-input" data-step="5" aria-label="Decrease timer minutes">â</button> 205 <div class="stepper-input-box"> 206 <input type="number" id="focus-input" min="1" max="180" value="15"> 207 <span class="stepper-unit">min</span> 208 </div> 209 <button type="button" class="stepper-btn stepper-plus" data-target="focus-input" data-step="5" aria-label="Increase timer minutes">+</button> 210 </div> 211 </div> 212 </div> 213 214 <div class="settings-divider"></div> 215 216 <!-- Card 3: Sous-Chef Intelligence --> 217 <div class="settings-section-card"> 218 <div class="settings-card-header"> 219 <span class="settings-card-icon">â¨</span> 220 <div class="settings-subtitle">Sous-Chef Intelligence</div> 221 </div> 222 223 <div class="settings-row select-row"> 224 <div class="settings-label-wrap"> 225 <label for="ai-provider-select">AI Engine</label> 226 <span class="settings-hint-text" id="ai-engine-hint">Chef Popiah Cloud (Built-in)</span> 227 </div> 228 <div class="settings-custom-select-wrap"> 229 <select id="ai-provider-select" class="settings-styled-select"> 230 <option value="edge" selected>â¡ Chef Popiah Cloud (Built-in)</option> 231 <option value="local">ð¥ï¸ Your Local LLM (Ollama / LM Studio / vLLM)</option> 232 <option value="gemini" disabled>⨠Google Gemini (BYOK - Coming Soon)</option> 233 <option value="openai" disabled>ð¤ OpenAI (BYOK - Coming Soon)</option> 234 <option value="groq" disabled>â¡ Groq (BYOK - Coming Soon)</option> 235 </select> 236 <svg class="select-chevron" width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 237 <polyline points="6 9 12 15 18 9"></polyline> 238 </svg> 239 </div> 240 </div> 241 242 <!-- Local LLM Configuration (Shown when "Your Local LLM" is selected) --> 243 <div id="local-ai-config-section" style="display: none; width: 100%; flex-direction: column; gap: 10px;"> 244 <div class="settings-row text-row" id="local-ai-endpoint-row"> 245 <div class="settings-label-wrap"> 246 <label for="local-ai-url-input">Endpoint URL</label>
247 <span class="settings-hint-text">Ollama, LM Studio, or vLLM</span> 248 </div> 249 <div class="settings-key-input-wrap"> 250 <input type="text" id="local-ai-url-input" placeholder="http://localhost:11434/v1" autocomplete="off" spellcheck="false"> 251 </div> 252 </div> 253 254 <div class="settings-row text-row" id="local-ai-model-row"> 255 <div class="settings-label-wrap"> 256 <label for="local-ai-model-input">Model Name</label> 257 <span class="settings-hint-text">Model loaded in local runner</span> 258 </div> 259 <div class="settings-key-input-wrap"> 260 <input type="text" id="local-ai-model-input" placeholder="llama3.2" autocomplete="off" spellcheck="false"> 261 </div> 262 </div> 263 264 <div class="settings-row text-row" id="local-ai-key-row"> 265 <div class="settings-label-wrap"> 266 <label for="local-ai-key-input">API Key (Optional)</label> 267 <span class="settings-hint-text">Only if your server requires auth</span> 268 </div> 269 <div class="settings-key-input-wrap"> 270 <input type="password" id="local-ai-key-input" placeholder="Optional (e.g. ollama, vllm)" autocomplete="off"> 271 </div> 272 </div> 273 274 <div class="settings-row actions-row" style="margin-top: 4px; justify-content: space-between; align-items: center;"> 275 <div class="settings-label-wrap"> 276 <span class="settings-hint-text" style="font-size: 0.68rem; color: #94a3b8;">ð Direct browser connection</span> 277 </div> 278 <button type="button" class="settings-test-btn" id="local-ai-test-btn" style="padding: 5px 12px; font-size: 0.72rem; font-weight: 600; border-radius: 8px; border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.08); color: #fed7aa; cursor: pointer; transition: all 0.2s;"> 279 ð Test Connection 280 </button> 281 </div> 282 <div id="local-ai-test-result" style="display: none; font-size: 0.72rem; padding: 6px 10px; border-radius: 8px; margin-top: 4px; line-height: 1.4;"></div> 283 <div class="settings-hint" style="margin-top: 4px; font-size: 0.65rem; color: #71717a; line-height: 1.35;"> 284 ð¡ <strong>Tip:</strong> Ensure your local runner has CORS enabled (e.g. <code>OLLAMA_ORIGINS="*"</code> for Ollama, or "Enable CORS" in LM Studio). 285 </div> 286 </div> 287 288 <div class="settings-row text-row" id="ai-key-row" style="display: none;"> 289 <div class="settings-label-wrap"> 290 <label for="ai-api-key-input">API Key</label> 291 <span class="settings-hint-text">ð Stored locally in browser</span> 292 </div> 293 <div class="settings-key-input-wrap"> 294 <input type="password" id="ai-api-key-input" placeholder="Paste API key..." autocomplete="off"> 295 </div> 296 </div> 297 </div> 298 299 <div class="settings-divider"></div> 300 301 <!-- Card 4: Dietary & Allergens --> 302 <div class="settings-section-card" id="guardrails-settings-card"> 303 <div class="settings-card-header"> 304 <span class="settings-card-icon">ð¡ï¸</span> 305 <div class="settings-subtitle" id="guardrails-settings-section">Dietary & Allergens</div> 306 </div> 307 <div class="settings-hint">Persistent rules for all recipes</div> 308 309 <div class="settings-row switch-row checkbox-row"> 310 <div class="settings-label-wrap"> 311 <label for="guardrail-halal">ð Halal (No Pork/Alcohol)</label> 312 <span class="settings-hint-text">Zero pork, lard, bacon, or cooking alcohol</span> 313 </div> 314 <label class="settings-toggle-switch" for="guardrail-halal"> 315 <input type="checkbox" id="guardrail-halal" class="settings-toggle-input">
316 <span class="settings-toggle-track"></span> 317 </label> 318 </div> 319 320 <div class="settings-card-divider"></div> 321 322 <div class="settings-row switch-row checkbox-row"> 323 <div class="settings-label-wrap"> 324 <label for="guardrail-kosher">â¡ï¸ Kosher (No Pork/Shellfish)</label> 325 <span class="settings-hint-text">Zero pork, zero shellfish, separated dairy</span> 326 </div> 327 <label class="settings-toggle-switch" for="guardrail-kosher"> 328 <input type="checkbox" id="guardrail-kosher" class="settings-toggle-input"> 329 <span class="settings-toggle-track"></span> 330 </label> 331 </div> 332 333 <div class="settings-card-divider"></div> 334 335 <div class="settings-allergens-wrap"> 336 <div class="settings-sublabel">Allergen Exclusions:</div> 337 <div class="settings-allergens-chips" id="settings-allergens-chips"> 338 <button type="button" class="allergen-chip" data-allergen="peanuts">ð¥ Peanuts</button> 339 <button type="button" class="allergen-chip" data-allergen="tree-nuts">ð° Tree Nuts</button> 340 <button type="button" class="allergen-chip" data-allergen="shellfish">ð¦ Shellfish</button> 341 <button type="button" class="allergen-chip" data-allergen="gluten">ð¾ Gluten</button> 342 <button type="button" class="allergen-chip" data-allergen="dairy">ð¥ Dairy</button> 343 <button type="button" class="allergen-chip" data-allergen="soy">ð« Soy</button> 344 <button type="button" class="allergen-chip" data-allergen="eggs">ð¥ Eggs</button> 345 <button type="button" class="allergen-chip" data-allergen="sesame">ð¿ Sesame</button> 346 </div> 347 </div> 348 </div> 349 </div> 350 351 <!-- Sticky Actions & Version Footer --> 352 <div class="settings-actions-footer"> 353 <div class="settings-actions"> 354 <button class="settings-cancel-btn transition-all duration-150 active:scale-95" id="settings-cancel-btn">Cancel</button> 355 <button class="settings-save-btn transition-all duration-150 active:scale-95" id="settings-save-btn">Save</button> 356 </div> 357 <div class="settings-version-info"> 358 v2.1.0 ⢠Sep 13, 2026 359 </div> 360 </div> 361 </div> 362 <!-- Culinary Sous-Chef HUD Bar (Compact horizontal header in recipe mode) --> 363 <div class="recipe-hud-bar" id="recipe-hud-bar"> 364 <div class="hud-left-group"> 365 <div class="logo-wrapper"> 366 <!-- SVG Red Abyssinian Cat Logo with code elements --> 367 <svg viewBox="0 2 100 70" fill="none" xmlns="http://www.w3.org/2000/svg"> 368 <defs> 369 <linearGradient id="cat-grad-l" x1="0%" y1="0%" x2="0%" y2="100%"> 370 <stop offset="0%" stop-color="var(--cat-fur-l-start, hsl(18, 90%, 58%))" /> 371 <stop offset="100%" stop-color="var(--cat-fur-l-end, hsl(18, 90%, 48%))" /> 372 </linearGradient> 373 <linearGradient id="cat-grad-r" x1="0%" y1="0%" x2="0%" y2="100%"> 374 <stop offset="0%" stop-color="var(--cat-fur-r-start, hsl(18, 85%, 52%))" /> 375 <stop offset="100%" stop-color="var(--cat-fur-r-end, hsl(18, 85%, 42%))" /> 376 </linearGradient> 377 <radialGradient id="eye-glow" cx="40%" cy="40%" r="60%"> 378 <stop offset="0%" stop-color="var(--cat-eye-start, hsl(42, 100%, 72%))" /> 379 <stop offset="100%" stop-color="var(--cat-eye-end, hsl(38, 95%, 48%))" /> 380 </radialGradient> 381 <filter id="eye-blur" filterUnits="userSpaceOnUse" x="0" y="0" width="100" height="70"> 382 <feGaussianBlur stdDeviation="1.5" /> 383 </filter> 384 </defs> 385 <!-- Left Ear --> 386 <!-- Curved Left Ear (Default) --> 387 <path class="cat-ear-l cat-ear-l-curved" d="M 28 42 c -1.4987 -3.0214, -7.3610 -14.1069, -8.9925 -18.1282 c -1.6315 -4.0213, -1.7318 -5.4579, -0.7963 -5.9997 c 0.9356 -0.5418, 3.1120 0.3805, 6.4100 2.7487 c 3.2980 2.3682, 11.1483 9.5505, 13.3788 11.3792 Z" fill="url(#cat-grad-l)" stroke="var(--border-glass-bright)" 388 stroke-width="1.2" stroke-linejoin="round" /> 389 <path class="cat-ear-l cat-ear-l-curved" d="M 26 38 c -0.7273 -2.0094, -3.6486 -9.3976, -4.3639 -12.0561 c -0.7153 -2.6586, -0.6352 -3.5874, 0.0721 -3.8953 c 0.7073 -0.3079, 2.1252 0.3801, 4.1723 2.0474 c 2.0472 1.6673, 6.7587 6.6303, 8.1196 7.9040 Z" fill="var(--cat-inner-ear, #4A1505)" opacity="0.65" /> 390 <!-- Pointy Left Ear (Focus Mode) --> 391 <path class="cat-ear-l cat-ear-l-pointy" d="M38 32 L12 12 L28 42 Z" fill="url(#cat-grad-l)" stroke="var(--border-glass-bright)" 392 stroke-width="1.2" stroke-linejoin="round" /> 393 <path class="cat-ear-l cat-ear-l-pointy" d="M34 32 L18 18 L26 38 Z" fill="var(--cat-inner-ear, #4A1505)" opacity="0.65" /> 394 395 <!-- Right Ear --> 396 <!-- Curved Right Ear (Default) --> 397 <path class="cat-ear-r cat-ear-r-curved" d="M 72 42 c 1.4987 -3.0214, 7.3610 -14.1069, 8.9925 -18.1282 c 1.6315 -4.0213, 1.7318 -5.4579, 0.7963 -5.9997 c -0.9356 -0.5418, -3.1120 0.3805, -6.4100 2.7487 c -3.2980 2.3682, -11.1483 9.5505, -13.3788 11.3792 Z" fill="url(#cat-grad-r)" stroke="var(--border-glass-bright)" 398 stroke-width="1.2" stroke-linejoin="round" /> 399 <path class="cat-ear-r cat-ear-r-curved" d="M 74 38 c 0.7273 -2.0094, 3.6486 -9.3976, 4.3639 -12.0561 c 0.7153 -2.6586, 0.6352 -3.5874, -0.0721 -3.8953 c -0.7073 -0.3079, -2.1252 0.3801, -4.1723 2.0474 c -2.0472 1.6673, -6.7587 6.6303, -8.1196 7.9040 Z" fill="var(--cat-inner-ear, #4A1505)" opacity="0.8" /> 400 <!-- Pointy Right Ear (Focus Mode) --> 401 <path class="cat-ear-r cat-ear-r-pointy" d="M62 32 L88 12 L72 42 Z" fill="url(#cat-grad-r)" stroke="var(--border-glass-bright)" 402 stroke-width="1.2" stroke-linejoin="round" /> 403 <path class="cat-ear-r cat-ear-r-pointy" d="M66 32 L82 18 L74 38 Z" fill="var(--cat-inner-ear, #4A1505)" opacity="0.8" /> 404 405 <!-- Head split (3D Bisection Fold) --> 406 <path d="M50 30 L28 42 L50 68 Z" fill="url(#cat-grad-l)" stroke="var(--border-glass)" stroke-width="0.5" 407 stroke-linejoin="round" /> 408 <path d="M50 30 L72 42 L50 68 Z" fill="url(#cat-grad-r)" stroke="var(--border-glass)" stroke-width="0.5" 409 stroke-linejoin="round" /> 410 411 <!-- Face Patch (toggled and styled via CSS) --> 412 <path class="cat-face-patch" d="M50 46 L42 60 L50 68 L58 60 Z" /> 413 414 <!-- Golden Almond Eyes --> 415 <path class="cat-eye-glow cat-eye-iris-l" d="M36 44 Q43 40 46 47 Q41 50 36 44 Z" fill="var(--cat-eye-glow, hsl(42, 95%, 52%))" 416 stroke="var(--cat-eye-glow, hsl(42, 95%, 52%))" stroke-width="2.5" stroke-linejoin="round" filter="url
416(#eye-blur)" /> 417 <path class="cat-eye-glow cat-eye-iris-r" d="M64 44 Q57 40 54 47 Q59 50 64 44 Z" fill="var(--cat-eye-glow, hsl(42, 95%, 52%))" 418 stroke="var(--cat-eye-glow, hsl(42, 95%, 52%))" stroke-width="2.5" stroke-linejoin="round" filter="url(#eye-blur)" /> 419 420 <path class="cat-eye cat-eye-iris-l" d="M36 44 Q43 40 46 47 Q41 50 36 44 Z" fill="url(#eye-glow)" /> 421 <ellipse class="cat-eye cat-pupil-l" cx="41.5" cy="45" rx="0.6" ry="2.2" fill="var(--cat-pupil, #0c0806)" /> 422 <circle class="cat-eye cat-eye-highlight" cx="40.5" cy="44" r="0.8" fill="white" opacity="0.9" /> 423 424 <path class="cat-eye cat-eye-iris-r" d="M64 44 Q57 40 54 47 Q59 50 64 44 Z" fill="url(#eye-glow)" /> 425 <ellipse class="cat-eye cat-pupil-r" cx="58.5" cy="45" rx="0.6" ry="2.2" fill="var(--cat-pupil, #0c0806)" /> 426 <circle class="cat-eye cat-eye-highlight" cx="57.5" cy="44" r="0.8" fill="white" opacity="0.9" /> 427 428 <!-- Nose --> 429 <path d="M48 56 L52 56 L50 59 Z" fill="var(--cat-nose, #5C3218)" /> 430 431 <!-- Developer Whiskers (Code Angle Brackets) --> 432 <path class="cat-whisker" d="M22 52 L10 60 L22 68" stroke="var(--cat-whisker, var(--primary))" stroke-width="2.5" 433 stroke-linecap="round" stroke-linejoin="round" /> 434 <path class="cat-whisker" d="M78 52 L90 60 L78 68" stroke="var(--cat-whisker, var(--primary))" stroke-width="2.5" 435 stroke-linecap="round" stroke-linejoin="round" /> 436 </svg> 437 </div> 438 <span class="hud-brand-tag transition-all duration-200" id="hud-brand-tag" title="Chef Popiah Culinary Assistant">Chef Popiah</span> 439 </div> 440 <h1 class="brand-title">Chef <span>Popiah</span></h1> 441 <div class="hud-center-group"> 442 <div class="clock-display" id="clock-time"><span class="clock-unit-hrs">00</span><span 443 class="clock-colon">:</span><span class="clock-unit-mins">00</span></div> 444 <button type="button" class="hud-timer-pause-btn transition-all duration-150 active:scale-90" id="hud-timer-pause-btn" title="Pause / Resume Cooking Timer" aria-label="Pause or Resume Timer" style="display: none;"> 445 <span class="hud-pause-icon">â¸ï¸</span> 446 <span class="hud-play-icon" style="display: none;">â¶ï¸</span> 447 </button> 448 <span class="hud-step-badge transition-all duration-150 active:scale-95 select-none" id="hud-step-badge" style="display: none;">0/0 done</span> 449 <div class="clock-meta" id="clock-meta"> 450 <span id="clock-date"></span> 451 <span class="clock-meta-divider">â¢</span> 452 <div class="clock-session-wrap"> 453 <span id="clock-session" title="Kitchen timer active ⢠Scroll wheel or drag to adjust ⢠Click to reset">Timer: 15:00</span> 454 <button type="button" class="picker-wheel-trigger" id="picker-wheel-trigger" title="Open Picker Wheel (Scroll or Drag to spin)">
455 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 456 <circle cx="12" cy="12" r="9"></circle> 457 <polyline points="12 6 12 12 15 15"></polyline> 458 </svg> 459 </button> 460 </div> 461 </div> 462 </div> 463 <div class="hud-right-group" id="hud-right-group"> 464 <button type="button" class="hud-action-btn transition-all duration-150 active:scale-95" id="hud-settings-btn" title="Settings" aria-label="Settings"> 465 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 466 <circle cx="12" cy="12" r="3"></circle> 467 <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"></path> 468 </svg> 469 </button> 470 <button type="button" class="hud-action-btn transition-all duration-150 active:scale-95" id="hud-pip-btn" title="Float Window (Always on Top)" aria-label="Picture in Picture"> 471 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 472 <rect x="2" y="2" width="20" height="20" rx="2" ry="2"></rect> 473 <rect x="13" y="13" width="9" height="9" rx="1" ry="1" fill="currentColor" fill-opacity="0.25"></rect> 474 </svg> 475 </button> 476 <button type="button" class="hud-action-btn hud-close-btn transition-all duration-150 active:scale-90" id="hud-close-recipe-btn" title="Exit Recipe" aria-label="Close Recipe">â</button> 477 </div> 478 </div> 479 <!-- Thin Step Progress Line --> 480 <div class="hud-progress-line-track" id="hud-progress-line-track" style="display: none;"> 481 <div class="hud-progress-line-fill" id="hud-progress-line-fill" style="width: 0%;"></div> 482 </div> 483 <div class="timer-adjust-bubble" id="timer-adjust-bubble" aria-live="polite"></div> 484 485 <!-- Interactive 3D Timer Picker Wheel --> 486 <div class="timer-picker-wheel" id="timer-picker-wheel" aria-label="Timer Picker Wheel"> 487 <div class="picker-wheel-card"> 488 <div class="picker-wheel-header"> 489 <button type="button" class="picker-wheel-close transition-all duration-150 active:scale-90" id="picker-wheel-close" title="Done (Esc)">â Done</button> 490 </div> 491 492 <div class="picker-wheel-cylinder-wrapper" id="picker-wheel-wrapper"> 493 <div class="picker-wheel-lens"></div> 494 <div class="picker-wheel-cylinder" id="picker-wheel-cylinder"> 495 <!-- Drum slats rendered dynamically with 3D rotation --> 496 </div> 497 </div> 498 </div> 499 </div> 500 501 <!-- Interactive 3D Servings / Pax Picker Wheel --> 502 <div class="servings-picker-wheel" id="servings-picker-wheel" aria-label="Servings Picker Wheel"> 503 <div class="picker-wheel-card"> 504 <div class="picker-wheel-header"> 505 <button type="button" class="picker-wheel-close transition-all duration-150 active:scale-90" id="servings-wheel-close" title="Done (Esc)">â Done</button> 506 </div> 507 508 <div class="picker-wheel-cylinder-wrapper" id="servings-wheel-wrapper"> 509 <div class="picker-wheel-lens"></div> 510 <div class="picker-wheel-cylinder" id="servings-wheel-cylinder"> 511 <!-- Drum slats rendered dynamically with 3D rotation (1 to 16) --> 512 </div> 513 </div> 514 </div> 515 </div> 516 517 <!-- Interactive 3D Dietary Preference Picker Wheel --> 518 <div class="diet-picker-wheel" id="diet-picker-wheel" aria-label="Dietary Preference Picker Wheel"> 519 <div class="picker-wheel-card"> 520 <div class="picker-wheel-header"> 521 <button type="button" class="picker-wheel-close transition-all duration-150 active:scale-90" id="diet-wheel-close" title="Done (Esc)">â Done</button> 522 </div> 523 524 <div class="picker-wheel-cylinder-wrapper" id="diet-wheel-wrapper"> 525 <div class="picker-wheel-lens"></div> 526 <div class="picker-wheel-cylinder" id="diet-wheel-cylinder"> 527 <!-- Drum slats rendered dynamically with 3D rotation --> 528 </div> 529 </div> 530 </div> 531 </div> 532 533 <!-- Interactive 3D Recipe Type / Category Picker Wheel --> 534 <div class="type-picker-wheel" id="type-picker-wheel" aria-label="Recipe Type Picker Wheel"> 535 <div class="picker-wheel-card"> 536 <div class="picker-wheel-header"> 537 <button type="button" class="picker-wheel-close transition-all duration-150 active:scale-90" id="type-wheel-close" title="Done (Esc)">â Done</button> 538 </div> 539 540 <div class="picker-wheel-cylinder-wrapper" id="type-wheel-wrapper"> 541 <div class="picker-wheel-lens"></div> 542 <div class="picker-wheel-cylinder" id="type-wheel-cylinder"> 543 <!-- Drum slats rendered dynamically with 3D rotation --> 544 </div> 545 </div> 546 </div> 547 </div> 548 549 <!-- Interactive 3D Time Budget Picker Wheel --> 550 <div class="time-picker-wheel" id="time-picker-wheel" aria-label="Time Budget Picker Wheel"> 551 <div class="picker-wheel-card"> 552 <div class="picker-wheel-header"> 553 <button type="button" class="picker-wheel-close transition-all duration-150 active:scale-90" id="time-wheel-close" title="Done (Esc)">â Done</button> 554 </div> 555 556 <div class="picker-wheel-cylinder-wrapper" id="time-wheel-wrapper"> 557 <div class="picker-wheel-lens"></div> 558 <div class="picker-wheel-cylinder" id="time-wheel-cylinder"> 559 <!-- Drum slats rendered dynamically with 3D rotation --> 560 </div> 561 </div> 562 </div> 563 </div> 564 <div class="clock-quote" id="clock-quote"></div> 565 566 <!-- Chef Popiah: Recipe & Timed Cooking Assistant --> 567 <div class="recipe-copilot" id="recipe-copilot"> 568 <div class="recipe-input-wrapper"> 569 <div class="recipe-input-top-row relative w-full min-w-0"> 570 <div class="recipe-input-prefix shrink-0" title="Chef Popiah AI Copilot"> 571 <svg class="recipe-prefix-icon" width="16" height="16" viewB
571ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"> 572 <circle cx="11" cy="11" r="8"></circle> 573 <line x1="21" y1="21" x2="16.65" y2="16.65"></line> 574 </svg> 575 </div> 576 <textarea id="recipe-input" class="recipe-input flex-1 min-w-0 w-0 placeholder:text-slate-500 text-slate-100" rows="1" 577 placeholder="What taste are you craving? (e.g. sizzling spicy, savory umami)..." 578 maxlength="500" autocomplete="off" spellcheck="false"></textarea> 579 <button id="recipe-clear-input" class="recipe-clear-input shrink-0 relative z-10 transition-all duration-150 hover:scale-110 active:scale-95" type="button" title="Clear input" style="display: none;"> 580 <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 581 <line x1="18" y1="6" x2="6" y2="18"></line> 582 <line x1="6" y1="6" x2="18" y2="18"></line> 583 </svg> 584 </button> 585 <button id="recipe-cook-btn" class="recipe-cook-btn shrink-0 relative z-10 whitespace-nowrap transition-all duration-200 active:scale-[0.96]" title="Cook up re
585cipe with timers (Enter)"> 586 <svg class="cook-icon shrink-0" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"> 587 <path d="M12 2a5 5 0 0 0-5 5c0 1.93 1.1 3.6 2.7 4.4L9 21a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1l-.7-9.6A5 5 0 0 0 17 7a5 5 0 0 0-5-5Z"/> 588 <path d="M8 7h8"/> 589 </svg> 590 <span class="cook-label whitespace-nowrap">Cook</span> 591 <kbd class="cook-kbd-hint shrink-0">âµ</kbd> 592 </button> 593 </div> 594 595 <!-- Integrated Bottom Toolbar: Pax & Diet on left, Surprise on right --> 596 <div class="recipe-input-bottom-bar"> 597 <div class="recipe-toolbar-capsule transition-all duration-200 hover:border-white/20" id="recipe-toolbar-capsule"> 598 <!-- Pax Quick Trigger --> 599 <button id="recipe-servings-btn" class="recipe-servings-btn transition-all duration-150 active:scale-95" type="button" 600 title="Portions: 2 pax ⢠Click to roll 3D wheel or scroll mouse" 601 aria-label="Serving size: 2 pax" aria-expanded="false" aria-haspopup="dialog"> 602 <span class="toolbar-label">Pax</span> 603 <span class="servings-num" id="recipe-servings-num">2</span> 604 <svg class="servings-chevron" width="7" height="7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"> 605 <polyline points="6 9 12 15 18 9"></polyline> 606 </svg> 607 </button> 608 609 <span class="toolbar-divider" aria-hidden="true"></span> 610 611 <!-- Dietary Preference Quick Trigger --> 612 <button id="recipe-diet-btn" class="recipe-diet-btn transition-all duration-150 active:scale-95" type="button" 613 title="Dietary preference: click to roll 3D wheel or scroll mouse" 614 aria-label="Dietary preference: Any Diet" aria-expanded="false" aria-haspopup="dialog"> 615 <span class="toolbar-label">Diet</span> 616 <span class="diet-icon" id="recipe-diet-icon" style="display: none;" aria-hidden="true">ð½ï¸</span> 617 <span class="diet-label" id="recipe-diet-label">Any</span> 618 <svg class="diet-chevron" width="7" height="7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"> 619 <polyline points="6 9 12 15 18 9"></polyline> 620 </svg> 621 </button> 622 623 <span class="toolbar-divider" aria-hidden="true"></span> 624 625 <!-- Category / Type Quick Trigger --> 626 <button id="recipe-type-btn" class="recipe-type-btn transition-all duration-150 active:scale-95" type="button" 627 title="Recipe type: click to roll 3D wheel or scroll mouse" 628 aria-label="Recipe type: All" aria-expanded="false" aria-haspopup="dialog"> 629 <span class="toolbar-label">Type</span> 630 <span class="type-label" id="recipe-type-label">All</span> 631 <svg class="type-chevron" width="7" height="7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"> 632 <polyline points="6 9 12 15 18 9"></polyline> 633 </svg> 634 </button> 635 636 <span class="toolbar-divider" aria-hidden="true"></span> 637 638 <!-- Time Limit Quick Trigger --> 639 <button id="recipe-time-btn" class="recipe-time-btn transition-all duration-150 active:scale-95" type="button" 640 title="Time budget: click to roll 3D wheel or scroll mouse" 641 aria-label="Time budget: Any" aria-expanded="false" aria-haspopup="dialog"> 642 <span class="toolbar-label">Time</span> 643 <span class="time-label" id="recipe-time-label">Any</span> 644 <svg class="time-chevron" width="7" height="7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"> 645 <polyline points="6 9 12 15 18 9"></polyline> 646 </svg> 647 </button> 648 </div> 649 650 <div class="recipe-input-actions"> 651 <!-- Persistent Dietary Guardrails Micro-Indicator --> 652 <div class="recipe-guardrails-wrapper" id="recipe-guardrails-wrapper" style="display: none;"> 653 <button id="recipe-guardrails-btn" class="recipe-guardrails-btn transition-all duration-150 active:scale-95" type="button" 654 title="Dietary Guardrails Active ⢠Tap to view" 655 aria-label="Active dietary guardrails" aria-haspopup="dialog" aria-expanded="false">
656 <span class="guardrails-shield-icon" aria-hidden="true">ð¡ï¸</span> 657 <span class="guardrails-icons-stack" id="recipe-guardrails-icons"></span> 658 </button> 659 </div> 660 661 <button id="recipe-surprise-btn" class="recipe-surprise-btn transition-all duration-150 active:scale-95" type="button" title="Surprise me with a mouth-watering flavor craving!" aria-label="Surprise craving"> 662 <span class="surprise-icon">ð²</span> 663 </button> 664 <button id="recipe-mode-toggle" class="recipe-mode-toggle is-fallback transition-all duration-150 active:scale-95" type="button" style="display: none;" title="AI unavailable â operating on local fallback. Click to restore AI."> 665 <span class="mode-icon">â¡</span> 666 <span class="mode-label">Fallback</span> 667 </button> 668 </div> 669 </div> 670 671 <!-- Floating Glass Tooltip for Active Dietary Guardrails --> 672 <div class="recipe-guardrails-tooltip" id="recipe-guardrails-tooltip" role="tooltip" aria-hidden="true"> 673 <div class="guardrails-tooltip-header"> 674 <div class="guardrails-tooltip-title-wrap"> 675 <span class="guardrails-tooltip-shield" aria-hidden="true">ð¡ï¸</span> 676 <span class="guardrails-tooltip-title">Active Guardrails</span> 677 </div> 678 <button type="button" class="guardrails-tooltip-close" id="guardrails-tooltip-close" aria-label="Close active guardrails tooltip">â</button> 679 </div> 680 <ul class="guardrails-tooltip-list" id="recipe-guardrails-list"></ul> 681 <div class="guardrails-tooltip-footer"> 682 <button type="button" class="guardrails-configure-btn" id="guardrails-configure-btn"> 683 <span>Configure in Settings</span> 684 <span class="configure-arrow" aria-hidden="true">â</span> 685 </button> 686 </div> 687 </div> 688 </div> 689 690 <!-- Sensory Craving Quick-Chips (Dynamic AI Appetite Stimulators) --> 691 <div class="recipe-prompt-suggestions" id="recipe-prompt-suggestions" aria-label="Culinary Craving Inspirations"> 692 <div class="suggestions-header" id="suggestions-header"> 693 <div class="suggestions-header-left"> 694 <span class="suggestions-title-tag" id="suggestions-title-tag"> 695 <span class="suggestions-sparkle">â¨</span> Fresh Cravings 696 </span> 697 </div> 698 699 <div class="suggestions-header-right"> 700 <button type="button" class="suggestions-roll-btn transition-all duration-150 active:scale-90" id="suggestions-roll-btn" title="Roll new AI craving recommendations"> 701 <svg class="roll-icon" width="11" height="11" viewB
701ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 702 <path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/> 703 </svg> 704 <span>Roll</span> 705 </button> 706 </div> 707 </div> 708 <div class="suggestions-chips-track" id="suggestions-chips-track"> 709 <button type="button" class="prompt-chip" data-prompt="Sizzling garlic butter stir-fry noodles with crispy shallots"> 710 <span class="chip-flame">ð¥</span> <span class="chip-title">Sizzling Garlic Butter</span> 711 </button> 712 <button type="button" class="prompt-chip" data-prompt="Rich umami miso ramen broth with charred scallions and soft egg"> 713 <span class="chip-flame">ð</span> <span class="chip-title">Rich Umami Miso</span> 714 </button> 715 <button type="button" class="prompt-chip" data-prompt="Crispy pan-seared lemon herb salmon with honey Dijon glaze"> 716 <span class="chip-flame">ð</span> <span class="chip-title">Charred Herb Salmon</span> 717 </button> 718 </div> 719 </div> 720 721 <!-- Tailwind Skeleton Shimmer Loader for Zero-CLS AI Generation --> 722 <div class="recipe-skeleton-loader animate-pulse flex-col gap-3 p-4 rounded-2xl bg-white/[0.04] border border-white/10 w-full" id="recipe-skeleton-loader" style="display: none;"> 723 <div class="flex items-center justify-between"> 724 <div class="h-6 bg-white/15 rounded-lg w-2/3"></div> 725 <div class="h-5 bg-white/10 rounded-full w-16"></div> 726 </div> 727 <div class="flex gap-2"> 728 <div class="h-5 bg-white/10 rounded-full w-20"></div> 729 <div class="h-5 bg-white/10 rounded-full w-16"></div> 730 <div class="h-5 bg-white/10 rounded-full w-24"></div> 731 </div> 732 <div class="h-24 bg-white/[0.04] rounded-xl w-full"></div> 733 <div class="space-y-2 mt-2"> 734 <div class="h-4 bg-white/10 rounded w-full"></div> 735 <div class="h-4 bg-white/10 rounded w-4/5"></div> 736 <div class="h-4 bg-white/10 rounded w-3/5"></div> 737 </div> 738 </div> 739 740 <!-- Recipe Card Container --> 741 <div class="recipe-card-container" id="recipe-card-container" style="display: none;"> 742 <div class="recipe-header"> 743 <div class="recipe-title-group"> 744 <h3 class="recipe-title" id="recipe-title">Dish Title</h3> 745 <div class="recipe-badges"> 746 <span class="recipe-badge source" id="recipe-source" style="display: none;">⨠AI</span> 747 <span class="recipe-badge time" id="recipe-time">â±ï¸ 15 min</span> 748 <span class="recipe-badge highlight" id="recipe-taste-badge" style="display: none;"></span> 749 <span class="recipe-badge diet" id="recipe-diet" style="display: none;"> 750 <span id="recipe-diet-badge-text">ð Halal</span> 751 </span> 752 <button type="button" class="recipe-badge servings interactive" id="recipe-servings" title="Click or scroll to adjust servings (scale ingredients)"> 753 <span id="recipe-servings-badge-text">2 pax</span> 754 <span class="badge-chevron">â¾</span> 755 </button> 756 </div> 757 </div> 758 <button class="recipe-clear-btn transition-all duration-150 active:scale-90" id="recipe-clear-btn" title="Clear recipe">Ã</button> 759 </div> 760 761 <!-- Dynamic Servings Scale Banner --> 762 <div class="recipe-servings-scale-banner" id="recipe-servings-scale-banner" style="display: none;"> 763 <div class="scale-banner-info"> 764 <span class="scale-banner-icon">âï¸</span> 765 <span class="scale-banner-text" id="recipe-scale-banner-text">Ingredients mathematically scaled for 4 pax</span> 766 </div> 767 <button type="button" class="scale-banner-recook-btn transition-all duration-150 active:scale-95" id="recipe-scale-recook-btn" title="Reset ingredients mathematically to original portions">â©ï¸ Reset portions</button> 768 </div> 769 770 <!-- User's Full Prompt Callout (never hidden or truncated) --> 771 <div class="recipe-prompt-callout" id="recipe-prompt-callout" style="display: none;" title="Click to edit or reprompt this recipe"> 772 <div class="prompt-callout-header"> 773 <div class="prompt-callout-header-left">
774 <span class="prompt-callout-icon">ð¬</span> 775 <span class="prompt-callout-label">Prompt</span> 776 </div> 777 <div class="prompt-callout-badges"> 778 <span class="prompt-callout-diet-badge" id="prompt-callout-diet-badge" style="display: none;">ð Halal</span> 779 <span class="prompt-callout-servings-badge" id="prompt-callout-servings-badge">2 pax</span> 780 </div> 781 </div> 782 <p class="prompt-callout-text" id="recipe-prompt-callout-text"></p> 783 </div> 784 785 <!-- Responsive 2-Column Culinary Grid for Screen Estate Maximization --> 786 <div class="recipe-grid-layout" id="recipe-grid-layout"> 787 <div class="recipe-grid-col-side" id="recipe-grid-col-side"> 788 <!-- Mouth-Watering Dish Presentation Showcase --> 789 <div class="recipe-hero-card" id="recipe-hero-card" style="display: none;"> 790 <div class="recipe-hero-media" id="recipe-hero-media"> 791 <img class="recipe-hero-img" id="recipe-hero-img" alt="Finished dish presentation" loading="eager" decoding="async" /> 792 <div class="recipe-hero-placeholder" id="recipe-hero-placeholder"> 793 <div class="recipe-hero-shimmer"></div> 794 <div class="recipe-hero-loader-body"> 795 <span class="recipe-hero-spinner-icon">ð¾</span> 796 <span class="recipe-hero-loader-text">Chef Popiah is plating your dish...</span> 797 <span class="recipe-hero-loader-sub">Generating mouth-watering culinary visual</span> 798 </div> 799 </div> 800 <div class="recipe-hero-badge-pill" id="recipe-hero-badge-pill"> 801 <span class="badge-dot"></span> 802 <span id="recipe-hero-badge-text">⨠Freshly Plated</span> 803 </div> 804 <div class="recipe-hero-controls"> 805 <button type="button" class="recipe-hero-action-btn transition-all duration-150 active:scale-95" id="recipe-hero-zoom-btn" title="Inspect full dish photograph in lightbox"> 806 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 807 <circle cx="11" cy="11" r="8"></circle> 808 <line x1="21" y1="21" x2="16.65" y2="16.65"></line> 809 <line x1="11" y1="8" x2="11" y2="14"></line> 810 <line x1="8" y1="11" x2="14" y2="11"></line> 811 </svg> 812 <span>Zoom</span> 813 </button> 814 <button type="button" class="recipe-hero-action-btn transition-all duration-150 active:scale-95" id="recipe-hero-regen-btn" title="Generate another culinary photography shot"> 815 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 816 <path d="M23 4v6h-6"></path> 817 <path d="M1 20v-6h6"></path> 818 <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path> 819 </svg> 820 <span>Re-plate</span> 821 </button> 822 </div> 823 <div class="recipe-hero-attribution" id="recipe-hero-attribution" style="display: none;"> 824 <span class="recipe-hero-attr-text" id="recipe-hero-attr-text"></span> 825 </div> 826 </div> 827 </div> 828 829 <p class="recipe-summary" id="recipe-summary"></p> 830 831 <!-- Mise en Place: Interactive Ingredients Prep & Smart Pantry Assistant --> 832 <div class="recipe-ingredients-section" id="recipe-ingredients-section"> 833 <div class="recipe-ingredients-header"> 834 <div class="recipe-ingredients-header-left"> 835 <button type="button" class="recipe-ingredients-collapse-btn p-1 rounded-md hover:bg-white/10 text-neutral-400 hover:text-white transition-all mr-1 cursor-pointer" id="recipe-ingredients-collapse-btn" aria-label="Toggle ingredients collapse" title="Collapse / Expand ingredients" aria-expanded="true"> 836 <svg class="w-3.5 h-3.5 transition-transform duration-200" id="recipe-ing-collapse-icon" viewB
836ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 837 <polyline points="6 9 12 15 18 9"></polyline> 838 </svg> 839 </button> 840 <span class="recipe-section-label flex items-center gap-1.5"><span class="text-amber-500">ðª</span> Mise en Place</span> 841 <span class="recipe-ingredients-count-badge" id="recipe-ingredients-count-badge" title="Mise en place prep status">0/0 prepped</span> 842 </div> 843 <div class="recipe-ingredients-header-actions"> 844 <button type="button" class="recipe-ing-toggle-btn" id="recipe-ing-toggle-all" title="Toggle check/uncheck all ingredients"> 845 Check all 846 </button> 847 </div> 848 </div> 849 850 <!-- Vertical interactive checklist --> 851 <div class="recipe-ingredients-list" id="recipe-ingredients-list" role="list" aria-label="Ingredients checklist"> 852 <!-- Rendered dynamically as checklist rows --> 853 </div> 854 855 <!-- Kept for backward compatibility if queried --> 856 <div class="recipe-ingredients-pills" id="recipe-ingredients-pills" style="display: none;"></div> 857 858 <!-- Dynamic Missing Ingredients Banner (adapts recipe or replaces missing items) --> 859 <div class="recipe-missing-banner" id="recipe-missing-banner" style="display: none;"> 860 <div class="missing-banner-content"> 861 <div class="missing-banner-header"> 862 <span class="missing-banner-icon" id="recipe-missing-banner-icon">ð¡</span> 863 <div class="missing-banner-text-group"> 864 <span class="missing-banner-title" id="recipe-missing-banner-title">Missing Ingredients</span> 865 <span class="missing-banner-desc" id="recipe-missing-banner-desc">Missing 1 item</span> 866 </div> 867 </div> 868 <div class="missing-banner-actions"> 869 <button type="button" class="missing-banner-btn missing-sub-btn" id="recipe-missing-sub-btn" title="Ask Chef Popiah to swap missing items with pantry alternatives"> 870 ð Replace with alternatives 871 </button> 872 <button type="button" class="missing-banner-btn missing-pivot-btn" id="recipe-missing-pivot-btn" style="display: none;" title="Invent a new dish using your available pantry ingredients"> 873 ðª Pivot to alternative dish 874 </button> 875 <button type="button" class="missing-banner-btn missing-omit-btn" id="recipe-missing-omit-btn" title="Ask Chef Popiah to adapt recipe to cook without missing ingredients">
876 ⨠Cook without missing 877 </button> 878 </div> 879 </div> 880 </div> 881 </div> 882 </div> 883 884 <div class="recipe-grid-col-main" id="recipe-grid-col-main"> 885 <!-- Step-by-Step Timed Cooking Instructions --> 886 <div class="recipe-steps-section"> 887 <div class="recipe-steps-header"> 888 <span class="recipe-section-label">Cooking Steps</span> 889 <span class="recipe-progress-text" id="recipe-progress-text">0/4 done</span> 890 </div> 891 <ul class="recipe-steps-list" id="recipe-steps-list"></ul> 892 </div> 893 894 <div class="recipe-chef-tip" id="recipe-chef-tip"></div> 895 </div> 896 </div> 897 </div> 898 899 <!-- Compact Recipe HUD for Picture-in-Picture mode --> 900 <div class="recipe-pip-hud" id="recipe-pip-hud" style="display: none;"> 901 <div class="recipe-pip-header"> 902 <span class="recipe-pip-dish" id="recipe-pip-dish">Dish Name</span> 903 <span class="recipe-pip-badge" id="recipe-pip-badge">Step 1/4</span> 904 </div> 905 <div class="recipe-pip-step-row"> 906 <input type="checkbox" id="recipe-pip-cb" class="recipe-pip-cb"> 907 <span class="recipe-pip-instruction" id="recipe-pip-instruction">Cooking step</span> 908 <button class="recipe-pip-timer-btn" id="recipe-pip-timer-btn" title="Start this step timer">â±ï¸ 3m</button> 909 </div> 910 </div> 911 </div> 912 </div> 913 </div> 914 915 <!-- Dish Showcase Lightbox Modal --> 916 <div class="dish-lightbox-modal" id="dish-lightbox-modal" style="display: none;" role="dialog" aria-modal="true" aria-hidden="true" aria-label="Dish photograph full view"> 917 <div class="dish-lightbox-backdrop" id="dish-lightbox-backdrop"></div> 918 <div class="dish-lightbox-content"> 919 <button type="button" class="dish-lightbox-close transition-all duration-200 active:scale-90" id="dish-lightbox-close" title="Close photo view (Esc)">Ã</button> 920 <div class="dish-lightbox-image-wrap"> 921 <img class="dish-lightbox-img" id="dish-lightbox-img" alt="Finished dish full presentation" /> 922 </div> 923 <div class="dish-lightbox-footer"> 924 <div class="dish-lightbox-info"> 925 <h4 class="dish-lightbox-title" id="dish-lightbox-title">Dish Title</h4> 926 <span class="dish-lightbox-subtitle" id="dish-lightbox-subtitle">Award-winning culinary presentation</span> 927 <div class="dish-lightbox-attribution" id="dish-lightbox-attribution" style="display: none;"> 928 <span class="dish-lightbox-attr-text" id="dish-lightbox-attr-text"></span> 929 </div> 930 </div> 931 <div class="dish-lightbox-actions"> 932 <a class="dish-lightbox-download-btn transition-all duration-200 hover:scale-[1.03] active:scale-95" id="dish-lightbox-download-btn" download="chef-popiah-dish.png" target="_blank" rel="noopener"> 933 ⬠Save Photo 934 </a> 935 </div> 936 </div> 937 </div> 938 </div> 939 940 <!-- Floating Glass Toast Notification Pill --> 941 <div id="toast-container" class="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 pointer-events-none flex flex-col items-center gap-2 max-w-[92vw]" aria-live="polite"></div> 942 943
943<script src="app.js?v=2.1.0"></script>
vendor: 1 bytes, line 943
943
944<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"4c9eed491d2f41e0a473912ad5b6ada6","r":1,"spa":2}' crossorigin="anonymous"></script>
944 945</body> 946 947</html>
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.