HTML 99%
JavaScript 1%
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) :</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) :</b> <span style={{color:"var(--texte2)"}}>{esp.comparableLNH}</span></div>913 <div style={{fontSize:13}}><b>Plafond projeté :</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}) :</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