apix/templates/index.html

569 lines
No EOL
40 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>aPix Image Workspace</title>
<link rel="icon" type="image/png" href="{{ url_for('static', filename='sdvn-logo.png') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@400;500;600;700&family=Playwrite+AU+SA&family=JetBrains+Mono:wght@400;500;600;700&display=swap"
rel="stylesheet">
</head>
<body>
<div class="app-container">
<aside class="sidebar">
<div class="sidebar-header">
<div class="brand">
<h1>aPix <span class="badge">by SDVN</span></h1>
</div>
<div class="sidebar-header-actions">
<button type="button" class="toolbar-info-btn info-icon-btn" data-popup-target="help"
aria-label="Thông tin và hướng dẫn">
<span aria-hidden="true">i</span>
</button>
<button type="button" id="open-api-settings-btn" class="toolbar-info-btn info-icon-btn"
aria-label="Thiết lập API key" aria-haspopup="dialog">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path
d="M20.1 9.2214C18.29 9.2214 17.55 7.9414 18.45 6.3714C18.97 5.4614 18.66 4.3014 17.75 3.7814L16.02 2.7914C15.23 2.3214 14.21 2.6014 13.74 3.3914L13.63 3.5814C12.73 5.1514 11.25 5.1514 10.34 3.5814L10.23 3.3914C9.78 2.6014 8.76 2.3214 7.97 2.7914L6.24 3.7814C5.33 4.3014 5.02 5.4714 5.54 6.3814C6.45 7.9414 5.71 9.2214 3.9 9.2214C2.86 9.2214 2 10.0714 2 11.1214V12.8814C2 13.9214 2.85 14.7814 3.9 14.7814C5.71 14.7814 6.45 16.0614 5.54 17.6314C5.02 18.5414 5.33 19.7014 6.24 20.2214L7.97 21.2114C8.76 21.6814 9.78 21.4014 10.25 20.6114L10.36 20.4214C11.26 18.8514 12.74 18.8514 13.65 20.4214L13.76 20.6114C14.23 21.4014 15.25 21.6814 16.04 21.2114L17.77 20.2214C18.68 19.7014 18.99 18.5314 18.47 17.6314C17.56 16.0614 18.3 14.7814 20.11 14.7814C21.15 14.7814 22.01 13.9314 22.01 12.8814V11.1214C22 10.0814 21.15 9.2214 20.1 9.2214ZM12 15.2514C10.21 15.2514 8.75 13.7914 8.75 12.0014C8.75 10.2114 10.21 8.7514 12 8.7514C13.79 8.7514 15.25 10.2114 15.25 12.0014C15.25 13.7914 13.79 15.2514 12 15.2514Z" />
</svg>
</button>
</div>
</div>
<div class="controls-section">
<div class="controls-content">
<div class="input-group">
<label for="prompt">Prompt</label>
<div class="prompt-wrapper prompt-highlighting">
<div id="prompt-highlight" class="prompt-highlight" aria-hidden="true"></div>
<textarea id="prompt" placeholder="Nhập prompt miêu tả..." rows="6"></textarea>
<div class="field-action-buttons" data-target="prompt" aria-label="Prompt actions">
<button type="button" class="field-action-btn" data-action="copy" title="Copy prompt"
aria-label="Copy prompt">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor"
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2.5" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</svg>
</button>
<button type="button" class="field-action-btn" data-action="paste" title="Paste"
aria-label="Paste vào prompt">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor"
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 4h8" />
<path d="M9 2h6a2 2 0 0 1 2 2v1H7V4a2 2 0 0 1 2-2z" />
<rect x="5" y="5" width="14" height="16" rx="2" />
<path d="M9 12h3" />
<path d="M9 16h6" />
</svg>
</button>
<button type="button" class="field-action-btn" data-action="clear" title="Clear prompt"
aria-label="Xoá prompt">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor"
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 6h18" />
<path d="M19 6v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" />
<path d="M10 11v6" />
<path d="M14 11v6" />
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
</svg>
</button>
</div>
</div>
<div class="prompt-actions">
<a href="https://chatgpt.com/g/g-6923d39c8efc8191be0bc3089bebc441-banana-prompt-guide"
target="_blank" rel="noopener noreferrer" class="prompt-action-btn"
title="Prompt Guide">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px"
viewBox="0 0 32 32" xml:space="preserve" fill="currentColor">
<path
d="M21,24c0,0.552-0.447,1-1,1h-8c-0.553,0-1-0.448-1-1s0.447-1,1-1h8C20.553,23,21,23.448,21,24z
M20,26h-8c-0.553,0-1,0.448-1,1s0.447,1,1,1h8c0.553,0,1-0.448,1-1S20.553,26,20,26z M15,29v1c0,0.552,0.448,1,1,1s1-0.448,1-1v-1
H15z M26,11c0,5-5,8-5,10c0,0.552-0.448,1-1,1h-8c-0.552,0-1-0.448-1-1c0-2-5-5-5-10C6,5.477,10.477,1,16,1S26,5.477,26,11z M17,4
c0-0.552-0.447-1-1-1c-4.411,0-8,3.589-8,8c0,0.552,0.447,1,1,1s1-0.448,1-1c0-3.309,2.691-6,6-6C16.553,5,17,4.552,17,4z" />
</svg>
<span>Prompt Guide</span>
</a>
<button id="refine-prompt-btn" class="prompt-action-btn" title="Refine with AI">
<svg fill="currentColor" height="16px" width="16px" version="1.1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512.422 512.422" xml:space="preserve">
<g>
<g>
<g>
<path d="M41.053,223.464c2.667,1.067,5.76,1.067,8.427-0.213l83.307-37.867c5.333-2.56,7.573-8.96,5.013-14.293
c-2.453-5.12-8.533-7.467-13.76-5.12l-58.347,26.56c27.84-83.307,105.387-138.987,194.667-138.987
c93.547,0,175.36,62.507,198.933,152c1.493,5.653,7.36,9.067,13.013,7.573c5.653-1.493,9.067-7.36,7.573-13.013
c-26.027-98.773-116.267-167.893-219.52-167.893c-98.453,0-184.107,61.44-215.04,153.387l-24.533-61.333
c-1.813-5.547-7.893-8.64-13.44-6.827c-5.547,1.813-8.64,7.893-6.827,13.44c0.107,0.427,0.32,0.853,0.533,1.28l34.027,85.333
C36.146,220.158,38.279,222.398,41.053,223.464z" />
<path
d="M511.773,380.904c-0.107-0.213-0.213-0.427-0.213-0.64l-34.027-85.333c-1.067-2.667-3.2-4.907-5.973-5.973
c-2.667-1.067-5.76-0.96-8.427,0.213l-83.307,37.867c-5.44,2.24-8,8.533-5.76,13.973c2.24,5.44,8.533,8,13.973,5.76
c0.213-0.107,0.427-0.213,0.64-0.32l58.347-26.56c-28.053,83.307-105.707,138.987-194.88,138.987
c-93.547,0-175.36-62.507-198.933-152c-1.493-5.653-7.36-9.067-13.013-7.573c-5.653,1.493-9.067,7.36-7.573,13.013
c25.92,98.88,116.267,167.893,219.52,167.893c98.453,0,184-61.44,215.04-153.387l24.533,61.333
c2.027,5.547,8.107,8.427,13.653,6.4C510.919,392.531,513.799,386.451,511.773,380.904z" />
</g>
</g>
</g>
</svg>
<span>Refine Prompt</span>
</button>
</div>
</div>
<div class="input-group">
<label for="prompt-note">Note (sẽ được thêm vào prompt)</label>
<div class="note-wrapper note-highlighting">
<div id="note-highlight" class="note-highlight" aria-hidden="true"></div>
<textarea id="prompt-note" placeholder="Thêm chi tiết hoặc điều chỉnh cho prompt..."
rows="2"></textarea>
<div class="field-action-buttons" data-target="note" aria-label="Note actions">
<button type="button" class="field-action-btn" data-action="copy" title="Copy note"
aria-label="Copy note">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor"
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2.5" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</svg>
</button>
<button type="button" class="field-action-btn" data-action="paste" title="Paste"
aria-label="Paste vào note">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor"
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 4h8" />
<path d="M9 2h6a2 2 0 0 1 2 2v1H7V4a2 2 0 0 1 2-2z" />
<rect x="5" y="5" width="14" height="16" rx="2" />
<path d="M9 12h3" />
<path d="M9 16h6" />
</svg>
</button>
<button type="button" class="field-action-btn" data-action="clear" title="Clear note"
aria-label="Xoá note">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor"
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 6h18" />
<path d="M19 6v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" />
<path d="M10 11v6" />
<path d="M14 11v6" />
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
</svg>
</button>
</div>
</div>
</div>
<div class="input-group image-inputs">
<div class="image-input-header">
<label>Reference Images</label>
</div>
<div id="image-input-grid" class="image-input-grid" aria-live="polite"></div>
<div class="image-url-input-wrapper" style="margin-top: 0.5rem;">
<input type="text" id="reference-url-input" placeholder="Nhập URL hoặc đường dẫn ảnh..."
style="width: 100%; padding: 0.5rem; border-radius: 4px; border: 1px solid var(--border-color); background: rgba(0,0,0,0.2); color: var(--text-primary); font-size: 0.85rem;">
</div>
</div>
<div class="input-group">
<label for="aspect-ratio">Aspect Ratio</label>
<select id="aspect-ratio">
<option value="Auto">Auto (Default)</option>
<option value="1:1">1:1 (Square)</option>
<option value="16:9">16:9 (Widescreen)</option>
<option value="4:3">4:3 (Standard)</option>
<option value="3:4">3:4 (Portrait)</option>
<option value="9:16">9:16 (Mobile)</option>
<option value="2:3">2:3</option>
<option value="3:2">3:2</option>
<option value="4:5">4:5</option>
<option value="5:4">5:4</option>
<option value="21:9">21:9 (Cinema)</option>
</select>
</div>
<div class="input-group">
<label for="resolution">Resolution</label>
<select id="resolution">
<option value="1K" selected>1K</option>
<option value="2K">2K</option>
<option value="4K">4K</option>
</select>
</div>
</div>
<div class="controls-footer">
<button id="generate-btn">
<span>Generate</span>
<div class="btn-shine"></div>
</button>
</div>
</div>
</aside>
<div class="sidebar-resize-handle" aria-hidden="true"></div>
<div class="content-area">
<main class="main-content">
<div class="image-display-area">
<div id="queue-counter" class="queue-counter hidden">
<span class="queue-spinner">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M12 2V6M12 18V22M6 12H2M22 12H18M19.07 4.93L16.24 7.76M7.76 16.24L4.93 19.07M19.07 19.07L16.24 16.24M7.76 7.76L4.93 4.93"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
</span>
<span class="queue-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M19 11H5M19 11C20.1046 11 21 11.8954 21 13V19C21 20.1046 20.1046 21 19 21H5C3.89543 21 3 20.1046 3 19V13C3 11.8954 3.89543 11 5 11M19 11V9C19 7.89543 18.1046 7 17 7M5 11V9C5 7.89543 5.89543 7 7 7M7 7V5C7 3.89543 7.89543 3 9 3H15C16.1046 3 17 3.89543 17 5V7M7 7H17"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
</span>
<span id="queue-count-text">0</span>
</div>
<div id="placeholder-state" class="state-view">
<div class="icon-placeholder"></div>
</div>
<div id="loading-state" class="state-view hidden">
<div class="spinner"></div>
<p>Creating masterpiece...</p>
</div>
<div id="error-state" class="state-view hidden">
<div class="error-icon">⚠️</div>
<p id="error-text"></p>
</div>
<div id="template-gallery-state" class="state-view hidden">
<!-- Language Toggle in top-left corner -->
<div class="canvas-lang-toggle">
<label class="canvas-lang-switch">
<input type="checkbox" id="canvas-lang-input">
<span class="canvas-lang-slider">
<span class="canvas-lang-option active" data-lang="vi">VI</span>
<span class="canvas-lang-option" data-lang="en">EN</span>
</span>
</label>
</div>
<div id="template-gallery-container" class="template-gallery-container"></div>
</div>
<div id="result-state" class="state-view hidden">
<img id="generated-image" src="" alt="Generated Image">
<div class="canvas-toolbar" role="toolbar">
<button type="button" class="canvas-btn" data-action="toggle-template"
aria-label="Toggle template view" title="Chọn mẫu prompt">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M19 3H5C3.89543 3 3 3.89543 3 5V19C3 20.1046 3.89543 21 5 21H19C20.1046 21 21 20.1046 21 19V5C21 3.89543 20.1046 3 19 3Z"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M3 9H21" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
<path d="M9 21V9" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
</button>
<button type="button" id="create-template-btn" class="canvas-btn icon-btn"
aria-label="Create Template" title="Create Template">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M10 14H12M12 14H14M12 14V16M12 14V12" stroke="currentColor"
stroke-width="1.5" stroke-linecap="round" />
<path
d="M22 11.7979C22 9.16554 22 7.84935 21.2305 6.99383C21.1598 6.91514 21.0849 6.84024 21.0062 6.76946C20.1506 6 18.8345 6 16.2021 6H15.8284C14.6747 6 14.0979 6 13.5604 5.84678C13.2651 5.7626 12.9804 5.64471 12.7121 5.49543C12.2237 5.22367 11.8158 4.81578 11 4L10.4497 3.44975C10.1763 3.17633 10.0396 3.03961 9.89594 2.92051C9.27652 2.40704 8.51665 2.09229 7.71557 2.01738C7.52976 2 7.33642 2 6.94975 2C6.06722 2 5.62595 2 5.25839 2.06935C3.64031 2.37464 2.37464 3.64031 2.06935 5.25839C2 5.62595 2 6.06722 2 6.94975M21.9913 16C21.9554 18.4796 21.7715 19.8853 20.8284 20.8284C19.6569 22 17.7712 22 14 22H10C6.22876 22 4.34315 22 3.17157 20.8284C2 19.6569 2 17.7712 2 14V11"
stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
</svg>
</button>
<button type="button" class="canvas-btn" data-action="zoom-out"></button>
<button type="button" class="canvas-btn" data-action="zoom-in"></button>
<button type="button" class="canvas-btn icon-btn" data-action="zoom-reset"
aria-label="Reset view"></button>
<a id="download-link" href="#" download="gemini_image.png" class="canvas-btn icon-btn"
aria-label="Download image">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M12.5535 16.5061C12.4114 16.6615 12.2106 16.75 12 16.75C11.7894 16.75 11.5886 16.6615 11.4465 16.5061L7.44648 12.1311C7.16698 11.8254 7.18822 11.351 7.49392 11.0715C7.79963 10.792 8.27402 10.8132 8.55352 11.1189L11.25 14.0682V3C11.25 2.58579 11.5858 2.25 12 2.25C12.4142 2.25 12.75 2.58579 12.75 3V14.0682L15.4465 11.1189C15.726 10.8132 16.2004 10.792 16.5061 11.0715C16.8118 11.351 16.833 11.8254 16.5535 12.1311L12.5535 16.5061Z"
fill="currentColor" />
<path
d="M3.75 15C3.75 14.5858 3.41422 14.25 3 14.25C2.58579 14.25 2.25 14.5858 2.25 15V15.0549C2.24998 16.4225 2.24996 17.5248 2.36652 18.3918C2.48754 19.2919 2.74643 20.0497 3.34835 20.6516C3.95027 21.2536 4.70814 21.5125 5.60825 21.6335C6.47522 21.75 7.57754 21.75 8.94513 21.75H15.0549C16.4225 21.75 17.5248 21.75 18.3918 21.6335C19.2919 21.5125 20.0497 21.2536 20.6517 20.6516C21.2536 20.0497 21.5125 19.2919 21.6335 18.3918C21.75 17.5248 21.75 16.4225 21.75 15.0549V15C21.75 14.5858 21.4142 14.25 21 14.25C20.5858 14.25 20.25 14.5858 20.25 15C20.25 16.4354 20.2484 17.4365 20.1469 18.1919C20.0482 18.9257 19.8678 19.3142 19.591 19.591C19.3142 19.8678 18.9257 20.0482 18.1919 20.1469C17.4365 20.2484 16.4354 20.25 15 20.25H9C7.56459 20.25 6.56347 20.2484 5.80812 20.1469C5.07435 20.0482 4.68577 19.8678 4.40901 19.591C4.13225 19.3142 3.9518 18.9257 3.85315 18.1919C3.75159 17.4365 3.75 16.4354 3.75 15Z"
fill="currentColor" />
</svg>
</a>
</div>
</div>
</div>
</main>
<section class="history-section">
<div class="history-header">
<div class="history-source-toggle" role="group" aria-label="Chọn nguồn lịch sử">
<button type="button" class="history-source-btn active" data-source="generated"
aria-pressed="true">History</button>
<button type="button" class="history-source-btn" data-source="uploads"
aria-pressed="false">Upload</button>
</div>
<div class="history-filter-group">
<input type="text" id="history-search-input" class="history-search-input" placeholder="Day...">
<button type="button" class="history-filter-btn history-favorites-btn" data-filter="favorites"
title="Favorites">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2">
<path
d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
</svg>
</button>
<button type="button" class="history-filter-btn active" data-filter="all">All</button>
<button type="button" class="history-filter-btn" data-filter="today">Today</button>
<button type="button" class="history-filter-btn" data-filter="week">This Week</button>
<button type="button" class="history-filter-btn" data-filter="month">This Month</button>
<button type="button" class="history-filter-btn" data-filter="year">This Year</button>
</div>
</div>
<div id="gallery-grid" class="gallery-grid">
<!-- Gallery items will be injected here -->
</div>
</section>
</div>
</div>
<div id="refine-modal" class="popup-overlay hidden">
<div class="popup-card">
<header class="popup-header">
<h2>Tinh chỉnh Prompt</h2>
<button id="close-refine-modal" type="button" class="popup-close" aria-label="Close">&times;</button>
</header>
<div class="popup-body">
<p style="color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 0.5rem;">Bạn muốn điều chỉnh
prompt hiện tại như thế nào?</p>
<textarea id="refine-instruction" placeholder="Ví dụ: Làm cho thật thực tế, thêm ánh sáng điện ảnh..."
rows="3"></textarea>
<div class="controls-footer" style="margin-top: 1rem; justify-content: flex-end; align-items: center;">
<button id="confirm-refine-btn">
<span>Tinh chỉnh</span>
<div class="btn-shine"></div>
</button>
<div id="refine-loading" class="hidden" style="color: var(--accent-color);">
<svg class="rotating-icon" fill="currentColor" height="32px" width="32px" version="1.1"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.422 512.422">
<path d="M41.053,223.464c2.667,1.067,5.76,1.067,8.427-0.213l83.307-37.867c5.333-2.56,7.573-8.96,5.013-14.293
c-2.453-5.12-8.533-7.467-13.76-5.12l-58.347,26.56c27.84-83.307,105.387-138.987,194.667-138.987
c93.547,0,175.36,62.507,198.933,152c1.493,5.653,7.36,9.067,13.013,7.573c5.653-1.493,9.067-7.36,7.573-13.013
c-26.027-98.773-116.267-167.893-219.52-167.893c-98.453,0-184.107,61.44-215.04,153.387l-24.533-61.333
c-1.813-5.547-7.893-8.64-13.44-6.827c-5.547,1.813-8.64,7.893-6.827,13.44c0.107,0.427,0.32,0.853,0.533,1.28l34.027,85.333
C36.146,220.158,38.279,222.398,41.053,223.464z" />
<path
d="M511.773,380.904c-0.107-0.213-0.213-0.427-0.213-0.64l-34.027-85.333c-1.067-2.667-3.2-4.907-5.973-5.973
c-2.667-1.067-5.76-0.96-8.427,0.213l-83.307,37.867c-5.44,2.24-8,8.533-5.76,13.973c2.24,5.44,8.533,8,13.973,5.76
c0.213-0.107,0.427-0.213,0.64-0.32l58.347-26.56c-28.053,83.307-105.707,138.987-194.88,138.987
c-93.547,0-175.36-62.507-198.933-152c-1.493-5.653-7.36-9.067-13.013-7.573c-5.653,1.493-9.067,7.36-7.573,13.013
c25.92,98.88,116.267,167.893,219.52,167.893c98.453,0,184-61.44,215.04-153.387l24.533,61.333
c2.027,5.547,8.107,8.427,13.653,6.4C510.919,392.531,513.799,386.451,511.773,380.904z" />
</svg>
</div>
</div>
</div>
</div>
</div>
<!-- Create Template Modal -->
<div id="create-template-modal" class="popup-overlay hidden">
<div class="popup-card" style="max-width: 600px;">
<header class="popup-header">
<h2>Create Template</h2>
<button id="close-template-modal" type="button" class="popup-close" aria-label="Close">&times;</button>
</header>
<div class="popup-body">
<div class="template-form-grid">
<div class="form-group">
<label for="template-title">Title</label>
<input type="text" id="template-title" placeholder="Template Name">
</div>
<div class="form-group">
<label>Preview Image</label>
<div id="template-preview-dropzone" class="template-preview-dropzone">
<img id="template-preview-img" src="" alt="Preview" class="hidden">
<div class="dropzone-placeholder">
<span>Drag & Drop Image or Click to Enter URL</span>
</div>
<input type="text" id="template-preview-url" class="template-preview-url-input hidden"
placeholder="Enter image URL or path">
</div>
</div>
<div class="form-group">
<label for="template-prompt">Prompt</label>
<textarea id="template-prompt" rows="3" placeholder="Template Prompt"></textarea>
</div>
<div class="form-group">
<label for="template-note">Note</label>
<textarea id="template-note" rows="2" placeholder="Template Note (optional)"></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="template-mode">Mode</label>
<select id="template-mode">
<option value="generate">Generate</option>
<option value="edit">Edit</option>
</select>
</div>
<div class="form-group">
<label for="template-category">Category</label>
<div class="category-input-wrapper">
<select id="template-category-select">
<option value="User">User</option>
<option value="Cinematic">Cinematic</option>
<option value="Anime">Anime</option>
<option value="Photography">Photography</option>
<option value="Digital Art">Digital Art</option>
<option value="new">+ New Category</option>
</select>
<input type="text" id="template-category-input" class="hidden"
placeholder="New Category Name">
</div>
</div>
</div>
<div class="form-group">
<label for="template-tags-input">Tags</label>
<div class="template-tag-control">
<div id="template-tag-list" class="template-tag-list" aria-live="polite"></div>
<input type="text" id="template-tags-input"
placeholder="Add keywords and press Enter (max 8)">
</div>
<p class="form-hint">Use short keywords to surface this template in searches.</p>
</div>
</div>
<div class="controls-footer" style="margin-top: 1.5rem; justify-content: flex-end;">
<button id="save-template-btn">
<span>Save Template</span>
<div class="btn-shine"></div>
</button>
</div>
</div>
</div>
</div>
<div id="api-settings-overlay" class="popup-overlay hidden" role="dialog" aria-modal="true"
aria-labelledby="api-settings-title">
<div class="popup-card" style="max-width: 480px;">
<header class="popup-header">
<h2 id="api-settings-title">Setting aPix</h2>
<button id="api-settings-close" type="button" class="popup-close" aria-label="Close">&times;</button>
</header>
<div class="popup-body api-settings-body">
<p class="api-settings-warning">
API cần thiết lập thanh toán với Google để sử dụng. Sau khi có key, lưu vào đây để ứng dụng hoạt
động.
</p>
<div class="input-group api-settings-input-group">
<label for="api-key">Google Cloud API Key</label>
<div class="api-key-field">
<input type="password" id="api-key" placeholder="Google Cloud API Key">
<button type="button" id="toggle-api-key-visibility" class="api-key-toggle-btn"
aria-label="Hiện API key" aria-pressed="false">
<svg class="icon-eye" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M12 4.5c-4.97 0-9.27 3.11-11 7.5 1.73 4.39 6.03 7.5 11 7.5s9.27-3.11 11-7.5C21.27 7.61 16.97 4.5 12 4.5zm0 12a4.5 4.5 0 110-9 4.5 4.5 0 010 9zm0-7a2.5 2.5 0 100 5 2.5 2.5 0 000-5z" />
</svg>
<svg class="icon-eye-off hidden" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M2 12c2.5-4.5 6.5-7 11-7 1.72 0 3.38.4 4.95 1.16l1.68-1.68L21.5 3 3 21.5l1.48-1.48 1.93-1.93C7.72 20.28 9.83 21 12 21c4.97 0 9.27-3.11 11-7.5-.56-1.43-1.46-2.73-2.55-3.84L20.84 7.8C20.95 8.03 21 8.26 21 8.5c0 3.59-3.39 6.5-9 6.5a8.9 8.9 0 01-4.72-1.27l1.45-1.45c.46.23.95.37 1.46.37 2.76 0 5-2.24 5-5 0-.5-.08-.98-.24-1.43l1.58-1.58C19.12 11.25 20 11.61 21 12c-1.73 4.39-6.03 7.5-11 7.5-1.72 0-3.38-.4-4.95-1.16L2 19.5 3.5 21l18.5-18.5L19.5 0 18 1.5l-1.63 1.63A10.95 10.95 0 0012 1c-4.97 0-9.27 3.11-11 7.5z" />
</svg>
</button>
</div>
<p class="input-hint api-key-hint">
Lấy API key tại
<a href="https://aistudio.google.com/api-keys" target="_blank"
rel="noreferrer">aistudio.google.com/api-keys</a>
</p>
</div>
<!-- Whisk Cookies Input -->
<div class="input-group api-settings-input-group hidden" id="whisk-cookies-group">
<label for="whisk-cookies">Whisk Cookies (dành cho ImageFX)</label>
<textarea id="whisk-cookies" rows="3" placeholder="Paste toàn bộ cookie string từ labs.google..."
style="width: 100%; padding: 0.5rem; background: rgba(0,0,0,0.2); border: 1px solid var(--border-color); color: var(--text-primary); border-radius: 4px; font-size: 0.8rem;"></textarea>
<p class="input-hint">
F12 trên labs.google > Network > Request bất kỳ > Copy Request Headers > Cookie.
</p>
</div>
<div class="input-group api-settings-input-group">
<label for="api-model">Model</label>
<div class="select-wrapper">
<select id="api-model"
style="width: 100%; padding: 0.75rem; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 0.5rem; color: var(--text-primary); font-size: 0.9rem;">
<option value="gemini-3-pro-image-preview">Gemini 3 Pro (Image Preview)</option>
<option value="gemini-2.5-flash-image">Gemini 2.5 Flash Image</option>
<option value="whisk">Whisk (ImageFX) [Experimental]</option>
</select>
</div>
</div>
<div class="input-group api-settings-input-group">
<label for="body-font">Body Font</label>
<div class="select-wrapper">
<select id="body-font"
style="width: 100%; padding: 0.75rem; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 0.5rem; color: var(--text-primary); font-size: 0.9rem;">
<option value="Be Vietnam Pro">Be Vietnam Pro (Default)</option>
<option value="Playwrite AU SA">Playwrite AU SA</option>
<option value="JetBrains Mono">JetBrains Mono</option>
</select>
</div>
</div>
<div class="input-group api-settings-input-group">
<label for="theme-options">Theme</label>
<div id="theme-options" class="theme-option-grid" role="listbox" aria-label="Chọn theme"></div>
</div>
<div class="controls-footer" style="justify-content: flex-end; margin-top: 0.5rem;">
<button id="save-api-settings-btn">
<span>Đóng</span>
<div class="btn-shine"></div>
</button>
</div>
</div>
</div>
</div>
<div id="delete-confirm-modal" class="popup-overlay hidden">
<div class="popup-card" style="max-width: 400px;">
<header class="popup-header">
<h2>Xác nhận xoá</h2>
<button id="close-delete-modal" type="button" class="popup-close" aria-label="Close">&times;</button>
</header>
<div class="popup-body">
<p style="color: var(--text-secondary); margin-bottom: 1.5rem;">Bạn có chắc chắn muốn xoá template này
không?</p>
<div class="controls-footer" style="justify-content: flex-end; gap: 0.5rem;">
<button id="cancel-delete-btn" class="action-btn"
style="background: rgba(255, 255, 255, 0.1); color: var(--text-primary);">Huỷ</button>
<button id="confirm-delete-btn" class="action-btn"
style="background: var(--danger-color); color: white;">Xoá</button>
</div>
</div>
</div>
</div>
<div id="popup-overlay" class="popup-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="popup-title">
<div class="popup-card">
<header class="popup-header">
<h2 id="popup-title"></h2>
<button id="popup-close" type="button" class="popup-close" aria-label="Close">&times;</button>
</header>
<div id="popup-body" class="popup-body"></div>
</div>
</div>
<script type="module" src="{{ url_for('static', filename='script.js') }}"></script>
</body>
</html>