Opera8 commited on
Commit
3c1a2de
·
verified ·
1 Parent(s): aa3f413

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +309 -174
app.py CHANGED
@@ -265,7 +265,118 @@ async (image) => {
265
  }
266
  """
267
 
268
- # --- CSS به‌روزرسانی شده (شامل استایل‌های جدید راهنمای IP) ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  css_code = """
270
  <style>
271
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
@@ -280,8 +391,11 @@ css_code = """
280
  --block-label-text-color: #374151 !important;
281
  --block-title-text-color: #111827 !important;
282
  --input-background-fill: #ffffff !important;
283
-
284
- /* متغیرهای جدید برای راهنمای IP */
 
 
 
285
  --guide-bg: rgba(255, 255, 255, 0.98);
286
  --guide-border: rgba(102, 126, 234, 0.2);
287
  --guide-text-title: #2d3748;
@@ -291,21 +405,11 @@ css_code = """
291
  --success-gradient-guide: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%);
292
  --radius-md-guide: 12px;
293
  --radius-lg-guide: 20px;
294
- --shadow-xl: 0 20px 25px -5px rgba(26, 32, 44, 0.07), 0 8px 10px -6px rgba(26, 32, 44, 0.05);
295
  --shadow-sm: 0 1px 2px 0 rgba(26, 32, 44, 0.03);
296
- --shadow-md: 0 4px 6px -1px rgba(26, 32, 44, 0.05);
297
-
298
- color-scheme: light !important;
299
- }
300
-
301
- body {
302
- font-family: 'Vazirmatn', sans-serif !important;
303
- background-color: #f5f7fa !important;
304
- margin: 0;
305
- padding: 10px;
306
  }
307
 
308
- /* انیمیشن‌های مورد نیاز */
309
  @keyframes float {
310
  0%, 100% { transform: translateY(0px); }
311
  50% { transform: translateY(-10px); }
@@ -315,196 +419,226 @@ body {
315
  to { opacity: 1; transform: translateY(0); }
316
  }
317
 
318
- /* استایل‌های اصلی کانتینر راهنمای IP */
319
  .ip-reset-guide-container {
320
  text-align: right;
321
  background: var(--guide-bg);
322
  backdrop-filter: blur(10px);
323
- padding: 40px;
324
  border-radius: var(--radius-lg-guide);
325
  box-shadow: var(--shadow-xl);
326
  border: 1px solid var(--guide-border);
327
  animation: slideInUp 0.6s cubic-bezier(0.4, 0, 0.2, 1) both;
328
  width: 100%;
 
329
  position: relative;
330
  overflow: hidden;
331
  box-sizing: border-box;
332
  font-family: 'Vazirmatn', sans-serif !important;
 
333
  }
334
  .ip-reset-guide-container::before {
335
- content: '';
336
- position: absolute;
337
- top: 0; left: 0; right: 0;
338
- height: 5px;
339
- background: var(--primary-gradient-guide);
340
  }
341
- .guide-header { display: flex; align-items: center; margin-bottom: 30px; direction: rtl; }
342
- .guide-header-icon { width: 60px; height: 60px; margin-left: 20px; animation: float 3s ease-in-out infinite; }
343
- .guide-header h2 { font-size: 1.5rem; color: var(--guide-text-title); font-weight: 700; margin: 0; }
344
  .guide-header p { color: var(--guide-text-body); font-size: 0.8rem; margin-top: 5px; margin-bottom: 0; }
345
- .guide-content { font-size: 0.95rem; color: var(--guide-text-body); line-height: 1.8; direction: rtl; }
346
- .info-card { background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%); border: 1px solid rgba(102, 126, 234, 0.2); border-radius: var(--radius-md-guide); padding: 20px; margin: 20px 0; position: relative; overflow: hidden; }
347
- .info-card p { font-size: 0.85rem; line-height: 1.7; margin: 0; }
 
 
348
  .info-card::before { content: ''; position: absolute; top: 0; right: 0; width: 4px; height: 100%; background: var(--primary-gradient-guide); }
