HugoPrnl28 commited on
Commit
08ed2c8
·
verified ·
1 Parent(s): 0f5cda1

Update index.html

Browse files
Files changed (1) hide show
  1. 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: 16px;
445
- border: 2px solid var(--gray-light);
446
  overflow: hidden;
447
- transition: transform 0.2s, box-shadow 0.2s;
448
- animation: fadeUp 0.4s ease both;
 
449
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  .idea-card:hover {
451
- transform: translateY(-2px);
452
- box-shadow: 0 8px 30px rgba(28,45,78,0.12);
 
453
  }
 
 
 
 
 
454
  @keyframes fadeUp {
455
- from { opacity:0; transform: translateY(16px); }
456
- to { opacity:1; transform: translateY(0); }
457
  }
 
458
  .card-accent {
459
- height: 4px;
460
  background: linear-gradient(90deg, var(--navy), var(--accent));
 
461
  }
462
- .card-accent.green { background: linear-gradient(90deg, #0f6e56, #1D9E75); }
463
- .card-accent.orange { background: linear-gradient(90deg, #854F0B, #EF9F27); }
464
- .card-accent.pink { background: linear-gradient(90deg, #993556, #D4537E); }
465
- .card-accent.teal { background: linear-gradient(90deg, #0F6E56, #5DCAA5); }
 
 
 
466
  .card-body {
467
- padding: 20px 22px 22px;
 
 
 
 
 
 
 
 
 
 
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: 4px 10px;
478
  border-radius: 20px;
479
- margin-bottom: 12px;
 
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: 16px;
490
  font-weight: 800;
491
  color: var(--navy);
492
- margin-bottom: 10px;
493
  line-height: 1.35;
 
494
  }
495
- .card-desc {
496
- font-size: 13px;
497
- color: #4a5568;
498
- line-height: 1.7;
499
- margin-bottom: 14px;
500
- }
501
  .card-divider {
502
  height: 1px;
503
  background: var(--gray-light);
504
- margin: 14px 0;
505
- }
506
- .card-meta {
507
- display: flex;
508
- flex-wrap: wrap;
509
- gap: 8px;
510
  }
511
- .meta-chip {
 
 
 
 
 
 
 
 
 
 
 
 
512
  display: flex;
513
  align-items: center;
514
  gap: 5px;
515
- font-size: 11px;
516
- font-weight: 600;
517
- color: var(--gray);
 
 
 
518
  background: var(--off-white);
519
- border-radius: 6px;
520
- padding: 5px 10px;
 
 
 
 
 
 
 
521
  }
522
- .meta-chip span { font-size: 13px; }
523
 
524
  /* STREAMING RAW (fallback) */
525
  .stream-raw {
526
  background: white;
527
- border-radius: 16px;
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
- font-size: 18px;
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
- height: 28px;
616
- border-radius: 50%;
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
- top: 16px;
649
- right: 18px;
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
- background: var(--navy);
667
- color: white;
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
- <div class="step-num">1</div>
723
- <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>
724
- </li>
725
- <li>
726
- <div class="step-num">2</div>
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
- // ── KNOWLEDGE BASE JUNIOR CGY ──────────────────────────────────────────────
942
- const JUNIOR_CGY_CONTEXT = `
943
- Quand on te demande des idées de contenu, événements, posts ou calendriers, tu réponds TOUJOURS en JSON valide (sans backticks, sans markdown) selon le format demandé. Pour les posts et calendriers, tu peux répondre en JSON avec un champ "html" contenant du HTML inline stylisé. Sois créatif, moderne, percutant, avec des emojis bien intégrés.
944
-
945
- Tu es l'IA officielle de Junior Création CGY, une junior-entreprise de l'université CY Cergy Paris Université (Licence Économie-Gestion).
946
-
947
- === QUI SOMMES-NOUS ===
948
- Junior Création CGY met en lien des étudiants en Licence Économie-Gestion (appelés "intervenants") avec des entreprises et cabinets du Val-d'Oise, qui ont besoin d'études et analyses à prix accessible.
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
- // ── CHIPS ──────────────────────────────────────────────────────────────────
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 isTrendsOn(id) {
1039
- return document.getElementById(id).classList.contains('on');
1040
- }
1041
 
1042
- // ── BUILD PROMPT ───────────────────────────────────────────────────────────
1043
  function buildPrompt(tab) {
1044
- let userPrompt = '';
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 = cibles.join(', ') || 'tous publics';
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 hasIntervenants = cibles.some(c => c.toLowerCase().includes('interven'));
1055
- const hasAdmins = cibles.some(c => c.toLowerCase().includes('admin'));
1056
- const hasClients = cibles.some(c => c.toLowerCase().includes('client') || c.toLowerCase().includes('pme') || c.toLowerCase().includes('cabinet'));
1057
- const hasTous = cibles.length === 0 || cibles.some(c => c.toLowerCase().includes('tous'));
1058
 
1059
  let approches = '';
1060
- if (hasIntervenants || hasTous) {
1061
- approches += `
1062
- APPROCHE 1 tag:"🔥 Probleme vecu" tagColor:red accentColor:default
1063
- Douleur: CV vide, cercle vicieux pas experience -> pas job -> pas argent. Accroche choc puis solution Junior Creation CGY.
1064
- APPROCHE 2 tag:"🚀 Projection futur" tagColor:purple accentColor:pink
1065
- Qui ils vont devenir: "Tu pourras dire en entretien j ai deja travaille sur des missions reelles." Plus un etudiant lambda.
1066
- APPROCHE 3 tag:"🏆 Preuve sociale" tagColor:green accentColor:green
1067
- Chiffres, temoignages anciens intervenants. Enleve la peur. Ex: +X etudiants ont deja realise des missions avec nous.
1068
- APPROCHE 4 tag:"⚡ Urgence et rarete" tagColor:orange accentColor:orange
1069
- Places limitees par semestre, recrutement ponctuel. "On ne prend que X intervenants ce semestre."
1070
- APPROCHE 5 tag:"🤝 Accompagnement" tagColor:teal accentColor:teal
1071
- "Tu n es jamais livre a toi-meme." Encadrement debut a fin, suivi pendant missions. Enleve la peur de ne pas etre pret.
1072
- APPROCHE 6 tag:"🧠 Briser le cercle" tagColor:blue accentColor:default
1073
- "Pas experience -> pas job -> pas argent... On casse ce cercle." Message fort, punchline memorisable.
1074
- APPROCHE 7 tag:"💸 Retribution concrete" tagColor:pink accentColor:pink
1075
- Parle argent franchement. Combien ca rapporte, comment ca fonctionne. Concret et rassurant.`;
1076
- }
1077
- if (hasAdmins || hasTous) {
1078
- approches += `
1079
- APPROCHE 1 tag:"🏛 Responsabilites reelles" tagColor:blue accentColor:default
1080
- "Tu peux gerer un pole entier, comme en startup." Vrai role, vraie responsabilite des le premier jour.
1081
- APPROCHE 2 tag:"🚀 Projection futur" tagColor:purple accentColor:pink
1082
- "Dans 6 mois tu geres un budget, tu pilotes une equipe, tu as des resultats concrets en entretien."
1083
- APPROCHE 3 tag:"🏆 Preuve sociale" tagColor:green accentColor:green
1084
- Temoignages anciens admins, exemples projets concrets realises par chaque pole.
1085
- APPROCHE 4 tag:"💎 Prestige et reseau" tagColor:teal accentColor:teal
1086
- "Tu travailles directement avec des entreprises du Val-d Oise." Reseau professionnel des la licence.
1087
- APPROCHE 5 tag:"⚡ Urgence recrutement" tagColor:orange accentColor:orange
1088
- Places rares par pole. Recrutement saisonnier. "Les postes partent vite."
1089
- APPROCHE 6 tag:"🎓 Differentiation vs stage" tagColor:pink accentColor:pink
1090
- Pourquoi nous plutot qu un stage? Liberte, impact reel, experience quasi-entrepreneuriale.
1091
- APPROCHE 7 tag:"🤝 Enrichissement personnel" tagColor:red accentColor:default
1092
- Competences specifiques par pole (commercial, com, RH, tresorerie). Montee en competences reelle.`;
1093
- }
1094
- if (hasClients || hasTous) {
1095
- approches += `
1096
- APPROCHE 1 tag:"🧠 Differentiation IA" tagColor:blue accentColor:default
1097
- "L IA vous donne une reponse generale. Nous, on travaille SUR votre entreprise, avec VOS donnees."
1098
- APPROCHE 2 tag:"🔥 Probleme vecu" tagColor:red accentColor:default
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 = document.getElementById('sujet-post').value.trim() || 'presentation de Junior CGY';
1133
- const ton = getSelected('ton').join(', ') || 'dynamique';
1134
- const trends = isTrendsOn('trends-post') ? ' Hook et structure viraux avril 2026.' : '';
1135
- userPrompt = JSON_INSTRUCTION + ` Format: {"post":{"reseau":"${reseau}","contenu":"Post complet pret a copier avec emojis et vrais sauts de ligne \\n","hashtags":"#tag1 #tag2 #tag3","conseil":"Conseil publication horaire format 💡"}}
1136
- Reseau: ${reseau} | Sujet: ${sujet} | Ton: ${ton}${trends}
1137
- Post doit stopper le scroll, etre fluide et rytme, avec CTA fort. Tout en francais.`;
1138
  }
1139
 
1140
- else if (tab === 'calendrier') {
1141
  const periode = getSelected('periode').join(', ') || '2 semaines';
1142
- const freq = getSelected('frequence').join(', ') || '2-3 posts / semaine';
1143
  const reseaux = getSelected('reseaux_cal').join(', ') || 'Instagram, LinkedIn';
1144
- const trends = isTrendsOn('trends-calendrier') ? ' Integre les tendances contenus viraux avril 2026.' : '';
1145
- userPrompt = JSON_INSTRUCTION + ` Format: {"conseil":"Conseil strategique 🎯","semaines":[{"titre":"Semaine 1 - theme","posts":[{"jour":"Lundi","reseau":"Instagram","format":"Diaporama","sujet":"Sujet avec emoji","angle":"Lien positionnement JC CGY"}]}]}
1146
- Periode: ${periode} | Frequence: ${freq} | Reseaux: ${reseaux}${trends}
1147
- Logique editoriale: alterne intervenants, admins, clients, preuve sociale. Progression coherente. Tout en francais.`;
1148
  }
1149
-
1150
- return userPrompt;
1151
  }
1152
 
1153
- // ── MODELS LIST (OpenRouter - gratuits sans CB) ───────────────────────────
1154
  const FREE_MODELS = [
1155
- 'meta-llama/llama-3.2-3b-instruct:free',
1156
- 'google/gemma-3-4b-it:free',
1157
- 'mistralai/mistral-7b-instruct:free',
 
1158
  ];
1159
 
1160
- // ── RENDER CARDS ───────────────────────────────────────────────────────────
1161
- function renderCards(tab, jsonText) {
 
 
1162
  const rc = document.getElementById('result-content');
1163
  let data;
1164
  try {
1165
- const clean = jsonText.replace(/```json|```/g, '').trim();
1166
- data = JSON.parse(clean);
 
1167
  } catch(e) {
1168
- rc.innerHTML = `<div class="stream-raw">${jsonText}</div>`;
1169
  return;
1170
  }
1171
-
1172
  rc.innerHTML = '';
1173
 
1174
- // CONTENU — ideas
1175
  if (data.ideas) {
1176
- data.ideas.forEach((idea, i) => {
1177
- const delay = i * 0.08;
1178
- const ac = idea.accentColor || 'default';
1179
- const acClass = ac === 'default' ? '' : ac;
1180
- rc.innerHTML += `
1181
- <div class="idea-card" style="animation-delay:${delay}s">
1182
- <div class="card-accent ${acClass}"></div>
1183
  <div class="card-body">
1184
- <span class="card-tag ${idea.tagColor || 'blue'}">${idea.tag}</span>
1185
- <div class="card-title">${idea.title}</div>
1186
- <div class="card-desc">${idea.description}</div>
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
- </div>
1193
- </div>`;
 
 
 
 
 
1194
  });
1195
  return;
1196
  }
1197
 
1198
- // ÉVÉNEMENTS — events
1199
  if (data.events) {
1200
- data.events.forEach((ev, i) => {
1201
- const delay = i * 0.08;
1202
- const ac = ev.accentColor || 'default';
1203
- rc.innerHTML += `
1204
- <div class="idea-card" style="animation-delay:${delay}s">
1205
- <div class="card-accent ${ac === 'default' ? '' : ac}"></div>
1206
  <div class="card-body">
1207
- <span class="card-tag ${ev.tagColor || 'blue'}">${ev.tag}</span>
1208
- <div class="card-title">${ev.title}</div>
1209
- <div class="card-desc">${ev.concept}</div>
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
- </div>
1216
- </div>`;
 
 
 
 
1217
  });
1218
  return;
1219
  }
1220
 
1221
- // POST
1222
  if (data.post) {
1223
  const p = data.post;
1224
- const lines = (p.contenu || '').replace(/\n/g, '<br>');
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-desc" style="font-size:14px;line-height:1.8;white-space:pre-wrap">${lines}</div>
1231
  <div class="card-divider"></div>
1232
- <div class="card-meta">
1233
- <div class="meta-chip"><span>🏷️</span> ${p.hashtags}</div>
1234
- <div class="meta-chip"><span>💡</span> ${p.conseil}</div>
1235
- </div>
1236
- </div>
1237
- </div>`;
1238
  return;
1239
  }
1240
 
1241
- // CALENDRIER
1242
  if (data.semaines) {
1243
  if (data.conseil) {
1244
- rc.innerHTML = `
1245
- <div class="idea-card">
1246
- <div class="card-accent teal"></div>
1247
- <div class="card-body">
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
- let postsHtml = sem.posts.map(p => `
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>${postsHtml}</div>
1269
- </div>
1270
- </div>`;
1271
  });
1272
  return;
1273
  }
1274
 
1275
- // Fallback
1276
- rc.innerHTML = `<div class="stream-raw">${jsonText}</div>`;
1277
  }
1278
 
1279
- // ── GENERATE ───────────────────────────────────────────────────────────────
1280
  async function generate(tab) {
1281
  if (!hfKey) {
1282
- alert('Entre ta clé OpenRouter dans la barre en haut.\n\nCrée un compte gratuit sur openrouter.ai/keys (pas de CB requise).');
1283
  return;
1284
  }
1285
 
1286
- const btn = document.querySelector(`#tab-${tab} .btn-generate`);
 
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...</p>
1296
  </div>`;
1297
 
1298
  const userPrompt = buildPrompt(tab);
1299
  const messages = [
1300
- { role: "user", content: JUNIOR_CGY_CONTEXT + '\n\n---\n\n' + userPrompt }
 
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">❌ Erreur de connexion. Vérifie ta clé OpenRouter sur openrouter.ai/keys et réessaie dans 30 secondes.</div>`;
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,'&lt;')}</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,'&lt;')}</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>