SPB Git forge

spb/draft2027

Public
1commits 1branches 0releases
92.0 KBsize
maindefault branch
19 days agolast push
HTML 99% JavaScript 1%
143.6 KB · 1,423 lines html
Raw Blame History
1<!DOCTYPE html>2<!--3  DraftVision 2027 — Plateforme de prévision du repêchage LNH 20274  Auteur : Simon-Pierre Boucher — contact@spboucher.ai5  Données : pipeline de recherche web du 2026-08-08 (voir RECHERCHE.md)6-->7<html lang="fr">8<head>9<meta charset="UTF-8">10<meta name="viewport" content="width=device-width, initial-scale=1.0">11<title>DraftVision 2027 — Prévision du repêchage LNH 2027</title>12<link rel="preconnect" href="https://fonts.googleapis.com">13<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">14<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>15<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>16<script src="https://unpkg.com/@babel/standalone@7.26.4/babel.min.js"></script>17<style>18  :root{19    --fond:#0A0E1A; --panneau:#111827; --panneau2:#0D1322; --bordure:#1F2A3F;20    --glace:#4FC3F7; --vert:#22C55E; --rouge:#EF4444; --ambre:#F59E0B;21    --texte:#E5EAF2; --texte2:#93A1B8; --texte3:#5C6B84;22  }23  *{box-sizing:border-box; margin:0; padding:0;}24  html{scroll-behavior:smooth;}25  body{background:var(--fond); color:var(--texte); font-family:'Inter',system-ui,sans-serif; font-size:14px; line-height:1.5;}26  h1,h2,h3,.titre{font-family:'Barlow Condensed',sans-serif; letter-spacing:.02em;}27  .num{font-variant-numeric:tabular-nums;}28  button{font-family:inherit; cursor:pointer;}29  input,select{font-family:inherit;}30  ::-webkit-scrollbar{width:10px;height:10px;}31  ::-webkit-scrollbar-track{background:var(--fond);}32  ::-webkit-scrollbar-thumb{background:var(--bordure); border-radius:5px;}33  @keyframes apparait{from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:none;}}34  @keyframes pulse-glace{0%,100%{box-shadow:0 0 0 0 rgba(79,195,247,.35);} 50%{box-shadow:0 0 0 8px rgba(79,195,247,0);}}35  .apparait{animation:apparait .25s ease both;}36  a{color:var(--glace);}37  button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible{outline:2px solid var(--glace); outline-offset:2px;}38</style>39</head>40<body>41<div id="racine"></div>42<script type="text/babel" data-presets="react">43const {useState, useMemo, useRef, useEffect, useCallback} = React;4445/* ============================================================46   DONNÉES — issues du pipeline de recherche web du 2026-08-0847   (Phases A→F, voir RECHERCHE.md). Aucune donnée inventée :48   ce qui est introuvable est null / « n.d. ».49   ============================================================ */5051const META = {52  dateGeneration: "2026-08-08",53  dateDonnees: "2026-08-08",54  phasesCompletees: ["A","B","C","D","E","F"],55  avertissements: [56    "La saison LNH 2026-27 n'a pas commencé : l'ordre de sélection est SIMULÉ à partir du classement final 2025-26 (le vrai ordre 2027 dépendra de la saison 2026-27 et de la loterie de mai 2027).",57    "La loterie 2027 n'a pas eu lieu — probabilités selon la table officielle 2026 (Daily Faceoff, avril 2026) ; cotes des rangs 12-16 : n.d.",58    "Tous les classements d'espoirs sont « way-too-early » (mars-juillet 2026) et changeront fortement d'ici juin 2027.",59    "Date, lieu et format du repêchage 2027 : non annoncés en date du 2026-08-08 (format décentralisé probable — reconduit en 2025 et 2026, soutien des clubs confirmé par Bill Daly). Nouveauté CBA 2026-2030 qui débute avec le repêchage 2027 : rétention des droits standardisée (18 ans → 4 ans de droits ; 19 ans+ → 3 ans ; exception NCAA maintenue). L'âge d'admissibilité reste 18 ans. Détails : ADMIN-REPECHAGE-2027.md.",60    "Portée réduite : 1re ronde seulement (32 choix). Pas assez de sources fiables pour projeter une 2e ronde, et aucun gardien n'est classé par les sources consultées.",61    "Statistiques affichées : saison 2025-26 (dernière saison complète). Le +/- et les statistiques de gardiens sont rarement publiés → « n.d. ».",62    "Coupe Hlinka-Gretzky 2026 (Edmonton, 3-8 août — Canada 8-1 USA en finale) : intégrée au calcul via des ajustements bornés (±3 rangs max) appliqués au consensus pondéré, appuyés sur le tableau statistique OFFICIEL du tournoi (Elite Prospects, saison 2026-27, consulté le 8 août — les matchs de médailles du jour n'y sont que partiellement reflétés, complétés par les comptes rendus TSN/PC, Sportsnet, CHL.ca, Daily Faceoff). Bonus ET malus documentés : ex. Joseph +1,0 rang (production discrète, 43e pointeur), England −1,5 (2 buts en finale). Le revers collectif du groupe NTDP américain (8-1, tirs 45-17) est signalé sans pénalité chiffrée supplémentaire."63  ]64};6566// Pondération renormalisée : les 7 sources prescrites sauf The Athletic n'ont67// rien publié pour 2027 (Central Scouting, McKenzie, EP, FCHockey, Dobber,68// McKeen's → retirées, poids redistribués sur les classements réels trouvés).69const SOURCES = [70  {cle:"wheeler",  nom:"The Athletic — Scott Wheeler",       date:"2026-03-31", poids:30},71  {cle:"dfo",      nom:"Daily Faceoff — Steven Ellis",       date:"2026-07-02", poids:25},72  {cle:"tank",     nom:"Tankathon (Big Board 2027)",         date:"2026-07 (approx.)", poids:20},73  {cle:"thn",      nom:"The Hockey News (top 10)",           date:"2026-06-28", poids:10},74  {cle:"br",       nom:"Bleacher Report (top 10)",           date:"2026-07-10", poids:10},75  {cle:"button",   nom:"TSN — Craig Button (aperçu pré-saison)", date:"2025-11-07", poids:5},76];77const SOURCES_NON_PUBLIEES = [78  "Bureau central de recrutement LNH (liste préliminaire attendue à l'automne 2026)",79  "Bob McKenzie/TSN (ne publie plus depuis 2025)",80  "Elite Prospects (liste de surveillance non classée seulement)",81  "FCHockey", "Dobber Prospects", "McKeen's Hockey", "The Athletic — Corey Pronman"82];8384// Couleurs = palettes officielles approximatives (aucun logo utilisé).85// banque = synthèse du classement des banques d'espoirs de Scott Wheeler86// (The Athletic, mars-avril 2026), corrigée qualitativement post-repêchage 2026.87const EQUIPES = {88  ANA:{nom:"Ducks d'Anaheim", c1:"#F47A38", c2:"#B9975B", pool:14, banque:{forces:"McQueen (en santé) parmi les meilleurs espoirs attaquants; bons espoirs en défense (Luneau, Solberg).", lacunes:"Peu d'élite derrière McQueen; profondeur de gardiens moyenne."}},89  BOS:{nom:"Bruins de Boston", c1:"#FFB81C", c2:"#000000", pool:19, banque:{forces:"Hagens en tête; bond de 11 rangs grâce au repêchage 2025.", lacunes:"Défense et gardiens encore minces."}},90  BUF:{nom:"Sabres de Buffalo", c1:"#003087", c2:"#FFB81C", pool:13, banque:{forces:"Positions premium garnies (Mrtka, Helenius, Östlund) + Rudolph (4e, 2026).", lacunes:"Aucun véritable espoir ailier."}},91  CGY:{nom:"Flames de Calgary", c1:"#D2001C", c2:"#FAAF19", pool:3, banque:{forces:"Parekh (D élite), Reschny, Gridin + Carels (6e, 2026).", lacunes:"Pas d'espoir attaquant vedette de calibre no 1."}},92  CAR:{nom:"Hurricanes de la Caroline", c1:"#CE1126", c2:"#76232F", pool:21, banque:{forces:"Volume (18 espoirs classés), succès dans les rondes intermédiaires et chez les Russes.", lacunes:"Pas de vedette; un seul choix de 1re ronde dans le groupe."}},93  CHI:{nom:"Blackhawks de Chicago", c1:"#CF0A2C", c2:"#FF671B", pool:1, banque:{forces:"Meilleure banque de la LNH (Wheeler) : espoirs de premier plan partout, 8 choix de 1re ronde dans le pool.", lacunes:"Il manque surtout un espoir « élite » consensuel."}},94  COL:{nom:"Avalanche du Colorado", c1:"#6F263D", c2:"#236192", pool:28, banque:{forces:"Le top-5 du pool (Brindley, Nabokov, Gulyayev, Behrens) est solide.", lacunes:"Peu de choix récents; profondeur limitée."}},95  CBJ:{nom:"Blue Jackets de Columbus", c1:"#002654", c2:"#CE1126", pool:17, banque:{forces:"Smith (D) et Andreyanov (G) en tête; bonne banque de gardiens.", lacunes:"Chute de 11 rangs (blessure de Lindstrom, graduations, échanges)."}},96  DAL:{nom:"Stars de Dallas", c1:"#006847", c2:"#8F8F8C", pool:31, banque:{forces:"Deux ailiers talentueux mais imparfaits (Hemming, Schmidt).", lacunes:"Seulement 8 espoirs classés; besoin criant partout."}},97  DET:{nom:"Red Wings de Détroit", c1:"#CE1126", c2:"#FFFFFF", pool:4, banque:{forces:"Deux des meilleurs gardiens espoirs hors LNH (Cossa, Augustine); Sandin-Pellikka.", lacunes:"Manque un attaquant « game-breaker »."}},98  EDM:{nom:"Oilers d'Edmonton", c1:"#041E42", c2:"#FF4C00", pool:30, banque:{forces:"Ike Howard en tête; Akey en défense.", lacunes:"Parmi les banques les plus pauvres depuis des années."}},99  FLA:{nom:"Panthers de la Floride", c1:"#041E42", c2:"#C8102E", pool:32, banque:{forces:"Quelques espoirs à surveiller (Devine, Alscher, Gerasimyuk).", lacunes:"Armoires vides : 4 repêchages consécutifs sans choix de 1re ronde."}},100  LAK:{nom:"Kings de Los Angeles", c1:"#111111", c2:"#A2AAAD", pool:27, banque:{forces:"3 solides espoirs D et 2 bons gardiens (George, Slukynsky).", lacunes:"Trou béant au centre; pas d'espoir vedette."}},101  MIN:{nom:"Wild du Minnesota", c1:"#154734", c2:"#A6192E", pool:23, banque:{forces:"La classe 2025 entre dans les classements; progrès de Stramel.", lacunes:"Chute de 21 rangs : pool vidé par les graduations et les échanges."}},102  MTL:{nom:"Canadiens de Montréal", c1:"#AF1E2D", c2:"#192168", pool:9, banque:{forces:"Espoir de calibre A- à chaque position (Fowler, Hage, Zharovsky, Reinbacher).", lacunes:"Manque d'espoir élite pur depuis la graduation de Demidov."}},103  NSH:{nom:"Predators de Nashville", c1:"#FFB81C", c2:"#041E42", pool:5, banque:{forces:"Peut-être le pool le plus profond (16 espoirs des 2 premières rondes).", lacunes:"Il manque un espoir A-plus (vedette)."}},104  NJD:{nom:"Devils du New Jersey", c1:"#CE1126", c2:"#000000", pool:22, banque:{forces:"Gardien étoile (Yegorov), Silayev et de vrais espoirs D.", lacunes:"Aucun top espoir à l'attaque."}},105  NYI:{nom:"Islanders de New York", c1:"#00539B", c2:"#F47D30", pool:12, banque:{forces:"Pool transformé : Ritchie + classe 2025 (Aitcheson, Eklund, Eiserman).", lacunes:"Gardiens minces derrière Gamzin après la graduation de Schaefer."}},106  NYR:{nom:"Rangers de New York", c1:"#0038A8", c2:"#CE1126", pool:18, banque:{forces:"Perreault (espoir premium) + Šmits (5e au total, 2026).", lacunes:"Manque de centres offensifs de haut niveau."}},107  OTT:{nom:"Sénateurs d'Ottawa", c1:"#DA1A32", c2:"#B79257", pool:26, banque:{forces:"Deux vrais espoirs D droitiers (Yakemchuk, Hensler); gardiens en quantité.", lacunes:"Peu de potentiel offensif de premier plan dans le reste du pool."}},108  PHI:{nom:"Flyers de Philadelphie", c1:"#F74902", c2:"#000000", pool:8, banque:{forces:"Vedette à l'aile (Martone), bons espoirs C et D, bonne profondeur.", lacunes:"Pas d'espoir vedette au centre ni à la ligne bleue."}},109  PIT:{nom:"Penguins de Pittsburgh", c1:"#FCB514", c2:"#000000", pool:16, banque:{forces:"Groupe transformé en 2 saisons (Horcoff, Brunicke, McGroarty, Zonnon).", lacunes:"Manque un espoir premium capable de changer le plafond de l'organisation."}},110  SJS:{nom:"Sharks de San Jose", c1:"#006D75", c2:"#EA7200", pool:2, banque:{forces:"Top espoirs partout : Misa, Dickinson, Ravensbergen + Stenberg (2e, 2026); défenseurs mobiles en quantité.", lacunes:"Profondeur au centre derrière Misa moins garnie; ailiers marqueurs recherchés."}},111  SEA:{nom:"Kraken de Seattle", c1:"#001628", c2:"#99D9D9", pool:7, banque:{forces:"Pool le plus nombreux; deux top espoirs au centre (Catton, O'Brien) + Reid (7e, 2026) en défense.", lacunes:"Longtemps sans top espoir en défense (en partie comblé par Reid)."}},112  STL:{nom:"Blues de St. Louis", c1:"#002F87", c2:"#FCB514", pool:10, banque:{forces:"Espoirs de haut niveau à chaque position (Carbonneau, Dvorsky, Jiricek) + Dagenais (16e, 2026).", lacunes:"Pas d'espoir véritablement élite."}},113  TBL:{nom:"Lightning de Tampa Bay", c1:"#002868", c2:"#FFFFFF", pool:24, banque:{forces:"Geekie et O'Reilly (acquis) + quelques espoirs pertinents.", lacunes:"Pool faible; longue disette de réussite au repêchage."}},114  TOR:{nom:"Maple Leafs de Toronto", c1:"#00205B", c2:"#FFFFFF", pool:29, banque:{forces:"Gavin McKenna (1er au total, 2026) + Cowan — sommet transformé.", lacunes:"Derrière le duo de tête, projections de profondeur seulement (Wheeler, mars 2026)."}},115  UTA:{nom:"Mammoth de l'Utah", c1:"#71AFE5", c2:"#090909", pool:6, banque:{forces:"Qualité : top espoir à chaque position (Iginla, Desnoyers, Simashev, Hrabal) + Belchetz (17e, 2026).", lacunes:"Quantité/profondeur moindre que les autres pools d'élite."}},116  VAN:{nom:"Canucks de Vancouver", c1:"#00205B", c2:"#00843D", pool:15, banque:{forces:"Un espoir de qualité à chaque position (Lekkerimäki, Willander, Cootes) + Malhotra (3e, 2026).", lacunes:"Quantité insuffisante; besoin d'un joueur d'impact au sommet."}},117  VGK:{nom:"Golden Knights de Vegas", c1:"#B4975A", c2:"#333F42", pool:25, banque:{forces:"Connelly (seul 1er choix du pool), gardiens solides.", lacunes:"Défense complètement à sec : aucun défenseur parmi les espoirs classés."}},118  WSH:{nom:"Capitals de Washington", c1:"#C8102E", c2:"#041E42", pool:11, banque:{forces:"5 vrais espoirs ailiers (Cristall, Lakovic, Parascak...) et Hutson en défense.", lacunes:"Aucun espoir légitime au centre; gardiens minces (Suvanto ajouté en 2026)."}},119  WPG:{nom:"Jets de Winnipeg", c1:"#041E42", c2:"#AC162C", pool:20, banque:{forces:"Une demi-douzaine d'espoirs de nom (Yager, Boumedienne...) + Björck (8e, 2026).", lacunes:"Plusieurs 1ers choix peinent à franchir la dernière marche vers la LNH."}},120};121const BANQUE_SOURCE = "Scott Wheeler, The Athletic (classement des banques d'espoirs, mars-avril 2026 — antérieur au repêchage 2026)";122123/* Ordre de base SIMULÉ (classement final 2025-26) :124   1-16 = équipes hors séries (ordre inverse, bris d'égalité officiels du125   repêchage 2026), 17-32 = équipes en séries selon l'ordre de la 1re ronde126   2026 (ESPN/NHL.com, juin 2026). */127const ORDRE_HORS_SERIES = ["VAN","CHI","NYR","CGY","TOR","SEA","WPG","FLA","SJS","NSH","STL","NJD","NYI","CBJ","DET","WSH"];128const ORDRE_SERIES = ["LAK","ANA","UTA","EDM","PHI","PIT","BOS","MIN","TBL","DAL","BUF","MTL","COL","VGK","CAR","OTT"];129130/* Table NOMINALE officielle de la loterie 2026 (NHL.com / Sportsnet,131   combinaisons sur 1000 : 185/135/…/5). Règle des 10 rangs : au 1er tirage,132   seuls les rangs 1-11 sont admissibles et les 7,0 points des rangs 12-16133   sont transférés à la pire équipe (effectif rang 1 : 25,5 % — Sportsnet) ;134   au 2e tirage, les rangs 1-12 sont admissibles. */135const COTES_NOMINALES = [18.5, 13.5, 11.5, 9.5, 8.5, 7.5, 6.5, 6.0, 5.0, 3.5, 3.0, 2.5, 2.0, 1.5, 0.5, 0.5];136const LOTERIE_SOURCE = "Table nominale officielle de la loterie 2026 — NHL.com « 2026 Draft Lottery Guide » / Sportsnet, avril-mai 2026";137138/* Choix de 1re ronde 2027 échangés (Phase D — Wikipedia « 2027 NHL entry139   draft », PuckPedia, NHL.com, ESPN, consultés le 2026-08-08). Les conditions140   sont réévaluées dynamiquement selon le rang (loterie comprise). */141const PICKS_ECHANGES = {142  FLA:{resoudre:(r)=>({detenteur:"CHI"}), condition:"Sans protection (condition convertie le 2026-04-16).", transaction:"Éch. Seth Jones ↔ Spencer Knight + ce choix (2025-03-01).", source:"Wikipedia / PuckPedia"},143  TOR:{resoudre:(r)=>({detenteur:"PHI", note:"Protection LEVÉE : en gagnant la loterie 2026 (McKenna), TOR a résolu la chaîne de conditions — le 1er tour 2027 va à PHI sans aucune protection (BOS reçoit le 1er tour 2028 non protégé). Rapporté par PuckPedia/Heavy, confirmation formelle de la LNH en attente."}),144       condition:"SANS PROTECTION depuis la loterie 2026 : la victoire de TOR (McKenna 1er au total) a basculé la condition — même un choix top-10 en 2027 part à PHI.", transaction:"Éch. Scott Laughton (PHI, 2025-03-06) / Brandon Carlo (BOS, 2025-03-07) ; bascule résolue en mai 2026.", source:"PuckPedia / Heavy Sports (mai 2026) / Wikipedia"},145  TBL:{resoudre:(r)=> r<=10 ? {detenteur:"TBL", note:"Protection top-10 déclenchée : le choix reste à TBL (SEA recevra le 1er tour 2028 + un 3e tour 2028)."} : {detenteur:"SEA"},146       condition:"Protégé top-10 : si top-10, devient le 1er tour 2028 de TBL (+ 3e tour 2028 pour SEA).", transaction:"Éch. Yanni Gourde / Oliver Bjorkstrand (2025-03-05).", source:"NHL.com (Kraken) / ESPN / Wikipedia"},147  COL:{resoudre:(r)=> r<=10 ? {detenteur:"COL", note:"Protection top-10 déclenchée : TOR recevra plutôt le 1er tour 2028 de COL non protégé."} : {detenteur:"TOR"},148       condition:"Protégé top-10 : si top-10, TOR reçoit le 1er tour 2028 de COL non protégé.", transaction:"Éch. Nicolas Roy (2026-03-05).", source:"ESPN / Wikipedia"},149  EDM:{resoudre:(r)=> r<=12 ? {detenteur:"EDM", note:"Top-12 : EDM peut choisir de transférer plutôt son 1er tour 2028 à CHI — issue incertaine, choix affiché à EDM."} : {detenteur:"CHI"},150       condition:"Si top-12, EDM peut différer et transmettre son 1er tour 2028 à CHI.", transaction:"Éch. Andrew Mangiapane ↔ Dickinson + Dach (2026-03-04).", source:"PuckPedia / Wikipedia"},151  VGK:{resoudre:(r)=> r<=10 ? {detenteur:"VGK", note:"Protection top-10 déclenchée : NJD recevra plutôt un 1er tour 2028."} : {detenteur:"NJD"},152       condition:"Protégé top-10 (via CGY) : si top-10, NJD reçoit un 1er tour 2028.", transaction:"VGK→CGY (2026-01-18), puis CGY→NJD dans l'éch. Simon Nemec (2026-06-23).", source:"Wikipedia / PuckPedia / Pro Hockey Rumors"},153};154155const DRAPEAUX = {CAN:"🇨🇦", USA:"🇺🇸", RUS:"🇷🇺", SWE:"🇸🇪", FIN:"🇫🇮", CZE:"🇨🇿", SVK:"🇸🇰", SUI:"🇨🇭", GER:"🇩🇪", LVA:"🇱🇻", "n.d.":"🏳️"};156const COULEURS_LIGUE = {WHL:"#F59E0B", OHL:"#EF4444", "LHJMQ":"#4FC3F7", NCAA:"#22C55E", "NTDP/USHL":"#818CF8", USHL:"#818CF8", "MHL (Russie)":"#F87171", "J20 Nationell":"#FBBF24", "U18 Nationell":"#FBBF24", "U20 SM-sarja":"#60A5FA", "Extraliga (Tchéquie)":"#F472B6", "Tchéquie U20":"#F472B6", "NL (Suisse)":"#A78BFA", "DEL (Allemagne)":"#34D399", "USHS-Prep":"#9CA3AF", NAHL:"#9CA3AF"};157158/* ============================================================159   ESPOIRS — stats 2025-26 (dernière saison complète), rangs par160   source datés, analyses/forces/faiblesses = synthèses originales.161   radar = évaluation ÉDITORIALE 20-80 synthétisée des rapports162   publics (pas des notes officielles). null = introuvable (n.d.).163   ============================================================ */164const ESPOIRS = [165 {id:"dupont", nom:"Landon DuPont", position:"D", tir:"D", taille:"6'00\"", tailleCm:183, poids:190, naissance:"2009-05-28", nationalite:"CAN",166  equipeActuelle:"Université du Michigan (ex-Everett)", ligue:"NCAA",167  stats:{mj:63,b:18,p:55,pts:73,plusMoins:59,moy:null,arr:null}, statsLigue:"WHL",168  rangsParSource:{wheeler:1,dfo:1,tank:1,thn:1,br:1,button:3}, tendance:"up", risque:"faible", sleeper:false,169  forces:["Transport de rondelle et patinage de calibre exceptionnel pour son âge","Vision et relances de premier plan (55 passes en 63 matchs)","Production historique : +59, champion WHL et Coupe Memorial 2026","Leadership précoce — capitaine du Canada au Hlinka-Gretzky 2026 (or)"],170  faiblesses:["Gabarit moyen (6'0\") pour un défenseur de premier duo","Défense en zone propre encore à raffiner contre des adultes (NCAA en 2026-27)"],171  comparableLNH:"Profil de défenseur droitier offensif moderne, à la Evan Bouchard (style, pas une promesse)",172  projectionPlafond:"Défenseur no 1", radar:{patinage:70,sensJeu:70,tir:55,competitivite:60,jeuDefensif:55},173  analyse:"Premier défenseur de l'histoire de la WHL admis sous le statut exceptionnel (2e joueur après Bedard), fils de Micki DuPont. No 1 quasi unanime (6 sources sur 7 ; seul l'aperçu TSN de nov. 2025 le plaçait 3e). Il rejoint l'Université du Michigan en 2026-27 — sa saison NCAA à 17 ans sera le vrai test. Poids rapporté entre 177 et 190 lb selon les sources."},174 {id:"joseph", nom:"Alexis Joseph", position:"C", tir:"G", taille:"6'04\"", tailleCm:196, poids:207, naissance:"2009-06-16", nationalite:"CAN",175  equipeActuelle:"Sea Dogs de Saint John", ligue:"LHJMQ",176  stats:{mj:54,b:24,p:36,pts:60,plusMoins:null,moy:null,arr:null}, statsLigue:"LHJMQ",177  rangsParSource:{wheeler:2,dfo:3,tank:3,thn:2,br:2,button:1}, tendance:"stable", risque:"faible", sleeper:false,178  forces:["Centre de 6'4\"-6'5\" avec des mains de marqueur","Point par match comme recrue de 16 ans dans la LHJMQ","Jeu complet : 50,1 % aux mises en jeu dès sa 1re saison","Assistant-capitaine du Canada au Hlinka-Gretzky 2026 (or)"],179  faiblesses:["Coup de patin à alourdir pour suivre le rythme LNH","Doit dicter le jeu plus constamment soir après soir"],180  comparableLNH:"Grand centre à deux vitesses, profil à la Tage Thompson (style, pas une promesse)",181  projectionPlafond:"Centre de premier trio", radar:{patinage:55,sensJeu:65,tir:60,competitivite:65,jeuDefensif:55},182  analyse:"Premier choix du repêchage LHJMQ 2025. Wheeler le décrit comme « le meilleur espoir de la LHJMQ depuis Alexis Lafrenière » et Craig Button le plaçait 1er en novembre 2025. Bémol frais : un Hlinka-Gretzky discret (1B-2P en 4 matchs, 43e pointeur du tournoi malgré le rôle d'assistant-capitaine du club champion) qui lui coûte un rang dans le consensus ajusté — sa saison LHJMQ 2026-27 dira si c'était un accident de parcours."},183 {id:"privalov", nom:"Nazar Privalov", position:"AG", tir:"G", taille:"6'04\"", tailleCm:193, poids:214, naissance:"2009-05-25", nationalite:"RUS",184  equipeActuelle:"Krasnaya Armiya Moskva (CSKA jr)", ligue:"MHL (Russie)",185  stats:{mj:51,b:30,p:19,pts:49,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL",186  rangsParSource:{wheeler:3,dfo:2,tank:2,thn:4,br:3,button:9}, tendance:"down", risque:"élevé", sleeper:false,187  forces:["Ailier de puissance de 6'4\" et plus de 210 lb","30 buts à 16 ans dans la MHL — seul Michkov a fait mieux au même âge","Tir et jeu autour du filet dominants pour sa cohorte"],188  faiblesses:["Contrat de 4 ans signé avec le CSKA (KHL) jusqu'en juin 2030 — disponibilité incertaine","Absent des tournois IIHF (Russie toujours exclue) : peu de matchs repères contre l'élite mondiale"],189  comparableLNH:"Ailier de puissance marqueur, profil à la Valeri Nichushkin (style, pas une promesse)",190  projectionPlafond:"Ailier top-6 d'impact", radar:{patinage:55,sensJeu:60,tir:70,competitivite:60,jeuDefensif:45},191  analyse:"Talent brut de top-3 (2e chez Daily Faceoff et Tankathon), mais son contrat KHL jusqu'en 2030 est le grand point d'interrogation de la cuvée : plusieurs sources anticipent une glissade le soir du repêchage. Recrue de l'année MHL 2025-26."},192 {id:"skvortsov", nom:"Sergei Skvortsov", position:"AG", tir:"D", taille:"6'00\"", tailleCm:183, poids:160, naissance:"2009-03-11", nationalite:"RUS",193  equipeActuelle:"Chaika Nizhny Novgorod", ligue:"MHL (Russie)",194  stats:{mj:52,b:19,p:24,pts:43,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL",195  rangsParSource:{wheeler:5,dfo:4,tank:6,br:5}, tendance:"stable", risque:"moyen", sleeper:false,196  forces:["Meilleur pointeur de son club à 16 ans","Match de 4 buts en séries MHL","Sens offensif et toucher de passe au-dessus de sa cohorte"],197  faiblesses:["Très frêle (154-165 lb selon les sources) — développement physique à suivre","Comme tous les espoirs russes : moins de matchs repères internationaux"],198  comparableLNH:"Ailier créatif longiligne, profil à la Kirill Marchenko (style, pas une promesse)",199  projectionPlafond:"Ailier top-6", radar:{patinage:60,sensJeu:65,tir:60,competitivite:50,jeuDefensif:40},200  analyse:"Classé entre 4e et 6e par toutes les sources qui l'ont évalué — l'un des consensus les plus stables du top-10. Son gabarit à remplir est le principal frein à une projection plus haute."},201 {id:"meyer", nom:"Carter Meyer", position:"C", tir:"G", taille:"6'00\"", tailleCm:183, poids:176, naissance:"2009-04-10", nationalite:"USA",202  equipeActuelle:"Remparts de Québec (dès 2026-27, ex-NTDP)", ligue:"LHJMQ",203  stats:{mj:41,b:18,p:27,pts:45,plusMoins:-20,moy:null,arr:null}, statsLigue:"NTDP U17",204  rangsParSource:{wheeler:6,dfo:5,tank:4,thn:5,br:6,button:2}, tendance:"down", risque:"moyen", sleeper:false,205  forces:["Plus d'un point par match avec le NTDP U17 (45 pts en 41 MJ)","10 points en 4 matchs au Défi mondial U17 (bronze)","Fils de l'ex-défenseur LNH Freddy Meyer — pedigree et sens du jeu"],206  faiblesses:["Libéré du programme national américain le 2026-07-14 — trajectoire chamboulée","-20 avec le U17; jeu sans la rondelle à solidifier"],207  comparableLNH:"Centre offensif polyvalent, profil à la Cole Caufield déplacé au centre (style, pas une promesse)",208  projectionPlafond:"Centre top-6", radar:{patinage:60,sensJeu:60,tir:55,competitivite:60,jeuDefensif:50},209  analyse:"Craig Button le voyait 2e en novembre 2025. Sa libération surprise du NTDP (rapportée par Jeff Marek) l'amène aux Remparts de Québec pour 2026-27, avant Boston University en 2028-29 : une saison LHJMQ dominante pourrait le relancer vers le top-5."},210 {id:"sundstrom", nom:"Milan Sundström", position:"C", tir:"G", taille:"6'02\"", tailleCm:188, poids:187, naissance:"2009-05-06", nationalite:"SWE",211  equipeActuelle:"MoDo Hockey U20", ligue:"J20 Nationell",212  stats:{mj:12,b:12,p:8,pts:20,plusMoins:null,moy:null,arr:null}, statsLigue:"J20",213  rangsParSource:{wheeler:4,dfo:15,tank:5,thn:3,br:4,button:7}, tendance:"up", risque:"moyen", sleeper:false,214  forces:["12 buts en 12 matchs J20 à 16 ans (plus 32 pts en 16 MJ au U18)","Meilleur joueur de la Suède au Hlinka-Gretzky 2026 (Daily Faceoff), but en prolongation contre la Slovaquie","Centre complet avec pedigree (fils de Niklas Sundström)"],215  faiblesses:["Classé entre 3e et 15e selon les sources — fourchette large","Échantillon J20 encore mince (12 matchs)"],216  comparableLNH:"Centre bidirectionnel suédois, profil à la William Karlsson offensif (style, pas une promesse)",217  projectionPlafond:"Centre top-6", radar:{patinage:55,sensJeu:65,tir:55,competitivite:60,jeuDefensif:60},218  analyse:"Le meilleur Suédois de la cuvée. Presque toutes les sources le voient 3e-5e; Daily Faceoff (15e) est l'exception — d'où sa fourchette affichée. Son Hlinka solide dans une équipe suédoise faible (7e) a confirmé son statut."},219 {id:"nelson", nom:"Sammy Nelson", position:"C", tir:"D", taille:"6'02\"", tailleCm:189, poids:192, naissance:"2008-09-19", nationalite:"USA",220  equipeActuelle:"Université Notre Dame (ex-NTDP U18)", ligue:"NCAA",221  stats:{mj:58,b:27,p:27,pts:54,plusMoins:null,moy:null,arr:null}, statsLigue:"NTDP U18",222  rangsParSource:{wheeler:8,dfo:6,tank:7,br:9}, tendance:"up", risque:"faible", sleeper:false,223  forces:["2e pointeur du NTDP U18 avec 5 buts gagnants","10 points en 18 matchs contre des équipes NCAA","Cote « A » sur la liste préliminaire de la Centrale de recrutement","Parmi les plus vieux de la cuvée (raté 2026 de 4 jours) : plus mature, saut direct en NCAA"],224  faiblesses:["Son âge gonfle la comparaison avec les plus jeunes de la cuvée","Doit prouver qu'il peut piloter un trio en NCAA dès 2026-27"],225  comparableLNH:"Centre nord-sud robuste, profil à la Brayden Schenn (style, pas une promesse)",226  projectionPlafond:"Centre top-6", radar:{patinage:55,sensJeu:60,tir:60,competitivite:60,jeuDefensif:55},227  analyse:"Frère de Danny Nelson (Islanders). Candidat au Mondial junior 2027 selon NHL.com. Son passage direct à Notre Dame en fait l'un des espoirs les plus faciles à évaluer cette saison."},228 {id:"england", nom:"Brock England", position:"C", tir:"G", taille:"5'11\"", tailleCm:180, poids:174, naissance:"2009-08-22", nationalite:"CAN",229  equipeActuelle:"Thunderbirds de Seattle", ligue:"WHL",230  stats:{mj:64,b:21,p:30,pts:51,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL",231  rangsParSource:{wheeler:7,dfo:7,tank:9,br:7,button:5}, tendance:"up", risque:"faible", sleeper:false,232  forces:["« Le meilleur patineur que j'ai vu dans cette cuvée » — Scott Wheeler","2 buts dans la finale du Hlinka-Gretzky 2026 (Canada 8-1 USA)","Moteur et rythme constants, dangereux en transition"],233  faiblesses:["Parmi les plus jeunes de la cuvée (né en août 2009) — encore léger (174 lb)","Doit convertir davantage son volume de chances en buts"],234  comparableLNH:"Centre explosif, profil à la Dylan Larkin (style, pas une promesse)",235  projectionPlafond:"Centre top-6", radar:{patinage:70,sensJeu:60,tir:50,competitivite:60,jeuDefensif:50},236  analyse:"Sa finale de Hlinka (2 buts le 8 août 2026) est le fait d'armes le plus récent de toute la cuvée. Le patin d'élite est la fondation ; la production WHL devrait exploser en 2026-27 avec un rôle élargi à Seattle."},237 {id:"zhilkin", nom:"Dima Zhilkin", position:"AD", tir:"D", taille:"5'10\"", tailleCm:178, poids:185, naissance:"2008-10-21", nationalite:"CAN",238  equipeActuelle:"Spirit de Saginaw (capitaine)", ligue:"OHL",239  stats:{mj:59,b:36,p:39,pts:75,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",240  rangsParSource:{wheeler:9,dfo:9,tank:8,br:8}, tendance:"up", risque:"faible", sleeper:false,241  forces:["36 buts et 100 minutes de punition : marqueur ET abrasif","5 buts en 5 matchs au Mondial U18 2026 comme sous-classé","Nommé capitaine de Saginaw avant ses 17 ans"],242  faiblesses:["Taille moyenne (5'10\") pour son style physique","Emballement/discipline à canaliser (100 PIM)"],243  comparableLNH:"Ailier marqueur teigneux, profil à la Brady Tkachuk format compact (style, pas une promesse)",244  projectionPlafond:"Ailier top-6", radar:{patinage:60,sensJeu:55,tir:65,competitivite:65,jeuDefensif:45},245  analyse:"Frère de Danil Zhilkin (Jets). The Hockey News le cite déjà comme cible potentielle de loterie. Son U18 dominant en avril 2026 (6e marqueur du tournoi comme sous-classé) est l'un des meilleurs arguments statistiques de la cuvée."},246 {id:"jacobson", nom:"Jaxon Jacobson", position:"C", tir:"G", taille:"5'10\"", tailleCm:176, poids:176, naissance:"2008-12-11", nationalite:"CAN",247  equipeActuelle:"Wheat Kings de Brandon", ligue:"WHL",248  stats:{mj:63,b:25,p:60,pts:85,plusMoins:8,moy:null,arr:null}, statsLigue:"WHL",249  rangsParSource:{wheeler:10,dfo:10,tank:10,thn:10,br:10}, tendance:"up", risque:"moyen", sleeper:false,250  forces:["85 points en 63 matchs — la meilleure production CHL de la cuvée","Vision de passeur d'élite (60 passes)","A produit malgré une blessure en cours de saison"],251  faiblesses:["5'9\"-5'10\" selon les sources : le gabarit divisera les recruteurs","Jeu défensif encore embryonnaire"],252  comparableLNH:"Petit centre créatif, profil à la Logan Stankoven (style, pas une promesse)",253  projectionPlafond:"Centre/ailier top-6", radar:{patinage:55,sensJeu:70,tir:50,competitivite:55,jeuDefensif:45},254  analyse:"Rang 10 unanime chez les cinq sources qui le classent — fait rarissime. L'écart entre sa production (no 1 de la cuvée en CHL) et son rang consensus en fait aussi un candidat « valeur » : seul le gabarit explique la retenue."},255 {id:"neuenschwander", nom:"Jonah Neuenschwander", position:"C", tir:"G", taille:"6'03\"", tailleCm:190, poids:187, naissance:"2009-03-10", nationalite:"SUI",256  equipeActuelle:"EHC Bienne", ligue:"NL (Suisse)",257  stats:{mj:32,b:5,p:7,pts:12,plusMoins:null,moy:null,arr:null}, statsLigue:"National League (pro)",258  rangsParSource:{wheeler:11,dfo:14,tank:11,thn:7,button:8}, tendance:"stable", risque:"moyen", sleeper:false,259  forces:["Joueur D-1 le plus productif de l'élite suisse en 60 ans","Déjà deux Mondiaux juniors disputés (le premier à 15 ans, une première depuis 2001)","Grand centre (6'3\") habitué au hockey d'hommes"],260  faiblesses:["Production brute modeste en pro (12 pts) — rôle limité","Position finale à trancher (centre ou aile selon les sources)"],261  comparableLNH:"Grand centre européen deux sens, profil à la Nico Hischier (style, pas une promesse)",262  projectionPlafond:"Centre top-9 avec plafond top-6", radar:{patinage:55,sensJeu:55,tir:55,competitivite:60,jeuDefensif:55},263  analyse:"Le meilleur espoir suisse depuis Hischier selon plusieurs observateurs. Évaluation difficile : ses 12 points en National League valent plus qu'ils n'y paraissent (25 pts en 18 MJ au niveau U21)."},264 {id:"yakunin", nom:"Yevgeni Yakunin", position:"C", tir:"G", taille:"6'03\"", tailleCm:190, poids:194, naissance:"2009-02-09", nationalite:"RUS",265  equipeActuelle:"MHK Spartak Moskva", ligue:"MHL (Russie)",266  stats:{mj:58,b:13,p:34,pts:47,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL",267  rangsParSource:{wheeler:13,dfo:17,tank:12}, tendance:"stable", risque:"élevé", sleeper:false,268  forces:["Record MHL d'assistances pour un joueur U17 (34)","Grand centre passeur de 6'3\"","Production régulière sur 58 matchs"],269  faiblesses:["Contrat KHL avec le Spartak Moscou jusqu'en 2031 — l'engagement le plus long de la cuvée, pire que Privalov","Tir peu menaçant (13 buts)"],270  comparableLNH:"Centre passeur format pro, profil à la Anton Lundell (style, pas une promesse)",271  projectionPlafond:"Centre top-9", radar:{patinage:50,sensJeu:65,tir:50,competitivite:55,jeuDefensif:55},272  analyse:"Le contrat jusqu'en 2031 (Daily Faceoff) pèsera sur son rang réel. Le talent de fabricant de jeu, lui, est indéniable — record historique U17 de la MHL à l'appui."},273 {id:"cripps", nom:"Brock Cripps", position:"D", tir:"D", taille:"5'10\"", tailleCm:178, poids:161, naissance:"2009-07-23", nationalite:"CAN",274  equipeActuelle:"Raiders de Prince Albert", ligue:"WHL",275  stats:{mj:62,b:6,p:31,pts:37,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL",276  rangsParSource:{wheeler:15,dfo:16,tank:17,thn:9}, tendance:"up", risque:"moyen", sleeper:false,277  forces:["2e choix du repêchage WHL 2024 ; ~26 minutes par match au Mondial U17 (or)","21 points en 20 matchs de séries WHL — a élevé son jeu","Défenseur droitier mobile et intelligent, denrée rare"],278  faiblesses:["161 lb : très loin d'un gabarit LNH","Devra prouver qu'il peut défendre contre du volume physique"],279  comparableLNH:"D droitier mobile sous-format, profil à la Jared Spurgeon (style, pas une promesse)",280  projectionPlafond:"Défenseur top-4", radar:{patinage:60,sensJeu:65,tir:45,competitivite:55,jeuDefensif:55},281  analyse:"The Hockey News le place déjà 9e. Ses séries WHL (plus d'un point par match) et son or au Défi mondial U17 avec un temps de glace massif dessinent un défenseur no 2-3 de confiance."},282 {id:"pustovoy", nom:"Andrei Pustovoy", position:"AD", tir:"G", taille:"6'02\"", tailleCm:190, poids:198, naissance:"2008-12-08", nationalite:"RUS",283  equipeActuelle:"Loko Yaroslavl", ligue:"MHL (Russie)",284  stats:{mj:52,b:32,p:30,pts:62,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL",285  rangsParSource:{wheeler:14,dfo:18,tank:13}, tendance:"stable", risque:"moyen", sleeper:false,286  forces:["Joueur U18 le plus productif de la MHL en 2025-26 (62 pts)","32 buts : gâchette naturelle avec gabarit (6'2\"-6'3\", ~200 lb)","Profil puissance-finition déjà mûr physiquement"],287  faiblesses:["Patinage à raffiner pour le rythme nord-américain","Jeu de soutien défensif inconstant"],288  comparableLNH:"Ailier marqueur de puissance, profil à la Andrei Svechnikov (style, pas une promesse)",289  projectionPlafond:"Ailier top-6", radar:{patinage:55,sensJeu:55,tir:65,competitivite:55,jeuDefensif:45},290  analyse:"Statistiquement, le meilleur attaquant U18 de toute la MHL. Classé 13e-18e par les trois sources qui le suivent — la stabilité du consensus tranche avec le peu de visibilité médiatique des Russes."},291 {id:"kazda", nom:"Timothy Kazda", position:"AD", tir:"D", taille:"6'01\"", tailleCm:185, poids:194, naissance:"2008-10-04", nationalite:"SVK",292  equipeActuelle:"Steel de Chicago", ligue:"USHL",293  stats:{mj:59,b:22,p:19,pts:41,plusMoins:-5,moy:null,arr:null}, statsLigue:"USHL",294  rangsParSource:{wheeler:null,dfo:11,tank:21}, mentionWheeler:true, tendance:"stable", risque:"moyen", sleeper:false,295  forces:["Première équipe des recrues USHL 2026","12 points en 12 matchs internationaux U18 avec la Slovaquie","Ailier énergique qui gagne ses batailles de rondelle"],296  faiblesses:["Fourchette large : 11e (Daily Faceoff) contre mention honorable (Wheeler)","Création de jeu à cinq contre cinq à démontrer"],297  comparableLNH:"Ailier de puissance slovaque, profil à la Martin Pospisil offensif (style, pas une promesse)",298  projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:50,tir:60,competitivite:65,jeuDefensif:50},299  analyse:"Le meilleur Slovaque de la cuvée. Daily Faceoff (11e) est nettement plus haut que Wheeler (mention honorable) — affiché en fourchette, conformément aux règles de la plateforme."},300 {id:"santala", nom:"Luca Santala", position:"C", tir:"D", taille:"6'02\"", tailleCm:188, poids:176, naissance:"2009-07-28", nationalite:"FIN",301  equipeActuelle:"Knights de London (dès 2026-27, ex-Kiekko-Espoo)", ligue:"OHL",302  stats:{mj:42,b:19,p:15,pts:34,plusMoins:null,moy:null,arr:null}, statsLigue:"U18+U20 Finlande (combiné)",303  rangsParSource:{wheeler:21,dfo:12,tank:18,thn:8,button:6}, tendance:"up", risque:"moyen", sleeper:false,304  forces:["Meilleur espoir finlandais 2009","Grand centre polyvalent qui joue dans les deux sens","Transfert chez les Knights de London (OHL) — machine à développement"],305  faiblesses:["Classé entre 6e et 21e : les sources sont divisées","Production U20 modeste (12 pts en 25 MJ) avant sa montée"],306  comparableLNH:"Centre finlandais complet, profil à la Anton Lundell (style, pas une promesse)",307  projectionPlafond:"Centre top-9 avec plafond top-6", radar:{patinage:55,sensJeu:60,tir:55,competitivite:55,jeuDefensif:55},308  analyse:"Son passage à London (signé le 23 juillet 2026, CHL.ca) est le meilleur indicateur de confiance : les Knights ne recrutent pas des projets ordinaires en Europe. La fourchette 6e-21e reflète l'incertitude du saut nord-américain."},309 {id:"tomek", nom:"Petr Tomek", position:"C", tir:"G", taille:"5'10\"", tailleCm:178, poids:161, naissance:"2008-10-23", nationalite:"CZE",310  equipeActuelle:"HC Energie Karlovy Vary", ligue:"Extraliga (Tchéquie)",311  stats:{mj:51,b:13,p:7,pts:20,plusMoins:null,moy:null,arr:null}, statsLigue:"Extraliga (pro)",312  rangsParSource:{wheeler:23,dfo:8,tank:19,button:10}, tendance:"stable", risque:"moyen", sleeper:false,313  forces:["13 buts PROS dans l'élite tchèque à 17 ans","Saison complète contre des hommes — rare dans la cuvée","Instincts de marqueur en zone payante"],314  faiblesses:["Classé entre 8e et 23e : fourchette très large","Gabarit léger (5'10\", ~161 lb) pour son style direct"],315  comparableLNH:"Attaquant tchèque opportuniste, profil à la Ondrej Palat (style, pas une promesse)",316  projectionPlafond:"Attaquant top-9", radar:{patinage:60,sensJeu:60,tir:55,competitivite:55,jeuDefensif:45},317  analyse:"Le cas le plus polarisant du milieu de première ronde : Daily Faceoff (8e) valorise ses 13 buts pros, Wheeler (23e) attend de le voir dominer sa cohorte. Né un mois après la date limite 2026 — il aurait été repêché cette année autrement."},318 {id:"fitzhenry", nom:"Nolan Fitzhenry", position:"C", tir:"G", taille:"5'11\"", tailleCm:180, poids:183, naissance:"2009-02-10", nationalite:"USA",319  equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL",320  stats:{mj:51,b:21,p:24,pts:45,plusMoins:-17,moy:null,arr:null}, statsLigue:"NTDP U17",321  rangsParSource:{wheeler:12,dfo:24,tank:14}, tendance:"stable", risque:"moyen", sleeper:false,322  forces:["45 points en 51 matchs au NTDP U17","Engagement NCAA vers North Dakota rapporté (Tankathon — non confirmé par une 2e source)","Bon toucher autour du filet (21 buts)"],323  faiblesses:["Écart 12e (Wheeler) vs 24e (Daily Faceoff)","-17 dans une équipe U17 en difficulté"],324  comparableLNH:"Centre américain travaillant, profil à la Frank Nazar (style, pas une promesse)",325  projectionPlafond:"Centre top-9", radar:{patinage:55,sensJeu:60,tir:50,competitivite:55,jeuDefensif:50},326  analyse:"L'un des piliers du NTDP 2009, groupe collectivement affaibli (finale du Hlinka perdue 8-1, départ de Meyer). Sa saison U18 dira s'il suit la trajectoire de Wheeler (12e) ou celle de Daily Faceoff (24e)."},327 {id:"meijer", nom:"Bosse Meijer", position:"C", tir:"G", taille:"5'10\"", tailleCm:178, poids:168, naissance:"2008-12-17", nationalite:"SWE",328  equipeActuelle:"Frölunda HC U20", ligue:"J20 Nationell",329  stats:{mj:31,b:16,p:21,pts:37,plusMoins:null,moy:null,arr:null}, statsLigue:"J20",330  rangsParSource:{wheeler:16,dfo:21,tank:15}, tendance:"up", risque:"moyen", sleeper:false,331  forces:["Plus d'un point par match en J20 et ~2 pts/match en séries","8 points en 7 matchs au Mondial U18 2026 comme admissible 2027 (Suède championne)","Débuts déjà faits en SHL"],332  faiblesses:["Gabarit moyen (5'10\", 168 lb)","Doit s'imposer physiquement au niveau homme"],333  comparableLNH:"Centre suédois fluide, profil à la Leo Carlsson format réduit (style, pas une promesse)",334  projectionPlafond:"Centre top-9", radar:{patinage:60,sensJeu:60,tir:50,competitivite:55,jeuDefensif:50},335  analyse:"4e marqueur de la Suède championne du monde U18 en avril 2026 alors qu'il était sous-classé — l'argument international le plus fort du milieu de ronde."},336 {id:"shtyrkhunov", nom:"Vladimir Shtyrkhunov", position:"D", tir:"D", taille:"6'00\"", tailleCm:183, poids:157, naissance:"2009-01-15", nationalite:"RUS",337  equipeActuelle:"Krasnaya Armiya Moskva (CSKA jr)", ligue:"MHL (Russie)",338  stats:{mj:55,b:4,p:28,pts:32,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL",339  rangsParSource:{wheeler:18,dfo:23,tank:20}, tendance:"stable", risque:"élevé", sleeper:false,340  forces:["2e saison U17 la plus productive de l'histoire de la MHL pour un défenseur","~20 minutes de jeu par match à 16-17 ans","Relance fluide, D droitier — profil recherché"],341  faiblesses:["157 lb : parmi les plus légers de la cuvée","Facteur russe : visibilité et calendrier de venue en Amérique incertains"],342  comparableLNH:"D droitier de transition, profil à la Shayne Gostisbehere (style, pas une promesse)",343  projectionPlafond:"Défenseur top-4", radar:{patinage:60,sensJeu:60,tir:45,competitivite:50,jeuDefensif:50},344  analyse:"Production historique pour un défenseur U17 de la MHL. Consensus stable (18e-23e) chez les trois sources qui le classent."},345 {id:"davidson", nom:"Noah Davidson", position:"C", tir:"G", taille:"6'03\"", tailleCm:190, poids:216, naissance:"2008-11-01", nationalite:"USA",346  equipeActuelle:"Tigers de Medicine Hat", ligue:"WHL",347  stats:{mj:67,b:30,p:22,pts:52,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL",348  rangsParSource:{wheeler:17,dfo:28,tank:16}, tendance:"stable", risque:"moyen", sleeper:false,349  forces:["30 buts comme recrue WHL — rare pour un attaquant de 6'3\", 216 lb","Déjà bâti comme un pro","Engagé avec Boston College (NCAA)"],350  faiblesses:["Fourchette 16e-28e selon les sources","Jeu de transition et première passe à polir"],351  comparableLNH:"Attaquant de puissance nord-sud, profil à la Chris Kreider (style, pas une promesse)",352  projectionPlafond:"Attaquant top-9 avec plafond top-6", radar:{patinage:50,sensJeu:50,tir:60,competitivite:65,jeuDefensif:50},353  analyse:"Le combo 30 buts + 216 lb en saison recrue WHL n'existe nulle part ailleurs dans la cuvée. Nationalité USA confirmée par le tableau officiel du Hlinka-Gretzky d'août 2025, où il a représenté USA U18 (6 pts en 5 matchs)."},354 {id:"gutierrez", nom:"Diego Gutierrez", position:"D", tir:"D", taille:"6'02\"", tailleCm:188, poids:187, naissance:"2009-05-13", nationalite:"USA",355  equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL",356  stats:{mj:38,b:2,p:17,pts:19,plusMoins:-8,moy:null,arr:null}, statsLigue:"NTDP U17",357  rangsParSource:{wheeler:19,dfo:22,tank:25}, tendance:"stable", risque:"moyen", sleeper:false,358  forces:["Meilleur défenseur des 2009 du programme américain","Droitier de 6'2\" avec bâton actif","Engagé avec Notre Dame (NCAA)"],359  faiblesses:["Production offensive modeste (19 pts en 38 MJ)","Prises de décision sous pression à stabiliser"],360  comparableLNH:"D droitier deux sens, profil à la K'Andre Miller côté droit (style, pas une promesse)",361  projectionPlafond:"Défenseur top-4", radar:{patinage:55,sensJeu:55,tir:45,competitivite:55,jeuDefensif:60},362  analyse:"Consensus serré (19e-25e). Le NTDP lui confiera les grosses minutes au U18 en 2026-27 — c'est là que son rang bougera."},363 {id:"tait", nom:"Boston Tait", position:"D", tir:"G", taille:"6'02\"", tailleCm:188, poids:183, naissance:"2009-04-13", nationalite:"CAN",364  equipeActuelle:"Wild de Wenatchee", ligue:"WHL",365  stats:{mj:62,b:5,p:18,pts:23,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL",366  rangsParSource:{wheeler:20,dfo:20,tank:31}, tendance:"stable", risque:"moyen", sleeper:false,367  forces:["Seul défenseur gaucher du top-25 de Wheeler","~21 minutes par match à 16-17 ans","Gabarit et rayon d'action de défenseur moderne"],368  faiblesses:["Production offensive limitée (23 pts)","55 PIM : discipline à surveiller"],369  comparableLNH:"D gaucher fiable, profil à la Jake Sanderson défensif (style, pas une promesse)",370  projectionPlafond:"Défenseur top-4", radar:{patinage:55,sensJeu:50,tir:45,competitivite:55,jeuDefensif:60},371  analyse:"La rareté a de la valeur : les défenseurs gauchers de qualité manquent cruellement dans cette cuvée, ce qui protège son rang malgré des chiffres modestes."},372 {id:"harper", nom:"Levi Harper", position:"D", tir:"D", taille:"5'11\"", tailleCm:180, poids:174, naissance:"2008-10-03", nationalite:"USA",373  equipeActuelle:"Spirit de Saginaw", ligue:"OHL",374  stats:{mj:68,b:12,p:45,pts:57,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",375  rangsParSource:{wheeler:null,dfo:19,tank:28}, mentionWheeler:true, tendance:"up", risque:"moyen", sleeper:true,376  forces:["57 points en 68 matchs comme défenseur recrue OHL","Quart-arrière d'avantage numérique naturel","79 PIM : joue avec du mordant"],377  faiblesses:["Mention honorable seulement chez Wheeler","Couverture défensive à resserrer"],378  comparableLNH:"D offensif recrue-éclair, profil à la Ryan Merkley assagi (style, pas une promesse)",379  projectionPlafond:"Défenseur top-4 offensif", radar:{patinage:55,sensJeu:60,tir:50,competitivite:50,jeuDefensif:45},380  analyse:"SLEEPER : 57 points comme D recrue en OHL, c'est une production de premier plan — l'écart entre ses chiffres et son rang consensus (19e-28e) est l'un des plus grands de la cuvée."},381 {id:"calce", nom:"Max Calce", position:"C", tir:"n.d.", taille:"5'11\"", tailleCm:180, poids:181, naissance:"2009-06-11", nationalite:"GER",382  equipeActuelle:"Adler Mannheim", ligue:"DEL (Allemagne)",383  stats:{mj:14,b:2,p:0,pts:2,plusMoins:null,moy:null,arr:null}, statsLigue:"DEL (pro) — plus 23 pts en 17 MJ au U20",384  rangsParSource:{wheeler:null,dfo:13,tank:45,thn:6}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:false,385  forces:["Meilleur buteur U18 d'Allemagne; 4 points en 5 matchs au Mondial U18 2026","19 min 27 s de temps de glace moyen au U18 mondial — usage massif","Déjà 14 matchs pros en DEL"],386  faiblesses:["Classé entre 6e (THN) et 45e (Tankathon) — l'écart le plus extrême de la cuvée","Échantillon contre sa propre cohorte encore mince"],387  comparableLNH:"Attaquant allemand polyvalent, profil à la Tim Stützle prudent (style, pas une promesse)",388  projectionPlafond:"Top-9 — fourchette exceptionnellement large", radar:{patinage:55,sensJeu:60,tir:55,competitivite:50,jeuDefensif:45},389  analyse:"⚡ Le joueur le plus volatil de la cuvée : 6e chez The Hockey News, 45e chez Tankathon. Anciennement connu sous le nom de Max Penkin. Le meilleur espoir allemand depuis Stützle si la version THN est la bonne."},390 {id:"gordoncarroll", nom:"Shaeffer Gordon-Carroll", position:"AD", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:190, naissance:"2008-11-26", nationalite:"USA",391  equipeActuelle:"Tigers de Medicine Hat", ligue:"WHL",392  stats:{mj:41,b:12,p:25,pts:37,plusMoins:null,moy:null,arr:null}, statsLigue:"WHL",393  rangsParSource:{wheeler:22,dfo:31,tank:22}, tendance:"stable", risque:"moyen", sleeper:false,394  forces:["37 points en 41 matchs avant une blessure — presque un point par match","Ailier intelligent qui joue plus grand que son gabarit","A représenté USA U18 au Hlinka-Gretzky d'août 2025 (nationalité USA confirmée)"],395  faiblesses:["Saison écourtée par blessure : échantillon réduit"],396  comparableLNH:"Ailier complémentaire productif, profil à la Seth Jarvis (style, pas une promesse)",397  projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:55,competitivite:55,jeuDefensif:50},398  analyse:"Son rythme avant blessure soutenait un rang plus élevé. Une saison santé à Medicine Hat, équipe puissante de la WHL, le stabilisera."},399 {id:"glance", nom:"Jamie Glance", position:"AD", tir:"n.d.", taille:"5'11\"", tailleCm:180, poids:182, naissance:"2008-09-23", nationalite:"USA",400  equipeActuelle:"USNTDP U18 (destination 2026-27 incertaine)", ligue:"NTDP/USHL",401  stats:{mj:62,b:23,p:33,pts:56,plusMoins:null,moy:null,arr:null}, statsLigue:"NTDP U18",402  rangsParSource:{wheeler:null,dfo:27,tank:23}, mentionWheeler:true, tendance:"down", risque:"moyen", sleeper:false,403  forces:["56 points en 62 matchs avec le NTDP U18","Parmi les plus vieux de la cuvée : production contre du U18 déjà établie"],404  faiblesses:["Avenir 2026-27 incertain (départ possible vers la LHJMQ selon Daily Faceoff)","Doit élargir son jeu hors de l'avantage numérique"],405  comparableLNH:"Ailier marqueur d'occasion, profil à la Alex Tuch compact (style, pas une promesse)",406  projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:60,competitivite:55,jeuDefensif:45},407  analyse:"Production réelle, mais l'incertitude sur sa destination 2026-27 et la faiblesse collective du groupe NTDP le tirent vers le bas des classements d'été."},408 {id:"edgar", nom:"Ryerson Edgar", position:"C", tir:"n.d.", taille:"5'10\"", tailleCm:178, poids:161, naissance:"2009-07-30", nationalite:"CAN",409  equipeActuelle:"IceDogs de Niagara", ligue:"OHL",410  stats:{mj:64,b:23,p:26,pts:49,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",411  rangsParSource:{wheeler:25,dfo:26,tank:26}, tendance:"stable", risque:"moyen", sleeper:false,412  forces:["49 points comme recrue OHL parmi les plus jeunes de la cuvée (né fin juillet 2009)","Moteur constant, bon en échec-avant","Engagement NCAA vers Michigan rapporté (Tankathon — non confirmé par une 2e source)"],413  faiblesses:["161 lb à développer","Doit devenir plus dangereux en possession prolongée"],414  comparableLNH:"Centre énergique, profil à la Yanni Gourde (style, pas une promesse)",415  projectionPlafond:"Centre top-9", radar:{patinage:60,sensJeu:55,tir:50,competitivite:55,jeuDefensif:45},416  analyse:"Consensus remarquablement stable (25e-26e partout). Son âge (parmi les plus jeunes admissibles) lui donne plus de piste de croissance que la plupart des joueurs classés autour de lui."},417 {id:"eshkawkogan", nom:"Kohyn Eshkawkogan", position:"D", tir:"D", taille:"5'11\"", tailleCm:180, poids:183, naissance:"2008-11-19", nationalite:"CAN",418  equipeActuelle:"67's d'Ottawa", ligue:"OHL",419  stats:{mj:68,b:8,p:45,pts:53,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",420  rangsParSource:{wheeler:24,dfo:30,tank:24}, tendance:"stable", risque:"moyen", sleeper:false,421  forces:["53 points en 68 matchs — équipe d'étoiles des recrues OHL 2025","D droitier créatif en sortie de zone","L'un des plus jeunes au camp Hlinka 2025"],422  faiblesses:["Couverture d'enclave à resserrer","Gabarit moyen pour les minutes difficiles"],423  comparableLNH:"D droitier offensif, profil à la Ethan Del Mastro inversé côté offensif (style, pas une promesse)",424  projectionPlafond:"Défenseur top-4", radar:{patinage:55,sensJeu:60,tir:45,competitivite:50,jeuDefensif:50},425  analyse:"Un des trois défenseurs droitiers de l'OHL qui se disputent la fin de première ronde avec Harper — son avance : la constance sur 68 matchs."},426 {id:"eklundaspe", nom:"Dorian Eklund Aspe", position:"C", tir:"n.d.", taille:"6'04\"", tailleCm:194, poids:209, naissance:"2009-02-04", nationalite:"SWE",427  equipeActuelle:"Djurgårdens IF U18", ligue:"U18 Nationell",428  stats:{mj:19,b:14,p:15,pts:29,plusMoins:null,moy:null,arr:null}, statsLigue:"U18 Nationell",429  rangsParSource:{wheeler:null,dfo:null,tank:27}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,430  forces:["29 points en 19 matchs U18 avec un gabarit de 6'4\", 209 lb","Présent au Hlinka-Gretzky 2026 avec la Suède"],431  faiblesses:["Classé par une seule source (Tankathon 27e) — incertitude élevée","N'a pas encore joué au niveau J20"],432  comparableLNH:"Grand attaquant suédois en développement, profil à la Jonathan Lekkerimäki costaud (style, pas une promesse)",433  projectionPlafond:"Top-9 — évaluation précoce", radar:{patinage:50,sensJeu:50,tir:55,competitivite:60,jeuDefensif:50},434  analyse:"Source unique : rang à prendre avec prudence. Le physique + la production U18 justifient la curiosité; la saison J20 2026-27 dira le reste."},435 {id:"hartl", nom:"Michal Hartl", position:"C", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:190, naissance:"2009-06-11", nationalite:"CZE",436  equipeActuelle:"HC Kometa Brno U20", ligue:"Tchéquie U20",437  stats:{mj:31,b:21,p:14,pts:35,plusMoins:null,moy:null,arr:null}, statsLigue:"Czechia U20",438  rangsParSource:{wheeler:null,dfo:null,tank:29}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false,439  forces:["21 buts en 31 matchs U20 tchèque (43 pts en 39 MJ tous niveaux)","Tir rapide en mouvement","Présent au Hlinka-Gretzky 2026 avec la Tchéquie"],440  faiblesses:["Classement ferme d'une seule source (Tankathon 29e)","Doit tester l'Extraliga ou l'Amérique du Nord"],441  comparableLNH:"Marqueur tchèque direct, profil à la Martin Necas ailier (style, pas une promesse)",442  projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:60,competitivite:55,jeuDefensif:45},443  analyse:"Mention honorable chez Wheeler et « also considered » chez Daily Faceoff : le 2e meilleur espoir tchèque derrière Tomek selon la plupart des lectures."},444 {id:"wycisk", nom:"Jaakko Wycisk", position:"AD", tir:"D", taille:"6'01\"", tailleCm:185, poids:190, naissance:"2009-03-16", nationalite:"CAN",445  equipeActuelle:"Storm de Guelph", ligue:"OHL",446  stats:{mj:60,b:17,p:26,pts:43,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",447  rangsParSource:{wheeler:null,dfo:null,tank:30}, mentionWheeler:true, tendance:"up", risque:"moyen", sleeper:false,448  forces:["4 points (1B-3P) en demi-finale du Hlinka-Gretzky 2026 contre la Finlande, but en finale","43 points comme recrue OHL","Ailier honnête dans les trois zones"],449  faiblesses:["Classement ferme d'une seule source (Tankathon 30e)","Doit devenir le moteur offensif de Guelph pour grimper"],450  comparableLNH:"Ailier deux sens en progression, profil à la Mason Marchment jeune (style, pas une promesse)",451  projectionPlafond:"Ailier top-9", radar:{patinage:55,sensJeu:55,tir:55,competitivite:60,jeuDefensif:50},452  analyse:"Parmi les meneurs canadiens du Hlinka 2026 (or) — le tournoi qui vient de se terminer a probablement fait grimper son nom sur les listes d'automne."},453 /* --- Banque élargie : sleepers, chutes et fiches allégées --- */454 {id:"scantlebury", nom:"James Scantlebury", position:"C", tir:"n.d.", taille:"5'10\"", tailleCm:178, poids:172, naissance:"2009-01-15", nationalite:"CAN",455  equipeActuelle:"Remparts de Québec (dès 2026-27, ex-Chicago Steel)", ligue:"LHJMQ",456  stats:{mj:62,b:16,p:23,pts:39,plusMoins:-6,moy:null,arr:null}, statsLigue:"USHL",457  rangsParSource:{wheeler:null,dfo:29,tank:32}, mentionWheeler:true, tendance:"up", risque:"moyen", sleeper:true,458  forces:["Meilleur pointeur U17 de toute la USHL en 2025-26 (devant Carter Meyer)","Première équipe des recrues USHL 2026","Québécois (Châteauguay) de retour dans la LHJMQ avec les Remparts"],459  faiblesses:["Classé seulement 29e-32e malgré sa production — d'où son statut de sleeper","Gabarit moyen (5'10\")"],460  comparableLNH:"Centre créatif sous-coté, profil à la Alex Newhook (style, pas une promesse)",461  projectionPlafond:"Centre top-9 avec plafond top-6", radar:{patinage:55,sensJeu:60,tir:50,competitivite:55,jeuDefensif:50},462  analyse:"SLEEPER no 1 : dominer les U17 de la USHL devant Meyer et n'être classé que 29e-32e, c'est l'écart production/rang le plus flagrant de la cuvée. Une grosse saison à Québec le fera exploser sur les listes."},463 {id:"naudins", nom:"Roberts Naudiņš", position:"AG", tir:"n.d.", taille:"6'06\"", tailleCm:199, poids:208, naissance:"2008-11-18", nationalite:"LVA",464  equipeActuelle:"Vees de Penticton (dès 2026-27, ex-Shattuck-St. Mary's)", ligue:"WHL",465  stats:{mj:51,b:24,p:50,pts:74,plusMoins:null,moy:null,arr:null}, statsLigue:"USHS-Prep",466  rangsParSource:{wheeler:null,dfo:null,tank:34}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:true,467  forces:["Plus grand joueur de la cuvée (6'6\") avec 74 points en 51 matchs","Mains souples pour son gabarit","Saut vers la WHL (Penticton) en 2026-27"],468  faiblesses:["Production réalisée au niveau préparatoire (Shattuck) — vraie référence à venir","Coordination/patinage en croissance, comme tous les géants"],469  comparableLNH:"Géant letton offensif, profil à la Zemgus Girgensons offensif (style, pas une promesse)",470  projectionPlafond:"Ailier top-9 à haut plafond", radar:{patinage:45,sensJeu:55,tir:55,competitivite:55,jeuDefensif:45},471  analyse:"SLEEPER : le profil physique le plus rare de la cuvée. Si la production suit à Penticton (WHL), il ne restera pas longtemps en fin de classement."},472 {id:"yermolov", nom:"Daniil Yermolov", position:"AG", tir:"n.d.", taille:"6'02\"", tailleCm:188, poids:183, naissance:"2009-02-15", nationalite:"RUS",473  equipeActuelle:"Krasnaya Armiya Moskva (CSKA jr)", ligue:"MHL (Russie)",474  stats:{mj:null,b:null,p:null,pts:null,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL — ligne complète n.d.",475  rangsParSource:{wheeler:null,dfo:null,tank:38}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:true,476  forces:["Considéré par Wheeler comme un des grands talents bruts de la cuvée","Ailier de 6'2\" avec des flashs de haut niveau"],477  faiblesses:["Échantillon MHL jugé trop mince par Wheeler pour le classer","Ligne statistique 2025-26 complète introuvable (n.d.)"],478  comparableLNH:"Talent brut russe, comparable prématuré (n.d.)",479  projectionPlafond:"n.d. — trop tôt", radar:null,480  analyse:"SLEEPER à haut risque : Wheeler écrit qu'il a le talent du top de la cuvée, sans le classer faute de matchs. Le nom à surveiller dès l'ouverture de la MHL."},481 {id:"kolmakov", nom:"Ilya Kolmakov", position:"AG", tir:"G", taille:"6'01\"", tailleCm:185, poids:165, naissance:"2008-09-30", nationalite:"RUS",482  equipeActuelle:"Phoenix de Sherbrooke", ligue:"LHJMQ",483  stats:{mj:62,b:13,p:35,pts:48,plusMoins:null,moy:null,arr:null}, statsLigue:"LHJMQ",484  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:true,485  forces:["48 points comme recrue LHJMQ — non classé par les grandes listes","Passeur naturel (35 aides)"],486  faiblesses:["Absent de tous les classements numérotés — seulement la liste de surveillance d'Elite Prospects","Données physiques introuvables (n.d.)"],487  comparableLNH:"n.d.",488  projectionPlafond:"n.d. — hors classements", radar:null,489  analyse:"SLEEPER : près de 50 points dans la LHJMQ sans même figurer aux classements d'été. Le genre de nom que la Centrale de recrutement ajoutera dès sa liste préliminaire d'automne."},490 {id:"murata", nom:"Charlie Murata", position:"AD", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:183, naissance:"2009-02-15", nationalite:"CAN",491  equipeActuelle:"Firebirds de Flint", ligue:"OHL",492  stats:{mj:59,b:5,p:13,pts:18,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",493  rangsParSource:{wheeler:null,tank:41,button:4}, mentionWheeler:true, tendance:"down", risque:"élevé", sleeper:false,494  forces:["Talent reconnu tôt : 4e du lookahead TSN/Button en novembre 2025","Engagé avec Michigan State (NCAA)"],495  faiblesses:["Saison OHL très décevante : 18 points en 59 matchs","Chute de 4e (nov. 2025) à 41e (été 2026) — la plus forte de la cuvée"],496  comparableLNH:"n.d. — projection suspendue à son rebond",497  projectionPlafond:"À rebâtir", radar:null,498  analyse:"⚡ EN CHUTE : personne n'a perdu plus de valeur en huit mois. Le talent qui séduisait Button en début de saison existe encore ; Flint devra lui donner le volume pour le prouver. Retenu par Équipe Canada au Hlinka 2026 (2 passes en 4 matchs — nationalité CAN confirmée par le tableau officiel du tournoi)."},499 {id:"selic", nom:"Tomas Selic", position:"AD", tir:"G", taille:"6'03\"", tailleCm:191, poids:198, naissance:"2009-05-08", nationalite:"SVK",500  equipeActuelle:"HC Kometa Brno U20", ligue:"Tchéquie U20",501  stats:{mj:45,b:21,p:29,pts:50,plusMoins:null,moy:null,arr:null}, statsLigue:"Czechia U20",502  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false,503  forces:["Co-meneur des pointeurs du Hlinka-Gretzky 2026 : 5B-3P en 4 matchs avec la Slovaquie","50 points en 45 matchs au U20 tchèque en 2025-26"],504  faiblesses:["Absent de tous les classements numérotés d'été (liste de surveillance EP seulement)","Données physiques et de naissance introuvables (n.d.)"],505  comparableLNH:"n.d.",506  projectionPlafond:"n.d. — à reclasser après son tournoi", radar:null,507  analyse:"Ajouté à la banque après le Hlinka 2026 : finir premier pointeur du tournoi à égalité (8 pts) sans figurer sur aucune liste d'été, c'est le profil type du joueur que les classements d'automne feront bondir. Bémol du sommaire officiel : blanchi au match de bronze (défaite 3-2) avec 2 pénalités en 1re période (rudesse, conduite antisportive). Le meilleur Slovaque de la cuvée avec Kazda."},508 {id:"pelosi", nom:"Rocco Pelosi", position:"C", tir:"n.d.", taille:"5'11\"", tailleCm:180, poids:176, naissance:"2009-01-28", nationalite:"USA",509  equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL",510  stats:{mj:53,b:11,p:11,pts:22,plusMoins:-23,moy:null,arr:null}, statsLigue:"NTDP U17",511  rangsParSource:{wheeler:null,dfo:25,tank:42}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:false,512  forces:["Frère cadet de Chris Pelosi (Bruins)","Centre responsable utilisé dans toutes les situations"],513  faiblesses:["Production U17 modeste (22 pts) et -23","Fourchette 25e-42e"],514  comparableLNH:"n.d.", projectionPlafond:"Centre de soutien", radar:null,515  analyse:"Fourchette large (25e chez Daily Faceoff, 42e chez Tankathon) : le profil « identité » séduit certains recruteurs plus que d'autres."},516 {id:"johnsson", nom:"Douglas Johnsson", position:"D", tir:"D", taille:"5'10\"", tailleCm:178, poids:163, naissance:"2009-07-01", nationalite:"SWE",517  equipeActuelle:"Skellefteå AIK U20", ligue:"J20 Nationell",518  stats:{mj:12,b:3,p:9,pts:12,plusMoins:null,moy:null,arr:null}, statsLigue:"J20",519  rangsParSource:{wheeler:null,dfo:32,tank:33}, mentionWheeler:true, tendance:"stable", risque:"élevé", sleeper:false,520  forces:["Un point par match en J20 comme défenseur de 16 ans","Production « superbe à tous les niveaux » (Daily Faceoff)"],521  faiblesses:["163 lb — gabarit à construire","12 matchs J20 seulement"],522  comparableLNH:"n.d.", projectionPlafond:"Défenseur top-4 si le physique suit", radar:null,523  analyse:"Le D suédois le mieux considéré de la cuvée pour l'instant, tout juste derrière la première ronde projetée."},524 {id:"mcgregor", nom:"Kaden McGregor", position:"C", tir:"D", taille:"5'11\"", tailleCm:180, poids:181, naissance:"2009-01-30", nationalite:"CAN",525  equipeActuelle:"Petes de Peterborough", ligue:"OHL",526  stats:{mj:39,b:7,p:13,pts:20,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",527  rangsParSource:{wheeler:null,tank:35}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,528  forces:["Outillage offensif au-dessus de sa production"], faiblesses:["20 points en 39 matchs — doit produire"],529  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,530  analyse:"Fiche allégée — données limitées (source de classement unique)."},531 {id:"walos", nom:"Easton Walos", position:"C", tir:"G", taille:"5'11\"", tailleCm:180, poids:174, naissance:"2008-12-28", nationalite:"USA",532  equipeActuelle:"Sting de Sarnia", ligue:"OHL",533  stats:{mj:68,b:25,p:23,pts:48,plusMoins:null,moy:null,arr:null}, statsLigue:"OHL",534  rangsParSource:{wheeler:null,tank:36}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"moyen", sleeper:false,535  forces:["25 buts comme recrue OHL"], faiblesses:["Création pour les autres plus limitée"],536  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,537  analyse:"Fiche allégée — données limitées (source de classement unique)."},538 {id:"conboy", nom:"Gunnar Conboy", position:"C", tir:"n.d.", taille:"6'04\"", tailleCm:193, poids:201, naissance:"2009-04-02", nationalite:"USA",539  equipeActuelle:"Gamblers de Green Bay", ligue:"USHL",540  stats:{mj:37,b:12,p:9,pts:21,plusMoins:null,moy:null,arr:null}, statsLigue:"USHL",541  rangsParSource:{wheeler:null,tank:37}, mentionWheeler:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false,542  forces:["Centre de 6'4\" ; seul but américain en finale du Hlinka-Gretzky 2026"], faiblesses:["Production USHL encore modeste"],543  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,544  analyse:"Fiche allégée. Son but en finale du Hlinka (8 août 2026) le met sur le radar de l'automne."},545 {id:"savin", nom:"Daniil Savin", position:"C", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:163, naissance:"2009-02-18", nationalite:"RUS",546  equipeActuelle:"Akademiya SKA St-Pétersbourg", ligue:"MHL (Russie)",547  stats:{mj:43,b:11,p:13,pts:24,plusMoins:null,moy:null,arr:null}, statsLigue:"MHL",548  rangsParSource:{wheeler:null,tank:39}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,549  forces:["Cité en mention honorable par Wheeler"], faiblesses:["Production MHL modeste"],550  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées."},551 {id:"kuukasjarvi", nom:"Roni Kuukasjärvi", position:"D", tir:"D", taille:"6'01\"", tailleCm:185, poids:165, naissance:"2009-04-08", nationalite:"FIN",552  equipeActuelle:"Ilves U20", ligue:"U20 SM-sarja",553  stats:{mj:34,b:0,p:14,pts:14,plusMoins:null,moy:null,arr:null}, statsLigue:"U20 SM-sarja",554  rangsParSource:{wheeler:null,tank:40}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,555  forces:["D droitier finlandais mobile","But gagnant du match de bronze au Hlinka 2026 (AN) + 1 passe"], faiblesses:["Aucun but en 34 matchs U20 en 2025-26"],556  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée. Son but gagnant en avantage numérique dans le match pour le bronze (13:27 de la 3e, Finlande 3-2 Slovaquie) est exactement le genre de moment qui fait apparaître un nom sur les listes d'automne."},557 {id:"sundberg", nom:"Oliver Sundberg", position:"AD", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:174, naissance:"2009-01-10", nationalite:"SWE",558  equipeActuelle:"Djurgårdens IF U18", ligue:"U18 Nationell",559  stats:{mj:18,b:10,p:19,pts:29,plusMoins:null,moy:null,arr:null}, statsLigue:"U18 (18-29 selon EP; Tankathon rapporte 22 MJ, 33 pts — fourchette)",560  rangsParSource:{wheeler:null,tank:43}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,561  forces:["Plus d'un point et demi par match au U18 suédois"], faiblesses:["Niveau J20 pas encore testé"],562  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées (les deux sources de stats divergent légèrement, fourchette affichée)."},563 {id:"sears", nom:"Finnegan Sears", position:"AG", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:187, naissance:"2009-05-04", nationalite:"USA",564  equipeActuelle:"USNTDP (U18 en 2026-27)", ligue:"NTDP/USHL",565  stats:{mj:null,b:null,p:null,pts:null,plusMoins:null,moy:null,arr:null}, statsLigue:"NTDP — ligne complète n.d.",566  rangsParSource:{wheeler:null,tank:44}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,567  forces:["Mention honorable Wheeler"], faiblesses:["Ligne statistique 2025-26 complète introuvable (n.d.)"],568  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées."},569 {id:"daley", nom:"Trevor Daley Jr.", position:"AG", tir:"n.d.", taille:"5'09\"", tailleCm:175, poids:185, naissance:"2009-06-11", nationalite:"USA",570  equipeActuelle:"Greyhounds de Soo (dès 2026-27, ex-NTDP)", ligue:"OHL",571  stats:{mj:4,b:0,p:1,pts:1,plusMoins:0,moy:null,arr:null}, statsLigue:"NTDP U17 (saison très limitée)",572  rangsParSource:{wheeler:null,tank:46}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false,573  forces:["Fils de l'ex-défenseur LNH Trevor Daley"], faiblesses:["4 matchs joués en 2025-26 — échantillon quasi nul"],574  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — saison 2025-26 très limitée, relance attendue à Soo (OHL)."},575 {id:"forsberg", nom:"Wiggo Forsberg", position:"C", tir:"n.d.", taille:"6'00\"", tailleCm:184, poids:168, naissance:"2009-06-11", nationalite:"SWE",576  equipeActuelle:"Frölunda HC U18", ligue:"U18 Nationell",577  stats:{mj:19,b:9,p:23,pts:32,plusMoins:null,moy:null,arr:null}, statsLigue:"U18 Nationell",578  rangsParSource:{wheeler:null,tank:47}, mentionWheeler:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,579  forces:["Passeur productif au U18 suédois"], faiblesses:["Niveau J20 pas encore testé"],580  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — données limitées."},581 {id:"kachlir", nom:"Lukáš Kachlíř", position:"D", tir:"D", taille:"5'08\"", tailleCm:173, poids:150, naissance:"2009-09-05", nationalite:"CZE",582  equipeActuelle:"Bílí Tygři Liberec U20", ligue:"Tchéquie U20",583  stats:{mj:29,b:6,p:21,pts:27,plusMoins:null,moy:null,arr:null}, statsLigue:"Czechia U20",584  rangsParSource:{}, mentionWheeler:true, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false,585  forces:["Wheeler : « un des meilleurs joueurs de sa cohorte »","4 points en 4 matchs au Hlinka précédent"],586  faiblesses:["5'8\", 150 lb — le plus petit joueur suivi de la cuvée; la taille limite sa projection"],587  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Aucun rang numérique : mentions seulement (Wheeler MH, DFO « also considered »)."},588 {id:"litalien", nom:"Malik L'Italien", position:"D", tir:"n.d.", taille:"n.d.", tailleCm:null, poids:null, naissance:"n.d.", nationalite:"CAN",589  equipeActuelle:"Mooseheads de Halifax", ligue:"LHJMQ",590  stats:{mj:64,b:null,p:null,pts:24,plusMoins:null,moy:null,arr:null}, statsLigue:"LHJMQ (24 pts — répartition B/P n.d.)",591  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false,592  forces:["Retenu par Équipe Canada au Hlinka 2026 (or) sans figurer sur aucun classement","1 but et 1 passe en demi-finale contre la Finlande, puis une passe sur un but en finale","24 points comme défenseur recrue LHJMQ"],593  faiblesses:["Absent de tous les classements numérotés d'été","Données physiques introuvables (n.d.)"],594  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,595  analyse:"Ajouté après le Hlinka 2026 : être choisi par Hockey Canada puis produire dans les matchs de médailles (sommaires officiels) sans être classé nulle part, c'est un profil de « riser » d'automne. Parmi les joueurs « tendance » d'Elite Prospects en août 2026."},596 /* --- Gardiens à surveiller (aucune source ne classe de gardien 2027 —597        stats réelles retrouvées dans les bases publiques le 2026-08-08) --- */598 {id:"deniger", nom:"Patrick Déniger", position:"G", tir:"n.d.", taille:"6'02\"", tailleCm:188, poids:190, naissance:"2008-10-02", nationalite:"CAN",599  equipeActuelle:"Remparts de Québec", ligue:"LHJMQ",600  stats:{mj:30,b:null,p:null,pts:null,plusMoins:null,moy:2.33,arr:0.910}, statsLigue:"LHJMQ",601  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"up", risque:"élevé", sleeper:false,602  forces:["Fiche 18-9-3, MOY 2,33 et ,910 comme recrue LHJMQ (hockeydb/chl.ca, recoupé 4 sources)","Cité par The Hockey News parmi les 5 joueurs LHJMQ à suivre pour 2027","A porté les couleurs de Canada U18 en 2025-26"],603  faiblesses:["Aucune source ne classe de gardien 2027 pour l'instant","Séries plus difficiles : 2,53 et ,902 en 10 matchs"],604  comparableLNH:"n.d.", projectionPlafond:"n.d. — les gardiens se classent tard", radar:null,605  analyse:"Le meilleur candidat québécois chez les gardiens 2027. Données retrouvées dans les bases publiques (hockeydb, chl.ca, PuckPedia, QuantHockey) alors que les classements d'été ignorent tous les gardiens."},606 {id:"vetrov", nom:"Yaroslav Vetrov", position:"G", tir:"n.d.", taille:"6'02\"", tailleCm:188, poids:183, naissance:"2009-01-12", nationalite:"RUS",607  equipeActuelle:"Sibirskie Snaipery Novosibirsk", ligue:"MHL (Russie)",608  stats:{mj:31,b:null,p:null,pts:null,plusMoins:null,moy:1.85,arr:0.919}, statsLigue:"MHL",609  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,610  forces:["MOY 1,85 et ,919 en 31 matchs (site officiel MHL)","Décrit comme « un des meilleurs gardiens de toute la MHL » (D. Griffing, juin 2026)","Play-ins : ,946 en 2 matchs"],611  faiblesses:["Facteur russe : visibilité et calendrier incertains","11e des Russes nés en 2009 selon Griffing"],612  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,613  analyse:"Statistiquement le gardien 2027 le plus dominant retrouvé — 1,85 de moyenne dans la MHL à 16-17 ans. Source : engmhl.khl.ru (575 arrêts, 51 buts contre)."},614 {id:"nikolaev", nom:"Andrei Nikolaev", position:"G", tir:"n.d.", taille:"6'04\"", tailleCm:194, poids:165, naissance:"2009-06-03", nationalite:"RUS",615  equipeActuelle:"Jr. Titans du New Jersey", ligue:"NAHL",616  stats:{mj:22,b:null,p:null,pts:null,plusMoins:null,moy:2.53,arr:0.914}, statsLigue:"NAHL",617  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,618  forces:["Gardien du mois NAHL en novembre 2025 (2,04 / ,929)","6'4\" — gabarit moderne","Engagé avec Boston University (NCAA)"],619  faiblesses:["165 lb à étoffer","Fiche divergente selon les sources (12-7-1 hockeydb vs 12-6 NAHL) — fourchette"],620  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,621  analyse:"Ligne complète reconstituée des bases publiques : 2,53 / ,914 (513 arrêts sur 561 tirs, 3 blanchissages). Orthographié « Nikolayev » chez Elite Prospects."},622 {id:"nikitins", nom:"Iļja Ņikitins", position:"G", tir:"n.d.", taille:"6'00\"", tailleCm:183, poids:171, naissance:"n.d.", nationalite:"LVA",623  equipeActuelle:"Rebels de Philadelphie", ligue:"NAHL",624  stats:{mj:40,b:null,p:null,pts:null,plusMoins:null,moy:2.85,arr:0.910}, statsLigue:"NAHL",625  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,626  forces:["40 matchs — la plus grosse charge de travail des gardiens 2027 recensés",",910 malgré une équipe faible (fiche 14-20)"],627  faiblesses:["1 seul blanchissage","Date de naissance exacte introuvable (n.d.)"],628  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,629  analyse:"Fiche allégée — source : nahl.com (2,847 / ,910). Sur le portail des gardiens 2027 d'Elite Prospects."},630 {id:"salenforsberg", nom:"Vilmer Salén Forsberg", position:"G", tir:"n.d.", taille:"6'06\"", tailleCm:197, poids:220, naissance:"2009-08-21", nationalite:"SWE",631  equipeActuelle:"Bulldogs de Brantford (dès 2026-27, ex-Södertälje)", ligue:"OHL",632  stats:{mj:18,b:null,p:null,pts:null,plusMoins:null,moy:null,arr:0.898}, statsLigue:"U18 Nationell (,898; J20 : 5 MJ, 2,48, ,890)",633  rangsParSource:{}, listeEP:true, sourceUnique:true, tendance:"stable", risque:"élevé", sleeper:false,634  forces:["6'6\" et 220 lb — le plus grand gardien de la cuvée","Signé par Brantford (OHL) pour 2026-27","A pris le filet suédois au Hlinka 2026"],635  faiblesses:["Hlinka difficile : 4,59 / ,897 en 3 matchs (Suède 7e)","Chiffres U18/J20 encore modestes"],636  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null,637  analyse:"Le pari physique chez les gardiens 2027. Son passage dans l'OHL le mettra sous les radars nord-américains dès octobre."},638 {id:"kokkonen", nom:"Lenni Kokkonen", position:"D", tir:"D", taille:"6'02\"", tailleCm:189, poids:190, naissance:"2009-03-25", nationalite:"FIN",639  equipeActuelle:"Kärpät U20", ligue:"U20 SM-sarja",640  stats:{mj:27,b:0,p:4,pts:4,plusMoins:null,moy:null,arr:null}, statsLigue:"U20 SM-sarja",641  rangsParSource:{}, mentionDfo:true, tendance:"stable", risque:"élevé", sleeper:false,642  forces:["Profil défensif pur cité par Daily Faceoff","3 passes au Hlinka 2026 (2 en demi-finale contre le Canada, 1 au match de bronze victorieux)"], faiblesses:["4 points en 27 matchs U20 en 2025-26"],643  comparableLNH:"n.d.", projectionPlafond:"n.d.", radar:null, analyse:"Fiche allégée — mention « also considered » de Daily Faceoff, mais 5 points en 3 matchs au tableau du Hlinka (22e pointeur) pour un défenseur « défensif » : à resuivre à l'automne. Médaillé de bronze."},644];645646/* ============================================================647   CONSENSUS — moyenne pondérée des rangs numériques, écart-type648   échantillonnal (volatil si > 8), calculés au chargement.649   ============================================================ */650/* Ajustements Coupe Hlinka-Gretzky 2026 (Edmonton, 3-8 août — terminée le651   jour de la génération). Performances individuelles SOURCÉES seulement,652   bornées à ±3 rangs, appliquées à la moyenne pondérée et affichées dans la653   fiche (rang brut → rang ajusté). Aucun malus individuel : aucun fait654   négatif individuel sourcé pour les joueurs de la banque. */655const AJUSTEMENTS_HLINKA = {656  dupont:   {aj:-1.0, fait:"Capitaine du Canada médaillé d'or; 1 but en demi-finale puis 4 passes en finale (sommaire officiel hlinkagretzkycup.ca — Sportsnet en rapportait 3 par erreur), meneur du match pour l'or", source:"Sommaires officiels hlinkagretzkycup.ca (matchs 5722/5726) · TSN/PC, 2026-08-08"},657  joseph:   {aj:+1.0, fait:"Or comme assistant-capitaine, mais production discrète pour son statut de no 2 : 1B-2P en 4 matchs — 43e pointeur du tournoi et 9e de son équipe, derrière Stroeder (8), Wycisk (8), Schultz (7), Veitch (6), Pue (6), Edgar (5), Cripps (5) et DuPont (4)", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"},658  england:  {aj:-1.5, fait:"2B-1P au tableau officiel (4 matchs) puis 2 buts dans la finale gagnée 8-1 contre les États-Unis", source:"Elite Prospects · TSN/PC · Sportsnet, 2026-08-08"},659  sundstrom:{aj:-1.0, fait:"2B-3P en 3 matchs (1,67 pt/match) dont le but en prolongation contre la Slovaquie; désigné meilleur joueur de la Suède au tournoi", source:"Elite Prospects · Daily Faceoff (jour 3), 2026-08-06/08"},660  wycisk:   {aj:-2.0, fait:"4e pointeur du tournoi (8 pts au tableau) : 1B-3P en demi-finale contre la Finlande puis 1B-1P en finale (passe sur le 2e but d'England + but à 12:15 de la 3e)", source:"Sommaires officiels hlinkagretzkycup.ca · Elite Prospects · CHL.ca, 2026-08-08"},661  edgar:    {aj:-1.0, fait:"3B-2P en 4 matchs — 19e pointeur du tournoi et 6e de l'équipe canadienne", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"},662  cripps:   {aj:-0.5, fait:"1B-4P en 4 matchs — meilleur pointeur des défenseurs canadiens (devant DuPont au tableau officiel)", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"},663  neuenschwander:{aj:-1.0, fait:"3B-3P en 4 matchs — 13e pointeur du tournoi avec la Suisse", source:"Elite Prospects (stats officielles 2026-27), consulté 2026-08-08"},664  conboy:   {aj:-0.5, fait:"1 passe en demi-finale puis le seul but américain de la finale (avantage numérique) — nommé joueur du match des États-Unis", source:"Sommaires officiels hlinkagretzkycup.ca · USA Hockey · TSN/PC, 2026-08-08"},665  santala:  {aj:-0.5, fait:"Fort dans les matchs de médailles : 1 passe en demi-finale contre le Canada puis 1B-1P dans la victoire de bronze de la Finlande (3-2 vs Slovaquie)", source:"Sommaires officiels hlinkagretzkycup.ca (matchs 5722/5724), 2026-08-08"},666  kuukasjarvi:{aj:-0.5, fait:"But GAGNANT du match pour la médaille de bronze (avantage numérique, 13:27 de la 3e) plus une passe sur le but de Santala", source:"Sommaire officiel hlinkagretzkycup.ca (match 5724), 2026-08-08"},667};668ESPOIRS.forEach(e => {669  const rangs = SOURCES.filter(s => Number.isFinite(e.rangsParSource[s.cle]));670  e.hlinka = AJUSTEMENTS_HLINKA[e.id] || null;671  if (rangs.length === 0) { e.rangConsensus = null; e.rangConsensusBrut = null; e.ecartType = null; e.volatil = false; return; }672  const poidsTotal = rangs.reduce((a,s)=>a+s.poids,0);673  e.rangConsensusBrut = rangs.reduce((a,s)=>a + s.poids*e.rangsParSource[s.cle],0) / poidsTotal;674  e.rangConsensus = Math.max(1, e.rangConsensusBrut + (e.hlinka ? e.hlinka.aj : 0));675  const vals = rangs.map(s=>e.rangsParSource[s.cle]);676  if (vals.length >= 2) {677    const m = vals.reduce((a,b)=>a+b,0)/vals.length;678    e.ecartType = Math.sqrt(vals.reduce((a,v)=>a+(v-m)*(v-m),0)/(vals.length-1));679  } else { e.ecartType = null; e.sourceUnique = true; }680  e.volatil = e.ecartType !== null && e.ecartType > 8;681  e.fourchette = [Math.min(...vals), Math.max(...vals)];682});683const parId = Object.fromEntries(ESPOIRS.map(e=>[e.id,e]));684685/* Tableau éditorial : ordre de sélection des joueurs (choix 1 → 32).686   Suit le consensus, ajusté par les besoins organisationnels (Phase E). */687const ORDRE_EDITORIAL = ["dupont","privalov","joseph","meyer","skvortsov","england","sundstrom","nelson","zhilkin","jacobson","neuenschwander","yakunin","cripps","pustovoy","kazda","santala","tomek","fitzhenry","meijer","shtyrkhunov","davidson","gutierrez","harper","tait","calce","glance","gordoncarroll","edgar","eshkawkogan","eklundaspe","hartl","wycisk"];688689/* Logique de chaque choix pour l'ORDRE DE BASE (pré-loterie) + plans B. */690const LOGIQUES_BASE = {691  1:{j:"dupont", txt:"Pire fiche 2025-26, Vancouver a besoin d'un joueur de concession : DuPont est le no 1 quasi unanime et le pool des Canucks manque justement de quantité et d'élite. Meilleur joueur disponible et besoin parfaitement alignés.", b:["joseph","privalov"]},692  2:{j:"privalov", txt:"La meilleure banque de la LNH (Wheeler) peut absorber le plus grand risque de la cuvée : Privalov, talent de top-2 (2e chez Daily Faceoff et Tankathon), passe devant Joseph dans notre consensus ajusté après le Hlinka discret de ce dernier. Son contrat KHL jusqu'en 2030 est exactement le pari de luxe qu'une organisation qui regorge d'espoirs peut se permettre.", b:["joseph","meyer"]},693  3:{j:"joseph", txt:"Les Rangers manquent de centres offensifs d'élite : Joseph, centre de 6'4\" point-par-match comme recrue de 16 ans dans la LHJMQ, reste un talent de top-2 sur papier. Son Hlinka discret (1B-2P en 4 matchs, 43e pointeur) le fait glisser d'un rang dans le consensus ajusté — au 3e rang, c'est la valeur qui rencontre le besoin.", b:["meyer","skvortsov"]},694  4:{j:"meyer", txt:"Calgary n'a pas d'espoir attaquant vedette de calibre no 1 — c'est la lacune assumée de son pool. Meyer, relancé aux Remparts de Québec, a le profil de centre offensif que Parekh et Carels attendent devant eux. Button le voyait 2e.", b:["skvortsov","sundstrom"]},695  5:{j:"skvortsov", txt:"Choix de Toronto — SANS protection depuis que les Leafs ont gagné la loterie 2026 (la victoire McKenna a levé la protection top-10, rapporté par PuckPedia). Philadelphie cherche un attaquant élite : Skvortsov est le meilleur pur talent offensif disponible, consensus 4e-6e stable — et contrairement à Privalov, sans contrat KHL long terme.", b:["sundstrom","england"]},696  6:{j:"england", txt:"Seattle prend le joueur le plus en vogue du moment : England, « meilleur patineur de la cuvée » (Wheeler), vient de marquer 2 buts dans la finale du Hlinka-Gretzky — son consensus ajusté (5,8) le place devant Sundström. Sa vitesse d'élite complète les centres cérébraux Catton et O'Brien.", b:["sundstrom","nelson"]},697  7:{j:"sundstrom", txt:"Winnipeg a vu plusieurs de ses premiers choix plafonner : Sundström, meilleur Suédois de la cuvée et désigné meilleur joueur de son équipe au Hlinka, offre le plancher bidirectionnel le plus fiable encore disponible.", b:["nelson","zhilkin"]},698  8:{j:"nelson", txt:"Choix de la Floride (via l'échange Jones/Knight, sans protection). Chicago repêche deux fois dans le top-8 et double au centre : Nelson, déjà en NCAA à Notre Dame, est l'espoir le plus mature de la cuvée — parfait pour une reconstruction qui veut accélérer.", b:["zhilkin","jacobson"]},699  9:{j:"zhilkin", txt:"San Jose a une banque pleine de défenseurs et un besoin d'ailiers marqueurs : Zhilkin, 36 buts et capitaine à Saginaw, coche la case finition ET la case caractère (100 PIM).", b:["jacobson","pustovoy"]},700  10:{j:"jacobson", txt:"Nashville a le pool le plus profond mais aucune vedette : Jacobson, meneur de la production CHL de la cuvée (85 pts), est le pari talent-pur qui manque. Le gabarit inquiète — pas à ce prix.", b:["neuenschwander","yakunin"]},701  11:{j:"neuenschwander", txt:"St. Louis n'a « pas d'espoir véritablement élite » (Wheeler) : Neuenschwander, grand centre déjà pro en Suisse, offre le plancher le plus sûr du milieu de ronde avec un plafond de top-6.", b:["yakunin","cripps"]},702  12:{j:"yakunin", txt:"Le New Jersey n'a aucun top espoir à l'attaque. Yakunin (record MHL d'assistances U17) est un grand centre passeur ; son contrat KHL jusqu'en 2031 est le risque que les Devils, bien nantis en défense et devant le filet, peuvent absorber.", b:["cripps","pustovoy"]},703  13:{j:"cripps", txt:"Les Islanders ont regarni l'attaque en 2025 ; derrière la graduation de Schaefer, un D droitier mobile comme Cripps (9e chez THN) rééquilibre la banque. Or au Mondial U17 avec 26 minutes par match.", b:["shtyrkhunov","tait"]},704  14:{j:"pustovoy", txt:"Columbus a des espoirs en défense et devant le filet (Smith, Andreyanov), moins à l'aile : Pustovoy, joueur U18 le plus productif de la MHL (62 pts, 32 buts), est le meilleur marqueur disponible.", b:["kazda","davidson"]},705  15:{j:"kazda", txt:"Détroit cherche un « game-breaker » offensif : Kazda (1re équipe des recrues USHL, 12 pts en 12 matchs internationaux avec la Slovaquie) apporte finition et robustesse. Daily Faceoff le voit 11e.", b:["santala","tomek"]},706  16:{j:"santala", txt:"Washington n'a aucun espoir légitime au centre — la lacune la plus nette de sa banque. Santala, meilleur Finlandais de la cuvée, arrive à London (OHL) : le fit besoin-joueur le plus évident de toute la ronde.", b:["tomek","fitzhenry"]},707  17:{j:"tomek", txt:"Los Angeles a un trou béant au centre. Tomek marque déjà chez les pros tchèques (13 buts en Extraliga à 17 ans) — Daily Faceoff le classe 8e ; à 17, le risque de la fourchette (8e-23e) vaut la peine pour combler LE besoin.", b:["fitzhenry","meijer"]},708  18:{j:"fitzhenry", txt:"Anaheim manque de profondeur d'élite derrière McQueen. Fitzhenry (45 pts au NTDP U17, en route vers North Dakota) redonne un centre de talent au pipeline.", b:["meijer","edgar"]},709  19:{j:"meijer", txt:"L'Utah privilégie la qualité mais manque de quantité : Meijer, 4e marqueur de la Suède championne U18 comme sous-classé et déjà passé par la SHL, ajoute un centre fiable au pool.", b:["davidson","gordoncarroll"]},710  20:{j:"shtyrkhunov", txt:"Choix d'Edmonton (conditionnel : hors top-12, il appartient à Chicago). CHI, déjà servi aux 2e et 8e rangs, peut prendre le risque long terme : Shtyrkhunov, D droitier au dossier historique en MHL, est le genre de pari qu'une banque riche s'offre.", b:["gutierrez","tait"]},711  21:{j:"davidson", txt:"Philadelphie (son propre choix) n'a pas de vedette au centre ni de gros gabarit dominant : Davidson, 30 buts et 216 lb en saison recrue WHL, répond aux deux manques d'un seul choix.", b:["gutierrez","glance"]},712  22:{j:"gutierrez", txt:"Pittsburgh a transformé sa banque à l'attaque mais cherche un espoir premium à la ligne bleue : Gutierrez, meilleur D des 2009 du NTDP, en route vers Notre Dame.", b:["harper","tait"]},713  23:{j:"harper", txt:"Boston a regarni l'attaque (Hagens) mais sa défense d'avenir est mince : Harper, 57 points comme D recrue dans l'OHL, est la meilleure valeur offensive disponible à la ligne bleue.", b:["tait","eshkawkogan"]},714  24:{j:"tait", txt:"Le pool du Minnesota s'est vidé (chute de 21 rangs chez Wheeler) : il faut du volume et des positions premium. Tait, rare D gaucher de la cuvée avec 21 minutes par match, répond au besoin structurel.", b:["eshkawkogan","edgar"]},715  25:{j:"calce", txt:"Choix de Tampa Bay (protégé top-10 — ici 25e, il est transféré à Seattle). SEA, banque déjà profonde, peut avaler la variance : Calce (6e chez THN, 45e chez Tankathon ⚡) est le billet de loterie au meilleur ratio risque-rendement de la ronde.", b:["glance","hartl"]},716  26:{j:"glance", txt:"Dallas a la banque la plus mince de la ligue à égalité : n'importe quel talent réel est un gain. Glance, 56 points avec le NTDP U18, est la production la plus sûre encore au tableau.", b:["gordoncarroll","edgar"]},717  27:{j:"gordoncarroll", txt:"Buffalo n'a « aucun véritable espoir ailier » (Wheeler) : Gordon-Carroll, presque un point par match à Medicine Hat avant sa blessure, comble précisément cette case.", b:["edgar","wycisk"]},718  28:{j:"edgar", txt:"Montréal a un espoir A- à chaque position mais rien d'élite depuis la graduation de Demidov : Edgar, l'un des plus jeunes de la cuvée (né fin juillet 2009) avec 49 pts recrue dans l'OHL, est le pari croissance du CH.", b:["hartl","wycisk"]},719  29:{j:"eshkawkogan", txt:"Choix du Colorado (protégé top-10 — ici 29e, il va à Toronto via l'échange Nicolas Roy). Derrière McKenna et Cowan, la banque des Leafs projette mal : Eshkawkogan, D droitier de 53 points dans l'OHL, relève le plancher.", b:["hartl","johnsson"]},720  30:{j:"eklundaspe", txt:"Choix de Vegas (protégé top-10 — ici 30e, il va au New Jersey via Calgary, échange Nemec). NJD n'a aucun top espoir offensif : Eklund Aspe, 6'4\" et 29 pts en 19 matchs U18, est le pari de gabarit offensif suédois.", b:["hartl","naudins"]},721  31:{j:"hartl", txt:"La Caroline excelle avec les Européens des rondes tardives : Hartl, 21 buts au U20 tchèque et présent au Hlinka, prolonge la filière qui a produit ses meilleures aubaines.", b:["wycisk","scantlebury"]},722  32:{j:"wycisk", txt:"Ottawa manque de potentiel offensif dans son pool : Wycisk sort d'un Hlinka en or (4 pts en demi-finale, but en finale) — le « riser » le plus frais du tournoi terminé la veille de ces données.", b:["scantlebury","naudins"]},723};724725/* Sleepers (écart production/rang ou momentum) et chutes (sourcées). */726const SLEEPERS = ["scantlebury","harper","naudins","yermolov","kolmakov"];727const CHUTES = [728  {id:"murata", raison:"4e de l'aperçu TSN/Button en novembre 2025 → 41e chez Tankathon à l'été 2026 après une saison de 18 points en 59 matchs à Flint (sources : TSN 2025-11-07; Tankathon 2026-07)."},729  {id:"privalov", raison:"Contrat de 4 ans signé avec le CSKA Moscou le liant à la KHL jusqu'au 1er juin 2030 — le facteur « disponibilité » évoqué par plusieurs sources comme frein à son rang réel (Complete Hockey News / S. Ellis, juin-juillet 2026)."},730  {id:"meyer", raison:"Libéré du programme national américain le 14 juillet 2026 (rapporté par Jeff Marek) ; trajectoire redirigée vers les Remparts de Québec — de 2e chez Button (nov. 2025) à 4e-6e sur les listes d'été (Daily Faceoff, 2026-07-14)."},731];732733/* ============================================================734   ORDRE DU REPÊCHAGE ET LOTERIE735   ============================================================ */736function construireOrdre(seq16){ // seq16 = ordre des 16 équipes hors séries737  return seq16.concat(ORDRE_SERIES).map((equipe,i)=>{738    const rang = i+1;739    const ech = PICKS_ECHANGES[equipe];740    let detenteur = equipe, noteCondition = null;741    if (ech) { const r = ech.resoudre(rang); detenteur = r.detenteur; noteCondition = r.note || null; }742    return {rang, equipeOriginale:equipe, detenteurActuel:detenteur, noteCondition,743            condition: ech ? ech.condition : null, transaction: ech ? ech.transaction : null, sourceEch: ech ? ech.source : null,744            joueurProjete: ORDRE_EDITORIAL[i] || null};745  });746}747/* Deux tirages pondérés sur cotes NOMINALES avec règle des 10 rangs :748   pour le choix n, seules les équipes au rang ≤ n+10 sont admissibles ;749   les points des inadmissibles sont transférés à la pire équipe admissible750   (mécanique du 1er tirage confirmée par Sportsnet ; appliquée par symétrie751   au 2e tirage, dont la LNH recalcule les cotes en direct — approximation752   documentée). */753function tirageLoterie(){754  const equipes = ORDRE_HORS_SERIES.map((eq,i)=>({eq, rang:i+1, cote:COTES_NOMINALES[i]}));755  const tirer = (pool, pick)=>{756    const eligibles = pool.filter(x=>x.rang - pick <= 10);      // remontée max 10 rangs757    const bonus = pool.filter(x=>x.rang - pick > 10).reduce((a,x)=>a+x.cote,0);758    const total = pool.reduce((a,x)=>a+x.cote,0);759    let r = Math.random()*total;760    for (const x of eligibles){761      const c = x===eligibles[0] ? x.cote + bonus : x.cote;      // transfert à la pire admissible762      r -= c; if (r<=0) return x;763    }764    return eligibles[eligibles.length-1];765  };766  const g1 = tirer(equipes, 1);767  const g2 = tirer(equipes.filter(x=>x!==g1), 2);768  const reste = ORDRE_HORS_SERIES.filter(eq=>eq!==g1.eq && eq!==g2.eq);769  return {gagnant1:g1.eq, gagnant2:g2.eq, ordre:[g1.eq, g2.eq, ...reste]};770}771772/* ============================================================773   COMPOSANTS UTILITAIRES774   ============================================================ */775const fmtRang = r => r==null ? "n.d." : (Math.round(r*10)/10).toFixed(1).replace(".", ",");776const nd = v => (v===null||v===undefined||v==="n.d.") ? "n.d." : v;777const ageAu = (naiss, ref="2027-06-30") => {778  if(!naiss || naiss==="n.d." || naiss.length<10) return null;779  const n=new Date(naiss), r=new Date(ref);780  let a=r.getFullYear()-n.getFullYear();781  if(r.getMonth()<n.getMonth()||(r.getMonth()===n.getMonth()&&r.getDate()<n.getDate())) a--;782  return a;783};784const TENDANCE = {up:{sym:"↑", coul:"var(--vert)", lib:"En hausse"}, down:{sym:"↓", coul:"var(--rouge)", lib:"En baisse"}, stable:{sym:"→", coul:"var(--texte2)", lib:"Stable"}};785786/* Vrais logos SVG des équipes (CDN officiel assets.nhle.com, variante fond787   sombre) — demande explicite de l'utilisateur. Repli : écusson stylisé788   (abréviation + couleurs) si le logo ne charge pas. */789function Ecusson({abbr, taille=38}){790  const eq = EQUIPES[abbr];791  const [erreur, setErreur] = useState(false);792  if(!erreur) return <img src={`https://assets.nhle.com/logos/nhl/svg/${abbr}_dark.svg`}793    alt={`Logo — ${eq.nom}`} title={eq.nom} width={taille} height={taille} loading="lazy"794    onError={()=>setErreur(true)} style={{flexShrink:0, display:"block", objectFit:"contain"}}/>;795  return <div role="img" aria-label={eq.nom} title={eq.nom} style={{width:taille, height:taille, borderRadius:8, flexShrink:0,796    background:`linear-gradient(135deg, ${eq.c1} 55%, ${eq.c2})`, display:"flex", alignItems:"center", justifyContent:"center",797    fontFamily:"'Barlow Condensed'", fontWeight:700, fontSize:taille*0.36, color:"#fff", textShadow:"0 1px 3px rgba(0,0,0,.6)", border:"1px solid rgba(255,255,255,.15)"}}>798    {abbr}799  </div>;800}801function Avatar({esp, taille=64}){802  const coul = COULEURS_LIGUE[esp.ligue] || "#4FC3F7";803  const initiales = esp.nom.split(" ").map(m=>m[0]).slice(0,2).join("");804  return <div role="img" aria-label={`Avatar de ${esp.nom} (initiales)`} style={{width:taille, height:taille, borderRadius:"50%", flexShrink:0,805    background:`linear-gradient(135deg, ${coul}33, ${coul}99)`, border:`2px solid ${coul}`, display:"flex", alignItems:"center", justifyContent:"center",806    fontFamily:"'Barlow Condensed'", fontWeight:700, fontSize:taille*0.34, color:"#fff"}}>{initiales}</div>;807}808function BadgeTendance({t}){809  const d = TENDANCE[t] || TENDANCE.stable;810  return <span aria-label={`Tendance : ${d.lib}`} title={`Tendance : ${d.lib}`} style={{color:d.coul, fontWeight:700, fontSize:13}}>{d.sym} <span style={{fontSize:10, fontWeight:500}}>{d.lib}</span></span>;811}812function BadgeVolatil({esp}){813  if(esp.volatil) return <span title={`Volatil : écart-type de ${fmtRang(esp.ecartType)} rangs entre les sources (fourchette ${esp.fourchette[0]}e-${esp.fourchette[1]}e)`}814    style={{color:"var(--ambre)", fontSize:11, fontWeight:600, border:"1px solid var(--ambre)", borderRadius:4, padding:"0 4px"}}>⚡ volatil</span>;815  if(esp.sourceUnique) return <span title="Classé par une seule source — incertitude élevée"816    style={{color:"var(--texte3)", fontSize:11, border:"1px solid var(--bordure)", borderRadius:4, padding:"0 4px"}}>source unique</span>;817  return null;818}819function InfoBulle({texte, children}){820  return <span tabIndex={0} title={texte} style={{borderBottom:"1px dotted var(--texte3)", cursor:"help"}}>{children}</span>;821}822function LigneStats({esp, compact}){823  const s = esp.stats;824  if(esp.position==="G") return <span className="num" style={{color:"var(--texte2)", fontSize:compact?12:13}}>825    {nd(s.mj)} MJ · MOY {s.moy==null?"n.d.":s.moy.toFixed(2)} · %Arr {s.arr==null?"n.d.":("."+Math.round(s.arr*1000))}</span>;826  if(s.pts==null) return <span style={{color:"var(--texte3)", fontSize:compact?12:13}}>stats 2025-26 : n.d.</span>;827  return <span className="num" style={{color:"var(--texte2)", fontSize:compact?12:13}}>828    {s.mj} MJ · {s.b} B · {s.p} P · <b style={{color:"var(--texte)"}}>{s.pts} PTS</b>{s.plusMoins!=null && <> · {s.plusMoins>0?"+":""}{s.plusMoins}</>}829    <span style={{color:"var(--texte3)"}}> ({esp.statsLigue}, 2025-26)</span></span>;830}831832/* Radar SVG 5 axes, échelle 20-80 (une seule série → couleur accent). */833function Radar({radar, taille=232}){834  if(!radar) return <div style={{color:"var(--texte3)", fontSize:12, padding:"16px 0"}}>Évaluation détaillée n.d. — données publiques insuffisantes.</div>;835  const axes=[["patinage","Patinage"],["sensJeu","Sens du jeu"],["tir","Tir"],["competitivite","Compétitivité"],["jeuDefensif","Jeu défensif"]];836  const c=taille/2, R=c-34;837  const pt=(i,val)=>{ const a=-Math.PI/2 + i*2*Math.PI/5; const r=R*(val-20)/60; return [c+r*Math.cos(a), c+r*Math.sin(a)]; };838  const poly=axes.map(([k],i)=>pt(i,radar[k]).join(",")).join(" ");839  return <figure style={{margin:0}}>840    <svg width={taille} height={taille} role="img" aria-label={"Graphique radar : " + axes.map(([k,l])=>`${l} ${radar[k]}`).join(", ") + " (échelle 20-80)"}>841      {[35,50,65,80].map(v=><polygon key={v} points={axes.map(([k],i)=>pt(i,v).join(",")).join(" ")} fill="none" stroke="var(--bordure)" strokeWidth="1"/>)}842      {axes.map(([k,l],i)=>{ const [x,y]=pt(i,80); return <line key={k} x1={c} y1={c} x2={x} y2={y} stroke="var(--bordure)"/>; })}843      <polygon points={poly} fill="rgba(79,195,247,.22)" stroke="var(--glace)" strokeWidth="2"/>844      {axes.map(([k],i)=>{ const [x,y]=pt(i,radar[k]); return <circle key={k} cx={x} cy={y} r="3.5" fill="var(--glace)"/>; })}845      {axes.map(([k,l],i)=>{ const [x,y]=pt(i,93); const xc=Math.max(56, Math.min(taille-56, x)); return <text key={k} x={xc} y={y} textAnchor="middle" dominantBaseline="middle" fill="var(--texte2)" fontSize="11">{l} <tspan fill="var(--glace)" fontWeight="700">{radar[k]}</tspan></text>; })}846    </svg>847    <figcaption style={{fontSize:10, color:"var(--texte3)", maxWidth:taille}}>Échelle 20-80 (style recrutement) — synthèse éditoriale des rapports publics, pas des notes officielles.</figcaption>848  </figure>;849}850851function TableRangs({esp}){852  const lignes = SOURCES.map(s=>{853    let val = esp.rangsParSource[s.cle];854    if(!Number.isFinite(val)){855      if(s.cle==="wheeler" && esp.mentionWheeler) val = "Mention honorable";856      else if(s.cle==="dfo" && esp.mentionDfo) val = "« Also considered »";857      else val = "n.c.";858    } else val = val + "e";859    return {...s, val};860  });861  return <table style={{width:"100%", borderCollapse:"collapse", fontSize:12}}>862    <caption style={{textAlign:"left", fontSize:11, color:"var(--texte3)", paddingBottom:4}}>Rangs par source (n.c. = non classé par cette source)</caption>863    <thead><tr>{["Source","Date","Rang"].map(h=><th key={h} style={{textAlign:"left", color:"var(--texte3)", fontWeight:600, padding:"3px 6px", borderBottom:"1px solid var(--bordure)"}}>{h}</th>)}</tr></thead>864    <tbody>{lignes.map(l=><tr key={l.cle}>865      <td style={{padding:"3px 6px", color:"var(--texte2)"}}>{l.nom} <span style={{color:"var(--texte3)"}}>({l.poids} %)</span></td>866      <td style={{padding:"3px 6px", color:"var(--texte3)"}} className="num">{l.date}</td>867      <td style={{padding:"3px 6px", fontWeight:600}} className="num">{l.val}</td></tr>)}868    </tbody></table>;869}870871/* ============================================================872   FICHE JOUEUR (panneau latéral)873   ============================================================ */874function Fiche({esp, onFermer, choix}){875  if(!esp) return null;876  const age = ageAu(esp.naissance);877  return <aside className="apparait" aria-label={`Fiche de ${esp.nom}`} style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:18, position:"sticky", top:12, maxHeight:"calc(100vh - 24px)", overflowY:"auto"}}>878    <div style={{display:"flex", justifyContent:"space-between", alignItems:"flex-start", gap:10}}>879      <div style={{display:"flex", gap:12, alignItems:"center"}}>880        <Avatar esp={esp} taille={62}/>881        <div>882          <h2 style={{fontSize:24, lineHeight:1.1}}>{esp.nom} <span aria-hidden="true">{DRAPEAUX[esp.nationalite]||"🏳️"}</span></h2>883          <div style={{color:"var(--texte2)", fontSize:12}}>884            {esp.position} · tir {nd(esp.tir)} · <InfoBulle texte={esp.tailleCm ? `${esp.tailleCm} cm` : "taille métrique n.d."}>{nd(esp.taille)}</InfoBulle> · {esp.poids ? esp.poids+" lb" : "poids n.d."} · {age!=null ? `${age} ans au repêchage` : "naissance n.d."}885          </div>886          <div style={{color:"var(--texte2)", fontSize:12}}>{esp.equipeActuelle} · {esp.ligue} · nationalité : {nd(esp.nationalite)}</div>887        </div>888      </div>889      <button onClick={onFermer} aria-label="Fermer la fiche" style={{background:"none", border:"1px solid var(--bordure)", color:"var(--texte2)", borderRadius:6, width:28, height:28}}>✕</button>890    </div>891    <div style={{display:"flex", gap:10, flexWrap:"wrap", margin:"10px 0", alignItems:"center"}}>892      <span style={{background:"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:6, padding:"2px 8px", fontSize:12}} className="num">893        Consensus : <b style={{color:"var(--glace)"}}>{fmtRang(esp.rangConsensus)}</b>{esp.hlinka && <span style={{color:"var(--texte3)"}}> (brut {fmtRang(esp.rangConsensusBrut)} {esp.hlinka.aj<0?"−":"+"}{Math.abs(esp.hlinka.aj).toFixed(1).replace(".",",")} Hlinka)</span>}{esp.fourchette && esp.fourchette[0]!==esp.fourchette[1] && <span style={{color:"var(--texte3)"}}> (classé entre {esp.fourchette[0]}e et {esp.fourchette[1]}e selon les sources)</span>}894      </span>895      {esp.hlinka && <span title={esp.hlinka.source} style={{background:"rgba(34,197,94,.10)", border:"1px solid var(--vert)", borderRadius:6, padding:"2px 8px", fontSize:11, color:"var(--vert)"}}>🏆 Hlinka 2026</span>}896      <BadgeTendance t={esp.tendance}/> <BadgeVolatil esp={esp}/>897      <span style={{fontSize:12, color: esp.risque==="élevé"?"var(--rouge)":esp.risque==="moyen"?"var(--ambre)":"var(--vert)"}}>Risque : {esp.risque}</span>898    </div>899    <LigneStats esp={esp}/>900    <div style={{display:"flex", justifyContent:"center", margin:"8px 0"}}><Radar radar={esp.radar}/></div>901    <TableRangs esp={esp}/>902    {esp.hlinka && <div style={{margin:"6px 0", background:"rgba(34,197,94,.08)", border:"1px solid rgba(34,197,94,.35)", borderRadius:8, padding:"6px 10px", fontSize:12}}>903      <b style={{color:"var(--vert)"}}>🏆 Coupe Hlinka-Gretzky 2026 (terminée le 8 août)&nbsp;:</b> <span style={{color:"var(--texte2)"}}>{esp.hlinka.fait}.</span>904      <span className="num" style={{color:"var(--texte2)"}}> Ajustement du consensus : <b>{esp.hlinka.aj<0?"−":"+"}{Math.abs(esp.hlinka.aj).toFixed(1).replace(".",",")} rang</b> ({fmtRang(esp.rangConsensusBrut)} → {fmtRang(esp.rangConsensus)}).</span>905      <span style={{color:"var(--texte3)"}}> Source : {esp.hlinka.source}.</span>906    </div>}907    <div style={{fontSize:10, color:"var(--texte3)", margin:"4px 0 10px"}}>Historique du consensus : n.d. — premier instantané (août 2026), aucune évolution à tracer encore.</div>908    <h3 style={{color:"var(--vert)", fontSize:15, marginTop:8}}>Forces</h3>909    <ul style={{paddingLeft:18, fontSize:13, color:"var(--texte2)"}}>{esp.forces.map((f,i)=><li key={i}>{f}</li>)}</ul>910    <h3 style={{color:"var(--rouge)", fontSize:15, marginTop:8}}>Points à améliorer</h3>911    <ul style={{paddingLeft:18, fontSize:13, color:"var(--texte2)"}}>{esp.faiblesses.map((f,i)=><li key={i}>{f}</li>)}</ul>912    <div style={{marginTop:8, fontSize:13}}><b>Comparable (style)&nbsp;:</b> <span style={{color:"var(--texte2)"}}>{esp.comparableLNH}</span></div>913    <div style={{fontSize:13}}><b>Plafond projeté&nbsp;:</b> <span style={{color:"var(--texte2)"}}>{esp.projectionPlafond}</span></div>914    {choix && <div style={{marginTop:10, background:"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:8, padding:10, fontSize:13}}>915      <b style={{color:"var(--glace)"}}>Logique du choix no {choix.rang} ({EQUIPES[choix.detenteurActuel].nom})&nbsp;:</b>916      <p style={{color:"var(--texte2)", marginTop:4}}>{choix.logique}</p>917      {choix.autresOptions && <p style={{color:"var(--texte3)", fontSize:12, marginTop:6}}>Plans B plausibles : {choix.autresOptions.map(id=>parId[id].nom).join(" · ")}</p>}918    </div>}919    <p style={{marginTop:10, fontSize:13, color:"var(--texte2)", borderLeft:"3px solid var(--glace)", paddingLeft:10}}>{esp.analyse}</p>920  </aside>;921}922923/* ============================================================924   TABLEAU DU MOCK DRAFT925   ============================================================ */926function RangeeChoix({choix, esp, selection, onSelection, apresLoterie}){927  const eq = EQUIPES[choix.detenteurActuel];928  const via = choix.detenteurActuel !== choix.equipeOriginale;929  return <div role="button" tabIndex={0} onClick={onSelection} onKeyDown={e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();onSelection();}}}930    aria-label={`Choix ${choix.rang}, ${eq.nom}${via?` via ${EQUIPES[choix.equipeOriginale].nom}`:""} : ${esp?esp.nom:"aucun joueur"}`}931    className="apparait"932    style={{display:"flex", alignItems:"center", gap:10, padding:"8px 10px", borderRadius:10, cursor:"pointer",933      background:selection?"rgba(79,195,247,.10)":"var(--panneau)", border:`1px solid ${selection?"var(--glace)":"var(--bordure)"}`, marginBottom:6}}>934    <div className="num titre" style={{width:30, textAlign:"center", fontSize:20, fontWeight:700, color: choix.rang<=3?"var(--glace)":"var(--texte2)"}}>{choix.rang}</div>935    <Ecusson abbr={choix.detenteurActuel}/>936    <div style={{minWidth:86}}>937      <div style={{fontWeight:600, fontSize:13}}>{choix.detenteurActuel}</div>938      {via && <div style={{fontSize:10, color:"var(--ambre)"}}>939        <InfoBulle texte={`${choix.condition||""} ${choix.transaction||""} (source : ${choix.sourceEch||"n.d."})`}>via {choix.equipeOriginale}</InfoBulle>940      </div>}941      {choix.noteCondition && <div style={{fontSize:10, color:"var(--ambre)"}}><InfoBulle texte={choix.noteCondition}>⚠ condition</InfoBulle></div>}942    </div>943    {esp ? <>944      <div style={{flex:1, minWidth:0}}>945        <div style={{display:"flex", gap:6, alignItems:"center", flexWrap:"wrap"}}>946          <b style={{fontSize:14}}>{esp.nom}</b>947          <span aria-hidden="true">{DRAPEAUX[esp.nationalite]||"🏳️"}</span>948          <span style={{fontSize:11, color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:4, padding:"0 4px"}}>{esp.position}</span>949          <span style={{fontSize:11, color:COULEURS_LIGUE[esp.ligue]||"var(--texte2)"}}>{esp.ligue}</span>950          <BadgeVolatil esp={esp}/>951        </div>952        <LigneStats esp={esp} compact/>953      </div>954      <BadgeTendance t={esp.tendance}/>955    </> : <div style={{flex:1, color:"var(--texte3)", fontSize:12}}>—</div>}956  </div>;957}958959/* ============================================================960   SIMULATEUR DE LOTERIE — révélation théâtrale du 16e au 1er961   ============================================================ */962function PanneauLoterie({onResultat, onReinit, historique, noSim, ordreActuel}){963  const [reveles, setReveles] = useState(null); // liste [{rang, equipe}] révélés progressivement964  const [enCours, setEnCours] = useState(false);965  const minuterie = useRef(null);966  useEffect(()=>()=>clearTimeout(minuterie.current),[]);967  const simuler = () => {968    if(enCours) return;969    const res = tirageLoterie();970    setEnCours(true); setReveles([]);971    const seq = res.ordre.map((eq,i)=>({rang:i+1, equipe:eq})).reverse(); // 16 → 1972    let i = 0;973    const etape = () => {974      i++;975      setReveles(seq.slice(0,i));976      if(i<seq.length){ minuterie.current = setTimeout(etape, seq.length-i<=3 ? 900 : 220); }977      else { setEnCours(false); onResultat(res); }978    };979    minuterie.current = setTimeout(etape, 300);980  };981  return <section aria-label="Simulateur de loterie" style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:16, marginBottom:14}}>982    <div style={{display:"flex", justifyContent:"space-between", flexWrap:"wrap", gap:8, alignItems:"center"}}>983      <h2 style={{fontSize:20}}>🎰 Simulateur de loterie <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>({LOTERIE_SOURCE})</span></h2>984      <div style={{display:"flex", gap:8}}>985        <button onClick={simuler} disabled={enCours} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:8, padding:"8px 14px", fontWeight:700, opacity:enCours?0.5:1}}>986          {enCours ? "Tirage en cours…" : "Simuler la loterie"}</button>987        <button onClick={()=>{setReveles(null); onReinit();}} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"8px 14px"}}>Réinitialiser à l'ordre de base</button>988      </div>989    </div>990    <p style={{fontSize:12, color:"var(--texte2)", margin:"6px 0"}}>Règles 2026 appliquées : 2 tirages, remontée maximale de 10 rangs (1er choix : rangs 1-11 admissibles, les 7,0 points des rangs 12-16 sont transférés à la pire équipe → {ORDRE_HORS_SERIES[0]} effectif 25,5 % ; 2e choix : rangs 1-12 admissibles). Cotes nominales officielles : {ORDRE_HORS_SERIES.map((eq,i)=>`${eq} ${COTES_NOMINALES[i].toFixed(1).replace(".",",")}`).join(" · ")} (%). Les cotes du 2e tirage sont recalculées après le 1er (approximation documentée).</p>991    {reveles && <div style={{display:"flex", flexWrap:"wrap", gap:6, marginTop:8}} aria-live="polite">992      {reveles.map(r=><div key={r.rang} className="apparait" style={{display:"flex", alignItems:"center", gap:6, background:"var(--panneau2)", border:`1px solid ${r.rang<=2?"var(--glace)":"var(--bordure)"}`, borderRadius:8, padding:"4px 8px", animation: r.rang<=2 ? "apparait .25s ease both, pulse-glace 1.6s ease 2" : undefined}}>993        <span className="num titre" style={{fontSize:16, fontWeight:700, color:r.rang<=2?"var(--glace)":"var(--texte2)"}}>{r.rang}</span>994        <Ecusson abbr={r.equipe} taille={26}/><span style={{fontSize:12}}>{r.equipe}</span>995      </div>)}996    </div>}997    {noSim>0 && <div style={{fontSize:12, color:"var(--texte3)", marginTop:8}}>998      Simulation n° {noSim} · Historique : {historique.map((h,i)=><span key={i} className="num"> [{h.gagnant1} 1er, {h.gagnant2} 2e]</span>)}999    </div>}1000  </section>;1001}10021003/* ============================================================1004   SLEEPERS ET CHUTES1005   ============================================================ */1006function SectionSleepers({onVoir}){1007  return <section aria-label="Sleepers et chutes" className="apparait" style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:16, marginBottom:14}}>1008    <h2 style={{fontSize:20, marginBottom:8}}>💎 Sleepers <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>— écart production/rang ou momentum fort</span></h2>1009    <div style={{display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(240px, 1fr))", gap:8}}>1010      {SLEEPERS.map(id=>{const e=parId[id]; return <button key={id} onClick={()=>onVoir(id)} style={{textAlign:"left", background:"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:8, padding:10, color:"var(--texte)"}}>1011        <div style={{display:"flex", gap:8, alignItems:"center"}}><Avatar esp={e} taille={34}/><div><b style={{fontSize:13}}>{e.nom}</b><div style={{fontSize:11, color:"var(--texte2)"}}>{e.position} · {e.ligue} · consensus {fmtRang(e.rangConsensus)}</div></div></div>1012        <div style={{fontSize:11, color:"var(--texte2)", marginTop:6}}>{e.analyse.length>150 ? e.analyse.slice(0,150)+"…" : e.analyse}</div>1013      </button>;})}1014    </div>1015    <h2 style={{fontSize:20, margin:"14px 0 8px"}}>📉 En chute <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>— explications factuelles sourcées</span></h2>1016    <div style={{display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(280px, 1fr))", gap:8}}>1017      {CHUTES.map(c=>{const e=parId[c.id]; return <button key={c.id} onClick={()=>onVoir(c.id)} style={{textAlign:"left", background:"var(--panneau2)", border:"1px solid rgba(239,68,68,.35)", borderRadius:8, padding:10, color:"var(--texte)"}}>1018        <div style={{display:"flex", gap:8, alignItems:"center"}}><Avatar esp={e} taille={34}/><b style={{fontSize:13}}>{e.nom} <span style={{color:"var(--rouge)"}}>↓</span></b></div>1019        <div style={{fontSize:11, color:"var(--texte2)", marginTop:6}}>{c.raison}</div>1020      </button>;})}1021    </div>1022  </section>;1023}10241025/* ============================================================1026   FILTRES / RECHERCHE / TRI1027   ============================================================ */1028const OPTIONS_TRI = [1029  {cle:"consensus", lib:"Rang consensus"}, {cle:"pts", lib:"Points"}, {cle:"ptsParMatch", lib:"Points/match"},1030  {cle:"taille", lib:"Taille"}, {cle:"age", lib:"Âge"},1031];1032function filtrerEspoirs(liste, f){1033  let r = liste;1034  if(f.recherche) r = r.filter(e=>e.nom.toLowerCase().includes(f.recherche.toLowerCase()));1035  if(f.position!=="Tous") r = r.filter(e=>e.position===f.position);1036  if(f.ligue!=="Toutes") r = r.filter(e=>e.ligue===f.ligue);1037  if(f.nationalite!=="Toutes") r = r.filter(e=>e.nationalite===f.nationalite);1038  if(f.risque!=="Tous") r = r.filter(e=>e.risque===f.risque);1039  if(f.tendance!=="Toutes") r = r.filter(e=>e.tendance===f.tendance);1040  const cmp = {1041    consensus:(a,b)=>(a.rangConsensus??999)-(b.rangConsensus??999),1042    pts:(a,b)=>(b.stats.pts??-1)-(a.stats.pts??-1),1043    ptsParMatch:(a,b)=>((b.stats.pts??0)/(b.stats.mj||1))-((a.stats.pts??0)/(a.stats.mj||1)),1044    taille:(a,b)=>(b.tailleCm??0)-(a.tailleCm??0),1045    age:(a,b)=>{const va=a.naissance&&a.naissance.length>=7?a.naissance:"9999"; const vb=b.naissance&&b.naissance.length>=7?b.naissance:"9999"; return va<vb?-1:va>vb?1:0;},1046  }[f.tri] || ((a,b)=>0);1047  return [...r].sort(cmp);1048}1049function BarreFiltres({f, setF, liste}){1050  const uniques = cle => ["Tous"==="Tous"?null:null, ...new Set(liste.map(e=>e[cle]))].filter(Boolean);1051  const sel = (label, cle, options, defaut) => <label style={{fontSize:11, color:"var(--texte2)", display:"flex", flexDirection:"column", gap:2}}>{label}1052    <select value={f[cle]} onChange={e=>setF({...f,[cle]:e.target.value})} style={{background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"5px 6px", fontSize:12}}>1053      <option>{defaut}</option>{options.map(o=><option key={o} value={o}>{o}</option>)}1054    </select></label>;1055  return <div style={{display:"flex", gap:8, flexWrap:"wrap", alignItems:"flex-end", marginBottom:10}}>1056    <label style={{fontSize:11, color:"var(--texte2)", display:"flex", flexDirection:"column", gap:2, flex:"1 1 160px"}}>Recherche1057      <input type="search" placeholder="Nom du joueur…" value={f.recherche} onChange={e=>setF({...f,recherche:e.target.value})}1058        style={{background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"5px 8px", fontSize:12}}/></label>1059    {sel("Position","position",[...new Set(liste.map(e=>e.position))],"Tous")}1060    {sel("Ligue","ligue",[...new Set(liste.map(e=>e.ligue))],"Toutes")}1061    {sel("Nationalité","nationalite",[...new Set(liste.map(e=>e.nationalite))],"Toutes")}1062    {sel("Risque","risque",["faible","moyen","élevé"],"Tous")}1063    {sel("Tendance","tendance",["up","down","stable"],"Toutes")}1064    <label style={{fontSize:11, color:"var(--texte2)", display:"flex", flexDirection:"column", gap:2}}>Tri1065      <select value={f.tri} onChange={e=>setF({...f,tri:e.target.value})} style={{background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"5px 6px", fontSize:12}}>1066        {OPTIONS_TRI.map(o=><option key={o.cle} value={o.cle}>{o.lib}</option>)}1067      </select></label>1068  </div>;1069}10701071/* ============================================================1072   API CLAUDE (Claudeception) — clé gérée par l'environnement,1073   jamais dans le code. Blocs traités par TYPE, jamais par position.1074   ============================================================ */1075async function appelClaude(messages, avecRecherche=false, maxTokens=1000){1076  const corps = {model:"claude-sonnet-4-6", max_tokens:maxTokens, messages};1077  if(avecRecherche) corps.tools = [{type:"web_search_20250305", name:"web_search"}];1078  const rep = await fetch("https://api.anthropic.com/v1/messages", {1079    method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify(corps)1080  });1081  if(!rep.ok) throw new Error(`L'API a répondu ${rep.status}`);1082  const data = await rep.json();1083  return data.content.filter(b=>b.type==="text").map(b=>b.text).join("\n");1084}1085function nettoyerJSON(txt){1086  let t = txt.trim();1087  t = t.replace(/^```json\s*/i,"").replace(/^```\s*/,"").replace(/```\s*$/,"");1088  const debut = Math.min(...["[","{"].map(c=>{const i=t.indexOf(c); return i===-1?Infinity:i;}));1089  if(Number.isFinite(debut)) t = t.slice(debut);1090  return t.trim();1091}1092function etatCompact(choix){1093  return JSON.stringify({1094    meta:{maj:META.dateDonnees, note:"ordre simulé (classement 2025-26), loterie 2027 non tenue"},1095    mock: choix.map(c=>({rang:c.rang, equipe:c.detenteurActuel, via:c.equipeOriginale!==c.detenteurActuel?c.equipeOriginale:undefined,1096      joueur:c.joueurProjete?parId[c.joueurProjete].nom:null})),1097    espoirs: ESPOIRS.filter(e=>e.rangConsensus!=null).map(e=>({nom:e.nom, pos:e.position, ligue:e.ligue, consensus:Math.round((e.rangConsensus)*10)/10, pts:e.stats.pts, mj:e.stats.mj, tendance:e.tendance, risque:e.risque}))1098  });1099}11001101/* ============================================================1102   CHAT ANALYTIQUE (repliable, bas droite)1103   ============================================================ */1104function Chat({choix}){1105  const [ouvert, setOuvert] = useState(false);1106  const [messages, setMessages] = useState([]); // {role, content} — historique complet renvoyé à chaque tour1107  const [saisie, setSaisie] = useState("");1108  const [charge, setCharge] = useState(false);1109  const [erreur, setErreur] = useState(null);1110  const bas = useRef(null);1111  useEffect(()=>{ bas.current && bas.current.scrollIntoView({behavior:"smooth"}); },[messages, charge]);1112  const envoyer = async () => {1113    const q = saisie.trim(); if(!q || charge) return;1114    setErreur(null); setSaisie("");1115    const prompteSys = `Tu es un recruteur-chef de la LNH. Réponds en français, brièvement, en te basant sur les données suivantes : ${etatCompact(choix)}. Pour toute question sur des faits récents, utilise web_search. Ne jamais inventer de statistique — dis « n.d. » si tu ne sais pas.`;1116    const nouveaux = [...messages, {role:"user", content: messages.length===0 ? prompteSys+"\n\nQuestion : "+q : q}];1117    setMessages([...messages, {role:"user", content:q, affiche:q}]);1118    setCharge(true);1119    try{1120      const texte = await appelClaude(nouveaux.map(m=>({role:m.role, content:m.content})), true, 800);1121      setMessages(m=>[...m.slice(0,-1), {role:"user", content:nouveaux[nouveaux.length-1].content, affiche:q}, {role:"assistant", content:texte, affiche:texte}]);1122    }catch(e){1123      setErreur("Échec de l'appel à l'assistant (" + e.message + "). Réessayez dans un instant — l'API n'est accessible que dans un environnement qui fournit la clé automatiquement.");1124      setMessages(m=>m.slice(0,-1));1125      setSaisie(q);1126    }finally{ setCharge(false); }1127  };1128  return <div style={{position:"fixed", right:14, bottom:14, zIndex:50, width: ouvert ? "min(380px, calc(100vw - 28px))" : "auto"}}>1129    {ouvert ? <div className="apparait" style={{background:"var(--panneau)", border:"1px solid var(--glace)", borderRadius:12, display:"flex", flexDirection:"column", height:"min(480px, 70vh)", boxShadow:"0 12px 40px rgba(0,0,0,.5)"}}>1130      <div style={{display:"flex", justifyContent:"space-between", alignItems:"center", padding:"10px 12px", borderBottom:"1px solid var(--bordure)"}}>1131        <b className="titre" style={{fontSize:16}}>💬 Recruteur-chef (IA)</b>1132        <button onClick={()=>setOuvert(false)} aria-label="Replier le chat" style={{background:"none", border:"none", color:"var(--texte2)", fontSize:16}}>▾</button>1133      </div>1134      <div style={{flex:1, overflowY:"auto", padding:12, display:"flex", flexDirection:"column", gap:8}} aria-live="polite">1135        {messages.length===0 && <div style={{fontSize:12, color:"var(--texte3)"}}>Posez une question sur le mock draft, un espoir, une équipe… L'assistant s'appuie sur les données de la plateforme et peut chercher le web pour les faits récents.</div>}1136        {messages.map((m,i)=><div key={i} style={{alignSelf:m.role==="user"?"flex-end":"flex-start", maxWidth:"85%", background:m.role==="user"?"rgba(79,195,247,.15)":"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:10, padding:"7px 10px", fontSize:13, whiteSpace:"pre-wrap"}}>{m.affiche}</div>)}1137        {charge && <div style={{fontSize:12, color:"var(--texte3)"}}>Le recruteur consulte ses listes<span className="apparait">…</span></div>}1138        {erreur && <div style={{fontSize:12, color:"var(--rouge)"}}>{erreur}</div>}1139        <div ref={bas}/>1140      </div>1141      <div style={{display:"flex", gap:6, padding:10, borderTop:"1px solid var(--bordure)"}}>1142        <input value={saisie} onChange={e=>setSaisie(e.target.value)} onKeyDown={e=>e.key==="Enter"&&envoyer()} placeholder="Votre question…" aria-label="Question au recruteur-chef"1143          style={{flex:1, background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:8, padding:"8px 10px", fontSize:13}}/>1144        <button onClick={envoyer} disabled={charge} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:8, padding:"8px 12px", fontWeight:700, opacity:charge?0.5:1}}>➤</button>1145      </div>1146    </div>1147    : <button onClick={()=>setOuvert(true)} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:24, padding:"12px 18px", fontWeight:700, boxShadow:"0 6px 24px rgba(79,195,247,.35)"}}>💬 Chat analytique</button>}1148  </div>;1149}11501151/* ============================================================1152   BOUTON « METTRE À JOUR LES DONNÉES » (web_search + JSON strict)1153   ============================================================ */1154function BoutonMaj({onFusion, onToast}){1155  const [charge, setCharge] = useState(false);1156  const [attente, setAttente] = useState(0); // anti-spam 60 s1157  useEffect(()=>{ if(attente<=0) return; const t=setTimeout(()=>setAttente(a=>a-1),1000); return ()=>clearTimeout(t); },[attente]);1158  const maj = async () => {1159    if(charge||attente>0) return;1160    setCharge(true);1161    try{1162      const texte = await appelClaude([{role:"user", content:"Trouve les classements les plus récents du repêchage LNH 2027 (NHL Entry Draft 2027) et retourne UNIQUEMENT un JSON de la forme [{\"nom\":\"Prénom Nom\",\"rangConsensus\":1,\"sourcesRecentes\":\"source (date)\"}] pour les 32 meilleurs espoirs, sans aucun texte avant ou après, sans clôture de code."}], true, 1500);1163      let liste;1164      try{ liste = JSON.parse(nettoyerJSON(texte)); }1165      catch(e){ throw new Error("réponse non analysable en JSON"); }1166      if(!Array.isArray(liste) || liste.length===0) throw new Error("liste vide ou mal formée");1167      onFusion(liste);1168      onToast({type:"succes", texte:`Données rafraîchies : ${liste.length} espoirs mis à jour (rangs et tendances fusionnés, fiches conservées).`});1169    }catch(e){1170      onToast({type:"echec", texte:"Échec de la mise à jour : " + e.message + ". Les données du 2026-08-08 restent affichées."});1171    }finally{ setCharge(false); setAttente(60); }1172  };1173  return <button onClick={maj} disabled={charge||attente>0}1174    style={{background:charge?"var(--panneau2)":"var(--glace)", color:charge?"var(--texte2)":"#04121F", border:"none", borderRadius:8, padding:"8px 14px", fontWeight:700, opacity:attente>0?0.55:1}}>1175    {charge ? "Recherche en cours…" : attente>0 ? `Mettre à jour (${attente} s)` : "⟳ Mettre à jour les données"}1176  </button>;1177}11781179/* ============================================================1180   MODE MOCK DRAFT PERSONNALISÉ — drag-and-drop + boutons ↑↓1181   (accessibilité clavier), analyse IA, export texte + image.1182   État en mémoire React uniquement (aucun localStorage).1183   ============================================================ */1184function ModePerso({choixBase, onToast}){1185  const [monOrdre, setMonOrdre] = useState(ORDRE_EDITORIAL.slice());1186  const [filtreBanque, setFiltreBanque] = useState("");1187  const [glisse, setGlisse] = useState(null); // id en cours de glissement1188  const [analyse, setAnalyse] = useState(null);1189  const [chargeAnalyse, setChargeAnalyse] = useState(false);1190  const canevas = useRef(null);1191  const banque = ESPOIRS.filter(e=>!monOrdre.includes(e.id) && e.nom.toLowerCase().includes(filtreBanque.toLowerCase()));1192  const deplacer = (i, delta) => {1193    const j = i+delta; if(j<0||j>=monOrdre.length) return;1194    const o = monOrdre.slice(); [o[i],o[j]]=[o[j],o[i]]; setMonOrdre(o);1195  };1196  const surDepot = (iCible) => {1197    if(glisse==null) return;1198    const o = monOrdre.slice();1199    const iSrc = o.indexOf(glisse);1200    if(iSrc>=0) o.splice(iSrc,1);           // réordonner1201    o.splice(iCible,0,glisse);1202    setMonOrdre(o.slice(0,32));             // garder 32 choix1203    setGlisse(null);1204  };1205  const retirer = (id) => setMonOrdre(monOrdre.filter(x=>x!==id));1206  const analyser = async () => {1207    if(chargeAnalyse) return;1208    setChargeAnalyse(true); setAnalyse(null);1209    try{1210      const mock = monOrdre.map((id,i)=>`${i+1}. ${EQUIPES[choixBase[i].detenteurActuel].nom} : ${parId[id].nom} (${parId[id].position}, consensus ${fmtRang(parId[id].rangConsensus)})`).join("\n");1211      const texte = await appelClaude([{role:"user", content:`Tu es un recruteur-chef de la LNH. Voici le mock draft 2027 d'un utilisateur (ordre d'équipes simulé sur le classement 2025-26) :\n${mock}\n\nNote ce repêchage choix par choix, en français et brièvement : pour chacun des 10 premiers choix puis en survol pour 11-32, indique accord ✅ ou désaccord ❌ avec une justification d'une phrase (besoin organisationnel vs meilleur disponible). Termine par une note globale sur 10. N'invente aucune statistique.`}], false, 1400);1212      setAnalyse(texte);1213    }catch(e){1214      setAnalyse(null);1215      onToast({type:"echec", texte:"Échec de l'analyse IA : " + e.message});1216    }finally{ setChargeAnalyse(false); }1217  };1218  const exporterTexte = () => {1219    const t = "MON MOCK DRAFT LNH 2027 — DraftVision (généré le "+META.dateGeneration+", ordre simulé)\n" +1220      monOrdre.map((id,i)=>`${String(i+1).padStart(2," ")}. ${choixBase[i].detenteurActuel} — ${parId[id].nom} (${parId[id].position}, ${parId[id].ligue})`).join("\n");1221    navigator.clipboard.writeText(t).then(1222      ()=>onToast({type:"succes", texte:"Résumé texte copié dans le presse-papiers."}),1223      ()=>onToast({type:"echec", texte:"Impossible de copier — sélectionnez le texte manuellement dans la console."}));1224  };1225  const exporterImage = () => {1226    const cv = canevas.current; const ctx = cv.getContext("2d");1227    cv.width=800; cv.height=560;1228    ctx.fillStyle="#0A0E1A"; ctx.fillRect(0,0,800,560);1229    ctx.fillStyle="#4FC3F7"; ctx.font="700 34px 'Barlow Condensed', sans-serif";1230    ctx.fillText("MON TOP-10 — MOCK DRAFT LNH 2027", 24, 48);1231    ctx.fillStyle="#93A1B8"; ctx.font="12px Inter, sans-serif";1232    ctx.fillText("DraftVision 2027 · ordre simulé (classement 2025-26) · données du "+META.dateDonnees, 24, 70);1233    monOrdre.slice(0,10).forEach((id,i)=>{1234      const e=parId[id], eq=EQUIPES[choixBase[i].detenteurActuel];1235      const y=100+i*44;1236      ctx.fillStyle=eq.c1; ctx.fillRect(24,y-24,34,34);1237      ctx.fillStyle="#fff"; ctx.font="700 13px 'Barlow Condensed'"; ctx.fillText(choixBase[i].detenteurActuel, 27, y-3);1238      ctx.fillStyle="#4FC3F7"; ctx.font="700 20px 'Barlow Condensed'"; ctx.fillText(String(i+1), 72, y);1239      ctx.fillStyle="#E5EAF2"; ctx.font="600 16px Inter"; ctx.fillText(e.nom, 104, y);1240      ctx.fillStyle="#93A1B8"; ctx.font="12px Inter"; ctx.fillText(`${e.position} · ${e.ligue}${e.stats.pts!=null?` · ${e.stats.pts} pts en ${e.stats.mj} MJ (2025-26)`:""}`, 104+ctx.measureText(e.nom).width+180<800?360:360, y);1241    });1242    const lien=document.createElement("a");1243    lien.download="mon-top10-draftvision2027.png"; lien.href=cv.toDataURL("image/png"); lien.click();1244    onToast({type:"succes", texte:"Image du top-10 téléchargée."});1245  };1246  return <section aria-label="Mode mock draft personnalisé" className="apparait" style={{background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:12, padding:16, marginBottom:14}}>1247    <div style={{display:"flex", justifyContent:"space-between", flexWrap:"wrap", gap:8, alignItems:"center", marginBottom:8}}>1248      <h2 style={{fontSize:20}}>✏️ Mon mock draft <span style={{fontSize:12, color:"var(--texte3)", fontWeight:400}}>— glisser-déposer, ou boutons ↑↓ au clavier</span></h2>1249      <div style={{display:"flex", gap:8, flexWrap:"wrap"}}>1250        <button onClick={analyser} disabled={chargeAnalyse} style={{background:"var(--glace)", color:"#04121F", border:"none", borderRadius:8, padding:"7px 12px", fontWeight:700, opacity:chargeAnalyse?0.5:1}}>{chargeAnalyse?"Analyse en cours…":"🧠 Analyser mon repêchage"}</button>1251        <button onClick={exporterTexte} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"7px 12px"}}>Copier le résumé</button>1252        <button onClick={exporterImage} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"7px 12px"}}>Image du top-10</button>1253        <button onClick={()=>setMonOrdre(ORDRE_EDITORIAL.slice())} style={{background:"none", color:"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"7px 12px"}}>Réinitialiser</button>1254      </div>1255    </div>1256    <div style={{display:"grid", gridTemplateColumns:"minmax(0,2fr) minmax(0,1fr)", gap:12}} className="grille-perso">1257      <ol style={{listStyle:"none"}} aria-label="Mes 32 choix">1258        {monOrdre.map((id,i)=>{const e=parId[id]; const c=choixBase[i]; return <li key={id} draggable1259          onDragStart={()=>setGlisse(id)} onDragOver={ev=>ev.preventDefault()} onDrop={()=>surDepot(i)}1260          style={{display:"flex", alignItems:"center", gap:8, padding:"5px 8px", marginBottom:4, background:glisse===id?"rgba(79,195,247,.12)":"var(--panneau2)", border:"1px solid var(--bordure)", borderRadius:8, cursor:"grab"}}>1261          <span className="num titre" style={{width:24, textAlign:"center", fontWeight:700, color:"var(--texte2)"}}>{i+1}</span>1262          <Ecusson abbr={c.detenteurActuel} taille={26}/>1263          <span style={{flex:1, fontSize:13}}><b>{e.nom}</b> <span style={{color:"var(--texte2)", fontSize:11}}>{e.position} · {e.ligue} · consensus {fmtRang(e.rangConsensus)}</span></span>1264          <button onClick={()=>deplacer(i,-1)} aria-label={`Monter ${e.nom}`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--texte2)", borderRadius:5, width:24, height:24}}>↑</button>1265          <button onClick={()=>deplacer(i,1)} aria-label={`Descendre ${e.nom}`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--texte2)", borderRadius:5, width:24, height:24}}>↓</button>1266          <button onClick={()=>retirer(id)} aria-label={`Retirer ${e.nom}`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--rouge)", borderRadius:5, width:24, height:24}}>✕</button>1267        </li>;})}1268      </ol>1269      <div>1270        <h3 style={{fontSize:14, marginBottom:6}}>Banque de joueurs disponibles ({banque.length})</h3>1271        <input type="search" placeholder="Filtrer la banque…" value={filtreBanque} onChange={e=>setFiltreBanque(e.target.value)} aria-label="Filtrer la banque de joueurs"1272          style={{width:"100%", background:"var(--panneau2)", color:"var(--texte)", border:"1px solid var(--bordure)", borderRadius:6, padding:"6px 8px", fontSize:12, marginBottom:6}}/>1273        <div style={{maxHeight:420, overflowY:"auto", display:"flex", flexDirection:"column", gap:4}}>1274          {banque.map(e=><div key={e.id} draggable onDragStart={()=>setGlisse(e.id)}1275            style={{display:"flex", alignItems:"center", gap:6, padding:"4px 8px", background:"var(--panneau2)", border:"1px dashed var(--bordure)", borderRadius:8, cursor:"grab", fontSize:12}}>1276            <Avatar esp={e} taille={24}/><span style={{flex:1}}>{e.nom} <span style={{color:"var(--texte3)"}}>{e.position} · consensus {fmtRang(e.rangConsensus)}</span></span>1277            <button onClick={()=>setMonOrdre([...monOrdre, e.id].slice(0,32))} aria-label={`Ajouter ${e.nom} à la fin de mon mock`} style={{background:"none", border:"1px solid var(--bordure)", color:"var(--vert)", borderRadius:5, width:22, height:22}}>+</button>1278          </div>)}1279        </div>1280      </div>1281    </div>1282    {analyse && <div className="apparait" style={{marginTop:10, background:"var(--panneau2)", border:"1px solid var(--glace)", borderRadius:8, padding:12, fontSize:13, whiteSpace:"pre-wrap", color:"var(--texte2)"}}>{analyse}</div>}1283    <canvas ref={canevas} style={{display:"none"}} aria-hidden="true"/>1284  </section>;1285}12861287/* ============================================================1288   APPLICATION1289   ============================================================ */1290function Toast({toast}){1291  if(!toast) return null;1292  return <div role="status" className="apparait" style={{position:"fixed", left:"50%", transform:"translateX(-50%)", bottom:18, zIndex:60,1293    background:toast.type==="succes"?"rgba(34,197,94,.14)":"rgba(239,68,68,.14)", border:`1px solid ${toast.type==="succes"?"var(--vert)":"var(--rouge)"}`,1294    color:"var(--texte)", borderRadius:10, padding:"10px 16px", fontSize:13, maxWidth:"min(560px, 90vw)"}}>{toast.texte}</div>;1295}12961297function App(){1298  const [ordreHS, setOrdreHS] = useState(ORDRE_HORS_SERIES);       // 16 équipes hors séries (réordonnées par loterie)1299  const [apresLoterie, setApresLoterie] = useState(false);1300  const [historique, setHistorique] = useState([]);                 // 5 dernières simulations1301  const [noSim, setNoSim] = useState(0);1302  const [selection, setSelection] = useState(null);                 // id espoir sélectionné1303  const [vue, setVue] = useState("mock");                           // mock | perso | sleepers1304  const [f, setF] = useState({recherche:"", position:"Tous", ligue:"Toutes", nationalite:"Toutes", risque:"Tous", tendance:"Toutes", tri:"consensus"});1305  const [majRangs, setMajRangs] = useState(null);                   // fusion du bouton MàJ1306  const [dateMaj, setDateMaj] = useState(META.dateDonnees);1307  const [toast, setToast] = useState(null);1308  useEffect(()=>{ if(!toast) return; const t=setTimeout(()=>setToast(null), 5000); return ()=>clearTimeout(t); },[toast]);13091310  const choix = useMemo(()=>{1311    const base = construireOrdre(ordreHS);1312    return base.map(c=>({...c, logique: apresLoterie1313      ? (c.joueurProjete ? `Ordre réorganisé par la loterie simulée — attribution recalculée : meilleur talent disponible au tableau éditorial. Banque de ${EQUIPES[c.detenteurActuel].nom} — forces : ${EQUIPES[c.detenteurActuel].banque.forces} Lacunes : ${EQUIPES[c.detenteurActuel].banque.lacunes}` : "")1314      : (LOGIQUES_BASE[c.rang] ? LOGIQUES_BASE[c.rang].txt : ""),1315      autresOptions: !apresLoterie && LOGIQUES_BASE[c.rang] ? LOGIQUES_BASE[c.rang].b : null}));1316  },[ordreHS, apresLoterie]);13171318  // Filtrage appliqué au tableau du mock (les rangées dont le joueur ne passe pas le filtre sont estompées)1319  const idsFiltres = useMemo(()=>new Set(filtrerEspoirs(ESPOIRS, f).map(e=>e.id)),[f]);1320  const espSelection = selection ? parId[selection] : null;1321  const choixSelection = espSelection ? choix.find(c=>c.joueurProjete===espSelection.id) : null;13221323  const surLoterie = (res)=>{1324    setOrdreHS(res.ordre); setApresLoterie(true); setNoSim(n=>n+1);1325    setHistorique(h=>[{gagnant1:res.gagnant1, gagnant2:res.gagnant2}, ...h].slice(0,5));1326  };1327  const surFusion = (liste)=>{1328    // Fusion intelligente : rangs/tendances mis à jour, fiches conservées.1329    let touches = 0;1330    liste.forEach(item=>{1331      const e = ESPOIRS.find(x=>x.nom.toLowerCase()===String(item.nom||"").toLowerCase());1332      if(e && Number.isFinite(item.rangConsensus)){1333        e.tendance = item.rangConsensus < (e.rangConsensus??99) - 1 ? "up" : item.rangConsensus > (e.rangConsensus??0) + 1 ? "down" : e.tendance;1334        e.rangConsensus = item.rangConsensus;1335        e.majRecente = item.sourcesRecentes || "mise à jour IA";1336        touches++;1337      }1338    });1339    setMajRangs({n:touches, quand:new Date().toISOString().slice(0,10)});1340    setDateMaj(new Date().toISOString().slice(0,10));1341  };13421343  return <div style={{maxWidth:1240, margin:"0 auto", padding:"14px 14px 80px"}}>1344    <header style={{display:"flex", justifyContent:"space-between", alignItems:"center", flexWrap:"wrap", gap:10, marginBottom:10}}>1345      <div>1346        <h1 style={{fontSize:38, lineHeight:1, color:"var(--glace)", textTransform:"uppercase"}}>DraftVision <span style={{color:"var(--texte)"}}>2027</span></h1>1347        <div style={{fontSize:12, color:"var(--texte2)"}}>Prévision de la 1re ronde du repêchage LNH 2027 · données du <b className="num">{dateMaj}</b> · générée le <span className="num">{META.dateGeneration}</span>{majRangs && <span style={{color:"var(--vert)"}}> · {majRangs.n} rangs rafraîchis via IA</span>}</div>1348      </div>1349      <BoutonMaj onFusion={surFusion} onToast={setToast}/>1350    </header>13511352    <div role="alert" style={{background:"rgba(245,158,11,.10)", border:"1px solid var(--ambre)", borderRadius:10, padding:"8px 12px", fontSize:12, color:"var(--texte2)", marginBottom:10}}>1353      ⚠️ <b style={{color:"var(--ambre)"}}>Projection, pas une prédiction :</b> la loterie 2027 n'a pas eu lieu et la saison 2026-27 n'a pas commencé — ordre basé sur le classement final 2025-26 {apresLoterie ? "+ LOTERIE SIMULÉE (fictive)" : "(pré-loterie)"} ; date/lieu du repêchage 2027 non annoncés ; classements d'espoirs « way-too-early » (mars-juillet 2026). Aucun gardien n'est classé par les sources → aucun gardien projeté. 2e ronde omise : sources insuffisantes pour 64 choix fiables.1354    </div>13551356    <nav aria-label="Sections" style={{display:"flex", gap:8, marginBottom:12, flexWrap:"wrap"}}>1357      {[["mock","📋 Mock draft"],["perso","✏️ Mode personnalisé"],["sleepers","💎 Sleepers et chutes"]].map(([v,l])=>1358        <button key={v} onClick={()=>setVue(v)} aria-pressed={vue===v}1359          style={{background:vue===v?"var(--glace)":"var(--panneau)", color:vue===v?"#04121F":"var(--texte2)", border:"1px solid var(--bordure)", borderRadius:8, padding:"8px 14px", fontWeight:600}}>{l}</button>)}1360    </nav>13611362    {vue==="mock" && <>1363      <PanneauLoterie onResultat={surLoterie} onReinit={()=>{setOrdreHS(ORDRE_HORS_SERIES); setApresLoterie(false);}} historique={historique} noSim={noSim}/>1364      <BarreFiltres f={f} setF={setF} liste={ESPOIRS}/>1365      <div style={{display:"grid", gridTemplateColumns: espSelection ? "minmax(0,1.4fr) minmax(300px,1fr)" : "1fr", gap:14}} className="grille-mock">1366        <div>1367          {choix.map(c=>{1368            const e = c.joueurProjete ? parId[c.joueurProjete] : null;1369            const passe = !e || idsFiltres.has(e.id);1370            return <div key={c.rang} style={{opacity:passe?1:0.25, transition:"opacity .2s"}}>1371              <RangeeChoix choix={c} esp={e} selection={espSelection && e && espSelection.id===e.id} onSelection={()=>e && setSelection(e.id===selection?null:e.id)} apresLoterie={apresLoterie}/>1372            </div>;})}1373          <details style={{marginTop:10, background:"var(--panneau)", border:"1px solid var(--bordure)", borderRadius:10, padding:"8px 12px"}}>1374            <summary style={{cursor:"pointer", fontSize:13, color:"var(--texte2)"}}>Hors première ronde — autres espoirs suivis ({ESPOIRS.filter(e=>!ORDRE_EDITORIAL.includes(e.id)).length})</summary>1375            <div style={{marginTop:8}}>1376              {filtrerEspoirs(ESPOIRS.filter(e=>!ORDRE_EDITORIAL.includes(e.id)), f).map(e=>1377                <div key={e.id} role="button" tabIndex={0} onClick={()=>setSelection(e.id===selection?null:e.id)} onKeyDown={ev=>{if(ev.key==="Enter"){setSelection(e.id);}}}1378                  style={{display:"flex", alignItems:"center", gap:8, padding:"5px 8px", borderRadius:8, cursor:"pointer", border:"1px solid transparent"}}>1379                  <Avatar esp={e} taille={28}/>1380                  <span style={{fontSize:13, flex:1}}><b>{e.nom}</b> <span style={{color:"var(--texte2)", fontSize:11}}>{e.position} · {e.ligue} · consensus {fmtRang(e.rangConsensus)}</span></span>1381                  <BadgeVolatil esp={e}/><BadgeTendance t={e.tendance}/>1382                </div>)}1383            </div>1384          </details>1385        </div>1386        {espSelection && <Fiche esp={espSelection} choix={choixSelection} onFermer={()=>setSelection(null)}/>}1387      </div>1388    </>}1389    {vue==="perso" && <ModePerso choixBase={choix} onToast={setToast}/>}1390    {vue==="sleepers" && <SectionSleepers onVoir={id=>{setSelection(id); setVue("mock"); window.scrollTo({top:0, behavior:"smooth"});}}/>}13911392    <footer style={{marginTop:24, borderTop:"1px solid var(--bordure)", paddingTop:14, fontSize:12, color:"var(--texte3)"}}>1393      <h3 style={{fontSize:15, color:"var(--texte2)", marginBottom:6}}>Sources consultées (pipeline du {META.dateGeneration})</h3>1394      <ul style={{paddingLeft:18, display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(320px,1fr))", gap:"2px 16px"}}>1395        {SOURCES.map(s=><li key={s.cle}>{s.nom} — {s.date} (poids {s.poids} %)</li>)}1396        <li>Statistiques : Elite Prospects Draft Center, Tankathon, NHL.com, usahockeyntdp.com, hockeydb, CHL.ca — consultés le 2026-08-08</li>1397        <li>Ordre/loterie : Daily Faceoff (avril 2026), NHL.com, ESPN (ordre du repêchage 2026)</li>1398        <li>Picks échangés : Wikipedia « 2027 NHL entry draft », PuckPedia, NHL.com, Pro Hockey Rumors — consultés le 2026-08-08</li>1399        <li>Banques d'espoirs : {BANQUE_SOURCE}</li>1400        <li>Momentum et ajustements Hlinka-Gretzky 2026 : TSN/La Presse Canadienne, Sportsnet, CHL.ca, Daily Faceoff (tournoi du 3-8 août 2026, finale Canada 8-1 USA) — ajustements bornés ±3 rangs sur le consensus, détaillés dans chaque fiche 🏆</li>1401      </ul>1402      <p style={{marginTop:8}}>Sources non publiées pour 2027 (retirées du consensus) : {SOURCES_NON_PUBLIEES.join(" · ")}.</p>1403      <p style={{marginTop:8}}>Documents compagnons : <a href="/ADMIN-REPECHAGE-2027.md">Administration du repêchage 2027 (CBA, loterie, jalons)</a> · <a href="/COULISSES-2027.txt">Coulisses 2027 — notes d'initié sourcées (contrats KHL, exode NTDP, NIL, clauses cachées)</a> · <a href="/RECHERCHE.md">Journal méthodologique du pipeline de recherche</a>.</p>1404      <p style={{marginTop:8}}>Logos d'équipes : marques officielles de la LNH et de ses clubs (servies depuis assets.nhle.com), utilisées à des fins d'identification éditoriale — site non affilié à la LNH. Aucune photo de joueur. Analyses, forces et faiblesses : synthèses originales de DraftVision. Les espoirs sont des adolescents : évaluations strictement sportives. Auteur : Simon-Pierre Boucher — contact@spboucher.ai</p>1405      <details style={{marginTop:8}}>1406        <summary style={{cursor:"pointer"}}>Avertissements méthodologiques complets</summary>1407        <ul style={{paddingLeft:18, marginTop:4}}>{META.avertissements.map((a,i)=><li key={i}>{a}</li>)}</ul>1408      </details>1409    </footer>14101411    <Chat choix={choix}/>1412    <Toast toast={toast}/>1413    <style>{`1414      @media (max-width: 900px){ .grille-mock{grid-template-columns:1fr !important;} .grille-perso{grid-template-columns:1fr !important;} }1415      @media (max-width: 768px){ h1{font-size:30px !important;} }1416    `}</style>1417  </div>;1418}1419ReactDOM.createRoot(document.getElementById("racine")).render(<App/>);1420</script>1421</body>1422</html>1423