349
- .info-card-header { display: flex; align-items: center; margin-bottom: 12px; }
350
- .info-card-icon { width: 24px; height: 24px; margin-left: 12px; }
351
- .info-card-title { font-weight: 600; color: var(--guide-text-title); font-size: 1rem; }
352
- .summary-section { margin-top: 25px; padding: 20px; border-radius: var(--radius-md-guide); background: linear-gradient(135deg, #56ab2f15 0%, #a8e06315 100%); border: 1px solid rgba(86, 171, 47, 0.2); position: relative; overflow: hidden; }
 
353
  .summary-section::before { content: ''; position: absolute; top: 0; right: 0; width: 4px; height: 100%; background: var(--success-gradient-guide); }
354
- .summary-header { display: flex; align-items: center; margin-bottom: 10px; }
355
- .summary-icon { width: 24px; height: 24px; margin-left: 10px; }
356
- .summary-title { font-weight: 600; color: #2f5a33; font-size: 1rem; }
357
- .summary-text { color: #2f5a33; font-size: 0.9rem; line-height: 1.7; }
358
- .video-button-container { text-align: center; margin: 25px 0 10px 0; }
359
- .elegant-video-button { display: inline-flex; align-items: center; justify-content: center; padding: 7px 18px; background-color: #f0f2f5; color: var(--guide-accent); border: 1px solid #e2e8f0; text-decoration: none; border-radius: var(--radius-md-guide); font-weight: 600; font-size: 0.8rem; cursor: pointer; font-family: inherit; transition: all 0.3s ease; box-shadow: var(--shadow-sm); }
 
360
  .elegant-video-button:hover { background: var(--primary-gradient-guide); color: white; border-color: transparent; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(102, 126, 234, 0.3); }
361
  .elegant-video-button-icon { width: 16px; height: 16px; margin-left: 8px; fill: currentColor; }
362
- .guide-actions { display: flex; gap: 15px; margin-top: 30px; padding-top: 25px; border-top: 1px solid #e2e8f0; direction: rtl; }
363
- .action-button { padding: 14px 24px; border: none; border-radius: var(--radius-md-guide); font-size: 0.95rem; font-weight: 600; cursor: pointer; flex: 1; transition: var(--transition-smooth); position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; font-family: inherit; }
364
- .action-button-icon { width: 20px; height: 20px; margin-right: 0; margin-left: 8px; }
 
365
  .back-button { background: white; color: var(--guide-text-body); border: 2px solid #e2e8f0; flex: 0.4; }
366
  .back-button:hover { background: #f7fafc; border-color: var(--guide-accent); transform: translateY(-2px); box-shadow: var(--shadow-md); }
367
  .retry-button { background: var(--primary-gradient-guide); color: white; flex: 0.6; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); }
368
  .retry-button:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4); }
369
 
370
- /* --- استایل‌های قبلی --- */
371
- #col-container { margin: 0 auto; max-width: 980px; direction: rtl; text-align: right; padding: 30px; background: #ffffff !important; border-radius: 24px; box-shadow: 0 10px 40px -10px rgba(0,0,0,0.08); border: 1px solid rgba(255,255,255,0.8); }
372
- #main-title h1 { font-size: 2.4em !important; text-align: center; color: #1a202c !important; margin-bottom: 15px; font-weight: 800; background: -webkit-linear-gradient(45deg, #2563eb, #1e40af); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
373
- #main-description { text-align: center; font-size: 1.15em; color: #4b5563 !important; margin-bottom: 40px; line-height: 1.6; }
374
- .gr-input-label, span.label-wrap, label span { font-weight: 700 !important; color: #374151 !important; font-size: 0.95em !important; margin-bottom: 8px !important; }
375
- textarea, input[type="text"] { border: 2px solid #e2e8f0 !important; border-radius: 12px !important; background-color: #ffffff !important; color: #111827 !important; padding: 12px !important; transition: all 0.3s ease; font-family: 'Vazirmatn', sans-serif !important; }
376
- textarea:focus, input[type="text"]:focus { border-color: #3b82f6 !important; box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1) !important; outline: none; }
377
- .gr-dropdown { background: #ffffff !important; border-radius: 12px !important; }
378
- .primary-btn, button.primary { background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important; border: none !important; color: white !important; font-weight: 700 !important; font-size: 1.1em !important; padding: 14px 28px !important; border-radius: 14px !important; box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3) !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; cursor: pointer !important; width: 100%; margin-top: 15px; }
379
- .primary-btn:hover, button.primary:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(16, 185, 129, 0.45) !important; }
380
- #download-btn { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important; box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3) !important; }
381
- #download-btn:hover { box-shadow: 0 8px 25px rgba(59, 130, 246, 0.45) !important; }
382
- .toast-body { direction: rtl !important; text-align: right !important; padding: 0 !important; border: none !important; background: transparent !important; box-shadow: none !important;}
383
- .toast-wrap { border: none !important; background: transparent !important; box-shadow: none !important; }
384
 
385
- @media (prefers-color-scheme: dark) {
386
- body, .gradio-container, .prose, table, tr, td, th { background-color: #ffffff !important; color: #333333 !important; }
 
 
 
 
 
 
 
 
387
  }
388
- </style>
389
- """
390
 
391
- # --- جاوااسکریپت سراسری (تزریق پیام خطای جدید پیشرفته) ---
392
- js_global_content = """
393
- <script>
394
- document.addEventListener('DOMContentLoaded', () => {
395
- // 1. Force Light Mode
396
- const forceLight = () => {
397
- const body = document.querySelector('body');
398
- if (body) {
399
- body.classList.remove('dark');
400
- body.style.backgroundColor = '#f5f7fa';
401
- body.style.color = '#333333';
402
- }
403
- document.querySelectorAll('.dark').forEach(el => el.classList.remove('dark'));
404
- };
405
- forceLight();
406
- setInterval(forceLight, 1000);
407
 
408
- // 2. NEW ADVANCED GPU Quota Replacer
409
- const observer = new MutationObserver((mutations) => {
410
- mutations.forEach((mutation) => {
411
- if (mutation.addedNodes.length) {
412
- mutation.addedNodes.forEach((node) => {
413
- // Check for Gradio error toasts
414
- if (node.nodeType === 1) {
415
- // Look for the toast container or body
416
- let targetNode = node.classList.contains('toast-body') ? node : node.querySelector('.toast-body');
417
-
418
- // Also check simple class structure in case Gradio updates
419
- if (!targetNode && (node.classList.contains('toast') || node.classList.contains('error'))) {
420
- targetNode = node;
421
- }
422
 
423
- if (targetNode) {
424
- const textContent = targetNode.innerText || "";
425
-
426
- // If it's a Quota error
427
- if (textContent.includes("exceeded your GPU quota") || textContent.includes("Quota Exceeded")) {
428
-
429
- // The exact HTML structure requested by the user
430
- const newHtml = `
431
- <div class="ip-reset-guide-container">
432
- <div class="guide-header">
433
- <svg class="guide-header-icon" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
434
- <defs><lineargradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color: #667eea; stop-opacity: 1;"></stop><stop offset="100%" style="stop-color: #764ba2; stop-opacity: 1;"></stop></lineargradient></defs>
435
- <circle cx="50" cy="50" r="45" fill="url(#grad1)" opacity="0.1"></circle>
436
- <circle cx="50" cy="50" r="35" fill="none" stroke="url(#grad1)" stroke-width="2" opacity="0.3"></circle>
437
- <path d="M35 50 L45 60 L65 40" stroke="url(#grad1)" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"></path>
438
- <circle cx="65" cy="35" r="8" fill="#fee140"></circle>
439
- <path d="M62 35 L68 35 M65 32 L65 38" stroke="white" stroke-width="2" stroke-linecap="round"></path>
440
- </svg>
441
- <div>
442
- <h2>یک قدم تا ساخت تصاویر جدید</h2>
443
- <p>نیازمند تغییر نقطه دستیابی</p>
444
- </div>
445
- </div>
446
- <div class="guide-content">
447
- <div class="info-card">
448
- <div class="info-card-header">
449
- <svg class="info-card-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#667eea" opacity="0.2"></path><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" stroke="#667eea" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
450
- <span class="info-card-title">راه حل سریع</span>
451
- </div>
452
- <p>طبق ویدیو آموزشی پایین بین نقطه دستیابی جابجا شوید تلاش مجدد بزنید تا تصاویر مجدداً تولید بشه.</p>
453
- </div>
454
- <div class="summary-section">
455
- <div class="summary-header">
456
- <svg class="summary-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#56ab2f" opacity="0.2"></circle><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" stroke="#56ab2f" stroke-width="2"></path><path d="M9 12l2 2 4-4" stroke="#56ab2f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
457
- <span class="summary-title">خلاصه راهنما</span>
458
- </div>
459
- <div class="summary-text">هربار که این صفحه را مشاهده کردید: از اینترنت سیم‌کارت استفاده کنید، VPN را خاموش کرده و طبق ویدیو آموزشی پایین نقطه دستیابی رو تغییر دهید. «تلاش مجدد» کلیک کنید. با این روش ساده می‌توانید به صورت نامحدود تصویر بسازید! ☘️</div>
460
- </div>
461
- <div class="video-button-container">
462
- <button onclick="window.open('https://www.aparat.com/v/your_video_id_here', '_blank')" class="elegant-video-button">
463
- <svg class="elegant-video-button-icon" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M8 5v14l11-7z"></path></svg>
464
- <span>دیدن ویدیو آموزشی استفاده نامحدود</span>
465
- </button>
466
- </div>
467
- </div>
468
- <div class="guide-actions">
469
- <button class="action-button back-button" onclick="this.closest('.toast-wrap').remove()">
470
- <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19 12H5M12 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
471
- <span>بازگشت</span>
472
- </button>
473
- <button class="action-button retry-button" onclick="this.closest('.toast-wrap').remove()">
474
- <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M23 4v6h-6M1 20v-6h6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
475
- <span>تلاش مجدد</span>
476
- </button>
477
- </div>
478
- </div>
479
- `;
480
-
481
- // Replace content
482
- targetNode.innerHTML = newHtml;
483
-
484
- // Clean up parent styles to allow full-width transparent display
485
- let wrapper = targetNode.closest('.toast-wrap');
486
- if(wrapper) {
487
- wrapper.style.backgroundColor = 'transparent';
488
- wrapper.style.boxShadow = 'none';
489
- wrapper.style.border = 'none';
490
- wrapper.style.maxWidth = '100%';
491
- wrapper.style.width = 'auto';
492
- }
493
- targetNode.style.backgroundColor = 'transparent';
494
- targetNode.style.padding = '0';
495
- targetNode.style.boxShadow = 'none';
496
- targetNode.style.border = 'none';
497
- }
498
- }
499
- }
500
- });
501
- }
502
- });
503
- });
504
 
505
- observer.observe(document.body, { childList: true, subtree: true });
506
- });
507
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  """
509
 
510
  # ادغام CSS و JS
@@ -536,7 +670,8 @@ with gr.Blocks() as demo:
536
 
537
  status_box = gr.HTML(label="وضعیت")
538
 
539
- run_button = gr.Button("✨ شروع پردازش و ساخت تصویر", variant="primary", elem_classes="primary-btn")
 
540
 
541
  with gr.Column():
542
  output_image = gr.Image(label="تصویر نهایی", interactive=False, format="png", height=380)
 
265
  }
266
  """
267
 
268
+ # --- جاوااسکریپت سراسری ---
269
+ js_global_content = """
270
+ <script>
271
+ document.addEventListener('DOMContentLoaded', () => {
272
+ // 1. Force Light Mode
273
+ const forceLight = () => {
274
+ const body = document.querySelector('body');
275
+ if (body) {
276
+ body.classList.remove('dark');
277
+ body.style.backgroundColor = '#f5f7fa';
278
+ body.style.color = '#333333';
279
+ }
280
+ document.querySelectorAll('.dark').forEach(el => el.classList.remove('dark'));
281
+ };
282
+ forceLight();
283
+ setInterval(forceLight, 1000);
284
+
285
+ // 2. NEW GPU Quota Replacer (Complex UI)
286
+ const observer = new MutationObserver((mutations) => {
287
+ mutations.forEach((mutation) => {
288
+ if (mutation.addedNodes.length) {
289
+ mutation.addedNodes.forEach((node) => {
290
+ // Check for Gradio error toast
291
+ if (node.nodeType === 1 && (node.classList.contains('toast-body') || node.classList.contains('error'))) {
292
+ const originalText = node.innerText;
293
+
294
+ // Check for Quota Exceeded pattern
295
+ const regex = /(\d+)s requested vs. (\d+)s left/;
296
+ const match = originalText.match(regex);
297
+
298
+ if (match && !node.dataset.translated) {
299
+
300
+ // HTML Template for the IP Reset Guide
301
+ const prettyHtml = `
302
+ <div class="ip-reset-guide-container">
303
+ <div class="guide-header">
304
+ <svg class="guide-header-icon" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
305
+ <defs><lineargradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color: #667eea; stop-opacity: 1;"></stop><stop offset="100%" style="stop-color: #764ba2; stop-opacity: 1;"></stop></lineargradient></defs>
306
+ <circle cx="50" cy="50" r="45" fill="url(#grad1)" opacity="0.1"></circle>
307
+ <circle cx="50" cy="50" r="35" fill="none" stroke="url(#grad1)" stroke-width="2" opacity="0.3"></circle>
308
+ <path d="M35 50 L45 60 L65 40" stroke="url(#grad1)" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"></path>
309
+ <circle cx="65" cy="35" r="8" fill="#fee140"></circle>
310
+ <path d="M62 35 L68 35 M65 32 L65 38" stroke="white" stroke-width="2" stroke-linecap="round"></path>
311
+ </svg>
312
+ <div>
313
+ <h2>یک قدم تا ساخت تصاویر جدید</h2>
314
+ <p>نیازمند تغییر نقطه دستیابی</p>
315
+ </div>
316
+ </div>
317
+
318
+ <div class="guide-content">
319
+ <div class="info-card">
320
+ <div class="info-card-header">
321
+ <svg class="info-card-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#667eea" opacity="0.2"></path><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" stroke="#667eea" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
322
+ <span class="info-card-title">راه حل سریع</span>
323
+ </div>
324
+ <p>طبق ویدیو آموزشی پایین بین نقطه دستیابی جابجا شوید تلاش مجدد بزنید تا تصاویر مجدداً تولید بشه.</p>
325
+ </div>
326
+
327
+ <div class="summary-section">
328
+ <div class="summary-header">
329
+ <svg class="summary-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" fill="#56ab2f" opacity="0.2"></circle><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" stroke="#56ab2f" stroke-width="2"></path><path d="M9 12l2 2 4-4" stroke="#56ab2f" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
330
+ <span class="summary-title">خلاصه راهنما</span>
331
+ </div>
332
+ <div class="summary-text">هربار که این صفحه را مشاهده کردید: از اینترنت سیم‌کارت استفاده کنید، VPN را خاموش کرده و طبق ویدیو آموزشی پایین نقطه دستیابی رو تغییر دهید. «تلاش مجدد» کلیک کنید. با این روش ساده می‌توانید به صورت نامحدود تصویر بسازید! ☘️</div>
333
+ </div>
334
+
335
+ <div class="video-button-container">
336
+ <button onclick="parent.postMessage({ type: 'NAVIGATE_TO_URL', url: '#/nav/online/news/getSingle/1149635/eyJpdiI6IjhHVGhPQWJwb3E0cjRXbnFWTW5BaUE9PSIsInZhbHVlIjoiS1V0dTdvT21wbXAwSXZaK1RCTG1pVXZqdlFJa1hXV1RKa2FLem9zU3pXMjd5MmlVOGc2YWY0NVdNR3h3Smp1aSIsIm1hYyI6IjY1NTA5ZDYzMjAzMTJhMGQyMWQ4NjA4ZDgyNGZjZDVlY2MyNjdiMjA2NWYzOWRjY2M4ZmVjYWRlMWNlMWQ3ODEiLCJ0YWciOiIifQ==/21135210' }, '*')" class="elegant-video-button">
337
+ <svg class="elegant-video-button-icon" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M8 5v14l11-7z"></path></svg>
338
+ <span>دیدن ویدیو آموزشی استفاده نامحدود</span>
339
+ </button>
340
+ </div>
341
+ </div>
342
+
343
+ <div class="guide-actions">
344
+ <button class="action-button back-button" onclick="this.closest('.toast-wrap').remove()">
345
+ <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19 12H5M12 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
346
+ <span>بازگشت</span>
347
+ </button>
348
+ <button class="action-button retry-button" onclick="
349
+ const runBtn = document.getElementById('run-btn');
350
+ if(runBtn) runBtn.click();
351
+ this.closest('.toast-wrap').remove();
352
+ ">
353
+ <svg class="action-button-icon" viewbox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M23 4v6h-6M1 20v-6h6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
354
+ <span>تلاش مجدد</span>
355
+ </button>
356
+ </div>
357
+ </div>
358
+ `;
359
+
360
+ // Set content
361
+ node.innerHTML = prettyHtml;
362
+ node.dataset.translated = 'true';
363
+
364
+ // Style adjustment for the container to fit nicely
365
+ node.style.padding = '0';
366
+ node.style.backgroundColor = 'transparent';
367
+ }
368
+ }
369
+ });
370
+ }
371
+ });
372
+ });
373
+
374
+ observer.observe(document.body, { childList: true, subtree: true });
375
+ });
376
+ </script>
377
+ """
378
+
379
+ # --- CSS Updated ---
380
  css_code = """
381
  <style>
382
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
 
391
  --block-label-text-color: #374151 !important;
392
  --block-title-text-color: #111827 !important;
393
  --input-background-fill: #ffffff !important;
394
+ color-scheme: light !important;
395
+ }
396
+
397
+ /* --- IP Reset Guide CSS Variables & Styles --- */
398
+ :root {
399
  --guide-bg: rgba(255, 255, 255, 0.98);
400
  --guide-border: rgba(102, 126, 234, 0.2);
401
  --guide-text-title: #2d3748;
 
405
  --success-gradient-guide: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%);
406
  --radius-md-guide: 12px;
407
  --radius-lg-guide: 20px;
 
408
  --shadow-sm: 0 1px 2px 0 rgba(26, 32, 44, 0.03);
409
+ --shadow-md: 0 4px 6px -1px rgba(26, 32, 44, 0.05), 0 2px 4px -2px rgba(26, 32, 44, 0.04);
410
+ --shadow-xl: 0 20px 25px -5px rgba(26, 32, 44, 0.07), 0 8px 10px -6px rgba(26, 32, 44, 0.05);
 
 
 
 
 
 
 
 
411
  }
412
 
 
413
  @keyframes float {
414
  0%, 100% { transform: translateY(0px); }
415
  50% { transform: translateY(-10px); }
 
419
  to { opacity: 1; transform: translateY(0); }
420
  }
421
 
 
422
  .ip-reset-guide-container {
423
  text-align: right;
424
  background: var(--guide-bg);
425
  backdrop-filter: blur(10px);
426
+ padding: 25px; /* Reduced padding for toast */
427
  border-radius: var(--radius-lg-guide);
428
  box-shadow: var(--shadow-xl);
429
  border: 1px solid var(--guide-border);
430
  animation: slideInUp 0.6s cubic-bezier(0.4, 0, 0.2, 1) both;
431
  width: 100%;
432
+ max-width: 450px; /* Constrain width inside toast */
433
  position: relative;
434
  overflow: hidden;
435
  box-sizing: border-box;
436
  font-family: 'Vazirmatn', sans-serif !important;
437
+ direction: rtl;
438
  }
439
  .ip-reset-guide-container::before {
440
+ content: ''; position: absolute; top: 0; left: 0; right: 0; height: 5px; background: var(--primary-gradient-guide);
 
 
 
 
441
  }
442
+ .guide-header { display: flex; align-items: center; margin-bottom: 20px; }
443
+ .guide-header-icon { width: 50px; height: 50px; margin-left: 15px; animation: float 3s ease-in-out infinite; flex-shrink: 0; }
444
+ .guide-header h2 { font-size: 1.3rem; color: var(--guide-text-title); font-weight: 700; margin: 0; }
445
  .guide-header p { color: var(--guide-text-body); font-size: 0.8rem; margin-top: 5px; margin-bottom: 0; }
446
+
447
+ .guide-content { font-size: 0.9rem; color: var(--guide-text-body); line-height: 1.6; }
448
+
449
+ .info-card { background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%); border: 1px solid rgba(102, 126, 234, 0.2); border-radius: var(--radius-md-guide); padding: 15px; margin: 15px 0; position: relative; overflow: hidden; }
450
+ .info-card p { font-size: 0.85rem; line-height: 1.6; margin: 0; }
451
  .info-card::before { content: ''; position: absolute; top: 0; right: 0; width: 4px; height: 100%; background: var(--primary-gradient-guide); }
452
+ .info-card-header { display: flex; align-items: center; margin-bottom: 10px; }
453
+ .info-card-icon { width: 20px; height: 20px; margin-left: 10px; }
454
+ .info-card-title { font-weight: 600; color: var(--guide-text-title); font-size: 0.95rem; }
455
+
456
+ .summary-section { margin-top: 15px; padding: 15px; border-radius: var(--radius-md-guide); background: linear-gradient(135deg, #56ab2f15 0%, #a8e06315 100%); border: 1px solid rgba(86, 171, 47, 0.2); position: relative; overflow: hidden; }
457
  .summary-section::before { content: ''; position: absolute; top: 0; right: 0; width: 4px; height: 100%; background: var(--success-gradient-guide); }
458
+ .summary-header { display: flex; align-items: center; margin-bottom: 8px; }
459
+ .summary-icon { width: 20px; height: 20px; margin-left: 10px; }
460
+ .summary-title { font-weight: 600; color: #2f5a33; font-size: 0.95rem; }
461
+ .summary-text { color: #2f5a33; font-size: 0.85rem; line-height: 1.6; }
462
+
463
+ .video-button-container { text-align: center; margin: 20px 0 10px 0; }
464
+ .elegant-video-button { display: inline-flex; align-items: center; justify-content: center; padding: 7px 15px; background-color: #f0f2f5; color: var(--guide-accent); border: 1px solid #e2e8f0; text-decoration: none; border-radius: var(--radius-md-guide); font-weight: 600; font-size: 0.8rem; cursor: pointer; font-family: inherit; transition: all 0.3s ease; box-shadow: var(--shadow-sm); }
465
  .elegant-video-button:hover { background: var(--primary-gradient-guide); color: white; border-color: transparent; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(102, 126, 234, 0.3); }
466
  .elegant-video-button-icon { width: 16px; height: 16px; margin-left: 8px; fill: currentColor; }
467
+
468
+ .guide-actions { display: flex; gap: 10px; margin-top: 20px; padding-top: 20px; border-top: 1px solid #e2e8f0; }
469
+ .action-button { padding: 10px 15px; border: none; border-radius: var(--radius-md-guide); font-size: 0.9rem; font-weight: 600; cursor: pointer; flex: 1; transition: all 0.3s ease; position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; font-family: inherit; }
470
+ .action-button-icon { width: 18px; height: 18px; margin-right: 0; margin-left: 8px; }
471
  .back-button { background: white; color: var(--guide-text-body); border: 2px solid #e2e8f0; flex: 0.4; }
472
  .back-button:hover { background: #f7fafc; border-color: var(--guide-accent); transform: translateY(-2px); box-shadow: var(--shadow-md); }
473
  .retry-button { background: var(--primary-gradient-guide); color: white; flex: 0.6; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); }
474
  .retry-button:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4); }
475
 
476
+ /* --- Main App CSS --- */
477
+ body {
478
+ font-family: 'Vazirmatn', sans-serif !important;
479
+ background-color: #f5f7fa !important;
480
+ margin: 0;
481
+ padding: 10px;
482
+ }
 
 
 
 
 
 
 
483
 
484
+ #col-container {
485
+ margin: 0 auto;
486
+ max-width: 980px;
487
+ direction: rtl;
488
+ text-align: right;
489
+ padding: 30px;
490
+ background: #ffffff !important;
491
+ border-radius: 24px;
492
+ box-shadow: 0 10px 40px -10px rgba(0,0,0,0.08);
493
+ border: 1px solid rgba(255,255,255,0.8);
494
  }
 
 
495
 
496
+ #main-title h1 {
497
+ font-size: 2.4em !important;
498
+ text-align: center;
499
+ color: #1a202c !important;
500
+ margin-bottom: 15px;
501
+ font-weight: 800;
502
+ background: -webkit-linear-gradient(45deg, #2563eb, #1e40af);
503
+ -webkit-background-clip: text;
504
+ -webkit-text-fill-color: transparent;
505
+ }
 
 
 
 
 
 
506
 
507
+ #main-description {
508
+ text-align: center;
509
+ font-size: 1.15em;
510
+ color: #4b5563 !important;
511
+ margin-bottom: 40px;
512
+ line-height: 1.6;
513
+ }
 
 
 
 
 
 
 
514
 
515
+ .gr-input-label, span.label-wrap, label span {
516
+ font-weight: 700 !important;
517
+ color: #374151 !important;
518
+ font-size: 0.95em !important;
519
+ margin-bottom: 8px !important;
520
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
 
522
+ textarea, input[type="text"] {
523
+ border: 2px solid #e2e8f0 !important;
524
+ border-radius: 12px !important;
525
+ background-color: #ffffff !important;
526
+ color: #111827 !important;
527
+ padding: 12px !important;
528
+ transition: all 0.3s ease;
529
+ font-family: 'Vazirmatn', sans-serif !important;
530
+ }
531
+
532
+ textarea:focus, input[type="text"]:focus {
533
+ border-color: #3b82f6 !important;
534
+ box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1) !important;
535
+ outline: none;
536
+ }
537
+
538
+ .gr-dropdown {
539
+ background: #ffffff !important;
540
+ border-radius: 12px !important;
541
+ }
542
+
543
+ .primary-btn, button.primary {
544
+ background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;
545
+ border: none !important;
546
+ color: white !important;
547
+ font-weight: 700 !important;
548
+ font-size: 1.1em !important;
549
+ padding: 14px 28px !important;
550
+ border-radius: 14px !important;
551
+ box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3) !important;
552
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
553
+ cursor: pointer !important;
554
+ width: 100%;
555
+ margin-top: 15px;
556
+ }
557
+
558
+ .primary-btn:hover, button.primary:hover {
559
+ transform: translateY(-2px);
560
+ box-shadow: 0 8px 25px rgba(16, 185, 129, 0.45) !important;
561
+ }
562
+
563
+ .primary-btn:active, button.primary:active {
564
+ transform: translateY(1px);
565
+ }
566
+
567
+ #download-btn {
568
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
569
+ box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3) !important;
570
+ }
571
+ #download-btn:hover {
572
+ box-shadow: 0 8px 25px rgba(59, 130, 246, 0.45) !important;
573
+ }
574
+
575
+ .gradio-container .prose table,
576
+ .gradio-container table {
577
+ background-color: #ffffff !important;
578
+ color: #111827 !important;
579
+ border: 1px solid #e5e7eb !important;
580
+ border-radius: 12px !important;
581
+ overflow: hidden !important;
582
+ width: 100% !important;
583
+ margin-top: 20px !important;
584
+ }
585
+
586
+ .gradio-container thead th {
587
+ background-color: #f3f4f6 !important;
588
+ color: #374151 !important;
589
+ font-weight: 700 !important;
590
+ border-bottom: 2px solid #e5e7eb !important;
591
+ padding: 12px !important;
592
+ text-align: right !important;
593
+ }
594
+
595
+ .gradio-container tbody tr {
596
+ background-color: #ffffff !important;
597
+ border-bottom: 1px solid #f3f4f6 !important;
598
+ }
599
+
600
+ .gradio-container tbody tr:hover {
601
+ background-color: #f9fafb !important;
602
+ }
603
+
604
+ .gradio-container tbody td {
605
+ background-color: #ffffff !important;
606
+ color: #374151 !important;
607
+ padding: 10px !important;
608
+ }
609
+
610
+ .gradio-container tbody td span,
611
+ .gradio-container tbody td p {
612
+ color: #374151 !important;
613
+ }
614
+
615
+ footer { display: none !important; }
616
+ .flagging { display: none !important; }
617
+
618
+ /* General Toast Override */
619
+ .toast-body {
620
+ direction: rtl !important;
621
+ text-align: right !important;
622
+ background: transparent !important;
623
+ box-shadow: none !important;
624
+ border: none !important;
625
+ padding: 0 !important;
626
+ max-width: 100% !important;
627
+ width: auto !important;
628
+ }
629
+ .toast-wrap {
630
+ background: transparent !important;
631
+ border: none !important;
632
+ box-shadow: none !important;
633
+ }
634
+
635
+ @media (prefers-color-scheme: dark) {
636
+ body, .gradio-container, .prose, table, tr, td, th {
637
+ background-color: #ffffff !important;
638
+ color: #333333 !important;
639
+ }
640
+ }
641
+ </style>
642
  """
643
 
644
  # ادغام CSS و JS
 
670
 
671
  status_box = gr.HTML(label="وضعیت")
672
 
673
+ # IMPORTANT: Added elem_id="run-btn" here for JS targeting
674
+ run_button = gr.Button("✨ شروع پردازش و ساخت تصویر", variant="primary", elem_classes="primary-btn", elem_id="run-btn")
675
 
676
  with gr.Column():
677
  output_image = gr.Image(label="تصویر نهایی", interactive=False, format="png", height=380)