DawnC commited on
Commit
009b829
1 Parent(s): ef9be46

update html_templates

Browse files
Files changed (1) hide show
  1. html_templates.py +34 -54
html_templates.py CHANGED
@@ -22,7 +22,7 @@ def get_akc_breeds_link(breed: str) -> str:
22
 
23
  def get_color_scheme(is_single_dog: bool) -> Union[str, List[str]]:
24
  """Get color scheme for dog detection visualization."""
25
- single_dog_color = '#34C759' # 適當淺度的綠色當作為單一品種的顏色
26
  color_list = [
27
  '#FF5733', # 珊瑚紅
28
  '#28A745', # 深綠色
@@ -36,12 +36,11 @@ def get_color_scheme(is_single_dog: bool) -> Union[str, List[str]]:
36
  '#FFE033' # 金黃色
37
  ]
38
  return single_dog_color if is_single_dog else color_list
39
-
40
 
41
  def format_hint_html(message: str) -> str:
42
  """
43
  提示訊息的 HTML。
44
-
45
  Args:
46
  message: str, 要顯示的提示訊息
47
  Returns:
@@ -221,7 +220,7 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
221
  # 獲取noise和health資訊
222
  noise_info = breed_noise_info.get(breed, {})
223
  health_info = breed_health_info.get(breed, {})
224
-
225
  # 處理噪音資訊
226
  noise_notes = noise_info.get('noise_notes', '').split('\n')
227
  noise_characteristics = []
@@ -277,7 +276,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
277
  {display_breeds_name}
278
  </h2>
279
  </div>
280
-
281
  <div class="breed-info">
282
  <!-- Basic Information -->
283
  <div class="section-header" style="margin-bottom: 15px;">
@@ -316,7 +314,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
316
  <span>{description['Lifespan']}</span>
317
  </div>
318
  </div>
319
-
320
  <!-- Care Requirements -->
321
  <div class="section-header" style="margin-bottom: 15px;">
322
  <h3>
@@ -367,7 +364,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
367
  <span>{description['Care Level']}</span>
368
  </div>
369
  </div>
370
-
371
  <!-- Noise Behavior -->
372
  <div class="section-header" style="margin-bottom: 15px;">
373
  <h3>
@@ -392,7 +388,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
392
  <div class="characteristics-list">
393
  {format_noise_items(noise_characteristics[:2])}
394
  </div>
395
-
396
  <details class="expandable-section" style="margin-top: 15px;">
397
  <summary class="expand-header" style="cursor: pointer; padding: 10px; background: #f8f9fa; border-radius: 6px;">
398
  Show Complete Noise Information
@@ -416,7 +411,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
416
  </div>
417
  </details>
418
  </div>
419
-
420
  <!-- Health Insights -->
421
  <div class="section-header" style="margin-bottom: 15px;">
422
  <h3>
@@ -437,7 +431,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
437
  <div class="key-considerations">
438
  {format_health_items(health_considerations[:2])}
439
  </div>
440
-
441
  <details class="expandable-section" style="margin-top: 15px;">
442
  <summary class="expand-header" style="cursor: pointer; padding: 10px; background: #f8f9fa; border-radius: 6px;">
443
  Show Complete Health Information
@@ -461,7 +454,6 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
461
  </div>
462
  </details>
463
  </div>
464
-
465
  <!-- Description -->
466
  <div class="section-header" style="margin-bottom: 15px;">
467
  <h3>
@@ -471,12 +463,11 @@ def format_single_dog_result(breed: str, description: Dict[str, Any], color: str
471
  <div class="description-section" style="background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 30px;">
472
  <p style="line-height: 1.6;">{description.get('Description', '')}</p>
473
  </div>
474
-
475
  <!-- Action Section -->
476
  <div class="action-section" style="text-align: center; margin-top: 30px;">
477
- <a href="{get_akc_breeds_link(breed)}"
478
- target="_blank"
479
- class="akc-button"
480
  style="display: inline-block; padding: 12px 24px; background: linear-gradient(90deg, #4299e1, #48bb78); color: white; text-decoration: none; border-radius: 6px;">
481
  <span class="icon">🌐</span>
482
  Learn more about {display_breeds_name} on AKC website
@@ -499,7 +490,7 @@ def format_health_items(items: List[str]) -> str:
499
  return "<div class='list-item'>Information not available</div>"
500
  return "\n".join([f"<div class='list-item'>• {item}</div>" for item in items])
501
 
502
-
503
  def format_multiple_breeds_result(
504
  topk_breeds: List[str],
505
  relative_probs: List[str],
@@ -509,7 +500,7 @@ def format_multiple_breeds_result(
509
  ) -> str:
510
  """Format multiple breed predictions into HTML with complete information."""
511
  display_breeds = [breed.replace('_', ' ') for breed in topk_breeds]
512
-
513
  result = f'''
514
  <!-- 主標題區塊 -->
515
  <div style="background: {color}10; border-radius: 12px 12px 0 0; padding: 20px;">
@@ -518,18 +509,16 @@ def format_multiple_breeds_result(
518
  <span style="font-size: 1.4em; font-weight: 600; color: {color};">Dog {index}</span>
519
  </div>
520
  </div>
521
-
522
  <!-- 內容區塊 -->
523
  <div style="padding: 20px;">
524
  <!-- 不確定性提示 -->
525
  <div style="margin-bottom: 20px;">
526
  <div style="display: flex; align-items: center; gap: 8px; padding: 12px; background: #f8f9fa; border-radius: 8px;">
527
  <span>ℹ️</span>
528
- <span>Note: The model is showing some uncertainty in its predictions.
529
  Here are the most likely breeds based on the available visual features.</span>
530
  </div>
531
  </div>
532
-
533
  <!-- 品種列表容器 -->
534
  <div class="breeds-list" style="display: grid; gap: 20px;">
535
  '''
@@ -591,7 +580,6 @@ def format_multiple_breeds_result(
591
  {f'<span style="background: {color}12; color: {color}; padding: 8px 16px; border-radius: 8px; font-size: 1em; font-weight: 500; box-shadow: 0 1px 2px {color}20;">Confidence: {prob}</span>' if prob else ''}
592
  </div>
593
  </div>
594
-
595
  <div class="breed-info" style="padding: 24px;">
596
  <!-- Basic Information -->
597
  <div style="margin-bottom: 32px;">
@@ -605,8 +593,8 @@ def format_multiple_breeds_result(
605
  <div style="display: flex; align-items: center; gap: 10px;">
606
  <span style="font-size: 1.1em;">📏</span>
607
  <span style="font-weight: 500;">Size</span>
608
- <div style="position: relative; display: inline-block;"
609
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
610
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
611
  <span style="cursor: help; color: #718096;">ⓘ</span>
612
  <div class="tooltip-content" style="
@@ -628,7 +616,7 @@ def format_multiple_breeds_result(
628
  • Medium: 20-60 pounds<br>
629
  • Large: Over 60 pounds<br>
630
  • Giant: Over 100 pounds
631
- <div style="position: absolute;
632
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
633
  width: 0;
634
  height: 0;
@@ -640,14 +628,13 @@ def format_multiple_breeds_result(
640
  </div>
641
  <span style="display: block; margin-top: 8px; color: #4a5568;">{description['Size']}</span>
642
  </div>
643
-
644
  <!-- Lifespan -->
645
  <div style="padding: 16px; border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;">
646
  <div style="display: flex; align-items: center; gap: 10px;">
647
  <span style="font-size: 1.1em;">⏳</span>
648
  <span style="font-weight: 500;">Lifespan</span>
649
- <div style="position: relative; display: inline-block;"
650
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
651
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
652
  <span style="cursor: help; color: #718096;">ⓘ</span>
653
  <div class="tooltip-content" style="
@@ -668,7 +655,7 @@ def format_multiple_breeds_result(
668
  • Short: 6-8 years<br>
669
  • Average: 10-15 years<br>
670
  • Long: 12-20 years
671
- <div style="position: absolute;
672
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
673
  width: 0;
674
  height: 0;
@@ -682,7 +669,6 @@ def format_multiple_breeds_result(
682
  </div>
683
  </div>
684
  </div>
685
-
686
  <!-- Care Requirements -->
687
  <div style="margin-bottom: 32px;">
688
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
@@ -695,8 +681,8 @@ def format_multiple_breeds_result(
695
  <div style="display: flex; align-items: center; gap: 10px;">
696
  <span style="font-size: 1.1em;">🏃</span>
697
  <span style="font-weight: 500;">Exercise</span>
698
- <div style="position: relative; display: inline-block;"
699
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
700
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
701
  <span style="cursor: help; color: #718096;">ⓘ</span>
702
  <div class="tooltip-content" style="
@@ -717,7 +703,7 @@ def format_multiple_breeds_result(
717
  • Low: Short walks<br>
718
  • Moderate: 1-2 hours daily<br>
719
  • High: 2+ hours daily
720
- <div style="position: absolute;
721
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
722
  width: 0;
723
  height: 0;
@@ -729,14 +715,13 @@ def format_multiple_breeds_result(
729
  </div>
730
  <span style="display: block; margin-top: 8px; color: #4a5568;">{description['Exercise Needs']}</span>
731
  </div>
732
-
733
  <!-- Grooming -->
734
  <div style="padding: 16px; border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;">
735
  <div style="display: flex; align-items: center; gap: 10px;">
736
  <span style="font-size: 1.1em;">✂️</span>
737
  <span style="font-weight: 500;">Grooming</span>
738
- <div style="position: relative; display: inline-block;"
739
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
740
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
741
  <span style="cursor: help; color: #718096;">ⓘ</span>
742
  <div class="tooltip-content" style="
@@ -757,7 +742,7 @@ def format_multiple_breeds_result(
757
  • Low: Basic brushing<br>
758
  • Moderate: Weekly grooming<br>
759
  • High: Daily maintenance
760
- <div style="position: absolute;
761
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
762
  width: 0;
763
  height: 0;
@@ -769,14 +754,13 @@ def format_multiple_breeds_result(
769
  </div>
770
  <span style="display: block; margin-top: 8px; color: #4a5568;">{description['Grooming Needs']}</span>
771
  </div>
772
-
773
  <!-- Care Level -->
774
  <div style="padding: 16px; border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;">
775
  <div style="display: flex; align-items: center; gap: 10px;">
776
  <span style="font-size: 1.1em;">⭐</span>
777
  <span style="font-weight: 500;">Care Level</span>
778
- <div style="position: relative; display: inline-block;"
779
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
780
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
781
  <span style="cursor: help; color: #718096;">ⓘ</span>
782
  <div class="tooltip-content" style="
@@ -797,7 +781,7 @@ def format_multiple_breeds_result(
797
  • Low: Basic care<br>
798
  • Moderate: Regular care<br>
799
  • High: Extensive care
800
- <div style="position: absolute;
801
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
802
  width: 0;
803
  height: 0;
@@ -811,14 +795,13 @@ def format_multiple_breeds_result(
811
  </div>
812
  </div>
813
  </div>
814
-
815
  <!-- Noise Behavior -->
816
  <div style="margin-bottom: 32px;">
817
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
818
  <span style="font-size: 1.2em;">🔊</span>
819
  <span style="font-size: 1.2em; font-weight: 600; color: #2d3748;">NOISE BEHAVIOR</span>
820
- <div style="position: relative; display: inline-block;"
821
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
822
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
823
  <span style="cursor: help; color: #718096;">ⓘ</span>
824
  <div class="tooltip-content" style="
@@ -839,7 +822,7 @@ def format_multiple_breeds_result(
839
  • Typical vocalization patterns<br>
840
  • Common triggers and frequency<br>
841
  • Based on breed characteristics
842
- <div style="position: absolute;
843
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
844
  width: 0;
845
  height: 0;
@@ -886,14 +869,13 @@ def format_multiple_breeds_result(
886
  </details>
887
  </div>
888
  </div>
889
-
890
  <!-- Health Insights -->
891
  <div style="margin-bottom: 32px;">
892
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
893
  <span style="font-size: 1.2em;">🏥</span>
894
  <span style="font-size: 1.2em; font-weight: 600; color: #2d3748;">HEALTH INSIGHTS</span>
895
- <div style="position: relative; display: inline-block;"
896
- onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
897
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
898
  <span style="cursor: help; color: #718096;">ⓘ</span>
899
  <div class="tooltip-content" style="
@@ -914,7 +896,7 @@ def format_multiple_breeds_result(
914
  • Common breed-specific conditions<br>
915
  • Recommended health screenings<br>
916
  • General health considerations
917
- <div style="position: absolute;
918
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
919
  width: 0;
920
  height: 0;
@@ -954,7 +936,6 @@ def format_multiple_breeds_result(
954
  </details>
955
  </div>
956
  </div>
957
-
958
  <!-- Description -->
959
  <div style="margin-bottom: 32px;">
960
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
@@ -965,11 +946,10 @@ def format_multiple_breeds_result(
965
  <p style="line-height: 1.6; margin: 0; color: #2d3748;">{description.get('Description', '')}</p>
966
  </div>
967
  </div>
968
-
969
  <!-- Action Section -->
970
  <div style="text-align: center; margin-top: 32px;">
971
- <a href="{get_akc_breeds_link(breed)}"
972
- target="_blank"
973
  rel="noopener noreferrer"
974
  style="display: inline-flex; align-items: center; gap: 8px; padding: 14px 28px; background: linear-gradient(90deg, #4299e1, #48bb78); color: white; text-decoration: none; border-radius: 8px; font-weight: 500; transition: opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
975
  <span style="font-size: 1.2em;">🌐</span>
@@ -980,7 +960,7 @@ def format_multiple_breeds_result(
980
  </div>
981
  </div>
982
  '''
983
-
984
  return result
985
 
986
 
@@ -1041,4 +1021,4 @@ def format_comparison_details(breed_data: Dict) -> str:
1041
  <p><strong>Good with Children:</strong> {original_data.get('Good with Children', 'N/A')}</p>
1042
  <p><strong>Temperament:</strong> {original_data.get('Temperament', 'N/A')}</p>
1043
  </div>
1044
- """
 
