Spaces:
Running
Running
Update index.html
Browse files- index.html +288 -491
index.html
CHANGED
|
@@ -50,12 +50,6 @@
|
|
| 50 |
gap: 12px;
|
| 51 |
}
|
| 52 |
|
| 53 |
-
.logo-area img {
|
| 54 |
-
height: 38px;
|
| 55 |
-
width: auto;
|
| 56 |
-
object-fit: contain;
|
| 57 |
-
}
|
| 58 |
-
|
| 59 |
.logo-text {
|
| 60 |
color: var(--white);
|
| 61 |
font-size: 15px;
|
|
@@ -95,12 +89,6 @@
|
|
| 95 |
min-width: 200px;
|
| 96 |
}
|
| 97 |
|
| 98 |
-
#setup-bar a {
|
| 99 |
-
color: var(--navy);
|
| 100 |
-
font-weight: 700;
|
| 101 |
-
font-size: 13px;
|
| 102 |
-
}
|
| 103 |
-
|
| 104 |
#key-input {
|
| 105 |
border: 2px solid #ffc107;
|
| 106 |
border-radius: 8px;
|
|
@@ -218,9 +206,7 @@
|
|
| 218 |
.card h2 span { font-size: 20px; }
|
| 219 |
|
| 220 |
/* FORM ELEMENTS */
|
| 221 |
-
.field {
|
| 222 |
-
margin-bottom: 20px;
|
| 223 |
-
}
|
| 224 |
|
| 225 |
label {
|
| 226 |
display: block;
|
|
@@ -232,11 +218,7 @@
|
|
| 232 |
letter-spacing: 0.5px;
|
| 233 |
}
|
| 234 |
|
| 235 |
-
.chips {
|
| 236 |
-
display: flex;
|
| 237 |
-
flex-wrap: wrap;
|
| 238 |
-
gap: 8px;
|
| 239 |
-
}
|
| 240 |
|
| 241 |
.chip {
|
| 242 |
padding: 8px 16px;
|
|
@@ -273,9 +255,7 @@
|
|
| 273 |
resize: vertical;
|
| 274 |
}
|
| 275 |
|
| 276 |
-
textarea:focus, input[type="text"]:focus {
|
| 277 |
-
border-color: var(--accent);
|
| 278 |
-
}
|
| 279 |
|
| 280 |
/* TRENDS TOGGLE */
|
| 281 |
.trends-toggle {
|
|
@@ -350,8 +330,6 @@
|
|
| 350 |
transition: all 0.2s;
|
| 351 |
letter-spacing: 0.5px;
|
| 352 |
margin-top: 4px;
|
| 353 |
-
position: relative;
|
| 354 |
-
overflow: hidden;
|
| 355 |
}
|
| 356 |
|
| 357 |
.btn-generate:hover:not(:disabled) {
|
|
@@ -360,16 +338,10 @@
|
|
| 360 |
box-shadow: 0 6px 20px rgba(28,45,78,0.3);
|
| 361 |
}
|
| 362 |
|
| 363 |
-
.btn-generate:disabled {
|
| 364 |
-
opacity: 0.6;
|
| 365 |
-
cursor: not-allowed;
|
| 366 |
-
}
|
| 367 |
|
| 368 |
/* RESULT */
|
| 369 |
-
#result-area {
|
| 370 |
-
margin-top: 28px;
|
| 371 |
-
display: none;
|
| 372 |
-
}
|
| 373 |
#result-area.show { display: block; }
|
| 374 |
|
| 375 |
.result-header {
|
|
@@ -378,6 +350,7 @@
|
|
| 378 |
justify-content: space-between;
|
| 379 |
margin-bottom: 18px;
|
| 380 |
}
|
|
|
|
| 381 |
.result-label {
|
| 382 |
font-size: 11px;
|
| 383 |
font-weight: 700;
|
|
@@ -388,6 +361,7 @@
|
|
| 388 |
align-items: center;
|
| 389 |
gap: 6px;
|
| 390 |
}
|
|
|
|
| 391 |
.result-label::before {
|
| 392 |
content: "";
|
| 393 |
width: 6px; height: 6px;
|
|
@@ -396,10 +370,12 @@
|
|
| 396 |
display: inline-block;
|
| 397 |
animation: pulse 1.5s infinite;
|
| 398 |
}
|
|
|
|
| 399 |
@keyframes pulse {
|
| 400 |
0%,100%{opacity:1;transform:scale(1)}
|
| 401 |
50%{opacity:0.4;transform:scale(1.4)}
|
| 402 |
}
|
|
|
|
| 403 |
.btn-copy {
|
| 404 |
background: white;
|
| 405 |
border: 2px solid var(--gray-light);
|
|
@@ -415,13 +391,10 @@
|
|
| 415 |
align-items: center;
|
| 416 |
gap: 5px;
|
| 417 |
}
|
|
|
|
| 418 |
.btn-copy:hover { background: var(--navy); color: white; border-color: var(--navy); }
|
| 419 |
|
| 420 |
-
#result-content {
|
| 421 |
-
display: flex;
|
| 422 |
-
flex-direction: column;
|
| 423 |
-
gap: 16px;
|
| 424 |
-
}
|
| 425 |
|
| 426 |
/* LOADING CARD */
|
| 427 |
.loading-card {
|
|
@@ -441,31 +414,67 @@
|
|
| 441 |
/* IDEA CARDS */
|
| 442 |
.idea-card {
|
| 443 |
background: white;
|
| 444 |
-
border-radius:
|
| 445 |
-
border:
|
| 446 |
overflow: hidden;
|
| 447 |
-
transition: transform 0.
|
| 448 |
-
animation: fadeUp 0.
|
|
|
|
| 449 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
.idea-card:hover {
|
| 451 |
-
transform: translateY(-
|
| 452 |
-
box-shadow: 0
|
|
|
|
| 453 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
@keyframes fadeUp {
|
| 455 |
-
from { opacity:0; transform: translateY(
|
| 456 |
-
to { opacity:1; transform: translateY(0); }
|
| 457 |
}
|
|
|
|
| 458 |
.card-accent {
|
| 459 |
-
height:
|
| 460 |
background: linear-gradient(90deg, var(--navy), var(--accent));
|
|
|
|
| 461 |
}
|
| 462 |
-
.card-accent.green { background: linear-gradient(90deg, #
|
| 463 |
-
.card-accent.orange { background: linear-gradient(90deg, #
|
| 464 |
-
.card-accent.pink { background: linear-gradient(90deg, #
|
| 465 |
-
.card-accent.teal { background: linear-gradient(90deg, #0F6E56, #
|
|
|
|
|
|
|
|
|
|
| 466 |
.card-body {
|
| 467 |
-
padding:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 468 |
}
|
|
|
|
| 469 |
.card-tag {
|
| 470 |
display: inline-flex;
|
| 471 |
align-items: center;
|
|
@@ -474,10 +483,14 @@
|
|
| 474 |
font-weight: 700;
|
| 475 |
text-transform: uppercase;
|
| 476 |
letter-spacing: 1px;
|
| 477 |
-
padding:
|
| 478 |
border-radius: 20px;
|
| 479 |
-
|
|
|
|
| 480 |
}
|
|
|
|
|
|
|
|
|
|
| 481 |
.card-tag.blue { background: #e6f1fb; color: #185FA5; }
|
| 482 |
.card-tag.green { background: #E1F5EE; color: #0F6E56; }
|
| 483 |
.card-tag.orange { background: #FAEEDA; color: #854F0B; }
|
|
@@ -485,46 +498,77 @@
|
|
| 485 |
.card-tag.teal { background: #E1F5EE; color: #085041; }
|
| 486 |
.card-tag.purple { background: #EEEDFE; color: #3C3489; }
|
| 487 |
.card-tag.red { background: #FCEBEB; color: #A32D2D; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 488 |
.card-title {
|
| 489 |
-
font-size:
|
| 490 |
font-weight: 800;
|
| 491 |
color: var(--navy);
|
| 492 |
-
margin-bottom:
|
| 493 |
line-height: 1.35;
|
|
|
|
| 494 |
}
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
line-height: 1.7;
|
| 499 |
-
margin-bottom: 14px;
|
| 500 |
-
}
|
| 501 |
.card-divider {
|
| 502 |
height: 1px;
|
| 503 |
background: var(--gray-light);
|
| 504 |
-
margin:
|
| 505 |
-
|
| 506 |
-
.card-meta {
|
| 507 |
-
display: flex;
|
| 508 |
-
flex-wrap: wrap;
|
| 509 |
-
gap: 8px;
|
| 510 |
}
|
| 511 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
display: flex;
|
| 513 |
align-items: center;
|
| 514 |
gap: 5px;
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
|
|
|
|
|
|
|
|
|
| 518 |
background: var(--off-white);
|
| 519 |
-
border-radius:
|
| 520 |
-
padding:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
}
|
| 522 |
-
.meta-chip span { font-size: 13px; }
|
| 523 |
|
| 524 |
/* STREAMING RAW (fallback) */
|
| 525 |
.stream-raw {
|
| 526 |
background: white;
|
| 527 |
-
border-radius:
|
| 528 |
padding: 24px;
|
| 529 |
font-size: 13px;
|
| 530 |
line-height: 1.8;
|
|
@@ -533,7 +577,7 @@
|
|
| 533 |
white-space: pre-wrap;
|
| 534 |
}
|
| 535 |
|
| 536 |
-
/* LOADING */
|
| 537 |
.loading-dots {
|
| 538 |
display: inline-flex;
|
| 539 |
gap: 5px;
|
|
@@ -557,19 +601,6 @@
|
|
| 557 |
40% { transform: scale(1); opacity: 1; }
|
| 558 |
}
|
| 559 |
|
| 560 |
-
/* STREAMED text */
|
| 561 |
-
.streaming-cursor::after {
|
| 562 |
-
content: '▊';
|
| 563 |
-
animation: blink 0.8s infinite;
|
| 564 |
-
color: var(--accent);
|
| 565 |
-
font-size: 14px;
|
| 566 |
-
}
|
| 567 |
-
|
| 568 |
-
@keyframes blink {
|
| 569 |
-
0%, 100% { opacity: 1; }
|
| 570 |
-
50% { opacity: 0; }
|
| 571 |
-
}
|
| 572 |
-
|
| 573 |
/* TUTO MODAL */
|
| 574 |
.tuto-overlay {
|
| 575 |
display: none;
|
|
@@ -591,98 +622,31 @@
|
|
| 591 |
box-shadow: 0 20px 60px rgba(28,45,78,0.25);
|
| 592 |
position: relative;
|
| 593 |
}
|
| 594 |
-
.tuto-box h3 {
|
| 595 |
-
|
| 596 |
-
font-weight: 800;
|
| 597 |
-
color: var(--navy);
|
| 598 |
-
margin-bottom: 6px;
|
| 599 |
-
}
|
| 600 |
-
.tuto-box .tuto-sub {
|
| 601 |
-
font-size: 13px;
|
| 602 |
-
color: var(--gray);
|
| 603 |
-
margin-bottom: 24px;
|
| 604 |
-
font-weight: 500;
|
| 605 |
-
}
|
| 606 |
.tuto-steps { list-style: none; padding: 0; }
|
| 607 |
-
.tuto-steps li {
|
| 608 |
-
display: flex;
|
| 609 |
-
gap: 14px;
|
| 610 |
-
align-items: flex-start;
|
| 611 |
-
margin-bottom: 16px;
|
| 612 |
-
}
|
| 613 |
.step-num {
|
| 614 |
-
width: 28px;
|
| 615 |
-
|
| 616 |
-
|
| 617 |
-
background: var(--navy);
|
| 618 |
-
color: white;
|
| 619 |
-
font-size: 12px;
|
| 620 |
-
font-weight: 800;
|
| 621 |
-
display: flex;
|
| 622 |
-
align-items: center;
|
| 623 |
-
justify-content: center;
|
| 624 |
-
flex-shrink: 0;
|
| 625 |
-
margin-top: 1px;
|
| 626 |
-
}
|
| 627 |
-
.step-text {
|
| 628 |
-
font-size: 13px;
|
| 629 |
-
color: var(--navy);
|
| 630 |
-
line-height: 1.6;
|
| 631 |
-
font-weight: 500;
|
| 632 |
-
}
|
| 633 |
-
.step-text a {
|
| 634 |
-
color: var(--accent);
|
| 635 |
-
font-weight: 700;
|
| 636 |
-
text-decoration: none;
|
| 637 |
-
}
|
| 638 |
-
.step-text code {
|
| 639 |
-
background: var(--gray-light);
|
| 640 |
-
padding: 2px 7px;
|
| 641 |
-
border-radius: 5px;
|
| 642 |
-
font-family: monospace;
|
| 643 |
-
font-size: 12px;
|
| 644 |
-
color: var(--navy);
|
| 645 |
}
|
|
|
|
|
|
|
|
|
|
| 646 |
.tuto-close {
|
| 647 |
-
position: absolute;
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
background: var(--gray-light);
|
| 651 |
-
border: none;
|
| 652 |
-
border-radius: 50%;
|
| 653 |
-
width: 30px;
|
| 654 |
-
height: 30px;
|
| 655 |
-
font-size: 16px;
|
| 656 |
-
cursor: pointer;
|
| 657 |
-
color: var(--navy);
|
| 658 |
-
display: flex;
|
| 659 |
-
align-items: center;
|
| 660 |
-
justify-content: center;
|
| 661 |
-
font-weight: 700;
|
| 662 |
}
|
| 663 |
.tuto-close:hover { background: var(--navy); color: white; }
|
| 664 |
.btn-tuto-done {
|
| 665 |
-
width: 100%;
|
| 666 |
-
|
| 667 |
-
|
| 668 |
-
border: none;
|
| 669 |
-
border-radius: 10px;
|
| 670 |
-
padding: 13px;
|
| 671 |
-
font-family: 'Montserrat', sans-serif;
|
| 672 |
-
font-size: 13px;
|
| 673 |
-
font-weight: 700;
|
| 674 |
-
cursor: pointer;
|
| 675 |
-
margin-top: 22px;
|
| 676 |
-
transition: background 0.2s;
|
| 677 |
}
|
| 678 |
.btn-tuto-done:hover { background: var(--navy-light); }
|
| 679 |
-
.tuto-link {
|
| 680 |
-
color: var(--accent) !important;
|
| 681 |
-
font-weight: 700;
|
| 682 |
-
cursor: pointer;
|
| 683 |
-
text-decoration: underline;
|
| 684 |
-
font-size: 13px;
|
| 685 |
-
}
|
| 686 |
|
| 687 |
/* RESPONSIVE */
|
| 688 |
@media (max-width: 600px) {
|
|
@@ -698,12 +662,11 @@
|
|
| 698 |
|
| 699 |
<header>
|
| 700 |
<div class="logo-area">
|
| 701 |
-
<div class="logo-text">Junior CGY</div>
|
| 702 |
<div class="badge">IA</div>
|
| 703 |
</div>
|
| 704 |
</header>
|
| 705 |
|
| 706 |
-
<!-- KEY SETUP BAR -->
|
| 707 |
<div id="setup-bar">
|
| 708 |
<span>🔑 Entre ta clé OpenRouter pour activer l'IA — <span class="tuto-link" onclick="document.getElementById('tuto-overlay').classList.add('show')">Comment obtenir ma clé gratuite ?</span></span>
|
| 709 |
<input type="text" id="key-input" placeholder="sk-or-v1-..." />
|
|
@@ -711,37 +674,18 @@
|
|
| 711 |
<span id="key-status"></span>
|
| 712 |
</div>
|
| 713 |
|
| 714 |
-
<!-- TUTO MODAL -->
|
| 715 |
<div class="tuto-overlay" id="tuto-overlay" onclick="closeTutoIfOutside(event)">
|
| 716 |
<div class="tuto-box" id="tuto-box">
|
| 717 |
<button class="tuto-close" onclick="document.getElementById('tuto-overlay').classList.remove('show')">✕</button>
|
| 718 |
<h3>🔑 Obtenir ta clé gratuite</h3>
|
| 719 |
<p class="tuto-sub">2 minutes chrono — pas de CB, juste un email</p>
|
| 720 |
<ol class="tuto-steps">
|
| 721 |
-
<li>
|
| 722 |
-
|
| 723 |
-
|
| 724 |
-
</li>
|
| 725 |
-
<li>
|
| 726 |
-
|
| 727 |
-
<div class="step-text">Crée ton compte avec ton adresse email (Google ou email classique) — <strong>aucune carte bancaire demandée</strong></div>
|
| 728 |
-
</li>
|
| 729 |
-
<li>
|
| 730 |
-
<div class="step-num">3</div>
|
| 731 |
-
<div class="step-text">Une fois connecté, clique sur <strong>"Get API keys"</strong> dans le menu à gauche</div>
|
| 732 |
-
</li>
|
| 733 |
-
<li>
|
| 734 |
-
<div class="step-num">4</div>
|
| 735 |
-
<div class="step-text">Clique sur <strong>"Create"</strong> en haut à droite, donne-lui un nom (ex : <em>"Junior CGY"</em>), laisse tout par défaut et valide</div>
|
| 736 |
-
</li>
|
| 737 |
-
<li>
|
| 738 |
-
<div class="step-num">5</div>
|
| 739 |
-
<div class="step-text">Copie la clé affichée — elle commence par <code>sk-or-v1-...</code> — elle n'apparaît qu'une seule fois !</div>
|
| 740 |
-
</li>
|
| 741 |
-
<li>
|
| 742 |
-
<div class="step-num">6</div>
|
| 743 |
-
<div class="step-text">Colle-la dans le champ en haut de cette page et clique <strong>"Enregistrer"</strong> ✅</div>
|
| 744 |
-
</li>
|
| 745 |
</ol>
|
| 746 |
<button class="btn-tuto-done" onclick="document.getElementById('tuto-overlay').classList.remove('show')">J'ai compris, je vais créer ma clé 🚀</button>
|
| 747 |
</div>
|
|
@@ -761,7 +705,6 @@
|
|
| 761 |
<!-- TAB 1 : CONTENU -->
|
| 762 |
<div id="tab-contenu" class="card active">
|
| 763 |
<h2><span>💡</span> Idées de contenu réseaux sociaux</h2>
|
| 764 |
-
|
| 765 |
<div class="field">
|
| 766 |
<label>Réseau social</label>
|
| 767 |
<div class="chips">
|
|
@@ -770,7 +713,6 @@
|
|
| 770 |
<div class="chip" data-group="reseau" onclick="toggleChip(this)">LinkedIn</div>
|
| 771 |
</div>
|
| 772 |
</div>
|
| 773 |
-
|
| 774 |
<div class="field">
|
| 775 |
<label>Format de contenu</label>
|
| 776 |
<div class="chips">
|
|
@@ -780,39 +722,30 @@
|
|
| 780 |
<div class="chip" data-group="format_contenu" onclick="toggleChip(this)">Story (visible 24h)</div>
|
| 781 |
</div>
|
| 782 |
</div>
|
| 783 |
-
|
| 784 |
<div class="field">
|
| 785 |
<label>Cible</label>
|
| 786 |
<div class="chips">
|
| 787 |
-
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">PME du Val d'Oise</div>
|
| 788 |
-
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Cabinets de conseil</div>
|
| 789 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Intervenants (étudiants missions)</div>
|
| 790 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Administrateurs (équipe asso)</div>
|
| 791 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Clients (PME / cabinets)</div>
|
| 792 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Tous publics</div>
|
| 793 |
</div>
|
| 794 |
</div>
|
| 795 |
-
|
| 796 |
<div class="field">
|
| 797 |
<label>Angle / message clé (optionnel)</label>
|
| 798 |
<textarea id="commentaire-contenu" rows="2" placeholder="Ex : On veut montrer qu'on accompagne vraiment les étudiants, ou insister sur le fait qu'on n'est pas remplaçable par l'IA…"></textarea>
|
| 799 |
</div>
|
| 800 |
-
|
| 801 |
<div id="trends-contenu" class="trends-toggle" onclick="toggleTrends('trends-contenu')">
|
| 802 |
<span class="toggle-icon">📈</span>
|
| 803 |
<span class="toggle-text">Intégrer les tendances du moment (avril 2026)</span>
|
| 804 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 805 |
</div>
|
| 806 |
-
|
| 807 |
-
<button class="btn-generate" onclick="generate('contenu')">
|
| 808 |
-
🚀 Générer 7 idées (une par approche)
|
| 809 |
-
</button>
|
| 810 |
</div>
|
| 811 |
|
| 812 |
<!-- TAB 2 : ÉVÉNEMENTS -->
|
| 813 |
<div id="tab-evenements" class="card">
|
| 814 |
<h2><span>🎉</span> Idées d'événements</h2>
|
| 815 |
-
|
| 816 |
<div class="field">
|
| 817 |
<label>Type d'événement</label>
|
| 818 |
<div class="chips">
|
|
@@ -823,7 +756,6 @@
|
|
| 823 |
<div class="chip" data-group="type_event" onclick="toggleChip(this)">Conférence / table ronde</div>
|
| 824 |
</div>
|
| 825 |
</div>
|
| 826 |
-
|
| 827 |
<div class="field">
|
| 828 |
<label>Public cible</label>
|
| 829 |
<div class="chips">
|
|
@@ -834,22 +766,17 @@
|
|
| 834 |
<div class="chip" data-group="public_event" onclick="toggleChip(this)">Mixte (étudiants + pros)</div>
|
| 835 |
</div>
|
| 836 |
</div>
|
| 837 |
-
|
| 838 |
<div id="trends-evenements" class="trends-toggle" onclick="toggleTrends('trends-evenements')">
|
| 839 |
<span class="toggle-icon">📈</span>
|
| 840 |
<span class="toggle-text">Intégrer les tendances du moment (avril 2026)</span>
|
| 841 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 842 |
</div>
|
| 843 |
-
|
| 844 |
-
<button class="btn-generate" onclick="generate('evenements')">
|
| 845 |
-
Générer 4 concepts d'événements
|
| 846 |
-
</button>
|
| 847 |
</div>
|
| 848 |
|
| 849 |
<!-- TAB 3 : POST -->
|
| 850 |
<div id="tab-post" class="card">
|
| 851 |
<h2><span>✍️</span> Rédiger un post</h2>
|
| 852 |
-
|
| 853 |
<div class="field">
|
| 854 |
<label>Réseau social</label>
|
| 855 |
<div class="chips">
|
|
@@ -858,12 +785,10 @@
|
|
| 858 |
<div class="chip" data-group="reseau_post" onclick="toggleChip(this)">LinkedIn</div>
|
| 859 |
</div>
|
| 860 |
</div>
|
| 861 |
-
|
| 862 |
<div class="field">
|
| 863 |
<label>Sujet ou message à communiquer</label>
|
| 864 |
<textarea id="sujet-post" rows="3" placeholder="Ex : On recrute des nouveaux membres, on a réalisé une mission pour une PME, on organise un event…"></textarea>
|
| 865 |
</div>
|
| 866 |
-
|
| 867 |
<div class="field">
|
| 868 |
<label>Ton souhaité</label>
|
| 869 |
<div class="chips">
|
|
@@ -873,22 +798,17 @@
|
|
| 873 |
<div class="chip" data-group="ton" onclick="toggleChip(this)">Proche / humain</div>
|
| 874 |
</div>
|
| 875 |
</div>
|
| 876 |
-
|
| 877 |
<div id="trends-post" class="trends-toggle" onclick="toggleTrends('trends-post')">
|
| 878 |
<span class="toggle-icon">📈</span>
|
| 879 |
<span class="toggle-text">Adapter au format viral du moment (avril 2026)</span>
|
| 880 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 881 |
</div>
|
| 882 |
-
|
| 883 |
-
<button class="btn-generate" onclick="generate('post')">
|
| 884 |
-
Rédiger le post
|
| 885 |
-
</button>
|
| 886 |
</div>
|
| 887 |
|
| 888 |
<!-- TAB 4 : CALENDRIER -->
|
| 889 |
<div id="tab-calendrier" class="card">
|
| 890 |
<h2><span>📅</span> Calendrier éditorial</h2>
|
| 891 |
-
|
| 892 |
<div class="field">
|
| 893 |
<label>Période</label>
|
| 894 |
<div class="chips">
|
|
@@ -897,7 +817,6 @@
|
|
| 897 |
<div class="chip" data-group="periode" onclick="toggleChip(this)">1 mois</div>
|
| 898 |
</div>
|
| 899 |
</div>
|
| 900 |
-
|
| 901 |
<div class="field">
|
| 902 |
<label>Fréquence de publication</label>
|
| 903 |
<div class="chips">
|
|
@@ -906,7 +825,6 @@
|
|
| 906 |
<div class="chip" data-group="frequence" onclick="toggleChip(this)">1 post / jour</div>
|
| 907 |
</div>
|
| 908 |
</div>
|
| 909 |
-
|
| 910 |
<div class="field">
|
| 911 |
<label>Réseaux à couvrir</label>
|
| 912 |
<div class="chips">
|
|
@@ -915,16 +833,12 @@
|
|
| 915 |
<div class="chip" data-group="reseaux_cal" onclick="toggleChip(this)">LinkedIn</div>
|
| 916 |
</div>
|
| 917 |
</div>
|
| 918 |
-
|
| 919 |
<div id="trends-calendrier" class="trends-toggle" onclick="toggleTrends('trends-calendrier')">
|
| 920 |
<span class="toggle-icon">📈</span>
|
| 921 |
<span class="toggle-text">Intégrer les tendances du moment (avril 2026)</span>
|
| 922 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 923 |
</div>
|
| 924 |
-
|
| 925 |
-
<button class="btn-generate" onclick="generate('calendrier')">
|
| 926 |
-
Générer le calendrier
|
| 927 |
-
</button>
|
| 928 |
</div>
|
| 929 |
|
| 930 |
<!-- RESULT AREA -->
|
|
@@ -938,58 +852,14 @@
|
|
| 938 |
</main>
|
| 939 |
|
| 940 |
<script>
|
| 941 |
-
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
-
|
| 946 |
-
|
| 947 |
-
|
| 948 |
-
|
| 949 |
-
|
| 950 |
-
=== NOS 2 TYPES DE MEMBRES ===
|
| 951 |
-
1. INTERVENANTS : étudiants de l'université qui réalisent les études pour les clients.
|
| 952 |
-
Ce qui les motive : être rétribués (argent), gagner une vraie expérience pour leur CV, s'enrichir personnellement, être accompagnés et encadrés.
|
| 953 |
-
Leur douleur : CV vide, pas d'expérience = pas de job = pas d'argent → cercle vicieux.
|
| 954 |
-
Ce qu'on leur apporte : missions concrètes et rémunérées, accompagnement du début à la fin, expérience valorisable en entretien, ils ne sont jamais livrés à eux-mêmes.
|
| 955 |
-
|
| 956 |
-
2. ADMINISTRATEURS : étudiants qui rejoignent l'équipe interne de l'association (pôle commercial, pôle communication, pôle RH, trésorerie).
|
| 957 |
-
Ce qui les motive : participer à une structure à forte valeur ajoutée, développer des compétences concrètes par pôle, enrichissement personnel, prestige et réseau pro.
|
| 958 |
-
Ce qu'on leur apporte : responsabilités réelles (gérer un pôle = gérer en startup), réseau avec entreprises du Val-d'Oise, expérience quasi-entrepreneuriale.
|
| 959 |
-
|
| 960 |
-
=== NOS CLIENTS ===
|
| 961 |
-
PME du Val-d'Oise et cabinets de conseil. Ils nous choisissent car :
|
| 962 |
-
- On travaille SUR leur entreprise (pas des réponses génériques comme l'IA)
|
| 963 |
-
- On livre des recommandations concrètes et directement exploitables
|
| 964 |
-
- Prix bien en dessous d'un cabinet classique
|
| 965 |
-
- Processus structuré : brief → réalisation → livrable → validation
|
| 966 |
-
- On leur fait gagner du temps : ils donnent le cap, on fait le reste
|
| 967 |
-
|
| 968 |
-
=== NOS OFFRES ===
|
| 969 |
-
- Analyse financière & performance économique (CdR, TSIG, bilan fonctionnel FRNG/BFR/TN)
|
| 970 |
-
- Benchmark concurrentiel (ciblé sur leurs vrais concurrents)
|
| 971 |
-
- Études quantitatives (enquête en ligne/téléphonique/face-à-face, échantillonnage, synthèse)
|
| 972 |
-
|
| 973 |
-
=== ARGUMENTS VS OBJECTIONS CLIENTS ===
|
| 974 |
-
- "L'IA fait ça" → "L'IA donne des réponses générales. Nous, on travaille sur VOTRE entreprise, avec VOS données."
|
| 975 |
-
- "Pas assez expérimentés" → "Méthodes académiques solides + encadrement structuré + regard neuf."
|
| 976 |
-
- "Trop cher" → "Le vrai coût c'est une mauvaise décision sans données."
|
| 977 |
-
- "Je peux le faire moi-même" → "Votre valeur est dans la décision, pas dans la collecte de données."
|
| 978 |
-
Punchlines clés : "L'IA vous donne une réponse. Nous, on vous donne une direction." / "Vous nous donnez le cap, on fait le reste."
|
| 979 |
-
|
| 980 |
-
=== ANGLES PERSUASIFS À UTILISER SELON LA CIBLE ===
|
| 981 |
-
- INTERVENANTS : partir de leur douleur (CV vide, cercle vicieux), projection future ("tu pourras dire en entretien..."), preuve sociale, urgence/rareté (places limitées), accompagnement ("jamais livré à toi-même")
|
| 982 |
-
- ADMINISTRATEURS : projection future (responsable de pôle, gère comme en entreprise), prestige/réseau, différenciation vs stage classique
|
| 983 |
-
- CLIENTS : personnalisation vs IA, gain de temps, coût de l'erreur, regard extérieur, argument émotionnel (investir dans la prochaine génération)
|
| 984 |
-
|
| 985 |
-
=== RÉSEAUX SOCIAUX === Instagram, TikTok, LinkedIn
|
| 986 |
-
|
| 987 |
-
=== TON & IDENTITÉ ===
|
| 988 |
-
Professionnel mais accessible, dynamique, percutant. Toujours ancrer dans la réalité du Val-d'Oise et de CY Cergy Paris Université. Réponds toujours en français.
|
| 989 |
-
`;
|
| 990 |
-
|
| 991 |
-
// ── STATE ──────────────────────────────────────────────────────────────────
|
| 992 |
-
localStorage.removeItem('hf_key'); // nettoyage ancienne clé
|
| 993 |
let hfKey = localStorage.getItem('or_key') || '';
|
| 994 |
if (hfKey) document.getElementById('setup-bar').classList.add('hidden');
|
| 995 |
|
|
@@ -1011,7 +881,6 @@ function saveKey() {
|
|
| 1011 |
setTimeout(() => document.getElementById('setup-bar').classList.add('hidden'), 1200);
|
| 1012 |
}
|
| 1013 |
|
| 1014 |
-
// ── TABS ───────────────────────────────────────────────────────────────────
|
| 1015 |
function switchTab(name, btn) {
|
| 1016 |
document.querySelectorAll('.card').forEach(c => c.classList.remove('active'));
|
| 1017 |
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
|
@@ -1020,238 +889,179 @@ function switchTab(name, btn) {
|
|
| 1020 |
document.getElementById('result-area').classList.remove('show');
|
| 1021 |
}
|
| 1022 |
|
| 1023 |
-
|
| 1024 |
-
function toggleChip(el) {
|
| 1025 |
-
el.classList.toggle('selected');
|
| 1026 |
-
}
|
| 1027 |
|
| 1028 |
function getSelected(group) {
|
| 1029 |
-
return [...document.querySelectorAll(`.chip[data-group="${group}"].selected`)]
|
| 1030 |
-
.map(c => c.textContent.trim());
|
| 1031 |
-
}
|
| 1032 |
-
|
| 1033 |
-
// ── TRENDS TOGGLE ──────────────────────────────────────────────────────────
|
| 1034 |
-
function toggleTrends(id) {
|
| 1035 |
-
document.getElementById(id).classList.toggle('on');
|
| 1036 |
}
|
| 1037 |
|
| 1038 |
-
function
|
| 1039 |
-
|
| 1040 |
-
}
|
| 1041 |
|
| 1042 |
-
// ── BUILD PROMPT ───────────────────────────────────────────────────────────
|
| 1043 |
function buildPrompt(tab) {
|
| 1044 |
-
|
| 1045 |
-
const JSON_INSTRUCTION = 'Reponds UNIQUEMENT en JSON valide pur, sans markdown, sans backticks, sans texte avant ou apres.';
|
| 1046 |
|
| 1047 |
if (tab === 'contenu') {
|
| 1048 |
const reseau = getSelected('reseau').join(', ') || 'tous reseaux';
|
| 1049 |
const format = getSelected('format_contenu').join(', ') || 'format libre';
|
| 1050 |
const cibles = getSelected('cible_contenu');
|
| 1051 |
-
const cible
|
| 1052 |
const commentaire = document.getElementById('commentaire-contenu').value.trim();
|
| 1053 |
const trends = isTrendsOn('trends-contenu') ? ' Integre les tendances virales et formats populaires avril 2026.' : '';
|
| 1054 |
-
const
|
| 1055 |
-
const
|
| 1056 |
-
const
|
| 1057 |
-
const hasTous = cibles.length === 0 || cibles.some(c => c.toLowerCase().includes('tous'));
|
| 1058 |
|
| 1059 |
let approches = '';
|
| 1060 |
-
if (
|
| 1061 |
-
|
| 1062 |
-
|
| 1063 |
-
|
| 1064 |
-
|
| 1065 |
-
|
| 1066 |
-
|
| 1067 |
-
|
| 1068 |
-
|
| 1069 |
-
|
| 1070 |
-
|
| 1071 |
-
"
|
| 1072 |
-
|
| 1073 |
-
|
| 1074 |
-
|
| 1075 |
-
|
| 1076 |
-
|
| 1077 |
-
|
| 1078 |
-
|
| 1079 |
-
|
| 1080 |
-
|
| 1081 |
-
|
| 1082 |
-
|
| 1083 |
-
|
| 1084 |
-
|
| 1085 |
-
|
| 1086 |
-
|
| 1087 |
-
|
| 1088 |
-
|
| 1089 |
-
|
| 1090 |
-
|
| 1091 |
-
|
| 1092 |
-
|
| 1093 |
-
|
| 1094 |
-
|
| 1095 |
-
|
| 1096 |
-
|
| 1097 |
-
|
| 1098 |
-
|
| 1099 |
-
"Vous prenez des decisions importantes sans donnees fiables?" Douleur du dirigeant, puis solution concrete.
|
| 1100 |
-
APPROCHE 3 tag:"⏱ Gain de temps" tagColor:teal accentColor:teal
|
| 1101 |
-
"Vous nous donnez le cap, on fait le reste." Collecte, analyse, synthese livres directement exploitables.
|
| 1102 |
-
APPROCHE 4 tag:"💸 Cout de l erreur" tagColor:orange accentColor:orange
|
| 1103 |
-
"Ce n est pas le cout de l etude qui est cher... c est le cout d une mauvaise decision."
|
| 1104 |
-
APPROCHE 5 tag:"🏆 Preuve sociale" tagColor:green accentColor:green
|
| 1105 |
-
Exemples missions realisees, types entreprises accompagnees dans le Val-d Oise.
|
| 1106 |
-
APPROCHE 6 tag:"🎓 Argument emotionnel" tagColor:pink accentColor:pink
|
| 1107 |
-
"Vous investissez dans la prochaine generation de talents." Bonus emotionnel differenciant.
|
| 1108 |
-
APPROCHE 7 tag:"🔍 Regard exterieur" tagColor:purple accentColor:pink
|
| 1109 |
-
"Vous etes trop dans votre entreprise pour voir ses failles. Nous, on les met en lumiere."`;
|
| 1110 |
-
}
|
| 1111 |
-
|
| 1112 |
-
userPrompt = JSON_INSTRUCTION + ` Format: {"ideas":[{"tag":"emoji label","tagColor":"red","accentColor":"default","title":"Titre court percutant","description":"Description vivante avec emojis naturels, rythme, energie. Ce qu on voit entend lit sur ${reseau} format ${format}.","visuel":"Conseil visuel concret 🎨","pourquoi":"Pourquoi imbattable pour cette cible ✅"}]}
|
| 1113 |
-
tagColor valeurs: red blue green orange pink teal purple | accentColor valeurs: default green orange pink teal
|
| 1114 |
-
Genere une idea par APPROCHE listee ci-dessous. Cible: ${cible}. ${commentaire ? 'Contexte: ' + commentaire : ''}${trends}
|
| 1115 |
-
Approches a traiter:
|
| 1116 |
-
${approches}
|
| 1117 |
-
Tout en francais. Sois percutant, moderne, high-level.`;
|
| 1118 |
-
}
|
| 1119 |
-
|
| 1120 |
-
else if (tab === 'evenements') {
|
| 1121 |
-
const type = getSelected('type_event').join(', ') || 'evenement general';
|
| 1122 |
-
const pub = getSelected('public_event').join(', ') || 'tous publics';
|
| 1123 |
-
const trends = isTrendsOn('trends-evenements') ? ' Integre les formats evenements tendance 2026.' : '';
|
| 1124 |
-
userPrompt = JSON_INSTRUCTION + ` Format: {"events":[{"tag":"emoji type","tagColor":"blue","accentColor":"default","title":"Nom evenement percutant","concept":"Concept vivant ambiance deroulé avec emojis 🎯","com":"Idee com reseaux concrete 📲","objectif":"Ce que ca apporte a JC CGY 🎯"}]}
|
| 1125 |
-
tagColor: red blue green orange pink teal purple | accentColor: default green orange pink teal
|
| 1126 |
-
Type: ${type} | Public: ${pub}${trends}
|
| 1127 |
-
Genere 4 concepts originaux et memorables. Tout en francais.`;
|
| 1128 |
-
}
|
| 1129 |
-
|
| 1130 |
-
else if (tab === 'post') {
|
| 1131 |
const reseau = getSelected('reseau_post').join(', ') || 'Instagram';
|
| 1132 |
-
const sujet
|
| 1133 |
-
const ton
|
| 1134 |
-
const trends = isTrendsOn('trends-post') ? ' Hook
|
| 1135 |
-
|
| 1136 |
-
Reseau: ${reseau} | Sujet: ${sujet} | Ton: ${ton}${trends}
|
| 1137 |
-
Post
|
| 1138 |
}
|
| 1139 |
|
| 1140 |
-
|
| 1141 |
const periode = getSelected('periode').join(', ') || '2 semaines';
|
| 1142 |
-
const freq
|
| 1143 |
const reseaux = getSelected('reseaux_cal').join(', ') || 'Instagram, LinkedIn';
|
| 1144 |
-
const trends
|
| 1145 |
-
|
| 1146 |
-
Periode: ${periode} | Frequence: ${freq} | Reseaux: ${reseaux}${trends}
|
| 1147 |
-
|
| 1148 |
}
|
| 1149 |
-
|
| 1150 |
-
return userPrompt;
|
| 1151 |
}
|
| 1152 |
|
| 1153 |
-
// ── MODELS LIST (OpenRouter - gratuits sans CB) ───────────────────────────
|
| 1154 |
const FREE_MODELS = [
|
| 1155 |
-
'
|
| 1156 |
-
'google/gemma-3-
|
| 1157 |
-
'
|
|
|
|
| 1158 |
];
|
| 1159 |
|
| 1160 |
-
|
| 1161 |
-
|
|
|
|
|
|
|
| 1162 |
const rc = document.getElementById('result-content');
|
| 1163 |
let data;
|
| 1164 |
try {
|
| 1165 |
-
const
|
| 1166 |
-
|
|
|
|
| 1167 |
} catch(e) {
|
| 1168 |
-
rc.innerHTML = `<div class="stream-raw">${
|
| 1169 |
return;
|
| 1170 |
}
|
| 1171 |
-
|
| 1172 |
rc.innerHTML = '';
|
| 1173 |
|
| 1174 |
-
// CONTENU — ideas
|
| 1175 |
if (data.ideas) {
|
| 1176 |
-
data.ideas.forEach((
|
| 1177 |
-
const
|
| 1178 |
-
const
|
| 1179 |
-
|
| 1180 |
-
|
| 1181 |
-
<div class="idea-card" style="animation-delay:${delay}s">
|
| 1182 |
-
<div class="card-accent ${acClass}"></div>
|
| 1183 |
<div class="card-body">
|
| 1184 |
-
<
|
| 1185 |
-
|
| 1186 |
-
|
| 1187 |
-
<div class="card-divider"></div>
|
| 1188 |
-
<div class="card-meta">
|
| 1189 |
-
<div class="meta-chip"><span>🎨</span> ${idea.visuel}</div>
|
| 1190 |
-
<div class="meta-chip"><span>✅</span> ${idea.pourquoi}</div>
|
| 1191 |
</div>
|
| 1192 |
-
|
| 1193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1194 |
});
|
| 1195 |
return;
|
| 1196 |
}
|
| 1197 |
|
| 1198 |
-
// ÉVÉNEMENTS — events
|
| 1199 |
if (data.events) {
|
| 1200 |
-
data.events.forEach((
|
| 1201 |
-
const
|
| 1202 |
-
const
|
| 1203 |
-
rc.innerHTML += `
|
| 1204 |
-
|
| 1205 |
-
<div class="card-accent ${ac === 'default' ? '' : ac}"></div>
|
| 1206 |
<div class="card-body">
|
| 1207 |
-
<
|
| 1208 |
-
|
| 1209 |
-
|
| 1210 |
-
<div class="card-divider"></div>
|
| 1211 |
-
<div class="card-meta">
|
| 1212 |
-
<div class="meta-chip"><span>📲</span> ${ev.com}</div>
|
| 1213 |
-
<div class="meta-chip"><span>🎯</span> ${ev.objectif}</div>
|
| 1214 |
</div>
|
| 1215 |
-
|
| 1216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1217 |
});
|
| 1218 |
return;
|
| 1219 |
}
|
| 1220 |
|
| 1221 |
-
// POST
|
| 1222 |
if (data.post) {
|
| 1223 |
const p = data.post;
|
| 1224 |
-
const
|
| 1225 |
-
rc.innerHTML = `
|
| 1226 |
-
<div class="idea-card">
|
| 1227 |
<div class="card-accent"></div>
|
| 1228 |
<div class="card-body">
|
| 1229 |
-
<span class="card-tag blue">✍️ ${p.reseau}</span>
|
| 1230 |
-
<div class="card-
|
| 1231 |
<div class="card-divider"></div>
|
| 1232 |
-
<div class="card-
|
| 1233 |
-
|
| 1234 |
-
|
| 1235 |
-
</div>
|
| 1236 |
-
</div>
|
| 1237 |
-
</div>`;
|
| 1238 |
return;
|
| 1239 |
}
|
| 1240 |
|
| 1241 |
-
// CALENDRIER
|
| 1242 |
if (data.semaines) {
|
| 1243 |
if (data.conseil) {
|
| 1244 |
-
rc.innerHTML = `
|
| 1245 |
-
|
| 1246 |
-
<div class="card-
|
| 1247 |
-
|
| 1248 |
-
<span class="card-tag teal">🎯 Stratégie</span>
|
| 1249 |
-
<div class="card-desc">${data.conseil}</div>
|
| 1250 |
-
</div>
|
| 1251 |
-
</div>`;
|
| 1252 |
}
|
| 1253 |
data.semaines.forEach((sem, si) => {
|
| 1254 |
-
|
| 1255 |
<div style="display:flex;gap:10px;align-items:flex-start;padding:10px 0;border-bottom:1px solid #f0f2f7">
|
| 1256 |
<div style="min-width:70px;font-size:11px;font-weight:700;color:#1C2D4E;background:#f4f6fa;border-radius:6px;padding:4px 8px;text-align:center">${p.jour}</div>
|
| 1257 |
<div style="flex:1">
|
|
@@ -1260,30 +1070,27 @@ function renderCards(tab, jsonText) {
|
|
| 1260 |
<div style="font-size:11px;color:#8a9bb8;margin-top:3px">🔗 ${p.angle}</div>
|
| 1261 |
</div>
|
| 1262 |
</div>`).join('');
|
| 1263 |
-
rc.innerHTML += `
|
| 1264 |
-
<div class="idea-card" style="animation-delay:${si*0.1}s">
|
| 1265 |
<div class="card-accent orange"></div>
|
| 1266 |
<div class="card-body">
|
| 1267 |
-
<span class="card-tag orange">📅 ${sem.titre}</span>
|
| 1268 |
-
<div>${
|
| 1269 |
-
</div>
|
| 1270 |
-
</div>`;
|
| 1271 |
});
|
| 1272 |
return;
|
| 1273 |
}
|
| 1274 |
|
| 1275 |
-
//
|
| 1276 |
-
rc.innerHTML = `<div class="stream-raw">${jsonText}</div>`;
|
| 1277 |
}
|
| 1278 |
|
| 1279 |
-
// ── GENERATE ───────────────────────────────────────────────────────────────
|
| 1280 |
async function generate(tab) {
|
| 1281 |
if (!hfKey) {
|
| 1282 |
-
|
| 1283 |
return;
|
| 1284 |
}
|
| 1285 |
|
| 1286 |
-
const
|
|
|
|
| 1287 |
btn.disabled = true;
|
| 1288 |
btn.innerHTML = 'Génération en cours<div class="loading-dots"><span></span><span></span><span></span></div>';
|
| 1289 |
|
|
@@ -1292,12 +1099,13 @@ async function generate(tab) {
|
|
| 1292 |
resultArea.classList.add('show');
|
| 1293 |
resultContent.innerHTML = `<div class="loading-card">
|
| 1294 |
<div class="loading-dots" style="justify-content:center"><span style="background:#1C2D4E"></span><span style="background:#1C2D4E"></span><span style="background:#1C2D4E"></span></div>
|
| 1295 |
-
<p>L'IA génère vos idées
|
| 1296 |
</div>`;
|
| 1297 |
|
| 1298 |
const userPrompt = buildPrompt(tab);
|
| 1299 |
const messages = [
|
| 1300 |
-
{ role:
|
|
|
|
| 1301 |
];
|
| 1302 |
|
| 1303 |
let success = false;
|
|
@@ -1312,44 +1120,33 @@ async function generate(tab) {
|
|
| 1312 |
'HTTP-Referer': 'https://hugoprnl28-junior-cgy-ia.hf.space',
|
| 1313 |
'X-Title': 'Junior CGY IA'
|
| 1314 |
},
|
| 1315 |
-
body: JSON.stringify({
|
| 1316 |
-
model: modelId,
|
| 1317 |
-
messages: messages,
|
| 1318 |
-
max_tokens: 2500,
|
| 1319 |
-
stream: false,
|
| 1320 |
-
temperature: 0.8
|
| 1321 |
-
})
|
| 1322 |
});
|
| 1323 |
|
| 1324 |
if (response.status === 401 || response.status === 403) {
|
| 1325 |
-
resultContent.innerHTML = `<div class="stream-raw">❌ Clé invalide. Vérifie ta clé sur openrouter.ai/keys — elle doit commencer par sk-or-v1-</div>`;
|
| 1326 |
-
btn.disabled = false;
|
| 1327 |
-
btn.innerHTML = 'Générer à nouveau';
|
| 1328 |
-
return;
|
| 1329 |
}
|
| 1330 |
|
| 1331 |
-
if (!response.ok) { continue; }
|
| 1332 |
|
| 1333 |
const data = await response.json();
|
| 1334 |
const text = data.choices?.[0]?.message?.content || '';
|
|
|
|
| 1335 |
renderCards(tab, text);
|
| 1336 |
success = true;
|
| 1337 |
break;
|
| 1338 |
-
|
| 1339 |
-
} catch (err) {
|
| 1340 |
-
continue;
|
| 1341 |
-
}
|
| 1342 |
}
|
| 1343 |
|
| 1344 |
if (!success) {
|
| 1345 |
-
resultContent.innerHTML = `<div class="stream-raw">❌
|
| 1346 |
}
|
| 1347 |
|
| 1348 |
btn.disabled = false;
|
| 1349 |
btn.innerHTML = '🚀 Générer à nouveau';
|
| 1350 |
}
|
| 1351 |
|
| 1352 |
-
// ── COPY ───────────────────────────────────────────────────────────────────
|
| 1353 |
function copyResult() {
|
| 1354 |
const text = document.getElementById('result-content').innerText;
|
| 1355 |
navigator.clipboard.writeText(text).then(() => {
|
|
@@ -1360,4 +1157,4 @@ function copyResult() {
|
|
| 1360 |
}
|
| 1361 |
</script>
|
| 1362 |
</body>
|
| 1363 |
-
</html>
|
|
|
|
| 50 |
gap: 12px;
|
| 51 |
}
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
.logo-text {
|
| 54 |
color: var(--white);
|
| 55 |
font-size: 15px;
|
|
|
|
| 89 |
min-width: 200px;
|
| 90 |
}
|
| 91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
#key-input {
|
| 93 |
border: 2px solid #ffc107;
|
| 94 |
border-radius: 8px;
|
|
|
|
| 206 |
.card h2 span { font-size: 20px; }
|
| 207 |
|
| 208 |
/* FORM ELEMENTS */
|
| 209 |
+
.field { margin-bottom: 20px; }
|
|
|
|
|
|
|
| 210 |
|
| 211 |
label {
|
| 212 |
display: block;
|
|
|
|
| 218 |
letter-spacing: 0.5px;
|
| 219 |
}
|
| 220 |
|
| 221 |
+
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
|
| 223 |
.chip {
|
| 224 |
padding: 8px 16px;
|
|
|
|
| 255 |
resize: vertical;
|
| 256 |
}
|
| 257 |
|
| 258 |
+
textarea:focus, input[type="text"]:focus { border-color: var(--accent); }
|
|
|
|
|
|
|
| 259 |
|
| 260 |
/* TRENDS TOGGLE */
|
| 261 |
.trends-toggle {
|
|
|
|
| 330 |
transition: all 0.2s;
|
| 331 |
letter-spacing: 0.5px;
|
| 332 |
margin-top: 4px;
|
|
|
|
|
|
|
| 333 |
}
|
| 334 |
|
| 335 |
.btn-generate:hover:not(:disabled) {
|
|
|
|
| 338 |
box-shadow: 0 6px 20px rgba(28,45,78,0.3);
|
| 339 |
}
|
| 340 |
|
| 341 |
+
.btn-generate:disabled { opacity: 0.6; cursor: not-allowed; }
|
|
|
|
|
|
|
|
|
|
| 342 |
|
| 343 |
/* RESULT */
|
| 344 |
+
#result-area { margin-top: 28px; display: none; }
|
|
|
|
|
|
|
|
|
|
| 345 |
#result-area.show { display: block; }
|
| 346 |
|
| 347 |
.result-header {
|
|
|
|
| 350 |
justify-content: space-between;
|
| 351 |
margin-bottom: 18px;
|
| 352 |
}
|
| 353 |
+
|
| 354 |
.result-label {
|
| 355 |
font-size: 11px;
|
| 356 |
font-weight: 700;
|
|
|
|
| 361 |
align-items: center;
|
| 362 |
gap: 6px;
|
| 363 |
}
|
| 364 |
+
|
| 365 |
.result-label::before {
|
| 366 |
content: "";
|
| 367 |
width: 6px; height: 6px;
|
|
|
|
| 370 |
display: inline-block;
|
| 371 |
animation: pulse 1.5s infinite;
|
| 372 |
}
|
| 373 |
+
|
| 374 |
@keyframes pulse {
|
| 375 |
0%,100%{opacity:1;transform:scale(1)}
|
| 376 |
50%{opacity:0.4;transform:scale(1.4)}
|
| 377 |
}
|
| 378 |
+
|
| 379 |
.btn-copy {
|
| 380 |
background: white;
|
| 381 |
border: 2px solid var(--gray-light);
|
|
|
|
| 391 |
align-items: center;
|
| 392 |
gap: 5px;
|
| 393 |
}
|
| 394 |
+
|
| 395 |
.btn-copy:hover { background: var(--navy); color: white; border-color: var(--navy); }
|
| 396 |
|
| 397 |
+
#result-content { display: flex; flex-direction: column; gap: 16px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
|
| 399 |
/* LOADING CARD */
|
| 400 |
.loading-card {
|
|
|
|
| 414 |
/* IDEA CARDS */
|
| 415 |
.idea-card {
|
| 416 |
background: white;
|
| 417 |
+
border-radius: 20px;
|
| 418 |
+
border: 1.5px solid var(--gray-light);
|
| 419 |
overflow: hidden;
|
| 420 |
+
transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.3s ease, border-color 0.3s ease;
|
| 421 |
+
animation: fadeUp 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
|
| 422 |
+
position: relative;
|
| 423 |
}
|
| 424 |
+
|
| 425 |
+
.idea-card::before {
|
| 426 |
+
content: '';
|
| 427 |
+
position: absolute;
|
| 428 |
+
inset: 0;
|
| 429 |
+
border-radius: 20px;
|
| 430 |
+
background: linear-gradient(135deg, rgba(74,127,212,0.04) 0%, rgba(28,45,78,0.02) 100%);
|
| 431 |
+
opacity: 0;
|
| 432 |
+
transition: opacity 0.3s ease;
|
| 433 |
+
pointer-events: none;
|
| 434 |
+
z-index: 0;
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
.idea-card:hover {
|
| 438 |
+
transform: translateY(-5px) scale(1.008);
|
| 439 |
+
box-shadow: 0 20px 50px rgba(28,45,78,0.13), 0 4px 12px rgba(74,127,212,0.08);
|
| 440 |
+
border-color: rgba(74,127,212,0.35);
|
| 441 |
}
|
| 442 |
+
|
| 443 |
+
.idea-card:hover::before { opacity: 1; }
|
| 444 |
+
.idea-card:hover .card-accent { height: 6px; }
|
| 445 |
+
.idea-card:hover .card-number { transform: scale(1.15) rotate(-5deg); }
|
| 446 |
+
|
| 447 |
@keyframes fadeUp {
|
| 448 |
+
from { opacity:0; transform: translateY(24px) scale(0.97); }
|
| 449 |
+
to { opacity:1; transform: translateY(0) scale(1); }
|
| 450 |
}
|
| 451 |
+
|
| 452 |
.card-accent {
|
| 453 |
+
height: 5px;
|
| 454 |
background: linear-gradient(90deg, var(--navy), var(--accent));
|
| 455 |
+
transition: height 0.3s ease;
|
| 456 |
}
|
| 457 |
+
.card-accent.green { background: linear-gradient(90deg, #085041, #5DCAA5); }
|
| 458 |
+
.card-accent.orange { background: linear-gradient(90deg, #633806, #EF9F27); }
|
| 459 |
+
.card-accent.pink { background: linear-gradient(90deg, #72243E, #ED93B1); }
|
| 460 |
+
.card-accent.teal { background: linear-gradient(90deg, #0F6E56, #9FE1CB); }
|
| 461 |
+
.card-accent.purple { background: linear-gradient(90deg, #3C3489, #AFA9EC); }
|
| 462 |
+
.card-accent.red { background: linear-gradient(90deg, #791F1F, #F09595); }
|
| 463 |
+
|
| 464 |
.card-body {
|
| 465 |
+
padding: 22px 24px 24px;
|
| 466 |
+
position: relative;
|
| 467 |
+
z-index: 1;
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
.card-header-row {
|
| 471 |
+
display: flex;
|
| 472 |
+
align-items: flex-start;
|
| 473 |
+
justify-content: space-between;
|
| 474 |
+
margin-bottom: 14px;
|
| 475 |
+
gap: 12px;
|
| 476 |
}
|
| 477 |
+
|
| 478 |
.card-tag {
|
| 479 |
display: inline-flex;
|
| 480 |
align-items: center;
|
|
|
|
| 483 |
font-weight: 700;
|
| 484 |
text-transform: uppercase;
|
| 485 |
letter-spacing: 1px;
|
| 486 |
+
padding: 5px 12px;
|
| 487 |
border-radius: 20px;
|
| 488 |
+
flex-shrink: 0;
|
| 489 |
+
transition: transform 0.2s ease;
|
| 490 |
}
|
| 491 |
+
|
| 492 |
+
.idea-card:hover .card-tag { transform: scale(1.04); }
|
| 493 |
+
|
| 494 |
.card-tag.blue { background: #e6f1fb; color: #185FA5; }
|
| 495 |
.card-tag.green { background: #E1F5EE; color: #0F6E56; }
|
| 496 |
.card-tag.orange { background: #FAEEDA; color: #854F0B; }
|
|
|
|
| 498 |
.card-tag.teal { background: #E1F5EE; color: #085041; }
|
| 499 |
.card-tag.purple { background: #EEEDFE; color: #3C3489; }
|
| 500 |
.card-tag.red { background: #FCEBEB; color: #A32D2D; }
|
| 501 |
+
|
| 502 |
+
.card-number {
|
| 503 |
+
width: 32px;
|
| 504 |
+
height: 32px;
|
| 505 |
+
border-radius: 50%;
|
| 506 |
+
background: var(--off-white);
|
| 507 |
+
color: var(--gray);
|
| 508 |
+
font-size: 12px;
|
| 509 |
+
font-weight: 800;
|
| 510 |
+
display: flex;
|
| 511 |
+
align-items: center;
|
| 512 |
+
justify-content: center;
|
| 513 |
+
flex-shrink: 0;
|
| 514 |
+
transition: transform 0.3s cubic-bezier(0.34,1.56,0.64,1);
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
.card-title {
|
| 518 |
+
font-size: 17px;
|
| 519 |
font-weight: 800;
|
| 520 |
color: var(--navy);
|
| 521 |
+
margin-bottom: 12px;
|
| 522 |
line-height: 1.35;
|
| 523 |
+
transition: color 0.2s ease;
|
| 524 |
}
|
| 525 |
+
|
| 526 |
+
.idea-card:hover .card-title { color: #2a4a7f; }
|
| 527 |
+
|
|
|
|
|
|
|
|
|
|
| 528 |
.card-divider {
|
| 529 |
height: 1px;
|
| 530 |
background: var(--gray-light);
|
| 531 |
+
margin: 16px 0;
|
| 532 |
+
transition: background 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
}
|
| 534 |
+
|
| 535 |
+
.idea-card:hover .card-divider { background: rgba(74,127,212,0.2); }
|
| 536 |
+
|
| 537 |
+
.card-section { margin-bottom: 14px; }
|
| 538 |
+
.card-section:last-child { margin-bottom: 0; }
|
| 539 |
+
|
| 540 |
+
.card-section-label {
|
| 541 |
+
font-size: 10px;
|
| 542 |
+
font-weight: 700;
|
| 543 |
+
text-transform: uppercase;
|
| 544 |
+
letter-spacing: 1px;
|
| 545 |
+
color: var(--gray);
|
| 546 |
+
margin-bottom: 6px;
|
| 547 |
display: flex;
|
| 548 |
align-items: center;
|
| 549 |
gap: 5px;
|
| 550 |
+
}
|
| 551 |
+
|
| 552 |
+
.card-section-content {
|
| 553 |
+
font-size: 13px;
|
| 554 |
+
color: #3d4f6b;
|
| 555 |
+
line-height: 1.75;
|
| 556 |
background: var(--off-white);
|
| 557 |
+
border-radius: 10px;
|
| 558 |
+
padding: 12px 14px;
|
| 559 |
+
border-left: 3px solid var(--gray-light);
|
| 560 |
+
transition: border-color 0.3s ease, background 0.3s ease;
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
.idea-card:hover .card-section-content {
|
| 564 |
+
border-left-color: var(--accent);
|
| 565 |
+
background: #f0f5ff;
|
| 566 |
}
|
|
|
|
| 567 |
|
| 568 |
/* STREAMING RAW (fallback) */
|
| 569 |
.stream-raw {
|
| 570 |
background: white;
|
| 571 |
+
border-radius: 20px;
|
| 572 |
padding: 24px;
|
| 573 |
font-size: 13px;
|
| 574 |
line-height: 1.8;
|
|
|
|
| 577 |
white-space: pre-wrap;
|
| 578 |
}
|
| 579 |
|
| 580 |
+
/* LOADING DOTS */
|
| 581 |
.loading-dots {
|
| 582 |
display: inline-flex;
|
| 583 |
gap: 5px;
|
|
|
|
| 601 |
40% { transform: scale(1); opacity: 1; }
|
| 602 |
}
|
| 603 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 604 |
/* TUTO MODAL */
|
| 605 |
.tuto-overlay {
|
| 606 |
display: none;
|
|
|
|
| 622 |
box-shadow: 0 20px 60px rgba(28,45,78,0.25);
|
| 623 |
position: relative;
|
| 624 |
}
|
| 625 |
+
.tuto-box h3 { font-size: 18px; font-weight: 800; color: var(--navy); margin-bottom: 6px; }
|
| 626 |
+
.tuto-box .tuto-sub { font-size: 13px; color: var(--gray); margin-bottom: 24px; font-weight: 500; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
.tuto-steps { list-style: none; padding: 0; }
|
| 628 |
+
.tuto-steps li { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 16px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 629 |
.step-num {
|
| 630 |
+
width: 28px; height: 28px; border-radius: 50%; background: var(--navy);
|
| 631 |
+
color: white; font-size: 12px; font-weight: 800;
|
| 632 |
+
display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-top: 1px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 633 |
}
|
| 634 |
+
.step-text { font-size: 13px; color: var(--navy); line-height: 1.6; font-weight: 500; }
|
| 635 |
+
.step-text a { color: var(--accent); font-weight: 700; text-decoration: none; }
|
| 636 |
+
.step-text code { background: var(--gray-light); padding: 2px 7px; border-radius: 5px; font-family: monospace; font-size: 12px; color: var(--navy); }
|
| 637 |
.tuto-close {
|
| 638 |
+
position: absolute; top: 16px; right: 18px; background: var(--gray-light);
|
| 639 |
+
border: none; border-radius: 50%; width: 30px; height: 30px; font-size: 16px;
|
| 640 |
+
cursor: pointer; color: var(--navy); display: flex; align-items: center; justify-content: center; font-weight: 700;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 641 |
}
|
| 642 |
.tuto-close:hover { background: var(--navy); color: white; }
|
| 643 |
.btn-tuto-done {
|
| 644 |
+
width: 100%; background: var(--navy); color: white; border: none;
|
| 645 |
+
border-radius: 10px; padding: 13px; font-family: 'Montserrat', sans-serif;
|
| 646 |
+
font-size: 13px; font-weight: 700; cursor: pointer; margin-top: 22px; transition: background 0.2s;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 647 |
}
|
| 648 |
.btn-tuto-done:hover { background: var(--navy-light); }
|
| 649 |
+
.tuto-link { color: var(--accent) !important; font-weight: 700; cursor: pointer; text-decoration: underline; font-size: 13px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 650 |
|
| 651 |
/* RESPONSIVE */
|
| 652 |
@media (max-width: 600px) {
|
|
|
|
| 662 |
|
| 663 |
<header>
|
| 664 |
<div class="logo-area">
|
| 665 |
+
<div class="logo-text">Junior Création CGY</div>
|
| 666 |
<div class="badge">IA</div>
|
| 667 |
</div>
|
| 668 |
</header>
|
| 669 |
|
|
|
|
| 670 |
<div id="setup-bar">
|
| 671 |
<span>🔑 Entre ta clé OpenRouter pour activer l'IA — <span class="tuto-link" onclick="document.getElementById('tuto-overlay').classList.add('show')">Comment obtenir ma clé gratuite ?</span></span>
|
| 672 |
<input type="text" id="key-input" placeholder="sk-or-v1-..." />
|
|
|
|
| 674 |
<span id="key-status"></span>
|
| 675 |
</div>
|
| 676 |
|
|
|
|
| 677 |
<div class="tuto-overlay" id="tuto-overlay" onclick="closeTutoIfOutside(event)">
|
| 678 |
<div class="tuto-box" id="tuto-box">
|
| 679 |
<button class="tuto-close" onclick="document.getElementById('tuto-overlay').classList.remove('show')">✕</button>
|
| 680 |
<h3>🔑 Obtenir ta clé gratuite</h3>
|
| 681 |
<p class="tuto-sub">2 minutes chrono — pas de CB, juste un email</p>
|
| 682 |
<ol class="tuto-steps">
|
| 683 |
+
<li><div class="step-num">1</div><div class="step-text">Va sur <a href="https://openrouter.ai" target="_blank">openrouter.ai</a> et clique sur <strong>"Sign up"</strong> en haut à droite</div></li>
|
| 684 |
+
<li><div class="step-num">2</div><div class="step-text">Crée ton compte avec ton adresse email — <strong>aucune carte bancaire demandée</strong></div></li>
|
| 685 |
+
<li><div class="step-num">3</div><div class="step-text">Une fois connecté, clique sur <strong>"Get API keys"</strong> dans le menu à gauche</div></li>
|
| 686 |
+
<li><div class="step-num">4</div><div class="step-text">Clique sur <strong>"Create"</strong> en haut à droite, donne un nom (ex : <em>"Junior CGY"</em>), laisse tout par défaut et valide</div></li>
|
| 687 |
+
<li><div class="step-num">5</div><div class="step-text">Copie la clé — elle commence par <code>sk-or-v1-...</code> — elle n'apparaît qu'une seule fois !</div></li>
|
| 688 |
+
<li><div class="step-num">6</div><div class="step-text">Colle-la dans le champ en haut de cette page et clique <strong>"Enregistrer"</strong> ✅</div></li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 689 |
</ol>
|
| 690 |
<button class="btn-tuto-done" onclick="document.getElementById('tuto-overlay').classList.remove('show')">J'ai compris, je vais créer ma clé 🚀</button>
|
| 691 |
</div>
|
|
|
|
| 705 |
<!-- TAB 1 : CONTENU -->
|
| 706 |
<div id="tab-contenu" class="card active">
|
| 707 |
<h2><span>💡</span> Idées de contenu réseaux sociaux</h2>
|
|
|
|
| 708 |
<div class="field">
|
| 709 |
<label>Réseau social</label>
|
| 710 |
<div class="chips">
|
|
|
|
| 713 |
<div class="chip" data-group="reseau" onclick="toggleChip(this)">LinkedIn</div>
|
| 714 |
</div>
|
| 715 |
</div>
|
|
|
|
| 716 |
<div class="field">
|
| 717 |
<label>Format de contenu</label>
|
| 718 |
<div class="chips">
|
|
|
|
| 722 |
<div class="chip" data-group="format_contenu" onclick="toggleChip(this)">Story (visible 24h)</div>
|
| 723 |
</div>
|
| 724 |
</div>
|
|
|
|
| 725 |
<div class="field">
|
| 726 |
<label>Cible</label>
|
| 727 |
<div class="chips">
|
|
|
|
|
|
|
| 728 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Intervenants (étudiants missions)</div>
|
| 729 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Administrateurs (équipe asso)</div>
|
| 730 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Clients (PME / cabinets)</div>
|
| 731 |
<div class="chip" data-group="cible_contenu" onclick="toggleChip(this)">Tous publics</div>
|
| 732 |
</div>
|
| 733 |
</div>
|
|
|
|
| 734 |
<div class="field">
|
| 735 |
<label>Angle / message clé (optionnel)</label>
|
| 736 |
<textarea id="commentaire-contenu" rows="2" placeholder="Ex : On veut montrer qu'on accompagne vraiment les étudiants, ou insister sur le fait qu'on n'est pas remplaçable par l'IA…"></textarea>
|
| 737 |
</div>
|
|
|
|
| 738 |
<div id="trends-contenu" class="trends-toggle" onclick="toggleTrends('trends-contenu')">
|
| 739 |
<span class="toggle-icon">📈</span>
|
| 740 |
<span class="toggle-text">Intégrer les tendances du moment (avril 2026)</span>
|
| 741 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 742 |
</div>
|
| 743 |
+
<button class="btn-generate" onclick="generate('contenu')">🚀 Générer 7 idées (une par approche)</button>
|
|
|
|
|
|
|
|
|
|
| 744 |
</div>
|
| 745 |
|
| 746 |
<!-- TAB 2 : ÉVÉNEMENTS -->
|
| 747 |
<div id="tab-evenements" class="card">
|
| 748 |
<h2><span>🎉</span> Idées d'événements</h2>
|
|
|
|
| 749 |
<div class="field">
|
| 750 |
<label>Type d'événement</label>
|
| 751 |
<div class="chips">
|
|
|
|
| 756 |
<div class="chip" data-group="type_event" onclick="toggleChip(this)">Conférence / table ronde</div>
|
| 757 |
</div>
|
| 758 |
</div>
|
|
|
|
| 759 |
<div class="field">
|
| 760 |
<label>Public cible</label>
|
| 761 |
<div class="chips">
|
|
|
|
| 766 |
<div class="chip" data-group="public_event" onclick="toggleChip(this)">Mixte (étudiants + pros)</div>
|
| 767 |
</div>
|
| 768 |
</div>
|
|
|
|
| 769 |
<div id="trends-evenements" class="trends-toggle" onclick="toggleTrends('trends-evenements')">
|
| 770 |
<span class="toggle-icon">📈</span>
|
| 771 |
<span class="toggle-text">Intégrer les tendances du moment (avril 2026)</span>
|
| 772 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 773 |
</div>
|
| 774 |
+
<button class="btn-generate" onclick="generate('evenements')">🚀 Générer 4 concepts d'événements</button>
|
|
|
|
|
|
|
|
|
|
| 775 |
</div>
|
| 776 |
|
| 777 |
<!-- TAB 3 : POST -->
|
| 778 |
<div id="tab-post" class="card">
|
| 779 |
<h2><span>✍️</span> Rédiger un post</h2>
|
|
|
|
| 780 |
<div class="field">
|
| 781 |
<label>Réseau social</label>
|
| 782 |
<div class="chips">
|
|
|
|
| 785 |
<div class="chip" data-group="reseau_post" onclick="toggleChip(this)">LinkedIn</div>
|
| 786 |
</div>
|
| 787 |
</div>
|
|
|
|
| 788 |
<div class="field">
|
| 789 |
<label>Sujet ou message à communiquer</label>
|
| 790 |
<textarea id="sujet-post" rows="3" placeholder="Ex : On recrute des nouveaux membres, on a réalisé une mission pour une PME, on organise un event…"></textarea>
|
| 791 |
</div>
|
|
|
|
| 792 |
<div class="field">
|
| 793 |
<label>Ton souhaité</label>
|
| 794 |
<div class="chips">
|
|
|
|
| 798 |
<div class="chip" data-group="ton" onclick="toggleChip(this)">Proche / humain</div>
|
| 799 |
</div>
|
| 800 |
</div>
|
|
|
|
| 801 |
<div id="trends-post" class="trends-toggle" onclick="toggleTrends('trends-post')">
|
| 802 |
<span class="toggle-icon">📈</span>
|
| 803 |
<span class="toggle-text">Adapter au format viral du moment (avril 2026)</span>
|
| 804 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 805 |
</div>
|
| 806 |
+
<button class="btn-generate" onclick="generate('post')">🚀 Rédiger le post</button>
|
|
|
|
|
|
|
|
|
|
| 807 |
</div>
|
| 808 |
|
| 809 |
<!-- TAB 4 : CALENDRIER -->
|
| 810 |
<div id="tab-calendrier" class="card">
|
| 811 |
<h2><span>📅</span> Calendrier éditorial</h2>
|
|
|
|
| 812 |
<div class="field">
|
| 813 |
<label>Période</label>
|
| 814 |
<div class="chips">
|
|
|
|
| 817 |
<div class="chip" data-group="periode" onclick="toggleChip(this)">1 mois</div>
|
| 818 |
</div>
|
| 819 |
</div>
|
|
|
|
| 820 |
<div class="field">
|
| 821 |
<label>Fréquence de publication</label>
|
| 822 |
<div class="chips">
|
|
|
|
| 825 |
<div class="chip" data-group="frequence" onclick="toggleChip(this)">1 post / jour</div>
|
| 826 |
</div>
|
| 827 |
</div>
|
|
|
|
| 828 |
<div class="field">
|
| 829 |
<label>Réseaux à couvrir</label>
|
| 830 |
<div class="chips">
|
|
|
|
| 833 |
<div class="chip" data-group="reseaux_cal" onclick="toggleChip(this)">LinkedIn</div>
|
| 834 |
</div>
|
| 835 |
</div>
|
|
|
|
| 836 |
<div id="trends-calendrier" class="trends-toggle" onclick="toggleTrends('trends-calendrier')">
|
| 837 |
<span class="toggle-icon">📈</span>
|
| 838 |
<span class="toggle-text">Intégrer les tendances du moment (avril 2026)</span>
|
| 839 |
<div class="toggle-switch"><div class="toggle-knob"></div></div>
|
| 840 |
</div>
|
| 841 |
+
<button class="btn-generate" onclick="generate('calendrier')">🚀 Générer le calendrier</button>
|
|
|
|
|
|
|
|
|
|
| 842 |
</div>
|
| 843 |
|
| 844 |
<!-- RESULT AREA -->
|
|
|
|
| 852 |
</main>
|
| 853 |
|
| 854 |
<script>
|
| 855 |
+
const JUNIOR_CGY_CONTEXT = `Tu es l'IA de Junior Creation CGY, junior-entreprise de CY Cergy Paris Universite (Licence Economie-Gestion).
|
| 856 |
+
INTERVENANTS : etudiants qui realisent des missions pour des entreprises. Motivations : argent, experience CV, accompagnement. Douleur : CV vide, cercle vicieux sans experience.
|
| 857 |
+
ADMINISTRATEURS : etudiants qui gerent l'asso (poles commercial, com, RH, tresorerie). Motivations : responsabilites reelles, reseau pro, prestige, competences.
|
| 858 |
+
CLIENTS : PME Val-d'Oise, cabinets de conseil. Avantage : on travaille SUR leur entreprise avec LEURS donnees. Punchline : "L'IA vous donne une reponse. Nous, une direction."
|
| 859 |
+
OFFRES : analyse financiere (CdR TSIG bilan fonctionnel FRNG BFR TN), benchmark concurrentiel, etudes quantitatives.
|
| 860 |
+
Reponds TOUJOURS en francais.`;
|
| 861 |
+
|
| 862 |
+
localStorage.removeItem('hf_key');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 863 |
let hfKey = localStorage.getItem('or_key') || '';
|
| 864 |
if (hfKey) document.getElementById('setup-bar').classList.add('hidden');
|
| 865 |
|
|
|
|
| 881 |
setTimeout(() => document.getElementById('setup-bar').classList.add('hidden'), 1200);
|
| 882 |
}
|
| 883 |
|
|
|
|
| 884 |
function switchTab(name, btn) {
|
| 885 |
document.querySelectorAll('.card').forEach(c => c.classList.remove('active'));
|
| 886 |
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
|
|
|
| 889 |
document.getElementById('result-area').classList.remove('show');
|
| 890 |
}
|
| 891 |
|
| 892 |
+
function toggleChip(el) { el.classList.toggle('selected'); }
|
|
|
|
|
|
|
|
|
|
| 893 |
|
| 894 |
function getSelected(group) {
|
| 895 |
+
return [...document.querySelectorAll(`.chip[data-group="${group}"].selected`)].map(c => c.textContent.trim());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 896 |
}
|
| 897 |
|
| 898 |
+
function toggleTrends(id) { document.getElementById(id).classList.toggle('on'); }
|
| 899 |
+
function isTrendsOn(id) { return document.getElementById(id).classList.contains('on'); }
|
|
|
|
| 900 |
|
|
|
|
| 901 |
function buildPrompt(tab) {
|
| 902 |
+
const J = 'Reponds UNIQUEMENT avec du JSON brut valide. Ta reponse commence DIRECTEMENT par { et se termine par }. Aucun backtick, aucun markdown, aucun texte avant ou apres.';
|
|
|
|
| 903 |
|
| 904 |
if (tab === 'contenu') {
|
| 905 |
const reseau = getSelected('reseau').join(', ') || 'tous reseaux';
|
| 906 |
const format = getSelected('format_contenu').join(', ') || 'format libre';
|
| 907 |
const cibles = getSelected('cible_contenu');
|
| 908 |
+
const cible = cibles.join(', ') || 'tous publics';
|
| 909 |
const commentaire = document.getElementById('commentaire-contenu').value.trim();
|
| 910 |
const trends = isTrendsOn('trends-contenu') ? ' Integre les tendances virales et formats populaires avril 2026.' : '';
|
| 911 |
+
const hasI = cibles.length === 0 || cibles.some(c => c.toLowerCase().includes('interven'));
|
| 912 |
+
const hasA = cibles.length === 0 || cibles.some(c => c.toLowerCase().includes('admin'));
|
| 913 |
+
const hasC = cibles.length === 0 || cibles.some(c => c.toLowerCase().includes('client') || c.toLowerCase().includes('pme') || c.toLowerCase().includes('cabinet'));
|
|
|
|
| 914 |
|
| 915 |
let approches = '';
|
| 916 |
+
if (hasI) approches += `
|
| 917 |
+
- tag:"🔥 Probleme vecu" tagColor:red — Douleur CV vide, cercle vicieux. Hook choc puis solution Junior Creation CGY.
|
| 918 |
+
- tag:"🚀 Projection futur" tagColor:purple — "Tu pourras dire en entretien j ai travaille sur de vraies missions." Plus un etudiant lambda.
|
| 919 |
+
- tag:"🏆 Preuve sociale" tagColor:green — Chiffres, temoignages. "+X etudiants ont travaille avec nous." Enleve la peur.
|
| 920 |
+
- tag:"⚡ Urgence et rarete" tagColor:orange — Places limitees, recrutement ponctuel. "On ne prend que X intervenants ce semestre."
|
| 921 |
+
- tag:"🤝 Accompagnement" tagColor:teal — "Tu n es jamais livre a toi-meme." Encadrement debut a fin.
|
| 922 |
+
- tag:"🧠 Briser le cercle" tagColor:blue — Punchline : "Pas experience -> pas job -> pas argent... On casse ce cercle."
|
| 923 |
+
- tag:"💸 Retribution concrete" tagColor:pink — Parle argent franchement. Combien, quand, comment. Tres concret.`;
|
| 924 |
+
if (hasA) approches += `
|
| 925 |
+
- tag:"🏛️ Responsabilites reelles" tagColor:blue — "Tu geres un pole entier comme en startup." Vrai role, pas stagiaire invisible.
|
| 926 |
+
- tag:"🚀 Devenir quelqu un" tagColor:purple — "Dans 6 mois tu pilotes une equipe, tu as des resultats concrets en entretien."
|
| 927 |
+
- tag:"💎 Prestige et reseau" tagColor:teal — Contacts directs entreprises Val-d'Oise, reseau pro des la licence.
|
| 928 |
+
- tag:"⚡ Places rares" tagColor:orange — Peu de places par pole. Recrutement saisonnier. Cree l urgence.
|
| 929 |
+
- tag:"🎓 Mieux qu un stage" tagColor:green — Liberte, impact reel, experience quasi-entrepreneuriale.`;
|
| 930 |
+
if (hasC) approches += `
|
| 931 |
+
- tag:"🧠 Vs IA" tagColor:blue — "L IA donne du generique. Nous on travaille SUR votre entreprise avec VOS donnees."
|
| 932 |
+
- tag:"🔥 Votre vrai probleme" tagColor:red — Decisions sans donnees, risques. Puis la solution concrete.
|
| 933 |
+
- tag:"⏱️ Gain de temps" tagColor:teal — "Vous donnez le cap, on fait le reste." Livrable directement exploitable.
|
| 934 |
+
- tag:"💸 Cout de l erreur" tagColor:orange — "Ce n est pas l etude qui est chere, c est la mauvaise decision."
|
| 935 |
+
- tag:"🔍 Regard exterieur" tagColor:purple — "Vous etes trop dans votre boite pour voir ses failles. Nous on les met en lumiere."`;
|
| 936 |
+
|
| 937 |
+
return J + ` Schema exact : {"ideas":[{"tag":"emoji label","tagColor":"red","title":"Titre percutant","description":"2-3 phrases vivantes avec emojis naturels sur ${reseau} format ${format}","scenario":"TRES DETAILLE : si video donne deroulé plan par plan avec durees, ressources (materiel personnes lieu musique), texte exact a dire. Si diaporama : chaque slide. Si image : cadrage couleurs texte overlay style graphique. Aussi precis que quelqu un produit ca sans se poser de questions.","visuel":"Conseils techniques : eclairage cadrage couleurs outils (CapCut Canva etc) astuces","pourquoi":"Pourquoi cet angle psychologique fonctionne sur cette cible et quel levier emotionnel il active"}]}
|
| 938 |
+
tagColor valeurs : red purple green orange teal blue pink
|
| 939 |
+
Cible : ${cible}. ${commentaire ? 'Contexte : ' + commentaire + '.' : ''}${trends}
|
| 940 |
+
Une idea par approche ci-dessous. Tres detaille dans scenario. Tout en francais.
|
| 941 |
+
Approches :${approches}`;
|
| 942 |
+
}
|
| 943 |
+
|
| 944 |
+
if (tab === 'evenements') {
|
| 945 |
+
const type = getSelected('type_event').join(', ') || 'evenement general';
|
| 946 |
+
const pub = getSelected('public_event').join(', ') || 'tous publics';
|
| 947 |
+
const trends = isTrendsOn('trends-evenements') ? ' Tendances evenements 2026.' : '';
|
| 948 |
+
return J + ` Schema : {"events":[{"tag":"emoji type","tagColor":"blue","title":"Nom evenement memorable","concept":"Format (presentiel/ligne/hybride), lieu ideal, duree, deroulé detaille minute par minute, nb participants, logistique, ce qui rend unique","com":"Strategie com : formats sur quels reseaux, accroches suggerees, ce qu on filme le jour J, contenu post-event","objectif":"Impact concret pour JC CGY : visibilite recrutement contacts retombees"}]}
|
| 949 |
+
tagColor : red blue green orange pink teal purple
|
| 950 |
+
Type : ${type} | Public : ${pub}${trends}
|
| 951 |
+
4 concepts tres detailles. Tout en francais.`;
|
| 952 |
+
}
|
| 953 |
+
|
| 954 |
+
if (tab === 'post') {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 955 |
const reseau = getSelected('reseau_post').join(', ') || 'Instagram';
|
| 956 |
+
const sujet = document.getElementById('sujet-post').value.trim() || 'presentation de Junior Creation CGY';
|
| 957 |
+
const ton = getSelected('ton').join(', ') || 'dynamique';
|
| 958 |
+
const trends = isTrendsOn('trends-post') ? ' Hook viral avril 2026.' : '';
|
| 959 |
+
return J + ` Schema : {"post":{"reseau":"${reseau}","contenu":"Post COMPLET avec emojis et sauts de ligne \\n. Premiere ligne = hook fort. Corps developpe. CTA final.","hashtags":"8-12 hashtags pertinents melange gros et niche","conseil":"Meilleur jour et heure, format visuel recommande, idee visuel, comment maximiser la portee"}}
|
| 960 |
+
Reseau : ${reseau} | Sujet : ${sujet} | Ton : ${ton}${trends}
|
| 961 |
+
Post tres developpe. Tout en francais.`;
|
| 962 |
}
|
| 963 |
|
| 964 |
+
if (tab === 'calendrier') {
|
| 965 |
const periode = getSelected('periode').join(', ') || '2 semaines';
|
| 966 |
+
const freq = getSelected('frequence').join(', ') || '2-3 posts / semaine';
|
| 967 |
const reseaux = getSelected('reseaux_cal').join(', ') || 'Instagram, LinkedIn';
|
| 968 |
+
const trends = isTrendsOn('trends-calendrier') ? ' Tendances contenus viraux avril 2026.' : '';
|
| 969 |
+
return J + ` Schema : {"conseil":"Conseil strategique sur la logique editoriale","semaines":[{"titre":"Semaine 1 - theme","posts":[{"jour":"Lundi","reseau":"Instagram","format":"Diaporama 5 slides","sujet":"Sujet precis avec emojis","angle":"Lien positionnement JC CGY + ton + idee visuelle"}]}]}
|
| 970 |
+
Periode : ${periode} | Frequence : ${freq} | Reseaux : ${reseaux}${trends}
|
| 971 |
+
Alterne recrutement intervenants, admins, clients, preuve sociale. Chaque post tres detaille. Tout en francais.`;
|
| 972 |
}
|
|
|
|
|
|
|
| 973 |
}
|
| 974 |
|
|
|
|
| 975 |
const FREE_MODELS = [
|
| 976 |
+
'deepseek/deepseek-chat-v3-0324:free',
|
| 977 |
+
'google/gemma-3-27b-it:free',
|
| 978 |
+
'meta-llama/llama-4-scout:free',
|
| 979 |
+
'microsoft/mai-ds-r1:free',
|
| 980 |
];
|
| 981 |
|
| 982 |
+
const BARMAP = {red:'bar-red',purple:'bar-purple',green:'bar-green',orange:'bar-orange',teal:'bar-teal',blue:'bar-default',pink:'bar-pink'};
|
| 983 |
+
const TAGMAP = {red:'tag-red',purple:'tag-purple',green:'tag-green',orange:'tag-orange',teal:'tag-teal',blue:'tag-blue',pink:'tag-pink'};
|
| 984 |
+
|
| 985 |
+
function renderCards(tab, raw) {
|
| 986 |
const rc = document.getElementById('result-content');
|
| 987 |
let data;
|
| 988 |
try {
|
| 989 |
+
const i = raw.indexOf('{'), j = raw.lastIndexOf('}');
|
| 990 |
+
if (i === -1 || j === -1) throw new Error('no json');
|
| 991 |
+
data = JSON.parse(raw.slice(i, j + 1));
|
| 992 |
} catch(e) {
|
| 993 |
+
rc.innerHTML = `<div class="stream-raw">${raw.replace(/</g,'<')}</div>`;
|
| 994 |
return;
|
| 995 |
}
|
|
|
|
| 996 |
rc.innerHTML = '';
|
| 997 |
|
|
|
|
| 998 |
if (data.ideas) {
|
| 999 |
+
data.ideas.forEach((d, i) => {
|
| 1000 |
+
const bar = BARMAP[d.tagColor] || 'bar-default';
|
| 1001 |
+
const tag = TAGMAP[d.tagColor] || 'tag-blue';
|
| 1002 |
+
rc.innerHTML += `<div class="idea-card" style="animation-delay:${i*.07}s">
|
| 1003 |
+
<div class="card-accent ${bar.replace('bar-','')}"></div>
|
|
|
|
|
|
|
| 1004 |
<div class="card-body">
|
| 1005 |
+
<div class="card-header-row">
|
| 1006 |
+
<span class="card-tag ${tag.replace('tag-','')}">${d.tag}</span>
|
| 1007 |
+
<div class="card-number">${i+1}</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1008 |
</div>
|
| 1009 |
+
<div class="card-title">${d.title}</div>
|
| 1010 |
+
<div class="card-divider"></div>
|
| 1011 |
+
<div class="card-section"><div class="card-section-label">✨ L'idée</div><div class="card-section-content">${d.description}</div></div>
|
| 1012 |
+
<div class="card-section"><div class="card-section-label">🎬 Scénario & ressources</div><div class="card-section-content">${(d.scenario||'').replace(/\n/g,'<br>')}</div></div>
|
| 1013 |
+
<div class="card-section"><div class="card-section-label">🎨 Mise en scène & outils</div><div class="card-section-content">${d.visuel||''}</div></div>
|
| 1014 |
+
<div class="card-section"><div class="card-section-label">✅ Pourquoi ça marche</div><div class="card-section-content">${d.pourquoi||''}</div></div>
|
| 1015 |
+
</div></div>`;
|
| 1016 |
});
|
| 1017 |
return;
|
| 1018 |
}
|
| 1019 |
|
|
|
|
| 1020 |
if (data.events) {
|
| 1021 |
+
data.events.forEach((d, i) => {
|
| 1022 |
+
const bar = BARMAP[d.tagColor] || 'bar-default';
|
| 1023 |
+
const tag = TAGMAP[d.tagColor] || 'tag-blue';
|
| 1024 |
+
rc.innerHTML += `<div class="idea-card" style="animation-delay:${i*.07}s">
|
| 1025 |
+
<div class="card-accent ${bar.replace('bar-','')}"></div>
|
|
|
|
| 1026 |
<div class="card-body">
|
| 1027 |
+
<div class="card-header-row">
|
| 1028 |
+
<span class="card-tag ${tag.replace('tag-','')}">${d.tag}</span>
|
| 1029 |
+
<div class="card-number">${i+1}</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1030 |
</div>
|
| 1031 |
+
<div class="card-title">${d.title}</div>
|
| 1032 |
+
<div class="card-divider"></div>
|
| 1033 |
+
<div class="card-section"><div class="card-section-label">🗺️ Concept & déroulé</div><div class="card-section-content">${(d.concept||'').replace(/\n/g,'<br>')}</div></div>
|
| 1034 |
+
<div class="card-section"><div class="card-section-label">📲 Stratégie com réseaux</div><div class="card-section-content">${d.com||''}</div></div>
|
| 1035 |
+
<div class="card-section"><div class="card-section-label">🎯 Impact pour Junior CGY</div><div class="card-section-content">${d.objectif||''}</div></div>
|
| 1036 |
+
</div></div>`;
|
| 1037 |
});
|
| 1038 |
return;
|
| 1039 |
}
|
| 1040 |
|
|
|
|
| 1041 |
if (data.post) {
|
| 1042 |
const p = data.post;
|
| 1043 |
+
const body = (p.contenu||'').replace(/\\n/g,'\n').replace(/\n/g,'<br>');
|
| 1044 |
+
rc.innerHTML = `<div class="idea-card">
|
|
|
|
| 1045 |
<div class="card-accent"></div>
|
| 1046 |
<div class="card-body">
|
| 1047 |
+
<div class="card-header-row"><span class="card-tag blue">✍️ ${p.reseau}</span><div class="card-number">1</div></div>
|
| 1048 |
+
<div class="card-section"><div class="card-section-label">📝 Post prêt à publier</div><div class="card-section-content" style="font-size:13px;line-height:1.85">${body}</div></div>
|
| 1049 |
<div class="card-divider"></div>
|
| 1050 |
+
<div class="card-section"><div class="card-section-label">🏷️ Hashtags</div><div class="card-section-content">${p.hashtags||''}</div></div>
|
| 1051 |
+
<div class="card-section"><div class="card-section-label">💡 Conseil de publication</div><div class="card-section-content">${p.conseil||''}</div></div>
|
| 1052 |
+
</div></div>`;
|
|
|
|
|
|
|
|
|
|
| 1053 |
return;
|
| 1054 |
}
|
| 1055 |
|
|
|
|
| 1056 |
if (data.semaines) {
|
| 1057 |
if (data.conseil) {
|
| 1058 |
+
rc.innerHTML = `<div class="idea-card"><div class="card-accent teal"></div><div class="card-body">
|
| 1059 |
+
<div class="card-header-row"><span class="card-tag teal">🎯 Stratégie</span></div>
|
| 1060 |
+
<div class="card-section-content" style="margin-top:10px">${data.conseil}</div>
|
| 1061 |
+
</div></div>`;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1062 |
}
|
| 1063 |
data.semaines.forEach((sem, si) => {
|
| 1064 |
+
const rows = (sem.posts||[]).map(p => `
|
| 1065 |
<div style="display:flex;gap:10px;align-items:flex-start;padding:10px 0;border-bottom:1px solid #f0f2f7">
|
| 1066 |
<div style="min-width:70px;font-size:11px;font-weight:700;color:#1C2D4E;background:#f4f6fa;border-radius:6px;padding:4px 8px;text-align:center">${p.jour}</div>
|
| 1067 |
<div style="flex:1">
|
|
|
|
| 1070 |
<div style="font-size:11px;color:#8a9bb8;margin-top:3px">🔗 ${p.angle}</div>
|
| 1071 |
</div>
|
| 1072 |
</div>`).join('');
|
| 1073 |
+
rc.innerHTML += `<div class="idea-card" style="animation-delay:${(si+1)*.1}s">
|
|
|
|
| 1074 |
<div class="card-accent orange"></div>
|
| 1075 |
<div class="card-body">
|
| 1076 |
+
<div class="card-header-row"><span class="card-tag orange">📅 ${sem.titre}</span></div>
|
| 1077 |
+
<div style="margin-top:12px">${rows}</div>
|
| 1078 |
+
</div></div>`;
|
|
|
|
| 1079 |
});
|
| 1080 |
return;
|
| 1081 |
}
|
| 1082 |
|
| 1083 |
+
rc.innerHTML = `<div class="stream-raw">${raw.replace(/</g,'<')}</div>`;
|
|
|
|
| 1084 |
}
|
| 1085 |
|
|
|
|
| 1086 |
async function generate(tab) {
|
| 1087 |
if (!hfKey) {
|
| 1088 |
+
document.getElementById('tuto-overlay').classList.add('show');
|
| 1089 |
return;
|
| 1090 |
}
|
| 1091 |
|
| 1092 |
+
const tabId = tab === 'evenements' ? 'evenements' : tab === 'calendrier' ? 'calendrier' : tab;
|
| 1093 |
+
const btn = document.querySelector(`#tab-${tabId} .btn-generate`);
|
| 1094 |
btn.disabled = true;
|
| 1095 |
btn.innerHTML = 'Génération en cours<div class="loading-dots"><span></span><span></span><span></span></div>';
|
| 1096 |
|
|
|
|
| 1099 |
resultArea.classList.add('show');
|
| 1100 |
resultContent.innerHTML = `<div class="loading-card">
|
| 1101 |
<div class="loading-dots" style="justify-content:center"><span style="background:#1C2D4E"></span><span style="background:#1C2D4E"></span><span style="background:#1C2D4E"></span></div>
|
| 1102 |
+
<p>L'IA génère vos idées, ça prend 15-20 secondes…</p>
|
| 1103 |
</div>`;
|
| 1104 |
|
| 1105 |
const userPrompt = buildPrompt(tab);
|
| 1106 |
const messages = [
|
| 1107 |
+
{ role: 'system', content: 'Tu es un assistant JSON strict. Reponds UNIQUEMENT avec du JSON brut valide. Commence par { et termine par }. Jamais de backticks ni markdown.' },
|
| 1108 |
+
{ role: 'user', content: JUNIOR_CGY_CONTEXT + '\n\n' + userPrompt }
|
| 1109 |
];
|
| 1110 |
|
| 1111 |
let success = false;
|
|
|
|
| 1120 |
'HTTP-Referer': 'https://hugoprnl28-junior-cgy-ia.hf.space',
|
| 1121 |
'X-Title': 'Junior CGY IA'
|
| 1122 |
},
|
| 1123 |
+
body: JSON.stringify({ model: modelId, messages, max_tokens: 3000, temperature: 0.8 })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1124 |
});
|
| 1125 |
|
| 1126 |
if (response.status === 401 || response.status === 403) {
|
| 1127 |
+
resultContent.innerHTML = `<div class="stream-raw">❌ Clé invalide (${response.status}). Vérifie ta clé sur openrouter.ai/keys — elle doit commencer par sk-or-v1-</div>`;
|
| 1128 |
+
btn.disabled = false; btn.innerHTML = '🚀 Réessayer'; return;
|
|
|
|
|
|
|
| 1129 |
}
|
| 1130 |
|
| 1131 |
+
if (!response.ok) { console.warn(modelId, response.status, await response.text().catch(()=>'')); continue; }
|
| 1132 |
|
| 1133 |
const data = await response.json();
|
| 1134 |
const text = data.choices?.[0]?.message?.content || '';
|
| 1135 |
+
if (!text) { console.warn('Vide:', modelId); continue; }
|
| 1136 |
renderCards(tab, text);
|
| 1137 |
success = true;
|
| 1138 |
break;
|
| 1139 |
+
} catch(e) { console.warn(modelId, e.message); continue; }
|
|
|
|
|
|
|
|
|
|
| 1140 |
}
|
| 1141 |
|
| 1142 |
if (!success) {
|
| 1143 |
+
resultContent.innerHTML = `<div class="stream-raw">❌ Tous les modèles sont indisponibles en ce moment. Réessaie dans 30 secondes.<br><br>💡 Ouvre F12 → Console pour voir l'erreur exacte.</div>`;
|
| 1144 |
}
|
| 1145 |
|
| 1146 |
btn.disabled = false;
|
| 1147 |
btn.innerHTML = '🚀 Générer à nouveau';
|
| 1148 |
}
|
| 1149 |
|
|
|
|
| 1150 |
function copyResult() {
|
| 1151 |
const text = document.getElementById('result-content').innerText;
|
| 1152 |
navigator.clipboard.writeText(text).then(() => {
|
|
|
|
| 1157 |
}
|
| 1158 |
</script>
|
| 1159 |
</body>
|
| 1160 |
+
</html>
|