22
 
23
  def get_color_scheme(is_single_dog: bool) -> Union[str, List[str]]:
24
  """Get color scheme for dog detection visualization."""
25
+ single_dog_color = '#34C759' # 清爽的綠色作為單狗顏色
26
  color_list = [
27
  '#FF5733', # 珊瑚紅
28
  '#28A745', # 深綠色
 
36
  '#FFE033' # 金黃色
37
  ]
38
  return single_dog_color if is_single_dog else color_list
 
39
 
40
  def format_hint_html(message: str) -> str:
41
  """
42
  提示訊息的 HTML。
43
+
44
  Args:
45
  message: str, 要顯示的提示訊息
46
  Returns:
 
220
  # 獲取noise和health資訊
221
  noise_info = breed_noise_info.get(breed, {})
222
  health_info = breed_health_info.get(breed, {})
223
+
224
  # 處理噪音資訊
225
  noise_notes = noise_info.get('noise_notes', '').split('\n')
226
  noise_characteristics = []
 
276
  {display_breeds_name}
277
  </h2>
278
  </div>
 
279
  <div class="breed-info">
280
  <!-- Basic Information -->
281
  <div class="section-header" style="margin-bottom: 15px;">
 
314
  <span>{description['Lifespan']}</span>
315
  </div>
316
  </div>
 
317
  <!-- Care Requirements -->
318
  <div class="section-header" style="margin-bottom: 15px;">
319
  <h3>
 
364
  <span>{description['Care Level']}</span>
365
  </div>
366
  </div>
 
367
  <!-- Noise Behavior -->
368
  <div class="section-header" style="margin-bottom: 15px;">
369
  <h3>
 
388
  <div class="characteristics-list">
389
  {format_noise_items(noise_characteristics[:2])}
390
  </div>
 
391
  <details class="expandable-section" style="margin-top: 15px;">
392
  <summary class="expand-header" style="cursor: pointer; padding: 10px; background: #f8f9fa; border-radius: 6px;">
393
  Show Complete Noise Information
 
411
  </div>
412
  </details>
413
  </div>
 
414
  <!-- Health Insights -->
415
  <div class="section-header" style="margin-bottom: 15px;">
416
  <h3>
 
431
  <div class="key-considerations">
432
  {format_health_items(health_considerations[:2])}
433
  </div>
 
434
  <details class="expandable-section" style="margin-top: 15px;">
435
  <summary class="expand-header" style="cursor: pointer; padding: 10px; background: #f8f9fa; border-radius: 6px;">
436
  Show Complete Health Information
 
454
  </div>
455
  </details>
456
  </div>
 
457
  <!-- Description -->
458
  <div class="section-header" style="margin-bottom: 15px;">
459
  <h3>
 
463
  <div class="description-section" style="background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 30px;">
464
  <p style="line-height: 1.6;">{description.get('Description', '')}</p>
465
  </div>
 
466
  <!-- Action Section -->
467
  <div class="action-section" style="text-align: center; margin-top: 30px;">
468
+ <a href="{get_akc_breeds_link(breed)}"
469
+ target="_blank"
470
+ class="akc-button"
471
  style="display: inline-block; padding: 12px 24px; background: linear-gradient(90deg, #4299e1, #48bb78); color: white; text-decoration: none; border-radius: 6px;">
472
  <span class="icon">🌐</span>
473
  Learn more about {display_breeds_name} on AKC website
 
490
  return "<div class='list-item'>Information not available</div>"
491
  return "\n".join([f"<div class='list-item'>• {item}</div>" for item in items])
492
 
493
+
494
  def format_multiple_breeds_result(
495
  topk_breeds: List[str],
496
  relative_probs: List[str],
 
500
  ) -> str:
501
  """Format multiple breed predictions into HTML with complete information."""
502
  display_breeds = [breed.replace('_', ' ') for breed in topk_breeds]
503
+
504
  result = f'''
505
  <!-- 主標題區塊 -->
506
  <div style="background: {color}10; border-radius: 12px 12px 0 0; padding: 20px;">
 
509
  <span style="font-size: 1.4em; font-weight: 600; color: {color};">Dog {index}</span>
510
  </div>
511
  </div>
 
512
  <!-- 內容區塊 -->
513
  <div style="padding: 20px;">
514
  <!-- 不確定性提示 -->
515
  <div style="margin-bottom: 20px;">
516
  <div style="display: flex; align-items: center; gap: 8px; padding: 12px; background: #f8f9fa; border-radius: 8px;">
517
  <span>ℹ️</span>
518
+ <span>Note: The model is showing some uncertainty in its predictions.
519
  Here are the most likely breeds based on the available visual features.</span>
520
  </div>
521
  </div>
 
522
  <!-- 品種列表容器 -->
523
  <div class="breeds-list" style="display: grid; gap: 20px;">
524
  '''
 
580
  {f'<span style="background: {color}12; color: {color}; padding: 8px 16px; border-radius: 8px; font-size: 1em; font-weight: 500; box-shadow: 0 1px 2px {color}20;">Confidence: {prob}</span>' if prob else ''}
581
  </div>
582
  </div>
 
583
  <div class="breed-info" style="padding: 24px;">
584
  <!-- Basic Information -->
585
  <div style="margin-bottom: 32px;">
 
593
  <div style="display: flex; align-items: center; gap: 10px;">
594
  <span style="font-size: 1.1em;">📏</span>
595
  <span style="font-weight: 500;">Size</span>
596
+ <div style="position: relative; display: inline-block;"
597
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
598
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
599
  <span style="cursor: help; color: #718096;">ⓘ</span>
600
  <div class="tooltip-content" style="
 
616
  • Medium: 20-60 pounds<br>
617
  • Large: Over 60 pounds<br>
618
  • Giant: Over 100 pounds
619
+ <div style="position: absolute;
620
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
621
  width: 0;
622
  height: 0;
 
628
  </div>
629
  <span style="display: block; margin-top: 8px; color: #4a5568;">{description['Size']}</span>
630
  </div>
 
631
  <!-- Lifespan -->
632
  <div style="padding: 16px; border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;">
633
  <div style="display: flex; align-items: center; gap: 10px;">
634
  <span style="font-size: 1.1em;">⏳</span>
635
  <span style="font-weight: 500;">Lifespan</span>
636
+ <div style="position: relative; display: inline-block;"
637
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
638
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
639
  <span style="cursor: help; color: #718096;">ⓘ</span>
640
  <div class="tooltip-content" style="
 
655
  • Short: 6-8 years<br>
656
  • Average: 10-15 years<br>
657
  • Long: 12-20 years
658
+ <div style="position: absolute;
659
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
660
  width: 0;
661
  height: 0;
 
669
  </div>
670
  </div>
671
  </div>
 
672
  <!-- Care Requirements -->
673
  <div style="margin-bottom: 32px;">
674
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
 
681
  <div style="display: flex; align-items: center; gap: 10px;">
682
  <span style="font-size: 1.1em;">🏃</span>
683
  <span style="font-weight: 500;">Exercise</span>
684
+ <div style="position: relative; display: inline-block;"
685
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
686
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
687
  <span style="cursor: help; color: #718096;">ⓘ</span>
688
  <div class="tooltip-content" style="
 
703
  • Low: Short walks<br>
704
  • Moderate: 1-2 hours daily<br>
705
  • High: 2+ hours daily
706
+ <div style="position: absolute;
707
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
708
  width: 0;
709
  height: 0;
 
715
  </div>
716
  <span style="display: block; margin-top: 8px; color: #4a5568;">{description['Exercise Needs']}</span>
717
  </div>
 
718
  <!-- Grooming -->
719
  <div style="padding: 16px; border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;">
720
  <div style="display: flex; align-items: center; gap: 10px;">
721
  <span style="font-size: 1.1em;">✂️</span>
722
  <span style="font-weight: 500;">Grooming</span>
723
+ <div style="position: relative; display: inline-block;"
724
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
725
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
726
  <span style="cursor: help; color: #718096;">ⓘ</span>
727
  <div class="tooltip-content" style="
 
742
  • Low: Basic brushing<br>
743
  • Moderate: Weekly grooming<br>
744
  • High: Daily maintenance
745
+ <div style="position: absolute;
746
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
747
  width: 0;
748
  height: 0;
 
754
  </div>
755
  <span style="display: block; margin-top: 8px; color: #4a5568;">{description['Grooming Needs']}</span>
756
  </div>
 
757
  <!-- Care Level -->
758
  <div style="padding: 16px; border-radius: 10px; background: #fff; border: 1px solid #e2e8f0;">
759
  <div style="display: flex; align-items: center; gap: 10px;">
760
  <span style="font-size: 1.1em;">⭐</span>
761
  <span style="font-weight: 500;">Care Level</span>
762
+ <div style="position: relative; display: inline-block;"
763
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
764
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
765
  <span style="cursor: help; color: #718096;">ⓘ</span>
766
  <div class="tooltip-content" style="
 
781
  • Low: Basic care<br>
782
  • Moderate: Regular care<br>
783
  • High: Extensive care
784
+ <div style="position: absolute;
785
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
786
  width: 0;
787
  height: 0;
 
795
  </div>
796
  </div>
797
  </div>
 
798
  <!-- Noise Behavior -->
799
  <div style="margin-bottom: 32px;">
800
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
801
  <span style="font-size: 1.2em;">🔊</span>
802
  <span style="font-size: 1.2em; font-weight: 600; color: #2d3748;">NOISE BEHAVIOR</span>
803
+ <div style="position: relative; display: inline-block;"
804
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
805
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
806
  <span style="cursor: help; color: #718096;">ⓘ</span>
807
  <div class="tooltip-content" style="
 
822
  • Typical vocalization patterns<br>
823
  • Common triggers and frequency<br>
824
  • Based on breed characteristics
825
+ <div style="position: absolute;
826
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
827
  width: 0;
828
  height: 0;
 
869
  </details>
870
  </div>
871
  </div>
 
872
  <!-- Health Insights -->
873
  <div style="margin-bottom: 32px;">
874
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
875
  <span style="font-size: 1.2em;">🏥</span>
876
  <span style="font-size: 1.2em; font-weight: 600; color: #2d3748;">HEALTH INSIGHTS</span>
877
+ <div style="position: relative; display: inline-block;"
878
+ onmouseover="this.querySelector('.tooltip-content').style.visibility='visible';this.querySelector('.tooltip-content').style.opacity='1';"
879
  onmouseout="this.querySelector('.tooltip-content').style.visibility='hidden';this.querySelector('.tooltip-content').style.opacity='0';">
880
  <span style="cursor: help; color: #718096;">ⓘ</span>
881
  <div class="tooltip-content" style="
 
896
  • Common breed-specific conditions<br>
897
  • Recommended health screenings<br>
898
  • General health considerations
899
+ <div style="position: absolute;
900
  {f'left: 20px; bottom: -8px; border-top: 8px solid #2C3E50;' if not prob else 'top: 50%; right: 100%; transform: translateY(-50%); border-right: 8px solid #2C3E50;'};
901
  width: 0;
902
  height: 0;
 
936
  </details>
937
  </div>
938
  </div>
 
939
  <!-- Description -->
940
  <div style="margin-bottom: 32px;">
941
  <h3 style="display: flex; align-items: center; gap: 10px; margin: 0 0 20px 0; padding: 12px; background: #f8f9fa; border-radius: 6px;">
 
946
  <p style="line-height: 1.6; margin: 0; color: #2d3748;">{description.get('Description', '')}</p>
947
  </div>
948
  </div>
 
949
  <!-- Action Section -->
950
  <div style="text-align: center; margin-top: 32px;">
951
+ <a href="{get_akc_breeds_link(breed)}"
952
+ target="_blank"
953
  rel="noopener noreferrer"
954
  style="display: inline-flex; align-items: center; gap: 8px; padding: 14px 28px; background: linear-gradient(90deg, #4299e1, #48bb78); color: white; text-decoration: none; border-radius: 8px; font-weight: 500; transition: opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
955
  <span style="font-size: 1.2em;">🌐</span>
 
960
  </div>
961
  </div>
962
  '''
963
+
964
  return result
965
 
966
 
 
1021
  <p><strong>Good with Children:</strong> {original_data.get('Good with Children', 'N/A')}</p>
1022
  <p><strong>Temperament:</strong> {original_data.get('Temperament', 'N/A')}</p>
1023
  </div>
1024
+ """