{"id":141,"date":"2026-07-16T09:04:57","date_gmt":"2026-07-16T07:04:57","guid":{"rendered":"https:\/\/berf.lultime-frisson.com\/index.php\/bureau-virtuel-episode-1\/"},"modified":"2026-07-25T07:55:50","modified_gmt":"2026-07-25T05:55:50","slug":"bureau-virtuel-episode-1","status":"publish","type":"page","link":"https:\/\/berf.lultime-frisson.com\/index.php\/bureau-virtuel-episode-1\/","title":{"rendered":"Bureau virtuel &#8211; Episode 1"},"content":{"rendered":"  <div class=\"berfdb-host\" data-berfdb-scenario=\"140\">\n    <script>\n      window.BERFDB = window.BERFDB || {};\n      window.BERFDB.BOOT = {\"scenarioId\":140,\"data\":{\"version\":1,\"mails\":{\"inbox\":[{\"id\":\"MAIL_SECURITE\",\"from_name\":\"Service securite\",\"from_email\":\"securite.interne@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Acces temporaire - protocole de chiffrement\",\"body_html\":\"<p>Agent,<\/p>\\n<p>Un acces temporaire vient de vous etre attribue sur l'environnement numerique du BERF.<\/p>\\n<p>Pour les communications emanant de la Direction, la cle de session est toujours associee au symbole du BERF.<\/p>\\n<p><strong>Indice :<\/strong> le symbole du BERF est la lanterne.<\/p>\\n<p>Service securite du BERF<\/p>\",\"date_iso\":\"2026-05-14 08:02\",\"attachments\":[],\"flags\":{\"unread\":true},\"visible_at_start\":true},{\"id\":\"MAIL_VERRIL_BRIEF\",\"from_name\":\"Verril Belhair\",\"from_email\":\"direction@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Dossier D-174 \/ priorite discrete\",\"body_html\":\"<p><strong>Message chiffre - cle requise.<\/strong><\/p>\\n<p><code>QKJYRIYV \/ XZCV-174<\/code><\/p>\\n<p>Utilisez le module Crypteur \/ Decrypteur avec la cle de session de la Direction.<\/p>\\n<hr>\\n<p><strong>Version decryptee attendue :<\/strong><\/p>\\n<p>Agent,<\/p>\\n<p>Je ne crois pas a la version officielle concernant la disparition d'Amaury Delacroix.<\/p>\\n<p>Amaury a disparu en Lozere apres avoir laisse un message vocal confus, ou il evoquait des elements inquietants \\\"au sein de l'agence\\\".<\/p>\\n<p>Votre objectif : comprendre ce qu'Amaury cherchait, determiner ce qui lui est arrive, identifier toute personne impliquee, puis me transmettre vos conclusions sous forme chiffree.<\/p>\\n<p>Ne faites confiance a personne par reflexe. Pas meme au BERF.<\/p>\\n<p><strong>Verril Belhair<\/strong><br>Directeur du BERF<\/p>\",\"date_iso\":\"2026-05-14 08:07\",\"attachments\":[{\"id\":\"PJ_ELEMENTS_ENQUETE\",\"name\":\"Les elements de l enquete.pdf\",\"type\":\"pdf\",\"url\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/plugins\/berf-desk-builder-2.10.3-bureau-epurexxx\/assets\/les-elements-de-l-enquete.pdf\"}],\"flags\":{\"unread\":true},\"visible_at_start\":true},{\"id\":\"MAIL_CLAIRE_OUTILS\",\"from_name\":\"Claire Gamerault\",\"from_email\":\"claire.gamerault@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Tes outils sont a jour\",\"body_html\":\"<p>Amaury,<\/p>\\n<p>J'ai pousse la mise a jour de ton bureau virtuel.<\/p>\\n<p>Deux rappels :<\/p>\\n<ol><li>Le module d'analyse de preuves garde les historiques de consultation, modification et suppression.<\/li><li>Seuls les profils de niveau III peuvent supprimer definitivement un indice.<\/li><\/ol>\\n<p>Donc si quelqu'un fait disparaitre un document, tu devrais encore voir une trace.<\/p>\\n<p>Pixel<\/p>\",\"date_iso\":\"2026-05-10 17:43\",\"attachments\":[],\"flags\":{\"unread\":false},\"visible_at_start\":true},{\"id\":\"MAIL_PAUL_ETUDE\",\"from_name\":\"Paul Dufort\",\"from_email\":\"paul.dufort@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Etude sur les pratiques rituelles du Gevaudan\",\"body_html\":\"<p>Amaury,<\/p>\\n<p>Comme convenu, je t'ai transmis mon etude sur les pratiques religieuses et rituelles du Gevaudan.<\/p>\\n<p>J'attire ton attention sur un passage en particulier : les temoignages concernant les \\\"Meneurs de loups\\\".<\/p>\\n<p>Dans notre metier, les legendes les plus absurdes sont parfois seulement des verites mal classees.<\/p>\\n<p>Sois prudent avec cette piste.<\/p>\\n<p>Paul<\/p>\",\"date_iso\":\"2026-05-10 14:11\",\"attachments\":[],\"flags\":{\"unread\":false},\"visible_at_start\":true},{\"id\":\"MAIL_ELENA_EMP\",\"from_name\":\"Elena Moreau\",\"from_email\":\"elena.moreau@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Analyse preliminaire - empreinte de Mirandol\",\"body_html\":\"<p>Amaury,<\/p>\\n<p>J'ai analyse la photographie et les mesures que tu m'as transmises.<\/p>\\n<p>L'empreinte ne correspond a aucun canide connu dans nos bases classiques.<\/p>\\n<p>La repartition du poids est incompatible avec une locomotion quadrupede ordinaire. La possibilite d'un deplacement bipede ne peut pas etre exclue.<\/p>\\n<p>Je veux voir le moulage original.<\/p>\\n<p>Elena<\/p>\",\"date_iso\":\"2026-05-12 18:04\",\"attachments\":[],\"flags\":{\"unread\":false},\"visible_at_start\":true},{\"id\":\"MAIL_ANONYME_RDV\",\"from_name\":\"Contact protege\",\"from_email\":\"contact.protege@8mail.com\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Chastel\",\"body_html\":\"<p>Vous cherchez depuis des annees a blanchir un nom qui n'a jamais ete le votre officiellement.<\/p>\\n<p>Vous avez raison sur un point : Jean Chastel n'etait pas le monstre que certains decrivent.<\/p>\\n<p>Vous avez tort sur un autre : ce qu'il a trahi n'a jamais disparu.<\/p>\\n<p>Jeudi. 22 h 40.<br>La ou les rails coupent la route et ou les chambres n'accueillent plus personne.<\/p>\\n<p>Venez en Chastel, pas en agent.<\/p>\",\"date_iso\":\"2026-05-13 12:16\",\"attachments\":[],\"flags\":{\"unread\":true},\"visible_at_start\":false},{\"id\":\"MAIL_VERRIL_FINAL\",\"from_name\":\"Verril Belhair\",\"from_email\":\"direction@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Rapport D-174 recu\",\"body_html\":\"<p>Agent,<\/p>\\n<p>J'ai bien recu votre rapport.<\/p>\\n<p>Vous venez de confirmer ce que je craignais : la disparition d'Amaury n'est pas un accident, et l'agence que je dirige abrite encore des zones que je ne controle pas.<\/p>\\n<p>Une derniere chose : le navigateur d'Amaury contenait un fichier cache, enregistre plusieurs jours apres sa disparition.<\/p>\\n<p>Je vous l'ouvre maintenant.<\/p>\\n<p>Verril<\/p>\",\"date_iso\":\"2026-05-14 10:42\",\"attachments\":[],\"flags\":{\"unread\":true},\"visible_at_start\":false}]},\"agenda\":{\"seed\":[{\"id\":\"AG_PAUL\",\"title\":\"Appel Paul - etude Gevaudan\",\"date\":\"2026-05-10T14:00\",\"note\":\"Paul signale un passage sur les Meneurs de loups.\",\"visible_at_start\":true},{\"id\":\"AG_MIRANDOL\",\"title\":\"Analyse empreinte\",\"date\":\"2026-05-11T18:30\",\"note\":\"Mirandol. Releve photo + mesures envoyees a Elena.\",\"visible_at_start\":true},{\"id\":\"AG_F713\",\"title\":\"Consultation archives F713\",\"date\":\"2026-05-12T09:00\",\"note\":\"Decision de justice de 1803. Georges Melonie.\",\"visible_at_start\":true},{\"id\":\"AG_RDV\",\"title\":\"Rendez-vous informateur\",\"date\":\"2026-05-13T22:40\",\"note\":\"Venir seul. Lieu non renseigne.\",\"visible_at_start\":false}],\"events\":[],\"constraints\":[]},\"triangulation\":{\"rules\":[],\"numbers\":[],\"notes\":[\"Format attendu : numero + date\/heure.\",\"Les donnees du 13\/05 autour de 22:40 sont prioritaires.\",\"Le signal d'Amaury se coupe apres le rendez-vous.\"],\"cases\":[{\"id\":\"TRI_AMAURY_2240\",\"phone\":\"0631084429\",\"agent_name\":\"Amaury Delacroix\",\"title\":\"Signal Amaury\",\"from\":\"2026-05-13T22:30\",\"to\":\"2026-05-13T22:55\",\"mode\":\"single\",\"history_message\":\"Signal perdu apres recoupement autour de l'Hotel des Ajustons.\",\"locations\":[{\"location\":\"Hotel des Ajustons, Lozere\",\"latitude\":\"44.5589\",\"longitude\":\"3.5017\",\"radius_km\":1.2}]},{\"id\":\"TRI_LEMOINE_2240\",\"phone\":\"0677138804\",\"agent_name\":\"Georges Lemoine\",\"title\":\"Signal Lemoine\",\"from\":\"2026-05-13T22:30\",\"to\":\"2026-05-13T23:10\",\"mode\":\"single\",\"history_message\":\"Presence confirmee pres de l'Hotel des Ajustons.\",\"locations\":[{\"location\":\"Hotel des Ajustons, Lozere\",\"latitude\":\"44.5589\",\"longitude\":\"3.5017\",\"radius_km\":1.2}]},{\"id\":\"TRI_PETERS_2240\",\"phone\":\"0642701963\",\"agent_name\":\"Marc Peters\",\"title\":\"Signal Peters\",\"from\":\"2026-05-13T22:30\",\"to\":\"2026-05-13T23:10\",\"mode\":\"single\",\"history_message\":\"Presence confirmee pres de l'Hotel des Ajustons.\",\"locations\":[{\"location\":\"Hotel des Ajustons, Lozere\",\"latitude\":\"44.5589\",\"longitude\":\"3.5017\",\"radius_km\":1.2}]},{\"id\":\"TRI_VALBERT_2240\",\"phone\":\"0658229140\",\"agent_name\":\"Sonia Valbert\",\"title\":\"Signal Valbert\",\"from\":\"2026-05-13T22:30\",\"to\":\"2026-05-13T23:10\",\"mode\":\"single\",\"history_message\":\"Presence confirmee pres de l'Hotel des Ajustons.\",\"locations\":[{\"location\":\"Hotel des Ajustons, Lozere\",\"latitude\":\"44.5589\",\"longitude\":\"3.5017\",\"radius_km\":1.2}]}]},\"postits\":{\"seed\":[{\"id\":\"POSTIT_CHASTEL\",\"text\":\"ScribeDargon@8mail.com\\nmdp: Yp9L57yr\\nCHASTEL ?\",\"x\":110,\"y\":130,\"color\":\"#ffef7a\"}]},\"files\":{\"seed\":[{\"id\":\"FD_BDG\",\"name\":\"La Bete du Gevaudan\",\"locked\":true,\"visible_at_start\":true,\"password\":\"CHASTEL\",\"error_message\":\"Mot de passe incorrect. Amaury aurait choisi un nom de famille.\",\"files\":[{\"id\":\"journal-sonore-notes-retranscrites\",\"label\":\"Journal sonore - notes retranscrites\",\"name\":\"Journal sonore - notes retranscrites.txt\",\"type\":\"text\",\"content\":\"AUDIO 1 - Message a Verril\\n\\nHmmm... salut Verril. C'est moi, Amaury. J'ai decouvert des trucs etranges au sein de l'agence. Si je ne rappelle pas, commence par F713.\\n\\nAUDIO 2 - Etude de Paul\\n\\nLes Meneurs de loups. Des hommes qui auraient ete capables de commander les loups. Si Jean Chastel n'avait pas tue la Bete parce qu'il etait son complice ? Et s'il l'avait tuee parce qu'il avait compris qui la tenait en laisse ?\\n\\nAUDIO 3 - F713\\n\\nDecision de justice, 1803. Georges Melonie, condamne pour sorcellerie apres l'attaque d'un village. Trois loups enormes auraient obei a sa voix.\\n\\nAUDIO 4 - Disparition de F713\\n\\nF713 a disparu. Pas archive. Pas deplace. Supprime. Quelqu'un a vu ce que je consultais.\\n\\nAUDIO 5 - Empreinte de Mirandol\\n\\nUne seule empreinte. Enorme. Une habitante dit avoir vu un animal marcher sur deux pattes.\\n\\nAUDIO 6 - Meneurs de loups\\n\\nLes archives parlent aussi d'immortalite. Si Melonie etait un Meneur de loups, sa condamnation en 1803 n'est peut-etre pas la fin de son histoire.\"},{\"id\":\"etude-paul-meneurs-de-loups\",\"label\":\"Etude Paul - Meneurs de loups\",\"name\":\"Etude Paul - Meneurs de loups.txt\",\"type\":\"text\",\"content\":\"Extrait : les Meneurs de loups seraient capables de commander des loups par la voix. Plusieurs recits du Gevaudan evoquent une Bete se comportant moins comme un animal sauvage que comme une arme dirigee.\"}]},{\"id\":\"FD_IDENTITE\",\"name\":\"Identite Amaury\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"arbre-genealogique-chastel\",\"label\":\"Arbre genealogique Chastel\",\"name\":\"Arbre genealogique Chastel.txt\",\"type\":\"text\",\"content\":\"Amaury Delacroix apparait dans une branche descendante de la famille Chastel. Le nom Delacroix correspond au nom maternel utilise dans les dossiers du BERF.\"},{\"id\":\"incendie-de-marvejols-1993\",\"label\":\"Incendie de Marvejols - 1993\",\"name\":\"Incendie de Marvejols - 1993.txt\",\"type\":\"text\",\"content\":\"Article local : la maison familiale Chastel a ete detruite par un incendie classe accident domestique. La famille a quitte la Lozere peu apres.\"}]},{\"id\":\"FD_CERCLE\",\"name\":\"Cercle des Douze\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"lettre-du-cercle-decryptee\",\"label\":\"Lettre du Cercle - decryptee\",\"name\":\"Lettre du Cercle - decryptee.txt\",\"type\":\"text\",\"content\":\"Amaury,\\n\\nTu as passe ta vie a fuir un nom que nous n'avons jamais oublie.\\n\\nChastel.\\n\\nTon ancetre nous a trahis. Il a detruit ce qui devait ouvrir la voie et a offert au peuple un heros de circonstance.\\n\\nTu as trouve Melonie. Tu as trouve F713. Tu as trouve assez pour devenir dangereux.\\n\\nMais pas assez pour comprendre ou tu mettais les pieds.\\n\\nLe Cercle ne s'ouvre pas aux curieux.\\nIl se referme sur eux.\"}]},{\"id\":\"FD_FINAL\",\"name\":\"Fichier cache Amaury\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"video-cachee-transcription\",\"label\":\"Video cachee - transcription\",\"name\":\"Video cachee - transcription.txt\",\"type\":\"text\",\"content\":\"TRANSCRIPTION VIDEO CACHEE\\n\\nL'image tremble. Amaury est assis contre un mur de pierre. Son visage est pale, couvert de terre sechee. Un bandage sale lui recouvre l'oeil gauche.\\n\\nAmaury :\\nIls ont cru que je voulais prouver l'innocence de ma famille. Au debut, c'etait vrai.\\n\\nMaintenant, je veux autre chose.\\n\\nIls ont voulu m'enterrer avec leurs secrets.\\n\\nAlors je vais ouvrir les tombes.\"}]}]},\"calculator\":{\"secrets\":[{\"id\":\"calc_genealogie_174\",\"label\":\"Archives genealogiques\",\"mode\":\"expression\",\"expression\":\"174\",\"action_type\":\"open_file_folder\",\"action_target\":\"FD_IDENTITE\",\"fail_message\":\"Aucune anomalie detectee.\",\"success_message\":\"Acces dissimule detecte : dossier genealogique restaure.\",\"repeatable\":false,\"close_after_success\":true},{\"id\":\"calc_rapport_final\",\"label\":\"Transmission rapport D-174\",\"mode\":\"expression\",\"expression\":\"F713\",\"action_type\":\"trigger_event\",\"action_target\":\"final_report_ready\",\"fail_message\":\"Le rapport attend l'ID de la preuve supprimee.\",\"success_message\":\"Rapport D-174 chiffre et transmis.\",\"repeatable\":false,\"close_after_success\":true}]},\"crypto\":{\"solutions\":[]},\"browser\":{\"tabs\":[{\"id\":\"tab_vera\",\"title\":\"Vera Investigations\",\"link\":\"vera-investigations.fr\/bete-gevaudan\",\"visible_at_start\":true,\"open_at_start\":true,\"shortcode\":\"<article class=\\\"berf-browser-doc\\\"><h2>La Bete du Gevaudan : et si le heros etait le complice ?<\/h2><p><strong>Carl Vera<\/strong><\/p><p>Jean Chastel est presente comme l'homme qui mit fin aux attaques. Mais une piste rarement citee merite attention : Georges Melonie, condamne en 1803 pour avoir mene trois loups contre un village.<\/p><p>Si Melonie n'etait pas un cas isole, alors la Bete n'etait peut-etre pas un animal. Elle etait peut-etre une arme.<\/p><\/article>\"},{\"id\":\"tab_forum_merlin\",\"title\":\"Le Nouveau Merlin\",\"link\":\"lenouveaumerlin.net\/chastel\",\"visible_at_start\":true,\"open_at_start\":false,\"shortcode\":\"<article class=\\\"berf-browser-doc\\\"><h2>Famille Chastel - heros ou imposteurs ?<\/h2><p><strong>ScribeDargon :<\/strong> Je cherche des sources fiables sur les descendants Chastel apres l'incendie de Marvejols en 1993.<\/p><p><strong>LoupGris48 :<\/strong> On disait que le fils aine avait change de nom. Delacroix peut-etre ? Nom de la mere.<\/p><\/article>\"},{\"id\":\"tab_vera_mort\",\"title\":\"48 Heures Infos\",\"link\":\"48heuresinfos.fr\/carl-vera\",\"visible_at_start\":false,\"open_at_start\":false,\"shortcode\":\"<article class=\\\"berf-browser-doc\\\"><h2>Le journaliste Carl Vera retrouve mort a son domicile<\/h2><p>Aucune trace d'effraction n'a ete relevee. Plusieurs documents de travail auraient ete saisis. Une source proche du dossier evoque la disparition d'une partie de ses archives personnelles.<\/p><\/article>\"}],\"search_rules\":[],\"logins\":[]},\"drone\":{\"access_code\":\"AJUSTONS\",\"title\":\"Surveillance D-17 \/ Hotel des Ajustons\",\"source_mode\":\"simulated\",\"live_stream_type\":\"hls\",\"live_stream_url\":\"\",\"simulated_media_type\":\"image\",\"simulated_attachment_id\":0,\"simulated_media_url\":\"\",\"status\":\"unstable\",\"autoplay\":true,\"loop\":false,\"show_hud\":true,\"show_timestamp\":true,\"notes\":\"Code d'acces derive du lieu du piege. Les images montrent Lemoine, Peters et Valbert dans la zone.\"},\"indices\":{\"seed\":[{\"id\":\"F713\",\"subscribed\":false,\"visible_at_start\":true,\"modified\":true,\"modified_by\":\"Eta005\",\"media_type\":\"\",\"attachment_id\":0,\"analysis\":\"<p><strong>Statut :<\/strong> supprime.<\/p><p>Trace residuelle : decision de justice de 1803 concernant Georges Melonie, accuse d'avoir dirige trois loups contre un village.<\/p><p>Historique : consultation Amaury Delacroix, puis consultation et modification metadata par Georges Lemoine. Suppression definitive par profil niveau III.<\/p>\"},{\"id\":\"EM044\",\"subscribed\":false,\"visible_at_start\":true,\"modified\":false,\"modified_by\":\"\",\"media_type\":\"\",\"attachment_id\":0,\"analysis\":\"<p>Empreinte de Mirandol. Morphologie proche d'un grand canide, mais appui vertical et pression du talon incompatibles avec une locomotion quadrupede ordinaire.<\/p>\"},{\"id\":\"D17A\",\"subscribed\":false,\"visible_at_start\":false,\"modified\":false,\"modified_by\":\"\",\"media_type\":\"\",\"attachment_id\":0,\"analysis\":\"<p>Drone D-17-A : Marc Peters charge un sac de toile dans un vehicule sombre. Une forme animale semble depasser de l'ouverture.<\/p>\"},{\"id\":\"D17B\",\"subscribed\":false,\"visible_at_start\":false,\"modified\":false,\"modified_by\":\"\",\"media_type\":\"\",\"attachment_id\":0,\"analysis\":\"<p>Drone D-17-B : Georges Lemoine se tient pres de l'entree de l'Hotel des Ajustons. Deux grandes formes animales restent immobiles derriere lui.<\/p>\"},{\"id\":\"D17C\",\"subscribed\":false,\"visible_at_start\":false,\"modified\":false,\"modified_by\":\"\",\"media_type\":\"\",\"attachment_id\":0,\"analysis\":\"<p>Drone D-17-C : Amaury apparait seul dans la cour. Trois silhouettes sont visibles aux fenetres du premier etage.<\/p>\"}]},\"events\":{\"rules\":[{\"id\":\"evt_brief_opened\",\"trigger_type\":\"open_mail\",\"trigger_target\":\"MAIL_VERRIL_BRIEF\",\"once\":true,\"effects\":[{\"type\":\"receive_mail\",\"target\":\"MAIL_ANONYME_RDV\",\"message\":\"Un ancien message adresse a Amaury vient d'etre restaure.\"},{\"type\":\"unlock_agenda_entry\",\"target\":\"AG_RDV\",\"message\":\"Rendez-vous restaure dans l'agenda.\"},{\"type\":\"mark_flag\",\"target\":\"briefing_lu\",\"message\":\"\"}]},{\"id\":\"evt_bdg_unlocked\",\"trigger_type\":\"unlock_file_folder\",\"trigger_target\":\"FD_BDG\",\"once\":true,\"effects\":[{\"type\":\"add_notification\",\"target\":\"F713\",\"message\":\"Indice F713 mentionne dans le journal sonore.\"},{\"type\":\"browser_unlock_tab\",\"target\":\"tab_vera_mort\",\"message\":\"Nouvel onglet navigateur disponible.\"},{\"type\":\"mark_flag\",\"target\":\"bdg_ouvert\",\"message\":\"\"}]},{\"id\":\"evt_f713_opened\",\"trigger_type\":\"open_index\",\"trigger_target\":\"F713\",\"once\":true,\"effects\":[{\"type\":\"unlock_file_folder\",\"target\":\"FD_IDENTITE\",\"message\":\"Dossier identite restaure.\"},{\"type\":\"add_notification\",\"target\":\"EM044\",\"message\":\"Le rapport d'Elena peut aider a qualifier la creature.\"},{\"type\":\"mark_flag\",\"target\":\"f713_lu\",\"message\":\"\"}]},{\"id\":\"evt_identity_opened\",\"trigger_type\":\"open_file_folder\",\"trigger_target\":\"FD_IDENTITE\",\"once\":true,\"effects\":[{\"type\":\"mark_flag\",\"target\":\"identite_amaury\",\"message\":\"\"}]},{\"id\":\"evt_tri_amaury\",\"trigger_type\":\"flag_set\",\"trigger_target\":\"f713_lu\",\"once\":true,\"effects\":[{\"type\":\"add_notification\",\"target\":\"D17A\",\"message\":\"Cherchez les numeros des suspects et testez la triangulation du 13\/05 a 22:40.\"}]},{\"id\":\"evt_drone_progress\",\"trigger_type\":\"flags_all\",\"trigger_target\":\"briefing_lu,bdg_ouvert,f713_lu,identite_amaury\",\"once\":true,\"effects\":[{\"type\":\"unlock_index\",\"target\":\"D17A\",\"message\":\"Photo drone restauree.\"},{\"type\":\"unlock_index\",\"target\":\"D17B\",\"message\":\"Photo drone restauree.\"},{\"type\":\"unlock_index\",\"target\":\"D17C\",\"message\":\"Photo drone restauree.\"},{\"type\":\"unlock_file_folder\",\"target\":\"FD_CERCLE\",\"message\":\"Lettre du Cercle restauree.\"},{\"type\":\"mark_flag\",\"target\":\"preuves_drone\",\"message\":\"\"}]},{\"id\":\"evt_final_report\",\"trigger_type\":\"calc_secret_solved\",\"trigger_target\":\"final_report_ready\",\"once\":true,\"effects\":[{\"type\":\"receive_mail\",\"target\":\"MAIL_VERRIL_FINAL\",\"message\":\"Verril a repondu au rapport D-174.\"},{\"type\":\"unlock_file_folder\",\"target\":\"FD_FINAL\",\"message\":\"Fichier cache restaure.\"},{\"type\":\"open_file_folder\",\"target\":\"FD_FINAL\",\"message\":\"\"}]}]},\"mission_registry\":{\"orders\":[],\"agents\":[]}}};\n      window.BERFDB.KB = [{\"id\":\"legend-1\",\"title\":\"Les Meneurs de loups\",\"origin\":\"France\",\"aliases\":\"charmeur de loups, conducteur de loups\",\"classification\":\"Entit\u00e9 occulte humano\u00efde\",\"threat_level\":\"Elev\u00e9e\",\"status\":\"Actif\",\"general_description\":\"Le Meneur de Loups d\u00e9signe un individu humain ayant acquis, par des moyens occultes, la capacit\u00e9 de commander et coordonner des meutes de loups sauvages. Les entit\u00e9s recens\u00e9es op\u00e8rent principalement en zones foresti\u00e8res isol\u00e9es et pr\u00e9sentent une long\u00e9vit\u00e9 anormalement \u00e9lev\u00e9e, sans signe de vieillissement.\",\"supposed_origin\":\"Les donn\u00e9es consolid\u00e9es du BERF convergent vers l\u2019hypoth\u00e8se d\u2019un pacte d\u00e9moniaque volontaire.\\n\\nCe pacte conf\u00e9rerait :\\n- Une immortalit\u00e9 fonctionnelle (absence de vieillissement et r\u00e9g\u00e9n\u00e9ration avanc\u00e9e)\\n- Une autorit\u00e9 instinctive sur les loups\",\"identified_capabilities\":\"- Commandement direct de meutes (coordination anormale des comportements)\\n- Synchronisation d\u2019attaques complexes\\n- Neutralisation de l\u2019agressivit\u00e9 animale en pr\u00e9sence du sujet\\n- R\u00e9g\u00e9n\u00e9ration rapide, y compris apr\u00e8s traumatismes s\u00e9v\u00e8res (ex : br\u00fblures)\\n- Discr\u00e9tion extr\u00eame et faible tra\u00e7abilit\u00e9 environnementale\\n- R\u00e9sistance physique sup\u00e9rieure aux standards humains\",\"activity_zones\":\"Massif Central\\nVosges\\nBretagne int\u00e9rieure\\nZones foresti\u00e8res isol\u00e9es \u00e0 faible densit\u00e9 humaine\",\"behavioral_analysis\":\"Le Meneur de Loups pr\u00e9sente un comportement structur\u00e9, non impulsif et souvent strat\u00e9gique.\\n\\nObservations :\\nS\u00e9lection non al\u00e9atoire des cibles\\nActivit\u00e9 territoriale marqu\u00e9e\\nInteraction indirecte avec les populations humaines\\n\\nHypoth\u00e8se BERF :\\nChaque individu conserve une part de volont\u00e9 propre, entra\u00eenant des comportements variables (pr\u00e9dateur, r\u00e9gulateur, observateur).\",\"internal_note\":\"\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Le-meneur-de-loups-BERF.png\",\"visibleAtStart\":true},{\"id\":\"LD-1634-POSS\",\"title\":\"Les poss\u00e9d\u00e9es de Loudun\",\"origin\":\"France\",\"aliases\":\"\",\"classification\":\"Ph\u00e9nom\u00e8ne de possession collective \/ manifestation d\u00e9moniaque pr\u00e9sum\u00e9e\",\"threat_level\":\"\u00c9lev\u00e9\",\"status\":\"Clos (\u00e9v\u00e9nement historique document\u00e9 \u2014 activit\u00e9 r\u00e9siduelle non exclue)\",\"general_description\":\"Affaire survenue entre 1632 et 1634 \u00e0 Loudun, impliquant un couvent d\u2019Ursulines dont plusieurs religieuses ont pr\u00e9sent\u00e9 des manifestations assimil\u00e9es \u00e0 des cas de possession.\\n\\n1632 : premi\u00e8res manifestations au sein du couvent \\n\u2192 troubles du comportement, visions, crises nocturnes\\n\\nLes religieuses affirment \u00eatre poss\u00e9d\u00e9es par des entit\u00e9s d\u00e9moniaques\\n\u2192 d\u00e9signent rapidement un responsable : Urbain Grandier\\n\\nD\u00e9but des exorcismes publics\\n\u2192 multiplication des crises en pr\u00e9sence de t\u00e9moins\\n\u2192 comportements extr\u00eames (convulsions, cris, blasph\u00e8mes)\\n\\n1634 : proc\u00e8s de Grandier\\n\u2192 accus\u00e9 de sorcellerie et de pacte d\u00e9moniaque\\n\u2192 condamn\u00e9 puis ex\u00e9cut\u00e9\\n\\nApr\u00e8s l\u2019ex\u00e9cution :\\n\u2192 persistance partielle des ph\u00e9nom\u00e8nes\\n\u2192 disparition progressive des manifestations\",\"supposed_origin\":\"Trois hypoth\u00e8ses principales :\\n\\n1. Origine d\u00e9moniaque r\u00e9elle\\n\\nEntit\u00e9s invoqu\u00e9es ou attir\u00e9es\\n\\nManifestations coh\u00e9rentes avec certains cas document\u00e9s\\n\\n2. Manipulation humaine\\n\\nConflits politiques et religieux\\n\\nGrandier utilis\u00e9 comme bouc \u00e9missaire\\n\\n3. Hyst\u00e9rie collective\\n\\nEffet de groupe en environnement clos\\n\\nAmplification par la mise en sc\u00e8ne publique\",\"identified_capabilities\":\"Convulsions et perte de contr\u00f4le moteur\\n\\nAlt\u00e9ration de la voix et du langage\\n\\nR\u00e9actions violentes \u00e0 des symboles religieux\\n\\nSynchronisation partielle entre plusieurs sujets\\n\\nConnaissances anormales rapport\u00e9es dans certains cas\",\"activity_zones\":\"Couvent des Ursulines de Loudun\",\"behavioral_analysis\":\"Intensit\u00e9 accrue en pr\u00e9sence d\u2019un public\\n\\nContagion comportementale observ\u00e9e\\n\\nInfluence majeure du contexte religieux\",\"internal_note\":\"\u00c0 Loudun, ce ne sont pas seulement des corps qui ont \u00e9t\u00e9 poss\u00e9d\u00e9s\u2026\\nmais une ville enti\u00e8re, par la peur, la foi\u2026 et peut-\u00eatre autre chose.\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Les-possedees-de-LOUDUN.png\",\"visibleAtStart\":true},{\"id\":\"CLB-PER-01\",\"title\":\"Lo Coulobre\",\"origin\":\"Perigord noir\",\"aliases\":\"\",\"classification\":\"Entit\u00e9 draconique aquatique\",\"threat_level\":\"Critique\",\"status\":\"Activit\u00e9 potentielle r\u00e9cente\",\"general_description\":\"Le Coulobre est une cr\u00e9ature l\u00e9gendaire du P\u00e9rigord d\u00e9crite comme un dragon serpentiforme de taille colossale, \u00e9voluant principalement dans les cours d\u2019eau profonds et cavit\u00e9s rocheuses.\\n\\nLes descriptions convergent vers une entit\u00e9 hybride pr\u00e9sentant :\\n\\n- un corps de couleuvre gigantesque\\n\\n- une m\u00e2choire massive garnie de dents\\n\\n- des excroissances cr\u00e2niennes (cornes, \u00e9pines)\\n\\n- des membres griffus et, selon certains t\u00e9moignages, des ailes\",\"supposed_origin\":\"Les archives locales et analyses BERF sugg\u00e8rent plusieurs hypoth\u00e8ses :\\n\\nHypoth\u00e8se 1 \u2014 Cr\u00e9ature relictuelle\\n\\nSurvivance d\u2019une esp\u00e8ce ancienne inconnue\\n\\nAdaptation aux milieux souterrains et aquatiques\\n\\nHypoth\u00e8se 2 \u2014 Entit\u00e9 d\u00e9moniaque\\n\\nAssimilation historique \u00e0 une manifestation du mal\\n\\nAffrontement rapport\u00e9 avec une figure religieuse (Saint Front)\\n\\nHypoth\u00e8se 3 \u2014 Entit\u00e9 territoriale li\u00e9e \u00e0 un point d\u2019ancrage\\n\\nPr\u00e9sence associ\u00e9e \u00e0 une grotte ou cavit\u00e9 inaccessible\\n\\nPossible lien avec un ph\u00e9nom\u00e8ne g\u00e9ologique ou occulte\\n\\nConclusion BERF :\\nEntit\u00e9 probablement unique ou extr\u00eamement rare, \u00e9voluant dans un territoire sp\u00e9cifique.\",\"identified_capabilities\":\"Force physique extr\u00eame (capacit\u00e9 \u00e0 renverser des embarcations)\\n\\nD\u00e9placement fluide entre eau et milieu terrestre\\n\\nAttaques rapides depuis les profondeurs\\n\\nProduction d\u2019une substance organique verd\u00e2tre \u00e0 forte odeur putride\\n\\n\u00c9mission de cris basse fr\u00e9quence perceptibles \u00e0 distance\\n\\nDiscr\u00e9tion \u00e9lev\u00e9e malgr\u00e9 sa taille (camouflage aquatique)\",\"activity_zones\":\"Vall\u00e9e de la Dordogne (P\u00e9rigord)\\n\\nSecteur historique : Saut de la Gratusse\\n\\nZones rocheuses, grottes, falaises surplombant le cours d\u2019eau\",\"behavioral_analysis\":\"Le Coulobre pr\u00e9sente un comportement territorial et opportuniste :\\n\\nAttaque des proies \u00e0 proximit\u00e9 de son domaine\\n\\nSorties ponctuelles hors de son antre pour se nourrir\\n\\nInteraction limit\u00e9e mais directe avec l\u2019activit\u00e9 humaine\",\"internal_note\":\"Si la Dordogne semble paisible en surface,\\nce n\u2019est peut-\u00eatre que parce que ce qui vit en dessous choisit de ne pas se montrer.\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Lo-Coulobre-BERF.png\",\"visibleAtStart\":true},{\"id\":\"LAV-NOC-01\",\"title\":\"Les lavandi\u00e8res de nuit\",\"origin\":\"France\",\"aliases\":\"Kannerezed Noz\",\"classification\":\"Entit\u00e9 spectrale collective\",\"threat_level\":\"\u00c9lev\u00e9 \u00e0 critique\",\"status\":\"Actif\",\"general_description\":\"Les Lavandi\u00e8res de Nuit sont des apparitions f\u00e9minines observ\u00e9es \u00e0 proximit\u00e9 de cours d\u2019eau, lavoirs abandonn\u00e9s ou zones humides isol\u00e9es, principalement durant les nuits de pleine lune.\\n\\nElles prennent l\u2019apparence de femmes pench\u00e9es sur l\u2019eau, lavant inlassablement un linge sombre. Leur comportement r\u00e9p\u00e9titif et leur apparente indiff\u00e9rence \u00e0 leur environnement masquent une nature profond\u00e9ment hostile.\",\"supposed_origin\":\"Les archives folkloriques et analyses BERF convergent vers une origine punitive :\\n\\n1. Hypoth\u00e8se principale \u2014 Ch\u00e2timent post-mortem\\n\\nFemmes condamn\u00e9es pour crimes graves\\n\\nPrincipalement infanticide (r\u00e9currence \u00e9lev\u00e9e dans les t\u00e9moignages)\\n\\nCondamnation \u00e0 une t\u00e2che \u00e9ternelle li\u00e9e \u00e0 leur crime\\n\\n2. Hypoth\u00e8se secondaire \u2014 Manifestation symbolique\\n\\nEntit\u00e9s non humaines adoptant une forme culturelle reconnaissable\\n\\nUtilisation de la culpabilit\u00e9 humaine comme ancrage\",\"identified_capabilities\":\"Apparition conditionnelle (nuit, isolement, proximit\u00e9 de l\u2019eau)\\n\\nInfluence psychologique (attirance, fascination, perte de discernement)\\n\\nInteraction physique directe possible\\n\\nForce anormale (capacit\u00e9 \u00e0 briser les os)\\n\\nAlt\u00e9ration perceptive (illusion du linge \u2192 r\u00e9alit\u00e9 organique)\\n\\nSynchronisation comportementale entre entit\u00e9s\",\"activity_zones\":\"Lavoirs abandonn\u00e9s\\n\\nBerges de rivi\u00e8res et ruisseaux\\n\\nZones rurales isol\u00e9es\",\"behavioral_analysis\":\"Les Lavandi\u00e8res pr\u00e9sentent un comportement rituel et conditionnel :\\n\\nR\u00e9p\u00e9tition constante d\u2019un acte (lavage, torsion)\\n\\nInteraction uniquement si pr\u00e9sence humaine d\u00e9tect\u00e9e\\n\\nMise \u00e0 l\u2019\u00e9preuve du t\u00e9moin (demande implicite ou explicite d\u2019aide)\\n\\nM\u00e9canisme cl\u00e9 identifi\u00e9 :\\nLa torsion du linge\\n\\nAide correcte \u2192 survie\\n\\nErreur \u2192 mort violente (fractures multiples, agonie)\",\"internal_note\":\"\u201cElles ne poursuivent pas. Elles attendent.\u201d\\n\u201cEt lorsque vous les voyez\u2026 il est d\u00e9j\u00e0 trop tard pour fuir.\u201d\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Lavandieres-de-nuit-BERF.png\",\"visibleAtStart\":true}];\n      window.BERFDB.KB_ALL = [{\"id\":\"legend-1\",\"title\":\"Les Meneurs de loups\",\"origin\":\"France\",\"aliases\":\"charmeur de loups, conducteur de loups\",\"classification\":\"Entit\u00e9 occulte humano\u00efde\",\"threat_level\":\"Elev\u00e9e\",\"status\":\"Actif\",\"general_description\":\"Le Meneur de Loups d\u00e9signe un individu humain ayant acquis, par des moyens occultes, la capacit\u00e9 de commander et coordonner des meutes de loups sauvages. Les entit\u00e9s recens\u00e9es op\u00e8rent principalement en zones foresti\u00e8res isol\u00e9es et pr\u00e9sentent une long\u00e9vit\u00e9 anormalement \u00e9lev\u00e9e, sans signe de vieillissement.\",\"supposed_origin\":\"Les donn\u00e9es consolid\u00e9es du BERF convergent vers l\u2019hypoth\u00e8se d\u2019un pacte d\u00e9moniaque volontaire.\\n\\nCe pacte conf\u00e9rerait :\\n- Une immortalit\u00e9 fonctionnelle (absence de vieillissement et r\u00e9g\u00e9n\u00e9ration avanc\u00e9e)\\n- Une autorit\u00e9 instinctive sur les loups\",\"identified_capabilities\":\"- Commandement direct de meutes (coordination anormale des comportements)\\n- Synchronisation d\u2019attaques complexes\\n- Neutralisation de l\u2019agressivit\u00e9 animale en pr\u00e9sence du sujet\\n- R\u00e9g\u00e9n\u00e9ration rapide, y compris apr\u00e8s traumatismes s\u00e9v\u00e8res (ex : br\u00fblures)\\n- Discr\u00e9tion extr\u00eame et faible tra\u00e7abilit\u00e9 environnementale\\n- R\u00e9sistance physique sup\u00e9rieure aux standards humains\",\"activity_zones\":\"Massif Central\\nVosges\\nBretagne int\u00e9rieure\\nZones foresti\u00e8res isol\u00e9es \u00e0 faible densit\u00e9 humaine\",\"behavioral_analysis\":\"Le Meneur de Loups pr\u00e9sente un comportement structur\u00e9, non impulsif et souvent strat\u00e9gique.\\n\\nObservations :\\nS\u00e9lection non al\u00e9atoire des cibles\\nActivit\u00e9 territoriale marqu\u00e9e\\nInteraction indirecte avec les populations humaines\\n\\nHypoth\u00e8se BERF :\\nChaque individu conserve une part de volont\u00e9 propre, entra\u00eenant des comportements variables (pr\u00e9dateur, r\u00e9gulateur, observateur).\",\"internal_note\":\"\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Le-meneur-de-loups-BERF.png\",\"visibleAtStart\":true},{\"id\":\"LD-1634-POSS\",\"title\":\"Les poss\u00e9d\u00e9es de Loudun\",\"origin\":\"France\",\"aliases\":\"\",\"classification\":\"Ph\u00e9nom\u00e8ne de possession collective \/ manifestation d\u00e9moniaque pr\u00e9sum\u00e9e\",\"threat_level\":\"\u00c9lev\u00e9\",\"status\":\"Clos (\u00e9v\u00e9nement historique document\u00e9 \u2014 activit\u00e9 r\u00e9siduelle non exclue)\",\"general_description\":\"Affaire survenue entre 1632 et 1634 \u00e0 Loudun, impliquant un couvent d\u2019Ursulines dont plusieurs religieuses ont pr\u00e9sent\u00e9 des manifestations assimil\u00e9es \u00e0 des cas de possession.\\n\\n1632 : premi\u00e8res manifestations au sein du couvent \\n\u2192 troubles du comportement, visions, crises nocturnes\\n\\nLes religieuses affirment \u00eatre poss\u00e9d\u00e9es par des entit\u00e9s d\u00e9moniaques\\n\u2192 d\u00e9signent rapidement un responsable : Urbain Grandier\\n\\nD\u00e9but des exorcismes publics\\n\u2192 multiplication des crises en pr\u00e9sence de t\u00e9moins\\n\u2192 comportements extr\u00eames (convulsions, cris, blasph\u00e8mes)\\n\\n1634 : proc\u00e8s de Grandier\\n\u2192 accus\u00e9 de sorcellerie et de pacte d\u00e9moniaque\\n\u2192 condamn\u00e9 puis ex\u00e9cut\u00e9\\n\\nApr\u00e8s l\u2019ex\u00e9cution :\\n\u2192 persistance partielle des ph\u00e9nom\u00e8nes\\n\u2192 disparition progressive des manifestations\",\"supposed_origin\":\"Trois hypoth\u00e8ses principales :\\n\\n1. Origine d\u00e9moniaque r\u00e9elle\\n\\nEntit\u00e9s invoqu\u00e9es ou attir\u00e9es\\n\\nManifestations coh\u00e9rentes avec certains cas document\u00e9s\\n\\n2. Manipulation humaine\\n\\nConflits politiques et religieux\\n\\nGrandier utilis\u00e9 comme bouc \u00e9missaire\\n\\n3. Hyst\u00e9rie collective\\n\\nEffet de groupe en environnement clos\\n\\nAmplification par la mise en sc\u00e8ne publique\",\"identified_capabilities\":\"Convulsions et perte de contr\u00f4le moteur\\n\\nAlt\u00e9ration de la voix et du langage\\n\\nR\u00e9actions violentes \u00e0 des symboles religieux\\n\\nSynchronisation partielle entre plusieurs sujets\\n\\nConnaissances anormales rapport\u00e9es dans certains cas\",\"activity_zones\":\"Couvent des Ursulines de Loudun\",\"behavioral_analysis\":\"Intensit\u00e9 accrue en pr\u00e9sence d\u2019un public\\n\\nContagion comportementale observ\u00e9e\\n\\nInfluence majeure du contexte religieux\",\"internal_note\":\"\u00c0 Loudun, ce ne sont pas seulement des corps qui ont \u00e9t\u00e9 poss\u00e9d\u00e9s\u2026\\nmais une ville enti\u00e8re, par la peur, la foi\u2026 et peut-\u00eatre autre chose.\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Les-possedees-de-LOUDUN.png\",\"visibleAtStart\":true},{\"id\":\"CLB-PER-01\",\"title\":\"Lo Coulobre\",\"origin\":\"Perigord noir\",\"aliases\":\"\",\"classification\":\"Entit\u00e9 draconique aquatique\",\"threat_level\":\"Critique\",\"status\":\"Activit\u00e9 potentielle r\u00e9cente\",\"general_description\":\"Le Coulobre est une cr\u00e9ature l\u00e9gendaire du P\u00e9rigord d\u00e9crite comme un dragon serpentiforme de taille colossale, \u00e9voluant principalement dans les cours d\u2019eau profonds et cavit\u00e9s rocheuses.\\n\\nLes descriptions convergent vers une entit\u00e9 hybride pr\u00e9sentant :\\n\\n- un corps de couleuvre gigantesque\\n\\n- une m\u00e2choire massive garnie de dents\\n\\n- des excroissances cr\u00e2niennes (cornes, \u00e9pines)\\n\\n- des membres griffus et, selon certains t\u00e9moignages, des ailes\",\"supposed_origin\":\"Les archives locales et analyses BERF sugg\u00e8rent plusieurs hypoth\u00e8ses :\\n\\nHypoth\u00e8se 1 \u2014 Cr\u00e9ature relictuelle\\n\\nSurvivance d\u2019une esp\u00e8ce ancienne inconnue\\n\\nAdaptation aux milieux souterrains et aquatiques\\n\\nHypoth\u00e8se 2 \u2014 Entit\u00e9 d\u00e9moniaque\\n\\nAssimilation historique \u00e0 une manifestation du mal\\n\\nAffrontement rapport\u00e9 avec une figure religieuse (Saint Front)\\n\\nHypoth\u00e8se 3 \u2014 Entit\u00e9 territoriale li\u00e9e \u00e0 un point d\u2019ancrage\\n\\nPr\u00e9sence associ\u00e9e \u00e0 une grotte ou cavit\u00e9 inaccessible\\n\\nPossible lien avec un ph\u00e9nom\u00e8ne g\u00e9ologique ou occulte\\n\\nConclusion BERF :\\nEntit\u00e9 probablement unique ou extr\u00eamement rare, \u00e9voluant dans un territoire sp\u00e9cifique.\",\"identified_capabilities\":\"Force physique extr\u00eame (capacit\u00e9 \u00e0 renverser des embarcations)\\n\\nD\u00e9placement fluide entre eau et milieu terrestre\\n\\nAttaques rapides depuis les profondeurs\\n\\nProduction d\u2019une substance organique verd\u00e2tre \u00e0 forte odeur putride\\n\\n\u00c9mission de cris basse fr\u00e9quence perceptibles \u00e0 distance\\n\\nDiscr\u00e9tion \u00e9lev\u00e9e malgr\u00e9 sa taille (camouflage aquatique)\",\"activity_zones\":\"Vall\u00e9e de la Dordogne (P\u00e9rigord)\\n\\nSecteur historique : Saut de la Gratusse\\n\\nZones rocheuses, grottes, falaises surplombant le cours d\u2019eau\",\"behavioral_analysis\":\"Le Coulobre pr\u00e9sente un comportement territorial et opportuniste :\\n\\nAttaque des proies \u00e0 proximit\u00e9 de son domaine\\n\\nSorties ponctuelles hors de son antre pour se nourrir\\n\\nInteraction limit\u00e9e mais directe avec l\u2019activit\u00e9 humaine\",\"internal_note\":\"Si la Dordogne semble paisible en surface,\\nce n\u2019est peut-\u00eatre que parce que ce qui vit en dessous choisit de ne pas se montrer.\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Lo-Coulobre-BERF.png\",\"visibleAtStart\":true},{\"id\":\"LAV-NOC-01\",\"title\":\"Les lavandi\u00e8res de nuit\",\"origin\":\"France\",\"aliases\":\"Kannerezed Noz\",\"classification\":\"Entit\u00e9 spectrale collective\",\"threat_level\":\"\u00c9lev\u00e9 \u00e0 critique\",\"status\":\"Actif\",\"general_description\":\"Les Lavandi\u00e8res de Nuit sont des apparitions f\u00e9minines observ\u00e9es \u00e0 proximit\u00e9 de cours d\u2019eau, lavoirs abandonn\u00e9s ou zones humides isol\u00e9es, principalement durant les nuits de pleine lune.\\n\\nElles prennent l\u2019apparence de femmes pench\u00e9es sur l\u2019eau, lavant inlassablement un linge sombre. Leur comportement r\u00e9p\u00e9titif et leur apparente indiff\u00e9rence \u00e0 leur environnement masquent une nature profond\u00e9ment hostile.\",\"supposed_origin\":\"Les archives folkloriques et analyses BERF convergent vers une origine punitive :\\n\\n1. Hypoth\u00e8se principale \u2014 Ch\u00e2timent post-mortem\\n\\nFemmes condamn\u00e9es pour crimes graves\\n\\nPrincipalement infanticide (r\u00e9currence \u00e9lev\u00e9e dans les t\u00e9moignages)\\n\\nCondamnation \u00e0 une t\u00e2che \u00e9ternelle li\u00e9e \u00e0 leur crime\\n\\n2. Hypoth\u00e8se secondaire \u2014 Manifestation symbolique\\n\\nEntit\u00e9s non humaines adoptant une forme culturelle reconnaissable\\n\\nUtilisation de la culpabilit\u00e9 humaine comme ancrage\",\"identified_capabilities\":\"Apparition conditionnelle (nuit, isolement, proximit\u00e9 de l\u2019eau)\\n\\nInfluence psychologique (attirance, fascination, perte de discernement)\\n\\nInteraction physique directe possible\\n\\nForce anormale (capacit\u00e9 \u00e0 briser les os)\\n\\nAlt\u00e9ration perceptive (illusion du linge \u2192 r\u00e9alit\u00e9 organique)\\n\\nSynchronisation comportementale entre entit\u00e9s\",\"activity_zones\":\"Lavoirs abandonn\u00e9s\\n\\nBerges de rivi\u00e8res et ruisseaux\\n\\nZones rurales isol\u00e9es\",\"behavioral_analysis\":\"Les Lavandi\u00e8res pr\u00e9sentent un comportement rituel et conditionnel :\\n\\nR\u00e9p\u00e9tition constante d\u2019un acte (lavage, torsion)\\n\\nInteraction uniquement si pr\u00e9sence humaine d\u00e9tect\u00e9e\\n\\nMise \u00e0 l\u2019\u00e9preuve du t\u00e9moin (demande implicite ou explicite d\u2019aide)\\n\\nM\u00e9canisme cl\u00e9 identifi\u00e9 :\\nLa torsion du linge\\n\\nAide correcte \u2192 survie\\n\\nErreur \u2192 mort violente (fractures multiples, agonie)\",\"internal_note\":\"\u201cElles ne poursuivent pas. Elles attendent.\u201d\\n\u201cEt lorsque vous les voyez\u2026 il est d\u00e9j\u00e0 trop tard pour fuir.\u201d\",\"description\":\"\",\"image\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/uploads\/2026\/03\/Lavandieres-de-nuit-BERF.png\",\"visibleAtStart\":true}];\n      window.BERFDB.BROWSER_TABS = [{\"id\":\"tab_vera\",\"title\":\"Vera Investigations\",\"link\":\"vera-investigations.fr\/bete-gevaudan\",\"visibleAtStart\":true,\"openAtStart\":true,\"html\":\"<article class=\\\"berf-browser-doc\\\"><h2>La Bete du Gevaudan : et si le heros etait le complice ?<\/h2><p><strong>Carl Vera<\/strong><\/p><p>Jean Chastel est presente comme l'homme qui mit fin aux attaques. Mais une piste rarement citee merite attention : Georges Melonie, condamne en 1803 pour avoir mene trois loups contre un village.<\/p><p>Si Melonie n'etait pas un cas isole, alors la Bete n'etait peut-etre pas un animal. Elle etait peut-etre une arme.<\/p><\/article>\",\"htmlRef\":\"berfdb-tab-html-tab_vera\"},{\"id\":\"tab_forum_merlin\",\"title\":\"Le Nouveau Merlin\",\"link\":\"lenouveaumerlin.net\/chastel\",\"visibleAtStart\":true,\"openAtStart\":false,\"html\":\"<article class=\\\"berf-browser-doc\\\"><h2>Famille Chastel - heros ou imposteurs ?<\/h2><p><strong>ScribeDargon :<\/strong> Je cherche des sources fiables sur les descendants Chastel apres l'incendie de Marvejols en 1993.<\/p><p><strong>LoupGris48 :<\/strong> On disait que le fils aine avait change de nom. Delacroix peut-etre ? Nom de la mere.<\/p><\/article>\",\"htmlRef\":\"berfdb-tab-html-tab_forum_merlin\"},{\"id\":\"tab_vera_mort\",\"title\":\"48 Heures Infos\",\"link\":\"48heuresinfos.fr\/carl-vera\",\"visibleAtStart\":false,\"openAtStart\":false,\"html\":\"<article class=\\\"berf-browser-doc\\\"><h2>Le journaliste Carl Vera retrouve mort a son domicile<\/h2><p>Aucune trace d'effraction n'a ete relevee. Plusieurs documents de travail auraient ete saisis. Une source proche du dossier evoque la disparition d'une partie de ses archives personnelles.<\/p><\/article>\",\"htmlRef\":\"berfdb-tab-html-tab_vera_mort\"}]; \n      window.BERFDB.BROWSER_SEARCH_RULES = [];\n      window.BERFDB.BROWSER_LOGINS = [];\n      window.BERFDB.INDEX_ALL = {\"F713\":{\"analysis\":\"<p><strong>Statut :<\/strong> supprime.<\/p><p>Trace residuelle : decision de justice de 1803 concernant Georges Melonie, accuse d'avoir dirige trois loups contre un village.<\/p><p>Historique : consultation Amaury Delacroix, puis consultation et modification metadata par Georges Lemoine. Suppression definitive par profil niveau III.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":true},\"EM044\":{\"analysis\":\"<p>Empreinte de Mirandol. Morphologie proche d'un grand canide, mais appui vertical et pression du talon incompatibles avec une locomotion quadrupede ordinaire.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":true},\"D17A\":{\"analysis\":\"<p>Drone D-17-A : Marc Peters charge un sac de toile dans un vehicule sombre. Une forme animale semble depasser de l'ouverture.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":false},\"D17B\":{\"analysis\":\"<p>Drone D-17-B : Georges Lemoine se tient pres de l'entree de l'Hotel des Ajustons. Deux grandes formes animales restent immobiles derriere lui.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":false},\"D17C\":{\"analysis\":\"<p>Drone D-17-C : Amaury apparait seul dans la cour. Trois silhouettes sont visibles aux fenetres du premier etage.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":false}};\n      window.BERFDB.AGENDA_ALL = [{\"id\":\"AG_PAUL\",\"title\":\"Appel Paul - etude Gevaudan\",\"date\":\"2026-05-10T14:00\",\"note\":\"Paul signale un passage sur les Meneurs de loups.\",\"visible_at_start\":true},{\"id\":\"AG_MIRANDOL\",\"title\":\"Analyse empreinte\",\"date\":\"2026-05-11T18:30\",\"note\":\"Mirandol. Releve photo + mesures envoyees a Elena.\",\"visible_at_start\":true},{\"id\":\"AG_F713\",\"title\":\"Consultation archives F713\",\"date\":\"2026-05-12T09:00\",\"note\":\"Decision de justice de 1803. Georges Melonie.\",\"visible_at_start\":true},{\"id\":\"AG_RDV\",\"title\":\"Rendez-vous informateur\",\"date\":\"2026-05-13T22:40\",\"note\":\"Venir seul. Lieu non renseigne.\",\"visible_at_start\":false}];\n      window.BERFDB.FILES_ALL = [{\"id\":\"FD_BDG\",\"name\":\"La Bete du Gevaudan\",\"parent_id\":\"\",\"locked\":true,\"visible_at_start\":true,\"password\":\"CHASTEL\",\"error_message\":\"Mot de passe incorrect. Amaury aurait choisi un nom de famille.\",\"files\":[{\"id\":\"journal-sonore-notes-retranscrites\",\"name\":\"Journal sonore - notes retranscrites.txt\",\"label\":\"Journal sonore - notes retranscrites\",\"type\":\"text\",\"url\":\"\",\"content\":\"AUDIO 1 - Message a Verril\\n\\nHmmm... salut Verril. C'est moi, Amaury. J'ai decouvert des trucs etranges au sein de l'agence. Si je ne rappelle pas, commence par F713.\\n\\nAUDIO 2 - Etude de Paul\\n\\nLes Meneurs de loups. Des hommes qui auraient ete capables de commander les loups. Si Jean Chastel n'avait pas tue la Bete parce qu'il etait son complice ? Et s'il l'avait tuee parce qu'il avait compris qui la tenait en laisse ?\\n\\nAUDIO 3 - F713\\n\\nDecision de justice, 1803. Georges Melonie, condamne pour sorcellerie apres l'attaque d'un village. Trois loups enormes auraient obei a sa voix.\\n\\nAUDIO 4 - Disparition de F713\\n\\nF713 a disparu. Pas archive. Pas deplace. Supprime. Quelqu'un a vu ce que je consultais.\\n\\nAUDIO 5 - Empreinte de Mirandol\\n\\nUne seule empreinte. Enorme. Une habitante dit avoir vu un animal marcher sur deux pattes.\\n\\nAUDIO 6 - Meneurs de loups\\n\\nLes archives parlent aussi d'immortalite. Si Melonie etait un Meneur de loups, sa condamnation en 1803 n'est peut-etre pas la fin de son histoire.\"},{\"id\":\"etude-paul-meneurs-de-loups\",\"name\":\"Etude Paul - Meneurs de loups.txt\",\"label\":\"Etude Paul - Meneurs de loups\",\"type\":\"text\",\"url\":\"\",\"content\":\"Extrait : les Meneurs de loups seraient capables de commander des loups par la voix. Plusieurs recits du Gevaudan evoquent une Bete se comportant moins comme un animal sauvage que comme une arme dirigee.\"}]},{\"id\":\"FD_IDENTITE\",\"name\":\"Identite Amaury\",\"parent_id\":\"\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"arbre-genealogique-chastel\",\"name\":\"Arbre genealogique Chastel.txt\",\"label\":\"Arbre genealogique Chastel\",\"type\":\"text\",\"url\":\"\",\"content\":\"Amaury Delacroix apparait dans une branche descendante de la famille Chastel. Le nom Delacroix correspond au nom maternel utilise dans les dossiers du BERF.\"},{\"id\":\"incendie-de-marvejols-1993\",\"name\":\"Incendie de Marvejols - 1993.txt\",\"label\":\"Incendie de Marvejols - 1993\",\"type\":\"text\",\"url\":\"\",\"content\":\"Article local : la maison familiale Chastel a ete detruite par un incendie classe accident domestique. La famille a quitte la Lozere peu apres.\"}]},{\"id\":\"FD_CERCLE\",\"name\":\"Cercle des Douze\",\"parent_id\":\"\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"lettre-du-cercle-decryptee\",\"name\":\"Lettre du Cercle - decryptee.txt\",\"label\":\"Lettre du Cercle - decryptee\",\"type\":\"text\",\"url\":\"\",\"content\":\"Amaury,\\n\\nTu as passe ta vie a fuir un nom que nous n'avons jamais oublie.\\n\\nChastel.\\n\\nTon ancetre nous a trahis. Il a detruit ce qui devait ouvrir la voie et a offert au peuple un heros de circonstance.\\n\\nTu as trouve Melonie. Tu as trouve F713. Tu as trouve assez pour devenir dangereux.\\n\\nMais pas assez pour comprendre ou tu mettais les pieds.\\n\\nLe Cercle ne s'ouvre pas aux curieux.\\nIl se referme sur eux.\"}]},{\"id\":\"FD_FINAL\",\"name\":\"Fichier cache Amaury\",\"parent_id\":\"\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"video-cachee-transcription\",\"name\":\"Video cachee - transcription.txt\",\"label\":\"Video cachee - transcription\",\"type\":\"text\",\"url\":\"\",\"content\":\"TRANSCRIPTION VIDEO CACHEE\\n\\nL'image tremble. Amaury est assis contre un mur de pierre. Son visage est pale, couvert de terre sechee. Un bandage sale lui recouvre l'oeil gauche.\\n\\nAmaury :\\nIls ont cru que je voulais prouver l'innocence de ma famille. Au debut, c'etait vrai.\\n\\nMaintenant, je veux autre chose.\\n\\nIls ont voulu m'enterrer avec leurs secrets.\\n\\nAlors je vais ouvrir les tombes.\"}]}];\n      window.BERFDB.CALCULATOR_SECRETS = [{\"id\":\"calc_genealogie_174\",\"label\":\"Archives genealogiques\",\"mode\":\"expression\",\"expression\":\"174\",\"action_type\":\"open_file_folder\",\"action_target\":\"FD_IDENTITE\",\"fail_message\":\"Aucune anomalie detectee.\",\"success_message\":\"Acces dissimule detecte : dossier genealogique restaure.\",\"repeatable\":false,\"close_after_success\":true},{\"id\":\"calc_rapport_final\",\"label\":\"Transmission rapport D-174\",\"mode\":\"expression\",\"expression\":\"F713\",\"action_type\":\"trigger_event\",\"action_target\":\"final_report_ready\",\"fail_message\":\"Le rapport attend l'ID de la preuve supprimee.\",\"success_message\":\"Rapport D-174 chiffre et transmis.\",\"repeatable\":false,\"close_after_success\":true}];\n      window.BERFDB.CRYPTO_SOLUTIONS = [];\n      window.BERFDB.DRONE = {\"accessCode\":\"AJUSTONS\",\"title\":\"Surveillance D-17 \/ Hotel des Ajustons\",\"sourceMode\":\"simulated\",\"liveStreamType\":\"hls\",\"liveStreamUrl\":\"\",\"simulatedMediaType\":\"image\",\"simulatedMedia\":null,\"simulatedMediaUrl\":\"\",\"status\":\"unstable\",\"autoplay\":true,\"loop\":false,\"showHud\":true,\"showTimestamp\":true,\"notes\":\"Code d'acces derive du lieu du piege. Les images montrent Lemoine, Peters et Valbert dans la zone.\"};\n      window.BERFDB.DRONE_DEBUG_ENDPOINT = \"https:\\\/\\\/berf.lultime-frisson.com\\\/wp-admin\\\/admin-ajax.php\";\n      window.BERFDB.DRONE_DEBUG_NONCE = \"55fbea713a\";\n      window.BERFDB.DEBUG = false;\n      window.BERFDB.MAIL_ATTACHMENT_MAP = [];\n\n      \/\/ localStorage scoped per scenario (player progression local)\n      (function(){\n        const scenario = String(140);\n        const mapKeys = new Set(['postit23_notes_v1','agenda_42_appts_v1','berf_agenda_appointments_v1','tri77_history_v1','emails','emailState','mailReceivedTime','berfdb_seed_emails_v1','berfdb_seed_emails_hash_v1','berfdb_seed_emails_v2','berfdb_seed_emails_hash_v2','berfdb_mail_open_folder','database','notifications','evidtool992_recents','berf_events_state_v1','berf_kb_unlocked_v1','berf_notifications_center_v1','berf_file_manager_state_v1','berf_file_manager_state_v2','berf_calculator_state_v1','berf_browser_auth_v1','berf_img_annotations_v1','suspects']);\n        const pfx = 'berf:' + scenario + ':';\n        const _get = localStorage.getItem.bind(localStorage);\n        const _set = localStorage.setItem.bind(localStorage);\n        const _rem = localStorage.removeItem.bind(localStorage);\n        localStorage.getItem = function(k){ return mapKeys.has(k) ? _get(pfx + k) : _get(k); };\n        localStorage.setItem = function(k,v){ return mapKeys.has(k) ? _set(pfx + k, v) : _set(k,v); };\n        localStorage.removeItem = function(k){ return mapKeys.has(k) ? _rem(pfx + k) : _rem(k); };\n      })();\n\n\n      \/\/ Seed event engine state\n      (function(){\n        try{\n          const boot = window.BERFDB && window.BERFDB.BOOT;\n          const rules = boot && boot.data && boot.data.events && Array.isArray(boot.data.events.rules) ? boot.data.events.rules : [];\n          const key = 'berf_events_state_v1';\n          const raw = localStorage.getItem(key);\n          let state = raw ? JSON.parse(raw) : null;\n          if(!state || typeof state !== 'object'){\n            state = { flags:{}, triggered:{} };\n          }\n          if(!state.triggered || typeof state.triggered !== 'object') state.triggered = {};\n          if(!state.rule_signatures || typeof state.rule_signatures !== 'object') state.rule_signatures = {};\n          const nextSignatures = {};\n          rules.forEach(rule=>{\n            if(!rule || !rule.id) return;\n            const id=String(rule.id);\n            const signature=JSON.stringify({trigger_type:rule.trigger_type||'',trigger_target:rule.trigger_target||'',once:rule.once!==false,effects:Array.isArray(rule.effects)?rule.effects:[]});\n            nextSignatures[id]=signature;\n            const previous=state.rule_signatures[id];\n            if((previous && previous!==signature) || (!previous && rule.trigger_type==='crypto_decryption_success')) delete state.triggered[id];\n          });\n          Object.keys(state.triggered).forEach(id=>{if(!rules.some(rule=>String(rule&&rule.id||'')===String(id)))delete state.triggered[id];});\n          state.rule_signatures=nextSignatures;\n          state.rules = rules;\n          localStorage.setItem(key, JSON.stringify(state));\n        }catch(e){ console.warn(e); }\n      })();\n\n      \/\/ Seed mailbox from backend BEFORE the desk initializes the mail tool\n      (function(){\n        \/\/ We re-seed when scenario data changes (hash) so updates in backend apply immediately.\n        const emails = [{\"id\":\"MAIL_SECURITE\",\"from_name\":\"Service securite\",\"from_email\":\"securite.interne@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Acces temporaire - protocole de chiffrement\",\"body_html\":\"<p>Agent,<\/p>\\n<p>Un acces temporaire vient de vous etre attribue sur l'environnement numerique du BERF.<\/p>\\n<p>Pour les communications emanant de la Direction, la cle de session est toujours associee au symbole du BERF.<\/p>\\n<p><strong>Indice :<\/strong> le symbole du BERF est la lanterne.<\/p>\\n<p>Service securite du BERF<\/p>\",\"date_iso\":\"2026-05-14 08:02\",\"attachments\":[],\"flags\":{\"unread\":true},\"visible_at_start\":true,\"folder\":\"inbox\"},{\"id\":\"MAIL_VERRIL_BRIEF\",\"from_name\":\"Verril Belhair\",\"from_email\":\"direction@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Dossier D-174 \/ priorite discrete\",\"body_html\":\"<p><strong>Message chiffre - cle requise.<\/strong><\/p>\\n<p><code>QKJYRIYV \/ XZCV-174<\/code><\/p>\\n<p>Utilisez le module Crypteur \/ Decrypteur avec la cle de session de la Direction.<\/p>\\n<hr>\\n<p><strong>Version decryptee attendue :<\/strong><\/p>\\n<p>Agent,<\/p>\\n<p>Je ne crois pas a la version officielle concernant la disparition d'Amaury Delacroix.<\/p>\\n<p>Amaury a disparu en Lozere apres avoir laisse un message vocal confus, ou il evoquait des elements inquietants \\\"au sein de l'agence\\\".<\/p>\\n<p>Votre objectif : comprendre ce qu'Amaury cherchait, determiner ce qui lui est arrive, identifier toute personne impliquee, puis me transmettre vos conclusions sous forme chiffree.<\/p>\\n<p>Ne faites confiance a personne par reflexe. Pas meme au BERF.<\/p>\\n<p><strong>Verril Belhair<\/strong><br>Directeur du BERF<\/p>\",\"date_iso\":\"2026-05-14 08:07\",\"attachments\":[{\"id\":0,\"name\":\"Les elements de l enquete.pdf\",\"type\":\"pdf\",\"url\":\"https:\/\/berf.lultime-frisson.com\/wp-content\/plugins\/berf-desk-builder-2.10.3-bureau-epurexxx\/assets\/les-elements-de-l-enquete.pdf\"}],\"flags\":{\"unread\":true},\"visible_at_start\":true,\"folder\":\"inbox\"},{\"id\":\"MAIL_CLAIRE_OUTILS\",\"from_name\":\"Claire Gamerault\",\"from_email\":\"claire.gamerault@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Tes outils sont a jour\",\"body_html\":\"<p>Amaury,<\/p>\\n<p>J'ai pousse la mise a jour de ton bureau virtuel.<\/p>\\n<p>Deux rappels :<\/p>\\n<ol><li>Le module d'analyse de preuves garde les historiques de consultation, modification et suppression.<\/li><li>Seuls les profils de niveau III peuvent supprimer definitivement un indice.<\/li><\/ol>\\n<p>Donc si quelqu'un fait disparaitre un document, tu devrais encore voir une trace.<\/p>\\n<p>Pixel<\/p>\",\"date_iso\":\"2026-05-10 17:43\",\"attachments\":[],\"flags\":{\"unread\":false},\"visible_at_start\":true,\"folder\":\"inbox\"},{\"id\":\"MAIL_PAUL_ETUDE\",\"from_name\":\"Paul Dufort\",\"from_email\":\"paul.dufort@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Etude sur les pratiques rituelles du Gevaudan\",\"body_html\":\"<p>Amaury,<\/p>\\n<p>Comme convenu, je t'ai transmis mon etude sur les pratiques religieuses et rituelles du Gevaudan.<\/p>\\n<p>J'attire ton attention sur un passage en particulier : les temoignages concernant les \\\"Meneurs de loups\\\".<\/p>\\n<p>Dans notre metier, les legendes les plus absurdes sont parfois seulement des verites mal classees.<\/p>\\n<p>Sois prudent avec cette piste.<\/p>\\n<p>Paul<\/p>\",\"date_iso\":\"2026-05-10 14:11\",\"attachments\":[],\"flags\":{\"unread\":false},\"visible_at_start\":true,\"folder\":\"inbox\"},{\"id\":\"MAIL_ELENA_EMP\",\"from_name\":\"Elena Moreau\",\"from_email\":\"elena.moreau@berf.gouv\",\"to_email\":\"agent.invite@berf.gouv\",\"subject\":\"Analyse preliminaire - empreinte de Mirandol\",\"body_html\":\"<p>Amaury,<\/p>\\n<p>J'ai analyse la photographie et les mesures que tu m'as transmises.<\/p>\\n<p>L'empreinte ne correspond a aucun canide connu dans nos bases classiques.<\/p>\\n<p>La repartition du poids est incompatible avec une locomotion quadrupede ordinaire. La possibilite d'un deplacement bipede ne peut pas etre exclue.<\/p>\\n<p>Je veux voir le moulage original.<\/p>\\n<p>Elena<\/p>\",\"date_iso\":\"2026-05-12 18:04\",\"attachments\":[],\"flags\":{\"unread\":false},\"visible_at_start\":true,\"folder\":\"inbox\"}] || [];\n        const seedKey = 'berfdb_seed_emails_v2';\n        const hashKey = 'berfdb_seed_emails_hash_v2';\n        \/\/ Invalide les anciennes cl\u00e9s v1 (mails cod\u00e9s en dur supprim\u00e9s)\n        localStorage.removeItem('berfdb_seed_emails_v1');\n        localStorage.removeItem('berfdb_seed_emails_hash_v1');\n        const hashNow = JSON.stringify(emails.map(m => ({\n          id: m && m.id ? m.id : '',\n          date_iso: m && m.date_iso ? m.date_iso : '',\n          subject: m && m.subject ? m.subject : '',\n          body: m && (m.body_html || m.body) ? (m.body_html || m.body) : '',\n          attachments: Array.isArray(m && m.attachments) ? m.attachments.map(a => ({\n            id: a && (a.id ?? a.attachment_id) ? (a.id ?? a.attachment_id) : null,\n            url: a && a.url ? a.url : '',\n            name: a && (a.name || a.filename || a.title) ? (a.name || a.filename || a.title) : ''\n          })) : []\n        })));\n        const hashPrev = localStorage.getItem(hashKey);\n\n        const mustSeed = !localStorage.getItem(seedKey) || hashPrev !== hashNow;\n\n        if(mustSeed){\n          const normalized = emails.map(m=>{\n            const rawAtt = Array.isArray(m.attachments) ? m.attachments : [];\n            const atts = rawAtt.map(a=>{\n              if(a && typeof a === 'object'){\n                return {\n                  id: a.id ?? a.attachment_id ?? null,\n                  name: a.name ?? a.filename ?? a.title ?? 'Pi\u00e8ce jointe',\n                  type: a.type ?? 'file',\n                  url: a.url ?? null\n                };\n              }\n              const id = parseInt(a,10);\n              return { id: Number.isFinite(id)?id:null, name: Number.isFinite(id)?('Pi\u00e8ce jointe #' + id):'Pi\u00e8ce jointe', type:'file', url:null };\n            }).filter(x=>x && x.url); \/\/ keep only openable attachments\n            return {\n              sender: (m.from_email || m.sender || ''),\n              subject: (m.subject || ''),\n              body: ((m.body_html || m.body || '').toString()),\n              attachments: atts,\n              folder: 'inbox',\n              date_iso: m.date_iso || '',\n              id: m.id || ''\n            };\n          });\n\n          localStorage.setItem('emails', JSON.stringify(normalized));\n          localStorage.removeItem('emailState'); \/\/ reset read\/unread indexes on reseed\n          localStorage.setItem('berfdb_mail_open_folder', 'inbox');\n          localStorage.setItem(seedKey, '1');\n          localStorage.setItem(hashKey, hashNow);\n        }\n      })();\n\n      \/\/ Seed indices BEFORE the evidence tool initializes\n      (function(){\n        try{\n          const indicesDb = {\"F713\":{\"analysis\":\"<p><strong>Statut :<\/strong> supprime.<\/p><p>Trace residuelle : decision de justice de 1803 concernant Georges Melonie, accuse d'avoir dirige trois loups contre un village.<\/p><p>Historique : consultation Amaury Delacroix, puis consultation et modification metadata par Georges Lemoine. Suppression definitive par profil niveau III.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":true},\"EM044\":{\"analysis\":\"<p>Empreinte de Mirandol. Morphologie proche d'un grand canide, mais appui vertical et pression du talon incompatibles avec une locomotion quadrupede ordinaire.<\/p>\",\"mediaType\":\"\",\"mediaSrc\":\"\",\"subscribers\":[],\"visibleAtStart\":true}} || {};\n          const indicesNotif = [] || [];\n          localStorage.setItem('database', JSON.stringify(indicesDb));\n          localStorage.setItem('notifications', JSON.stringify(indicesNotif));\n          if(!localStorage.getItem('evidtool992_recents')){\n            localStorage.setItem('evidtool992_recents', JSON.stringify([]));\n          }\n        }catch(e){ console.warn(e); }\n      })();\n    <\/script>\n\n        <template id=\"berfdb-tab-html-tab_vera\"><article class=\"berf-browser-doc\"><h2>La Bete du Gevaudan : et si le heros etait le complice ?<\/h2><p><strong>Carl Vera<\/strong><\/p><p>Jean Chastel est presente comme l'homme qui mit fin aux attaques. Mais une piste rarement citee merite attention : Georges Melonie, condamne en 1803 pour avoir mene trois loups contre un village.<\/p><p>Si Melonie n'etait pas un cas isole, alors la Bete n'etait peut-etre pas un animal. Elle etait peut-etre une arme.<\/p><\/article><\/template>\n        <template id=\"berfdb-tab-html-tab_forum_merlin\"><article class=\"berf-browser-doc\"><h2>Famille Chastel - heros ou imposteurs ?<\/h2><p><strong>ScribeDargon :<\/strong> Je cherche des sources fiables sur les descendants Chastel apres l'incendie de Marvejols en 1993.<\/p><p><strong>LoupGris48 :<\/strong> On disait que le fils aine avait change de nom. Delacroix peut-etre ? Nom de la mere.<\/p><\/article><\/template>\n        <template id=\"berfdb-tab-html-tab_vera_mort\"><article class=\"berf-browser-doc\"><h2>Le journaliste Carl Vera retrouve mort a son domicile<\/h2><p>Aucune trace d'effraction n'a ete relevee. Plusieurs documents de travail auraient ete saisis. Une source proche du dossier evoque la disparition d'une partie de ses archives personnelles.<\/p><\/article><\/template>\n    \n    <!-- ============================================================\nBERF DESK \u2014 CODE COMPLET (Outils existants inchang\u00e9s)\n+ AJOUT : Tennis (am\u00e9lior\u00e9) accessible via le clic sur \"Tennis\" (id=\"colision\") dans le Start menu\n\u26a0\ufe0f Je n\u2019ai PAS modifi\u00e9 l\u2019apparence ni la logique de tes outils (MAIL \/ SUSPECTS \/ CRYPTO \/ TROMBI \/ FILES).\nJ\u2019ai uniquement AJOUT\u00c9 :\n- Le HTML de la modale Tennis (dans #berfDesk)\n- Le CSS Tennis (scop\u00e9 #berfDesk)\n- Le JS Tennis (scop\u00e9 + robuste, requestAnimationFrame, resize, pause, controls souris\/tactile)\n============================================================ -->\n<link href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.5.0\/css\/all.min.css\" rel=\"stylesheet\"\/>\n<link href=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.css\" rel=\"stylesheet\"\/>\n<link href=\"https:\/\/fonts.googleapis.com\" rel=\"preconnect\">\n<link crossorigin=\"\" href=\"https:\/\/fonts.gstatic.com\" rel=\"preconnect\"\/>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Roboto+Mono:wght@400;700&amp;family=Special+Elite&amp;display=swap\" rel=\"stylesheet\"\/>\n<script src=\"https:\/\/unpkg.com\/exifr\/dist\/full.umd.js\">\n\n\n<\/script>\n<div id=\"berfDesk\">\n<div id=\"berfSessionTransition\" aria-hidden=\"true\"><div class=\"berf-session-card\"><div class=\"berf-session-spinner\"><\/div><strong id=\"berfSessionStep\">Fermeture de la session actuelle\u2026<\/strong><small>Terminal s\u00e9curis\u00e9 BERF<\/small><\/div><\/div>\n<div id=\"berfSessionBadge\" hidden><\/div>\n<div aria-hidden=\"true\" id=\"postit23-container\"><\/div>\n<div aria-hidden=\"true\" class=\"berf-brandplate\">\n  <img decoding=\"async\" src=\"https:\/\/berf.lultime-frisson.com\/wp-content\/plugins\/berf-desk-builder\/assets\/logo-berf.svg\" alt=\"\" \/>\n  <div>\n    <strong>B.E.R.F.<\/strong>\n  <\/div>\n<\/div>\n<!-- Left quick bar -->\n<div aria-label=\"Outils rapides\" class=\"berf-leftbar\">\n<button aria-label=\"Bo\u00eete mail\" class=\"berf-app mail-widget\" data-open-oc=\"mail\" type=\"button\">\n<i class=\"fa-solid fa-envelope\"><\/i>\n<span aria-hidden=\"true\" class=\"berf-badge\">0<\/span>\n<\/button>\n<button aria-label=\"Tableau des suspects\" class=\"berf-app\" data-open-oc=\"suspects\" type=\"button\">\n<i class=\"fa-solid fa-user-secret\"><\/i>\n<\/button>\n<button aria-label=\"Crypteur \/ D\u00e9crypteur\" class=\"berf-app\" data-open-oc=\"crypto\" type=\"button\">\n<i class=\"fa-solid fa-key\"><\/i>\n<\/button>\n<!-- Trombinoscope -->\n<button aria-label=\"Registre des missions\" class=\"berf-app\" data-open-oc=\"registry\" type=\"button\">\n<i class=\"fa-solid fa-clipboard-list\"><\/i>\n<\/button>\n<button aria-label=\"Gestionnaire de fichiers\" class=\"berf-app\" data-open-oc=\"filemanager\" type=\"button\">\n<i class=\"fa-solid fa-folder-tree\"><\/i>\n<\/button>\n<button aria-label=\"Calculatrice s\u00e9curis\u00e9e\" class=\"berf-app\" data-open-oc=\"calculator\" type=\"button\">\n<i class=\"fa-solid fa-calculator\"><\/i>\n<\/button>\n<\/div>\n<div aria-hidden=\"true\" class=\"berf-bg\"><\/div>\n<!-- ============================================================\n  BARRE DU BAS + MENU START (Windows)\n  ============================================================ -->\n<div aria-label=\"Barre des t\u00e2ches\" class=\"berf-taskbar\">\n<div class=\"start-menu-container\">\n<!-- Bouton du menu style Windows -->\n<button aria-label=\"Menu Windows\" class=\"start-button\" id=\"startButton\" type=\"button\">\n<i class=\"fab fa-microsoft\"><\/i>\n<\/button>\n<!-- Search (AJOUT) -->\n<div class=\"search-container93 berf-taskbar-search\">\n<input autocomplete=\"off\" id=\"searchInput45\" placeholder=\"Tapez pour rechercher...\" type=\"text\"\/>\n<div class=\"search-results56\" id=\"searchResults78\" style=\"display: none;\"><\/div>\n<\/div>\n<!-- Apps taskbar (ic\u00f4nes) -->\n<div aria-label=\"Applications\" class=\"berf-taskbar-apps\">\n<button aria-label=\"Navigateur\" class=\"berf-taskbar-app\" data-open-oc=\"browser\" type=\"button\">\n<i class=\"fa-solid fa-globe\"><\/i>\n<\/button>\n<button aria-label=\"Agenda\" class=\"berf-taskbar-app\" data-open-oc=\"agenda\" type=\"button\">\n<i class=\"fa-solid fa-calendar-days\"><\/i>\n<\/button>\n<button aria-label=\"Triangulation\" class=\"berf-taskbar-app\" data-open-oc=\"triangulation\" type=\"button\">\n<i class=\"fa-solid fa-tower-cell\"><\/i>\n<\/button>\n<button aria-label=\"Analyse d'image\" class=\"berf-taskbar-app\" data-open-oc=\"imgtool\" type=\"button\">\n<i class=\"fa-solid fa-image\"><\/i>\n<\/button><button aria-label=\"Analyse sonore\" class=\"berf-taskbar-app\" data-open-oc=\"audiotool\" type=\"button\"><i class=\"fa-solid fa-wave-square\"><\/i><\/button>\n<button aria-label=\"Analyse indices\" class=\"berf-taskbar-app evid-taskbar-widget\" data-open-oc=\"evidencetool\" data-unread=\"0\" type=\"button\"><i class=\"fa-solid fa-layer-group\"><\/i><span aria-hidden=\"true\" class=\"berf-badge evid-taskbar-badge\">0<\/span><\/button>\n<button aria-label=\"Calculatrice\" class=\"berf-taskbar-app\" data-open-oc=\"calculator\" type=\"button\"><i class=\"fa-solid fa-calculator\"><\/i><\/button>\n<button aria-label=\"Base de connaissance\" class=\"berf-taskbar-app\" data-open-oc=\"knowledge\" type=\"button\"><i class=\"fa-solid fa-book-skull\"><\/i><\/button>\n<button aria-label=\"Suivi d'itin\u00e9raire\" class=\"berf-taskbar-app\" data-open-oc=\"route23\" type=\"button\"><i class=\"fa-solid fa-route\"><\/i><\/button>\n<button aria-label=\"Drone\" class=\"berf-taskbar-app\" data-open-oc=\"drone\" type=\"button\"><i class=\"fa-solid fa-helicopter-symbol\"><\/i><\/button>\n<button aria-label=\"Post-it\" class=\"berf-taskbar-app\" data-postit-toggle=\"postit23\" type=\"button\"><i class=\"fa-solid fa-note-sticky\"><\/i><\/button>\n<button aria-label=\"Notifications\" class=\"berf-taskbar-app berf-notify-btn\" id=\"berfNotifyBtn\" data-unread=\"0\" type=\"button\"><i class=\"fa-solid fa-bell\"><\/i><span aria-hidden=\"true\" class=\"berf-badge berf-notify-badge\" id=\"berfNotifyBadge\">0<\/span><\/button>\n<\/div>\n<!-- Menu contextuel -->\n<div aria-hidden=\"true\" class=\"start-menu\" id=\"startMenu\">\n<ul class=\"menu-shortcuts\">\n<!-- Raccourcis \u201cjeux\u201d -->\n<li><a id=\"snake_v1\">Snake<\/a><\/li>\n<li><a id=\"playlist_v1\">Musique<\/a><\/li>\n<li><a id=\"colision\">Tennis<\/a><\/li>\n<li aria-hidden=\"true\" class=\"berf-sep\"><\/li>\n<!-- Raccourcis outils (branch\u00e9s sur tes off-canvas via data-open-oc) -->\n<li><a data-berf-open=\"mail\"><i class=\"fa-solid fa-envelope\"><\/i> Bo\u00eete mail<\/a><\/li>\n<li><a data-berf-open=\"suspects\"><i class=\"fa-solid fa-user-secret\"><\/i> Dossier suspects<\/a><\/li>\n<li><a data-berf-open=\"crypto\"><i class=\"fa-solid fa-key\"><\/i> Crypteur<\/a><\/li>\n<li><a data-berf-open=\"registry\"><i class=\"fa-solid fa-clipboard-list\"><\/i> Registre des missions<\/a><\/li>\n<li><a data-berf-open=\"filemanager\"><i class=\"fa-solid fa-folder-tree\"><\/i> Gestionnaire de fichiers<\/a><\/li>\n<li><a data-berf-open=\"calculator\"><i class=\"fa-solid fa-calculator\"><\/i> Calculatrice<\/a><\/li>\n<li><a data-berf-open=\"drone\"><i class=\"fa-solid fa-helicopter-symbol\"><\/i> Module drone<\/a><\/li>\n<\/ul>\n<!-- Section en bas du menu -->\n<div class=\"menu-bottom-icons\">\n<div class=\"icon-container\">\n<i aria-label=\"Quitter\" class=\"fas fa-power-off\" id=\"powerButton\"><\/i>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div aria-hidden=\"true\" class=\"berf-notify-drawer\" id=\"berfNotifyDrawer\" data-open=\"false\">\n  <div class=\"berf-notify-drawer__head\">\n    <div class=\"berf-notify-drawer__title\"><i class=\"fa-solid fa-bell\"><\/i> Notifications<\/div>\n    <button type=\"button\" class=\"berf-notify-drawer__close\" id=\"berfNotifyClose\" aria-label=\"Fermer\">\u00d7<\/button>\n  <\/div>\n  <div class=\"berf-notify-drawer__sub\">Centre d\u2019alertes BERF<\/div>\n  <div class=\"berf-notify-drawer__list\" id=\"berfNotifyList\"><\/div>\n<\/div>\n<div class=\"berf-toast-stack\" id=\"berfToastStack\" aria-live=\"polite\" aria-atomic=\"false\"><\/div>\n\n<!-- ============================================================\n  AJOUT : MODALE TENNIS (scop\u00e9e #berfDesk)\n  ============================================================ -->\n<div aria-hidden=\"true\" aria-label=\"Jeu Tennis\" id=\"bdd-modal\" role=\"dialog\">\n<div id=\"bdd-modal-content\" role=\"document\">\n<button aria-label=\"Fermer le jeu\" id=\"bdd-close-button\" type=\"button\">\u00d7<\/button>\n<div id=\"bdd-hud\">\n<div class=\"bdd-hud-left\">\n<span class=\"bdd-pill\" id=\"bdd-score\">Score: 0<\/span>\n<span class=\"bdd-pill\" id=\"bdd-level\">Level: 1<\/span>\n<\/div>\n<div class=\"bdd-hud-right\">\n<span class=\"bdd-hint\">\u2190 \u2192 \/ Souris \/ Tactile<\/span>\n<span class=\"bdd-hint\">Espace: Pause<\/span>\n<button aria-label=\"Recommencer\" class=\"bdd-btn\" id=\"bdd-restart\" type=\"button\">Recommencer<\/button>\n<\/div>\n<\/div>\n<div id=\"bdd-canvas-wrap\">\n<canvas id=\"bdd-canvas\"><\/canvas>\n<div aria-live=\"polite\" id=\"bdd-overlay\">\n<div class=\"bdd-overlay-card\">\n<div class=\"bdd-overlay-title\">Tennis<\/div>\n<div class=\"bdd-overlay-text\">\n              D\u00e9place la raquette en bas et renvoie la balle.<br\/>\n<b>\u2190 \u2192<\/b> (ou souris\/tactile) \u2022 <b>Espace<\/b> pause \u2022 <b>Esc<\/b> fermer\n            <\/div>\n<button aria-label=\"D\u00e9marrer\" class=\"bdd-btn bdd-btn-primary\" id=\"bdd-play\" type=\"button\">Jouer<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\n  OFF-CANVAS : MAIL\n  ============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-mail\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Bo\u00eete mail\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-envelope\"><\/i> Bo\u00eete mail<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div id=\"berfMailTool\">\n<div aria-label=\"Bo\u00eete de r\u00e9ception\" class=\"inbox-container\">\n<div aria-label=\"Liste des emails\" class=\"email-list\">\n<button aria-label=\"Nouveau Mail\" id=\"newMailButton\">Nouveau Mail<\/button>\n<\/div>\n<div aria-label=\"D\u00e9tails du mail s\u00e9lectionn\u00e9\" class=\"email-details\" style=\"display:none;\">\n<div class=\"details-header\">\n<div class=\"details-avatar\" id=\"details-avatar\">A<\/div>\n<h2 class=\"details-subject\" id=\"email-subject\">Sujet du mail s\u00e9lectionn\u00e9<\/h2>\n<\/div>\n<p class=\"sender-info\">\n<strong>De :<\/strong>\n<span id=\"sender-name\"><\/span> &lt;&lt;<span id=\"sender-email\"><\/span>&gt;&gt;\n<\/p>\n<p class=\"sender-date\"><strong>Date :<\/strong> <span id=\"email-date-display\"><\/span><\/p>\n<div class=\"message-body\">Corps du message...<\/div>\n<div aria-label=\"Pi\u00e8ces jointes\" class=\"attachments\"><p>Pi\u00e8ces jointes :<\/p><\/div>\n<button aria-label=\"R\u00e9pondre au mail\" id=\"replyButton\">R\u00e9pondre<\/button>\n<\/div>\n<\/div>\n<!-- Modale Nouveau Mail -->\n<div aria-modal=\"true\" class=\"modal\" id=\"newMailModal\">\n<div class=\"modal-content\">\n<span aria-label=\"Fermer\" class=\"close\">\u00d7<\/span>\n<h2>Nouveau Mail<\/h2>\n<form id=\"newMailForm\">\n<label for=\"recipient\">Destinataire :<\/label>\n<input id=\"recipient\" name=\"recipient\" required=\"\" type=\"email\"\/>\n<label for=\"subject\">Objet :<\/label>\n<input id=\"subject\" name=\"subject\" required=\"\" type=\"text\"\/>\n<label for=\"message\">Message :<\/label>\n<textarea id=\"message\" name=\"message\" required=\"\" rows=\"5\"><\/textarea>\n<label for=\"attachments\">Joindre des fichiers :<\/label>\n<input id=\"attachments\" multiple=\"\" name=\"attachments\" type=\"file\"\/>\n<button type=\"submit\">Envoyer<\/button>\n<\/form>\n<\/div>\n<\/div>\n<!-- Modale R\u00e9pondre -->\n<div aria-modal=\"true\" class=\"modal\" id=\"replyModal\">\n<div class=\"modal-content\">\n<span aria-label=\"Fermer\" class=\"close\">\u00d7<\/span>\n<h2>R\u00e9pondre \u00e0 un mail<\/h2>\n<form id=\"replyForm\">\n<label for=\"replyRecipient\">Destinataire :<\/label>\n<input id=\"replyRecipient\" name=\"replyRecipient\" readonly=\"\" type=\"email\"\/>\n<label for=\"replySubject\">Objet :<\/label>\n<input id=\"replySubject\" name=\"replySubject\" readonly=\"\" type=\"text\"\/>\n<label for=\"replyMessage\">Message :<\/label>\n<textarea id=\"replyMessage\" name=\"replyMessage\" required=\"\" rows=\"5\"><\/textarea>\n<label for=\"replyAttachments\">Joindre des fichiers :<\/label>\n<input id=\"replyAttachments\" multiple=\"\" name=\"replyAttachments\" type=\"file\"\/>\n<button type=\"submit\">Envoyer<\/button>\n<\/form>\n<\/div>\n<\/div>\n<!-- Modale pi\u00e8ces jointes -->\n<div aria-modal=\"true\" class=\"modal\" id=\"attachmentModal\">\n<div class=\"modal-content berf-mail-viewer\">\n<div class=\"berf-mail-viewer-head\">\n<div>\n<span class=\"berf-mail-viewer-kicker\">Visionneuse securisee<\/span>\n<h2 id=\"attachmentViewerTitle\">Piece jointe<\/h2>\n<p id=\"attachmentViewerMeta\">Dossier D-174<\/p>\n<\/div>\n<span aria-label=\"Fermer\" class=\"close\">\u00d7<\/span>\n<\/div>\n<div id=\"attachmentPreview\"><\/div>\n<div class=\"berf-viewer-actionbar\">\n<a id=\"attachmentOpenExternal\" class=\"berf-viewer-open-btn\" href=\"#\" target=\"_blank\" rel=\"noopener\"><i class=\"fa-solid fa-up-right-from-square\"><\/i> Ouvrir dans un onglet<\/a>\n<button id=\"attachmentAnalyzeBtn\" class=\"berf-viewer-analyze-btn\" type=\"button\" style=\"display:none;\" hidden><i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser l'image<\/button>\n<button id=\"attachmentCollectBtn\" class=\"berf-viewer-analyze-btn berf-viewer-collect-btn\" type=\"button\" style=\"display:none;\" hidden><i class=\"fa-solid fa-download\"><\/i> Ajouter aux \u00e9l\u00e9ments collect\u00e9s<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\n  OFF-CANVAS : SUSPECTS\n  ============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-suspects\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Dossier suspects\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-user-secret\"><\/i> Dossier suspects<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div id=\"berfSuspectsTool\">\n<div class=\"container42X\">\n<h1>D\u00e9partement des Enqu\u00eates Sp\u00e9ciales - Dossier Suspects<\/h1>\n<button class=\"btn42X\" id=\"btnNewSuspect42X\">Nouveau Suspect<\/button>\n<table class=\"suspect-table42X\">\n<thead>\n<tr>\n<th>Avatar<\/th>\n<th>Nom<\/th>\n<th>Mobile<\/th>\n<th>Alibi<\/th>\n<th>Actes<\/th>\n<th>Pi\u00e8ces jointes<\/th>\n<th>Actions<\/th>\n<\/tr>\n<\/thead>\n<tbody id=\"suspect-table-body42X\"><\/tbody>\n<\/table>\n<\/div>\n<!-- Modale Ajouter\/Modifier Suspect -->\n<div class=\"modal42X\" id=\"suspectModal42X\">\n<div class=\"modal-content42X\">\n<h2 class=\"modal-header42X\" id=\"modal-title42X\">Ajouter un Suspect<\/h2>\n<form id=\"suspect-form42X\">\n<div class=\"form-group42X\">\n<label for=\"suspect-name42X\">Nom du Suspect:<\/label>\n<input class=\"form-control42X\" id=\"suspect-name42X\" required=\"\" type=\"text\"\/>\n<\/div>\n<div class=\"form-group42X\">\n<label for=\"suspect-mobile42X\">Mobile du suspect:<\/label>\n<input class=\"form-control42X\" id=\"suspect-mobile42X\" required=\"\" type=\"text\"\/>\n<\/div>\n<div class=\"form-group42X\">\n<label for=\"suspect-alibi42X\">Alibi:<\/label>\n<input class=\"form-control42X\" id=\"suspect-alibi42X\" required=\"\" type=\"text\"\/>\n<\/div>\n<div class=\"form-group42X\">\n<label for=\"suspect-relation42X\">Actes Commis:<\/label>\n<input class=\"form-control42X\" id=\"suspect-relation42X\" type=\"text\"\/>\n<\/div>\n<div class=\"form-group42X\">\n<label>Pi\u00e8ces jointes au dossier :<\/label>\n<button class=\"btn42X evidence-picker-open42X\" id=\"suspect-evidence-open42X\" type=\"button\"><i class=\"fa-solid fa-paperclip\"><\/i> Joindre des indices<\/button>\n<div class=\"evidence-selection42X\" id=\"suspect-evidence-list42X\"><span>Aucun fichier associ\u00e9.<\/span><\/div>\n<\/div>\n<div class=\"modal-footer42X\">\n<button class=\"btn42X\" id=\"btnCancelSuspect42X\" type=\"button\">Annuler<\/button>\n<button class=\"btn42X\" type=\"submit\">Sauvegarder<\/button>\n<\/div>\n<\/form>\n<\/div>\n<\/div>\n<!-- Modale Envoyer Rapport -->\n<div class=\"modal42X\" id=\"reportModal42X\">\n<div class=\"modal-content42X\">\n<h2 class=\"modal-header42X\">Envoyer un Rapport<\/h2>\n<form id=\"report-form42X\">\n<div class=\"form-group42X\">\n<label for=\"report-email42X\">S\u00e9lectionner l'Email de Destination:<\/label>\n<div class=\"custom-dropdown42X\">\n<select class=\"form-control42X\" id=\"report-email42X\" required=\"\">\n<option value=\"\">Choisir un email...<\/option>\n<\/select>\n<\/div>\n<\/div>\n<div class=\"form-group42X\">\n<label for=\"report-reason42X\">Motif du Rapport:<\/label>\n<input class=\"form-control42X\" id=\"report-reason42X\" required=\"\" type=\"text\"\/>\n<\/div>\n<div class=\"form-group42X\">\n<label for=\"report-details42X\">Informations Compl\u00e9mentaires:<\/label>\n<textarea class=\"form-control42X\" id=\"report-details42X\" rows=\"4\"><\/textarea>\n<\/div>\n<div class=\"form-group42X\">\n<label>Pi\u00e8ces transmises avec le rapport (maximum 10) :<\/label>\n<button class=\"btn42X evidence-picker-open42X\" id=\"report-evidence-open42X\" type=\"button\"><i class=\"fa-solid fa-folder-open\"><\/i> S\u00e9lectionner dans l\u2019explorateur<\/button>\n<div class=\"evidence-selection42X\" id=\"report-evidence-list42X\"><span>Aucun fichier s\u00e9lectionn\u00e9.<\/span><\/div>\n<div class=\"warning-message42X\" id=\"file-limit-warning42X\">Vous avez d\u00e9pass\u00e9 la limite de 10 fichiers.<\/div>\n<\/div>\n<div class=\"modal-footer42X\">\n<button class=\"btn42X\" id=\"btnCancelReport42X\" type=\"button\">Annuler<\/button>\n<button class=\"btn42X\" type=\"submit\">Envoyer le Rapport<\/button>\n<\/div>\n<div class=\"loader42X\" id=\"report-loader42X\"><\/div>\n<div class=\"success-message42X\" id=\"report-success42X\">Rapport envoy\u00e9 avec succ\u00e8s!<\/div>\n<div class=\"error-message42X\" id=\"report-error42X\">Erreur lors de l'envoi du rapport.<\/div>\n<\/form>\n<\/div>\n<\/div>\n<!-- S\u00e9lecteur de fichiers virtuel -->\n<div class=\"evidence-picker42X\" id=\"evidencePicker42X\" aria-hidden=\"true\">\n<div class=\"evidence-picker42X__backdrop\" data-evidence-picker-close><\/div>\n<div class=\"evidence-picker42X__dialog\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Joindre des indices\">\n<div class=\"evidence-picker42X__head\"><div><strong>Joindre des indices<\/strong><span>S\u00e9lectionnez des fichiers accessibles dans l\u2019explorateur.<\/span><\/div><button type=\"button\" data-evidence-picker-close aria-label=\"Fermer\">\u00d7<\/button><\/div>\n<div class=\"evidence-picker42X__body\"><aside id=\"evidencePickerFolders42X\"><\/aside><main id=\"evidencePickerFiles42X\"><\/main><\/div>\n<div class=\"evidence-picker42X__foot\"><span id=\"evidencePickerCount42X\">0 fichier s\u00e9lectionn\u00e9<\/span><div><button class=\"btn42X\" type=\"button\" data-evidence-picker-close>Annuler<\/button><button class=\"btn42X\" id=\"evidencePickerConfirm42X\" type=\"button\">Joindre au rapport<\/button><\/div><\/div>\n<\/div>\n<\/div>\n<div class=\"log-container42X\" id=\"log-container42X\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\n  OFF-CANVAS : CRYPTO\n  ============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-crypto\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Crypteur \/ D\u00e9crypteur\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-key\"><\/i> Crypteur \/ D\u00e9crypteur<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div id=\"berfCryptoTool\">\n<div class=\"mode-indicator01 encrypt-mode01\" id=\"modeIndicator01\">Mode : Crypteur<\/div>\n<div class=\"container01\">\n<div class=\"column01\">\n<label for=\"key01\">Cl\u00e9 :<\/label>\n<input id=\"key01\" placeholder=\"Entrez la cl\u00e9...\" type=\"text\"\/>\n<label for=\"message01\" id=\"message-label01\">Message \u00e0 crypter :<\/label>\n<textarea id=\"message01\" placeholder=\"Entrez le message...\" rows=\"5\"><\/textarea>\n<\/div>\n<div class=\"center-button01\">\n<button class=\"switch-button01\" id=\"btnToggleMode01\" type=\"button\">\n<i class=\"fas fa-exchange-alt\"><\/i>\n<\/button>\n<\/div>\n<div class=\"column01\">\n<label for=\"output01\" id=\"output-label01\">Message crypt\u00e9 :<\/label>\n<div style=\"position: relative;\">\n<textarea id=\"output01\" readonly=\"\" rows=\"5\"><\/textarea>\n<button class=\"copy-button01\" id=\"btnCopy01\" type=\"button\">\n<i class=\"fas fa-copy\"><\/i>\n<\/button>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"toast\" id=\"toast\">Texte copi\u00e9 !<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\n  OFF-CANVAS : TROMBI\n  ============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-registry\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Registre des missions BERF\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-clipboard-list\"><\/i> Registre des missions BERF<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div id=\"berfMissionRegistry\">\n<div class=\"berf-registry-tabs\" role=\"tablist\"><button type=\"button\" class=\"is-active\" data-registry-tab=\"orders\">Ordres de mission<\/button><button type=\"button\" data-registry-tab=\"agents\">Agents<\/button><\/div>\n<section class=\"berf-registry-panel is-active\" data-registry-panel=\"orders\">\n<div class=\"berf-registry-heading\"><div><h2>Ordres de mission<\/h2><\/div><\/div>\n<div class=\"berf-registry-search\"><label>R\u00e9f\u00e9rence<input id=\"berfRegistrySearch\" type=\"search\" placeholder=\"COT_23_01_118\"><\/label><button type=\"button\" id=\"berfRegistrySearchBtn\">Rechercher<\/button><\/div>\n<div class=\"berf-registry-result\" id=\"berfRegistryResult\"><div class=\"berf-registry-empty\"><i class=\"fa-solid fa-magnifying-glass\"><\/i><strong>Rechercher un ordre de mission<\/strong><span>Saisissez sa r\u00e9f\u00e9rence officielle, un agent ou un mot de son objet.<\/span><\/div><\/div>\n<\/section>\n<section class=\"berf-registry-panel\" data-registry-panel=\"agents\">\n<div id=\"berfTrombiTool\">\n<div class=\"trombi77__header\">\n<input autocomplete=\"off\" id=\"search-bar-77\" placeholder=\"Rechercher (nom, pr\u00e9nom, code, sp\u00e9cialit\u00e9, email\u2026)\" type=\"text\"\/>\n<div class=\"trombi77__count\"><span id=\"trombiCount77\">0<\/span> agents<\/div>\n<\/div>\n<div class=\"trombi77__grid\" id=\"trombinoscope-77\"><\/div>\n<div aria-hidden=\"true\" class=\"trombi77__modal\" id=\"modal-77\">\n<div aria-label=\"Fiche agent\" class=\"trombi77__modalCard\" role=\"dialog\">\n<button aria-label=\"Fermer\" class=\"trombi77__close\" id=\"trombiClose77\" type=\"button\">\u00d7<\/button>\n<div class=\"trombi77__modalTop\">\n<img alt=\"Photo de l'agent\" id=\"modal-photo\"\/>\n<div class=\"trombi77__modalIdentity\">\n<h2 id=\"modal-nom\"><\/h2>\n<div class=\"trombi77__pill\"><i class=\"fa-solid fa-fingerprint\"><\/i> <span id=\"modal-nom-de-code\"><\/span><\/div>\n<div class=\"trombi77__sub\" id=\"modal-specialite\"><\/div>\n<\/div>\n<\/div>\n<div class=\"trombi77__fields\">\n<div class=\"trombi77__field\"><span>Date de naissance<\/span><b id=\"modal-date-naissance\"><\/b><\/div>\n<div class=\"trombi77__field\"><span>Lieu de naissance<\/span><b id=\"modal-lieu-naissance\"><\/b><\/div>\n<div class=\"trombi77__field\"><span>Entr\u00e9e au BERF<\/span><b id=\"modal-date-entree\"><\/b><\/div>\n<div class=\"trombi77__field\"><span>T\u00e9l\u00e9phone<\/span><b id=\"modal-phone\"><\/b><\/div>\n<div class=\"trombi77__field\"><span>Email<\/span><b id=\"modal-email\"><\/b><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/section>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\nOFF-CANVAS : AGENDA\n============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-agenda\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Agenda\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-calendar-days\"><\/i> Agenda<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<!-- AGENDA TOOL -->\n<div id=\"berfAgendaTool\">\n<div class=\"agenda_42_container\">\n<nav class=\"agenda_42_navigation\">\n<button class=\"agenda_42_navbtn active\" data-tab=\"agenda_42_tab_rdv\">\n<i class=\"fa-solid fa-calendar-days\"><\/i> Rendez-vous\n          <\/button>\n<button class=\"agenda_42_navbtn\" data-tab=\"agenda_42_tab_add\">\n<i class=\"fa-solid fa-circle-plus\"><\/i> Ajouter\n          <\/button>\n<\/nav>\n<div class=\"agenda_42_content\">\n<div class=\"agenda_42_tab active\" id=\"agenda_42_tab_rdv\">\n<div class=\"agenda_42_next\">\n<h3>Prochain Rendez-vous :<\/h3>\n<p id=\"agenda_42_next_item\">Aucun rdv pr\u00e9vu prochainement<\/p>\n<\/div>\n<div class=\"agenda_42_calwrap\">\n<div class=\"agenda_42_controls\">\n<button id=\"agenda_42_prev\" type=\"button\"><i class=\"fa-solid fa-chevron-left\"><\/i><\/button>\n<span id=\"agenda_42_current_month\"><\/span>\n<select class=\"agenda_42_year\" id=\"agenda_42_year_select\"><\/select>\n<button id=\"agenda_42_next\" type=\"button\"><i class=\"fa-solid fa-chevron-right\"><\/i><\/button>\n<\/div>\n<div class=\"agenda_42_calendar\" id=\"agenda_42_calendar\"><\/div>\n<\/div>\n<\/div>\n<div class=\"agenda_42_tab\" id=\"agenda_42_tab_add\">\n<div class=\"agenda_42_formgroup\">\n<label for=\"agenda_42_title\">Titre du Rendez-vous :<\/label>\n<input id=\"agenda_42_title\" placeholder=\"Titre du Rendez-vous\" type=\"text\"\/>\n<\/div>\n<div class=\"agenda_42_formgroup\">\n<label for=\"agenda_42_date\">Date et Heure :<\/label>\n<input id=\"agenda_42_date\" type=\"datetime-local\"\/>\n<\/div>\n<button class=\"agenda_42_addbtn\" id=\"agenda_42_add_btn\" type=\"button\">Ajouter<\/button>\n<\/div>\n<\/div>\n<!-- Modal -->\n<div aria-hidden=\"true\" class=\"agenda_42_modal\" id=\"agenda_42_modal\">\n<div class=\"agenda_42_modalcontent\" role=\"document\">\n<button aria-label=\"Fermer\" class=\"agenda_42_close\" id=\"agenda_42_modal_close\" type=\"button\">\u00d7<\/button>\n<div class=\"agenda_42_modalheader\">\n<h3 id=\"agenda_42_modal_date_title\"><\/h3>\n<\/div>\n<div class=\"agenda_42_modalappts\">\n<h3>Rendez-vous pour cette journ\u00e9e :<\/h3>\n<ul class=\"agenda_42_list\" id=\"agenda_42_modal_list\"><\/ul>\n<\/div>\n<div class=\"agenda_42_formgroup\">\n<label for=\"agenda_42_modal_title\">Titre du Rendez-vous :<\/label>\n<input id=\"agenda_42_modal_title\" placeholder=\"Titre du Rendez-vous\" type=\"text\"\/>\n<\/div>\n<div class=\"agenda_42_formgroup\">\n<label for=\"agenda_42_modal_date\">Date et Heure :<\/label>\n<input id=\"agenda_42_modal_date\" type=\"datetime-local\"\/>\n<\/div>\n<button class=\"agenda_42_addbtn\" id=\"agenda_42_modal_add\" type=\"button\">Ajouter<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\nOFF-CANVAS : TRIANGULATION\n============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-triangulation\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Triangulation t\u00e9l\u00e9phonique\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\">\n<i class=\"fa-solid fa-tower-cell\"><\/i>\n<span>Triangulation<\/span>\n<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\n<i class=\"fa-solid fa-xmark\"><\/i>\n<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div class=\"tri77\" id=\"berfTriangulation77\">\n<div class=\"tri77__grid\">\n<aside class=\"tri77__col tri77__left\">\n<h3>Configuration<\/h3>\n<div class=\"tri77__field\">\n<label for=\"mapView77\">Vue de la carte<\/label>\n<select id=\"mapView77\">\n<option value=\"satellite\">Satellite<\/option>\n<option value=\"plan\">Plan<\/option>\n<\/select>\n<\/div>\n<div class=\"tri77__hint\">\n<div class=\"tri77__hintTitle\"><i class=\"fa-solid fa-circle-info\"><\/i> R\u00e8gles<\/div>\n<ul>\n<li>Num\u00e9ros inconnus \u2192 <b>non trouv\u00e9<\/b>.<\/li>\n<li>Le num\u00e9ro <b>0742105676<\/b> suit des dates sp\u00e9cifiques.<\/li>\n<li>D\u00e9placement agents : vitesse moyenne <b>60 km\/h<\/b>.<\/li>\n<\/ul>\n<\/div>\n<\/aside>\n<main class=\"tri77__col tri77__center\">\n<section class=\"tri77__card\" id=\"triForm77\">\n<div class=\"tri77__cardHead\">\n<div class=\"tri77__badge\"><i class=\"fa-solid fa-satellite-dish\"><\/i><\/div>\n<div>\n<div class=\"tri77__title\">Triangulation T\u00e9l\u00e9phonique<\/div>\n<div class=\"tri77__sub\">Entrez un num\u00e9ro + date\/heure pour localiser l\u2019appareil.<\/div>\n<\/div>\n<\/div>\n<div class=\"tri77__inputs\">\n<input autocomplete=\"off\" id=\"phoneInput77\" inputmode=\"numeric\" placeholder=\"Num\u00e9ro de t\u00e9l\u00e9phone\" type=\"text\"\/>\n<input id=\"dateInput77\" type=\"datetime-local\"\/>\n<button class=\"tri77__btn tri77__btnPrimary\" id=\"triStartBtn77\" type=\"button\">\n<i class=\"fa-solid fa-crosshairs\"><\/i> Lancer la triangulation\n                <\/button>\n<\/div>\n<\/section>\n<section class=\"tri77__card tri77__result\" id=\"triResult77\" style=\"display:none;\">\n<div class=\"tri77__loading\" id=\"triLoading77\" style=\"display:none;\">\n<div class=\"tri77__loadingCore\">\n<div class=\"tri77__radarWrap\">\n<div class=\"tri77__relay tri77__relay--1\"><\/div>\n<div class=\"tri77__relay tri77__relay--2\"><\/div>\n<div class=\"tri77__relay tri77__relay--3\"><\/div>\n<div class=\"tri77__radar\">\n<div class=\"tri77__radarSweep\"><\/div>\n<div class=\"tri77__radarRing tri77__radarRing--1\"><\/div>\n<div class=\"tri77__radarRing tri77__radarRing--2\"><\/div>\n<div class=\"tri77__radarRing tri77__radarRing--3\"><\/div>\n<div class=\"tri77__radarDot\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tri77__loadingTitle\">Triangulation en cours\u2026<\/div>\n<div class=\"tri77__loadingText\" id=\"triLoadingText77\">Connexion aux antennes relais\u2026<\/div>\n<div class=\"tri77__loadingMeta\" id=\"triLoadingMeta77\">Signal brut : 12% \u00b7 Antennes verrouill\u00e9es : 0\/3<\/div>\n<div class=\"tri77__loadingBar\"><span id=\"triLoadingBar77\"><\/span><\/div>\n<\/div>\n<\/div>\n<div class=\"tri77__resultText\" id=\"resultText77\"><\/div>\n<div class=\"tri77__map\" id=\"map77\" style=\"display:none;\"><\/div>\n<button class=\"tri77__btn tri77__btnGhost\" id=\"triReturnBtn77\" style=\"display:none;\" type=\"button\">\n<i class=\"fa-solid fa-rotate-left\"><\/i> Retour\n              <\/button>\n<\/section>\n<\/main>\n<aside class=\"tri77__col tri77__right\">\n<h3>Historique<\/h3>\n<div class=\"tri77__history\" id=\"historyList77\"><\/div>\n<\/aside>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- ============================================================\nOFF-CANVAS : ANALYSE IMAGE\n============================================================ -->\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-imgtool\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Analyse d'image\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\">\n<i aria-hidden=\"true\" class=\"fa-solid fa-image\"><\/i>\n<span>Analyse d'image<\/span>\n<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\n<i class=\"fa-solid fa-xmark\"><\/i>\n<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div class=\"berf-imgtool-wrap\" id=\"imgtool991-root\">\n<div class=\"imgtool991-notice\" id=\"imgtool991-notice\" style=\"display:none;\">\n          Application de deux filtres impossible. R\u00e9initialisez l'image !\n          <button aria-label=\"Fermer\" id=\"imgtool991-close-notice\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"imgtool991-grid\" id=\"imgtool991-container\">\n<div class=\"imgtool991-panel\" id=\"imgtool991-left\">\n<label class=\"imgtool991-slider\"><span>Contraste <b id=\"imgtool991-contrast-value\">0<\/b><\/span><input id=\"imgtool991-contrast\" type=\"range\" min=\"-100\" max=\"100\" step=\"1\" value=\"0\"\/><\/label>\n<label class=\"imgtool991-slider\"><span>Luminosit\u00e9 <b id=\"imgtool991-brightness-value\">0<\/b><\/span><input id=\"imgtool991-brightness\" type=\"range\" min=\"-100\" max=\"100\" step=\"1\" value=\"0\"\/><\/label>\n<button class=\"imgtool991-btn\" id=\"imgtool991-invert\"><i class=\"fa-solid fa-circle-half-stroke\"><\/i> Inverser<\/button>\n<div class=\"imgtool991-row\">\n<button class=\"imgtool991-btn\" id=\"imgtool991-zoom-in\"><i class=\"fa-solid fa-magnifying-glass-plus\"><\/i> Zoom +<\/button>\n<button class=\"imgtool991-btn\" id=\"imgtool991-zoom-out\"><i class=\"fa-solid fa-magnifying-glass-minus\"><\/i> Zoom -<\/button>\n<\/div>\n<div class=\"imgtool991-zoomline\"><span id=\"imgtool991-zoom-value\">100 %<\/span><button class=\"imgtool991-mini\" id=\"imgtool991-fit\" type=\"button\">Ajuster<\/button><\/div>\n<button class=\"imgtool991-btn\" id=\"imgtool991-compare\" type=\"button\"><i class=\"fa-solid fa-code-compare\"><\/i> Comparer \u00e0 l'original<\/button>\n<label class=\"imgtool991-slider\" id=\"imgtool991-compare-wrap\" hidden><span>Original \u2190 s\u00e9paration \u2192 Modifi\u00e9e<\/span><input id=\"imgtool991-compare-position\" type=\"range\" min=\"0\" max=\"100\" step=\"1\" value=\"50\"\/><\/label>\n<button class=\"imgtool991-btn imgtool991-btn--green\" id=\"imgtool991-reload\" style=\"display:none;\">\n<i class=\"fa-solid fa-upload\"><\/i> Charger une image\n            <\/button>\n<\/div>\n<div class=\"imgtool991-canvas\" id=\"imgtool991-canvas-container\" title=\"Cliquez pour charger une image (ou glissez-d\u00e9posez)\">\n<label class=\"imgtool991-upload\" for=\"imgtool991-upload-input\" id=\"imgtool991-upload-button\">\n              Cliquez ici pour charger une image<br\/><span>ou glissez-d\u00e9posez<\/span>\n<\/label>\n<input accept=\"image\/*\" id=\"imgtool991-upload-input\" style=\"display:none;\" type=\"file\"\/>\n<canvas id=\"imgtool991-canvas\"><\/canvas>\n<div id=\"imgtool991-modeOverlay\"><\/div>\n<div id=\"imgtool991-grainOverlay\"><\/div>\n<\/div>\n<div class=\"imgtool991-panel\" id=\"imgtool991-right\">\n<button class=\"imgtool991-btn\" id=\"imgtool991-meta\"><i class=\"fa-solid fa-circle-info\"><\/i> M\u00e9tadonn\u00e9es<\/button>\n<button class=\"imgtool991-btn\" id=\"imgtool991-annotate\" type=\"button\"><i class=\"fa-solid fa-location-dot\"><\/i> Placer un rep\u00e8re<\/button>\n<div class=\"imgtool991-row\"><button class=\"imgtool991-btn\" id=\"imgtool991-annotation-undo\" type=\"button\">Annuler<\/button><button class=\"imgtool991-btn\" id=\"imgtool991-annotation-clear\" type=\"button\">Effacer<\/button><\/div>\n<div class=\"imgtool991-row\">\n<button class=\"imgtool991-btn imgtool991-color\" id=\"imgtool991-r\">R<\/button>\n<button class=\"imgtool991-btn imgtool991-color\" id=\"imgtool991-g\">G<\/button>\n<button class=\"imgtool991-btn imgtool991-color\" id=\"imgtool991-b\">B<\/button>\n<button class=\"imgtool991-btn\" id=\"imgtool991-rgb-off\">Normal<\/button>\n<\/div>\n<button class=\"imgtool991-btn imgtool991-mode\" id=\"imgtool991-mode-night\">\ud83c\udf19 Vision nocturne<\/button>\n<button class=\"imgtool991-btn imgtool991-mode\" id=\"imgtool991-mode-uv\">\ud83e\uddea UV \/ Traces<\/button>\n<button class=\"imgtool991-btn imgtool991-mode\" id=\"imgtool991-mode-archive\">\ud83d\udcdc Archive 1803<\/button>\n<button class=\"imgtool991-btn imgtool991-mode\" id=\"imgtool991-mode-normal\">Mode normal<\/button>\n<button class=\"imgtool991-btn imgtool991-btn--danger\" id=\"imgtool991-reset\"><i class=\"fa-solid fa-rotate-left\"><\/i> R\u00e9initialiser<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div><div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-audiotool\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Analyse sonore\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\">\n<i aria-hidden=\"true\" class=\"fa-solid fa-wave-square\"><\/i>\n<span>Analyse sonore<\/span>\n<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\n<i class=\"fa-solid fa-xmark\"><\/i>\n<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div class=\"berf-audiotool\" id=\"audiotool772-root\">\n<div class=\"audiotool772-grid\">\n<div class=\"audiotool772-panel\">\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-pitch\">Pitch (demi-tons) : <span id=\"audiotool772-pitch-v\">0<\/span><\/label>\n<input id=\"audiotool772-pitch\" max=\"12\" min=\"-12\" step=\"1\" type=\"range\" value=\"0\"\/>\n<\/div>\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-filter\">Filtre passe-bas (Hz) : <span id=\"audiotool772-filter-v\">1000<\/span><\/label>\n<input id=\"audiotool772-filter\" max=\"5000\" min=\"100\" step=\"100\" type=\"range\" value=\"1000\"\/>\n<\/div>\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-reverb\">Reverb (wet) : <span id=\"audiotool772-reverb-v\">0.0<\/span><\/label>\n<input id=\"audiotool772-reverb\" max=\"1\" min=\"0\" step=\"0.1\" type=\"range\" value=\"0\"\/>\n<\/div>\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-delay\">Delay (wet) : <span id=\"audiotool772-delay-v\">0.0<\/span><\/label>\n<input id=\"audiotool772-delay\" max=\"1\" min=\"0\" step=\"0.1\" type=\"range\" value=\"0\"\/>\n<\/div>\n<\/div>\n<div class=\"audiotool772-center\">\n<label class=\"audiotool772-upload\" for=\"audiotool772-upload\">Choisir un fichier audio<\/label>\n<input accept=\"audio\/*\" id=\"audiotool772-upload\" type=\"file\"\/>\n<div class=\"audiotool772-status\">\n<div class=\"audiotool772-pill\" id=\"audiotool772-file\">Aucun fichier<\/div>\n<div class=\"audiotool772-pill\" id=\"audiotool772-time\">00:00 \/ 00:00<\/div>\n<\/div>\n<div class=\"audiotool772-wave\" id=\"audiotool772-wave\"><\/div>\n<div class=\"audiotool772-actions\">\n<button disabled=\"\" id=\"audiotool772-play\" type=\"button\"><i class=\"fa-solid fa-play\"><\/i> Play<\/button>\n<button class=\"audiotool772-muted\" disabled=\"\" id=\"audiotool772-reset\" type=\"button\"><i class=\"fa-solid fa-rotate-left\"><\/i> R\u00e9initialiser<\/button>\n<\/div>\n<\/div>\n<div class=\"audiotool772-panel\">\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-eq-low\">Basses (dB) : <span id=\"audiotool772-eq-low-v\">0<\/span><\/label>\n<input id=\"audiotool772-eq-low\" max=\"20\" min=\"-20\" step=\"1\" type=\"range\" value=\"0\"\/>\n<\/div>\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-eq-mid\">M\u00e9diums (dB) : <span id=\"audiotool772-eq-mid-v\">0<\/span><\/label>\n<input id=\"audiotool772-eq-mid\" max=\"20\" min=\"-20\" step=\"1\" type=\"range\" value=\"0\"\/>\n<\/div>\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-eq-high\">Aigus (dB) : <span id=\"audiotool772-eq-high-v\">0<\/span><\/label>\n<input id=\"audiotool772-eq-high\" max=\"20\" min=\"-20\" step=\"1\" type=\"range\" value=\"0\"\/>\n<\/div>\n<div class=\"audiotool772-slider\">\n<label for=\"audiotool772-speed\">Vitesse : <span id=\"audiotool772-speed-v\">1.0<\/span>x<\/label>\n<input id=\"audiotool772-speed\" max=\"2\" min=\"0.5\" step=\"0.1\" type=\"range\" value=\"1\"\/>\n<\/div>\n<div class=\"audiotool772-toggle\">\n<div class=\"audiotool772-toggle__label\">Inverser l'audio<\/div>\n<label class=\"audiotool772-switch\">\n<input id=\"audiotool772-reverse\" type=\"checkbox\"\/>\n<span class=\"audiotool772-switch__track\"><\/span>\n<span class=\"audiotool772-switch__knob\"><\/span>\n<\/label>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- Evidence \/ Indices tool -->\n<div aria-label=\"Outil d'analyse d'indices\" aria-modal=\"true\" class=\"berf-oc berf-oc--nochrome\" id=\"berf-oc-evidencetool\" role=\"dialog\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div class=\"berf-oc__main\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-layer-group\"><\/i> Analyse d'indices<\/div>\n<!-- IMPORTANT: m\u00eame attribut que les autres fen\u00eatres (data-close=\"\") pour que le handler global fonctionne -->\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div class=\"evidtool992-wrap\" id=\"evidtool992-root\">\n<div class=\"evidtool992-app\">\n<!-- Home \/ Search -->\n<section class=\"evidtool992-screen is-active\" id=\"evidtool992-home\">\n<div class=\"evidtool992-topbar\">\n<div class=\"evidtool992-brand\"><span class=\"evidtool992-berf\">BERF<\/span><span class=\"evidtool992-sub\">Base d'indices<\/span><\/div>\n<button aria-label=\"Fermer l'outil\" class=\"evidtool992-iconbtn\" data-close=\"\" id=\"evidtool992-close\" title=\"Fermer\" type=\"button\"><i class=\"fa-solid fa-xmark\"><\/i><\/button>\n<button aria-label=\"Notifications\" class=\"evidtool992-iconbtn\" id=\"evidtool992-bell\" type=\"button\">\n<i class=\"fa-solid fa-bell\"><\/i>\n<span class=\"evidtool992-badge\" id=\"evidtool992-badge\">3<\/span>\n<\/button>\n<\/div>\n<div class=\"evidtool992-card\">\n<div class=\"evidtool992-scanbar\"><div class=\"evidtool992-scanline\"><\/div><\/div>\n<label class=\"evidtool992-label\" for=\"evidtool992-input\">ID de l'indice<\/label>\n<div class=\"evidtool992-row\">\n<input autocomplete=\"off\" class=\"evidtool992-input\" id=\"evidtool992-input\" placeholder=\"Ex: MS808, AG283\u2026\" type=\"text\"\/>\n<button class=\"evidtool992-btn evidtool992-btn-primary\" id=\"evidtool992-analyze\" type=\"button\">\n<i class=\"fa-solid fa-magnifying-glass\"><\/i> Analyser\n              <\/button>\n<\/div>\n<div class=\"evidtool992-actions\">\n<button class=\"evidtool992-btn evidtool992-btn-ghost\" id=\"evidtool992-subs\" type=\"button\">\n<i class=\"fa-solid fa-bookmark\"><\/i> Abonnements\n              <\/button>\n<button aria-label=\"Derniers consult\u00e9s\" class=\"evidtool992-btn evidtool992-btn-ghost\" id=\"evidtool992-recents\" title=\"Raccourci: garde les derniers consult\u00e9s\" type=\"button\">\n<i class=\"fa-solid fa-clock-rotate-left\"><\/i> R\u00e9cents\n              <\/button>\n<\/div>\n<div class=\"evidtool992-hint\">\n              Astuce: clique sur un m\u00e9dia pour l'ouvrir en plein \u00e9cran (zoom possible).\n            <\/div>\n<\/div>\n<\/section>\n<!-- Detail -->\n<section class=\"evidtool992-screen\" id=\"evidtool992-detail\">\n<div class=\"evidtool992-detailhead\">\n<div class=\"evidtool992-titlewrap\">\n<button aria-label=\"Retour\" class=\"evidtool992-iconbtn\" id=\"evidtool992-back\" type=\"button\"><i class=\"fa-solid fa-chevron-left\"><\/i><\/button>\n<h3 class=\"evidtool992-title\" id=\"evidtool992-title\">Indice<\/h3>\n<\/div>\n<div class=\"evidtool992-detailactions\">\n<button class=\"evidtool992-btn evidtool992-btn-ghost\" id=\"evidtool992-copy\" title=\"Copier l'ID\" type=\"button\"><i class=\"fa-regular fa-copy\"><\/i><\/button>\n<button class=\"evidtool992-btn evidtool992-btn-primary\" id=\"evidtool992-subscribe\" type=\"button\"><i class=\"fa-solid fa-bell\"><\/i> S'abonner<\/button>\n<\/div>\n<\/div>\n<div class=\"evidtool992-grid\">\n<div class=\"evidtool992-media\">\n<div class=\"evidtool992-mediaframe\" id=\"evidtool992-mediaframe\">\n<img alt=\"Indice\" id=\"evidtool992-img\" style=\"display:none;\"\/>\n<video controls=\"\" id=\"evidtool992-vid\" style=\"display:none;\"><\/video>\n<audio controls=\"\" id=\"evidtool992-aud\" style=\"display:none;\"><\/audio>\n<div class=\"evidtool992-medialabel\" id=\"evidtool992-medialabel\">Aucun m\u00e9dia<\/div>\n<\/div>\n<\/div>\n<div class=\"evidtool992-analysis\">\n<div class=\"evidtool992-sectiontitle\">Analyse<\/div>\n<p class=\"evidtool992-desc\" id=\"evidtool992-desc\">\u2026<\/p>\n<div class=\"evidtool992-bottomactions\">\n<button class=\"evidtool992-btn evidtool992-btn-ghost\" id=\"evidtool992-edit\" type=\"button\"><i class=\"fa-solid fa-pen-to-square\"><\/i> \u00c9diter<\/button>\n<button class=\"evidtool992-btn evidtool992-btn\" id=\"evidtool992-sendToImg\" style=\"display:none;\" type=\"button\"><i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser l'image<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/section>\n<!-- Edit -->\n<section class=\"evidtool992-screen\" id=\"evidtool992-editScreen\">\n<div class=\"evidtool992-detailhead\">\n<div class=\"evidtool992-titlewrap\">\n<button aria-label=\"Retour\" class=\"evidtool992-iconbtn\" id=\"evidtool992-editBack\" type=\"button\"><i class=\"fa-solid fa-chevron-left\"><\/i><\/button>\n<h3 class=\"evidtool992-title\">\u00c9diter l'analyse<\/h3>\n<\/div>\n<div class=\"evidtool992-detailactions\">\n<button class=\"evidtool992-btn evidtool992-btn-primary\" id=\"evidtool992-save\" type=\"button\"><i class=\"fa-solid fa-floppy-disk\"><\/i> Sauvegarder<\/button>\n<\/div>\n<\/div>\n<textarea class=\"evidtool992-textarea\" id=\"evidtool992-textarea\" placeholder=\"Saisir l'analyse\u2026\"><\/textarea>\n<\/section>\n<!-- Subs -->\n<section class=\"evidtool992-screen\" id=\"evidtool992-subsScreen\">\n<div class=\"evidtool992-detailhead\">\n<div class=\"evidtool992-titlewrap\">\n<button aria-label=\"Retour\" class=\"evidtool992-iconbtn\" id=\"evidtool992-subsBack\" type=\"button\"><i class=\"fa-solid fa-chevron-left\"><\/i><\/button>\n<h3 class=\"evidtool992-title\">Abonnements<\/h3>\n<\/div>\n<\/div>\n<div class=\"evidtool992-list\" id=\"evidtool992-subsList\"><\/div>\n<\/section>\n<!-- Notifs -->\n<section class=\"evidtool992-screen\" id=\"evidtool992-notifScreen\">\n<div class=\"evidtool992-detailhead\">\n<div class=\"evidtool992-titlewrap\">\n<button aria-label=\"Retour\" class=\"evidtool992-iconbtn\" id=\"evidtool992-notifBack\" type=\"button\"><i class=\"fa-solid fa-chevron-left\"><\/i><\/button>\n<h3 class=\"evidtool992-title\">Notifications<\/h3>\n<\/div>\n<\/div>\n<div class=\"evidtool992-list\" id=\"evidtool992-notifList\"><\/div>\n<\/section>\n<!-- Recents -->\n<section class=\"evidtool992-screen\" id=\"evidtool992-recentsScreen\">\n<div class=\"evidtool992-detailhead\">\n<div class=\"evidtool992-titlewrap\">\n<button aria-label=\"Retour\" class=\"evidtool992-iconbtn\" id=\"evidtool992-recentsBack\" type=\"button\"><i class=\"fa-solid fa-chevron-left\"><\/i><\/button>\n<h3 class=\"evidtool992-title\">R\u00e9cents<\/h3>\n<\/div>\n<\/div>\n<div class=\"evidtool992-list\" id=\"evidtool992-recentsList\"><\/div>\n<\/section>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<!-- Knowledge Base tool -->\n<div aria-label=\"Base de connaissance\" aria-modal=\"true\" class=\"berf-oc\" id=\"berf-oc-knowledge\" role=\"dialog\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div class=\"berf-oc__main\" role=\"dialog\" aria-label=\"Base de connaissance\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-book-skull\"><\/i> Base de connaissance<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div class=\"kb901-wrap\" id=\"kb901-root\">\n  <div class=\"kb901-shell\">\n    <aside class=\"kb901-side\">\n      <div class=\"kb901-sideTop\">\n        <div class=\"kb901-brand\">\n          <span class=\"kb901-brandTop\">BERF<\/span>\n          <span class=\"kb901-brandSub\">Annuaire des l\u00e9gendes<\/span>\n        <\/div>\n        <div class=\"kb901-scan\"><span><\/span><\/div>\n      <\/div>\n      <div class=\"kb901-searchRow\">\n        <input id=\"kb901-search\" class=\"kb901-search\" type=\"text\" placeholder=\"Rechercher une l\u00e9gende, un alias, une origine...\" autocomplete=\"off\"\/>\n      <\/div>\n      <div id=\"kb901-list\" class=\"kb901-list\" aria-label=\"R\u00e9sultats\"><\/div>\n    <\/aside>\n    <main class=\"kb901-main\">\n      <div id=\"kb901-empty\" class=\"kb901-empty\">\n        <i class=\"fa-solid fa-book-skull\"><\/i>\n        <h3>Base pr\u00eate<\/h3>\n        <p>S\u00e9lectionne une l\u00e9gende dans la liste ou utilise la recherche.<\/p>\n      <\/div>\n\n      <article id=\"kb901-detail\" class=\"kb901-detail\" style=\"display:none;\">\n        <div class=\"kb901-detailHead\">\n          <div>\n            <div class=\"kb901-kicker\">Fiche de r\u00e9f\u00e9rence<\/div>\n            <h2 id=\"kb901-title\" class=\"kb901-title\">Titre<\/h2>\n            <div id=\"kb901-meta\" class=\"kb901-meta\"><\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"kb901-detailGrid\">\n          <div class=\"kb901-figureWrap\">\n            <div class=\"kb901-figureFrame\" style=\"background:#fff;\">\n              <img id=\"kb901-image\" alt=\"Illustration\" style=\"display:none;\"\/>\n              <div id=\"kb901-noimage\" class=\"kb901-noimage\">\n                <i class=\"fa-regular fa-image\"><\/i>\n                <span>Aucune illustration<\/span>\n              <\/div>\n            <\/div>\n          <\/div>\n          <div class=\"kb901-content\">\n            <div class=\"kb901-tabs\" id=\"kb901-tabs\" role=\"tablist\">\n              <button type=\"button\" class=\"kb901-tab is-active\" data-kb-tab=\"general\">Description g\u00e9n\u00e9rale<\/button>\n              <button type=\"button\" class=\"kb901-tab\" data-kb-tab=\"origin\">Origine suppos\u00e9e<\/button>\n              <button type=\"button\" class=\"kb901-tab\" data-kb-tab=\"capabilities\">Capacit\u00e9s identifi\u00e9es<\/button>\n              <button type=\"button\" class=\"kb901-tab\" data-kb-tab=\"zones\">Zones d\u2019activit\u00e9<\/button>\n              <button type=\"button\" class=\"kb901-tab\" data-kb-tab=\"behavior\">Analyse comportementale<\/button>\n              <button type=\"button\" class=\"kb901-tab\" data-kb-tab=\"note\">Note interne<\/button>\n            <\/div>\n            <div class=\"kb901-tabPanels\">\n              <section class=\"kb901-tabPanel is-active\" data-kb-panel=\"general\">\n                <div class=\"kb901-generalMeta\">\n                  <div class=\"kb901-metaCard\"><span>Classification<\/span><strong id=\"kb901-classification\">\u2014<\/strong><\/div>\n                  <div class=\"kb901-metaCard\"><span>Niveau de menace<\/span><strong id=\"kb901-threat\">\u2014<\/strong><\/div>\n                  <div class=\"kb901-metaCard\"><span>Statut<\/span><strong id=\"kb901-status\">\u2014<\/strong><\/div>\n                <\/div>\n                <div id=\"kb901-general-description\" class=\"kb901-description\"><\/div>\n              <\/section>\n              <section class=\"kb901-tabPanel\" data-kb-panel=\"origin\">\n                <div id=\"kb901-supposed-origin\" class=\"kb901-description\"><\/div>\n              <\/section>\n              <section class=\"kb901-tabPanel\" data-kb-panel=\"capabilities\">\n                <div id=\"kb901-capabilities\" class=\"kb901-description\"><\/div>\n              <\/section>\n              <section class=\"kb901-tabPanel\" data-kb-panel=\"zones\">\n                <div id=\"kb901-zones\" class=\"kb901-description\"><\/div>\n              <\/section>\n              <section class=\"kb901-tabPanel\" data-kb-panel=\"behavior\">\n                <div id=\"kb901-behavior\" class=\"kb901-description\"><\/div>\n              <\/section>\n              <section class=\"kb901-tabPanel\" data-kb-panel=\"note\">\n                <div id=\"kb901-internal-note\" class=\"kb901-description\"><\/div>\n              <\/section>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/article>\n    <\/main>\n  <\/div>\n\n  <div id=\"kb901-viewer\" class=\"kb901-viewer\" aria-hidden=\"true\">\n    <button type=\"button\" id=\"kb901-viewerClose\" class=\"kb901-viewerClose\" aria-label=\"Fermer\">\u00d7<\/button>\n    <div class=\"kb901-viewerInner\">\n      <img id=\"kb901-viewerImg\" alt=\"Illustration agrandie\"\/>\n      <div class=\"berf-viewer-actionbar\">\n        <button id=\"kb901-analyzeBtn\" class=\"berf-viewer-analyze-btn\" type=\"button\"><i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser l'image<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<!-- Route \/ Itin\u00e9raire tool -->\n<div aria-label=\"Outil de suivi d'itin\u00e9raire\" aria-modal=\"true\" class=\"berf-oc\" id=\"berf-oc-route23\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-route\"><\/i> Suivi d'itin\u00e9raire<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div class=\"route23-wrap\" id=\"route23-root\">\n<div class=\"route23-app\">\n<aside class=\"route23-panel route23-panel--left\">\n<div class=\"route23-panelTitle\">Ajouter un point<\/div>\n<div class=\"route23-field\">\n<label class=\"route23-label\" for=\"route23-search\">Localisation ou GPS<\/label>\n<input autocomplete=\"off\" class=\"route23-input\" id=\"route23-search\" placeholder=\"Ex: Saint-Denis, 48.8566, 2.3522\" type=\"text\"\/>\n<\/div>\n<div class=\"route23-row\">\n<button class=\"route23-btn route23-btn-primary\" id=\"route23-add\" type=\"button\"><i class=\"fa-solid fa-plus\"><\/i> Ajouter<\/button>\n<button class=\"route23-btn route23-btn-ghost\" id=\"route23-center\" title=\"Recentrer\" type=\"button\"><i class=\"fa-solid fa-crosshairs\"><\/i><\/button>\n<\/div>\n<div class=\"route23-hint\">Astuce: clic sur la carte pour ajouter un point \u201csans nom\u201d.<\/div>\n<div class=\"route23-mini\">\n<div class=\"route23-miniTitle\">Trace<\/div>\n<div class=\"route23-miniText\">Les segments se coupent automatiquement si deux points cons\u00e9cutifs sont identiques.<\/div>\n<\/div>\n<\/aside>\n<main class=\"route23-mapWrap\">\n<div aria-label=\"Carte\" class=\"route23-map\" id=\"route23-map\"><\/div>\n<\/main>\n<aside class=\"route23-panel route23-panel--right\">\n<div class=\"route23-panelTitle\">Localisations ajout\u00e9es<\/div>\n<div aria-label=\"Liste des localisations\" class=\"route23-list\" id=\"route23-list\"><\/div>\n<button class=\"route23-btn route23-btn-danger\" id=\"route23-clear\" style=\"display:none;\" type=\"button\"><i class=\"fa-solid fa-trash\"><\/i> Supprimer tout<\/button>\n<\/aside>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- Evidence viewer modal (top layer) -->\n<div aria-hidden=\"true\" class=\"evidtool992-viewer\" id=\"evidtool992-viewer\">\n<button aria-label=\"Fermer\" class=\"evidtool992-viewerClose\" id=\"evidtool992-viewerClose\" type=\"button\">\u00d7<\/button>\n<div aria-label=\"Visionneuse indice\" aria-modal=\"true\" class=\"evidtool992-viewerInner\" role=\"dialog\">\n<div class=\"evidtool992-viewerMedia\" id=\"evidtool992-viewerMedia\">\n<img alt=\"Indice\" id=\"evidtool992-viewerImg\" style=\"display:none;\"\/>\n<video controls=\"\" id=\"evidtool992-viewerVid\" style=\"display:none;\"><\/video>\n<audio controls=\"\" id=\"evidtool992-viewerAud\" style=\"display:none;\"><\/audio>\n<\/div>\n<div class=\"evidtool992-viewerHint\">Clique sur l'image pour zoomer.<\/div>\n<div class=\"berf-viewer-actionbar\">\n<button id=\"evidtool992-analyzeViewerBtn\" class=\"berf-viewer-analyze-btn\" type=\"button\" style=\"display:none;\"><i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser l'image<\/button>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"imgtool991-modal-overlay\" id=\"imgtool991-modal\">\n<div class=\"imgtool991-modal\">\n<div class=\"imgtool991-modal-head\">Informations de l'image<\/div>\n<div class=\"imgtool991-modal-body\" id=\"imgtool991-modal-content\"><\/div>\n<button class=\"imgtool991-btn\" id=\"imgtool991-modal-close\">Fermer<\/button>\n<\/div>\n<\/div>\n<!-- ============================================================\nOFF-CANVAS : NAVIGATEUR FICTIF (AJOUT)\n============================================================ -->\n\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-drone\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Module drone\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-helicopter-symbol\"><\/i> Module drone<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"berf-oc__body berf-oc__body--drone\">\n<div id=\"berfDroneTool\" class=\"berf-drone\">\n  <div class=\"berf-drone__sidebar\">\n    <div class=\"berf-drone__head\">\n      <div class=\"berf-drone__eyebrow\">BERF \/ SURVEILLANCE<\/div>\n      <div class=\"berf-drone__name\" data-drone-title>Module drone<\/div>\n      <div class=\"berf-drone__statusBadge\" data-drone-badge data-state=\"offline\">Hors ligne<\/div>\n    <\/div>\n    <label class=\"berf-drone__label\">Code d'acc\u00e8s\n      <input type=\"text\" data-drone-code placeholder=\"Entrer le code drone\" \/>\n    <\/label>\n    <button type=\"button\" class=\"berf-drone__unlock\" data-drone-unlock>Connecter le flux<\/button>\n    <div class=\"berf-drone__meta\">\n      <div><span>\u00c9tat<\/span><strong data-drone-status>Hors ligne<\/strong><\/div>\n      <div><span>Horodatage<\/span><strong data-drone-ts>--<\/strong><\/div>\n    <\/div>\n    <div class=\"berf-drone__notesTitle\">Briefing<\/div>\n    <div class=\"berf-drone__notes\" data-drone-notes>Aucun briefing.<\/div>\n  <\/div>\n  <div class=\"berf-drone__viewer\">\n    <div class=\"berf-drone__hud\" data-drone-hud>\n      <span>ALT 124 m<\/span><span>SIG 98%<\/span><span>CAM 01<\/span><span class=\"berf-drone__rec\">REC<\/span>\n    <\/div>\n    <div class=\"berf-drone__feed\" data-drone-feed>\n      <div class=\"berf-drone-empty\">En attente d'un code d'acc\u00e8s valide.<\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-browser\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Navigateur\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-globe\"><\/i> Navigateur<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div id=\"berfBrowserTool\">\n<div class=\"browser123 berfBrowser\">\n<div class=\"browser-header123 berfBrowser__top\">\n<div class=\"nav-buttons123 berfBrowser__nav\">\n<button aria-label=\"Retour\" class=\"nav-btn123 berfBrowser__btn\" data-nav=\"back\" type=\"button\">\n<i class=\"fa-solid fa-arrow-left\"><\/i>\n<\/button>\n<button aria-label=\"Avancer\" class=\"nav-btn123 berfBrowser__btn\" data-nav=\"forward\" type=\"button\">\n<i class=\"fa-solid fa-arrow-right\"><\/i>\n<\/button>\n<button aria-label=\"Accueil\" class=\"nav-btn123 berfBrowser__btn\" data-nav=\"home\" type=\"button\">\n<i class=\"fa-solid fa-house\"><\/i>\n<\/button>\n<\/div>\n<input autocomplete=\"off\" class=\"address-bar123 berfBrowser__address\" id=\"addressBar123\" placeholder=\"Recherche ou URL (bdgchastel-myblog.com, test.com, helton.fr)\" type=\"text\">\n<button aria-label=\"Historique\" class=\"menu-btn123 berfBrowser__btn\" id=\"historyBtn123\" type=\"button\">\n<i class=\"fa-solid fa-clock-rotate-left\"><\/i>\n<\/button>\n<\/input><\/div>\n<div class=\"browser-tabs123 berfBrowser__tabs\" id=\"tabContainer123\">\n<div aria-label=\"Nouvel onglet\" class=\"browser-tab123 berfBrowser__tab\" id=\"addTab123\" role=\"button\" tabindex=\"0\">+<\/div>\n<\/div>\n<div class=\"browser-content123 berfBrowser__content\" id=\"content123\"><\/div>\n<\/div>\n<div aria-hidden=\"true\" class=\"history-modal123 berfBrowser__history\" id=\"historyModal123\">\n<button aria-label=\"Fermer\" class=\"close-history123 berfBrowser__btn\" id=\"historyClose123\" type=\"button\">\u00d7<\/button>\n<h3>Historique<\/h3>\n<div id=\"historyList123\"><\/div>\n<\/div>\n<div aria-hidden=\"true\" class=\"berfBrowser__eggOverlay\" id=\"easterEggOverlay123\"><\/div>\n<div aria-hidden=\"true\" class=\"berfBrowser__egg\" id=\"easterEggContainer123\">\n<h2>\ud83c\udf89 Surprise ! \ud83c\udf89<\/h2>\n<p>Acc\u00e8s cach\u00e9 d\u00e9bloqu\u00e9.<\/p>\n<button class=\"berfBrowser__eggClose\" id=\"closeEasterEgg123\" type=\"button\">Fermer<\/button>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-filemanager\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Gestionnaire de fichiers\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-folder-tree\"><\/i> Gestionnaire de fichiers<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n<div id=\"berfFileManagerTool\" class=\"berf-filemanager\">\n  <div class=\"berf-filemanager__sidebar\">\n    <div class=\"berf-filemanager__sidebarHead\">\n      <div class=\"berf-filemanager__sidebarTitle\">Dossiers<\/div>\n      <div class=\"berf-filemanager__sidebarSub\">Archives BERF<\/div>\n    <\/div>\n    <div id=\"berfFileManagerFolders\" class=\"berf-filemanager__folders\"><\/div>\n  <\/div>\n\n  <div class=\"berf-filemanager__main\">\n    <div class=\"berf-filemanager__toolbar\">\n      <button type=\"button\" class=\"berf-filemanager__ghost\" id=\"berfFileManagerBack\" style=\"display:none;\">\n        <i class=\"fa-solid fa-arrow-left\"><\/i> Retour\n      <\/button>\n      <div class=\"berf-filemanager__crumbs\" id=\"berfFileManagerCrumbs\">S\u00e9lectionne un dossier<\/div>\n      <button type=\"button\" class=\"berf-filemanager__primary\" id=\"berfFileManagerLockBtn\" style=\"display:none;\">\n        <i class=\"fa-solid fa-lock\"><\/i> Verrouiller ce dossier\n      <\/button>\n    <\/div>\n\n    <div class=\"berf-filemanager__stage\" id=\"berfFileManagerStage\">\n      <div class=\"berf-filemanager__empty\">\n        <i class=\"fa-solid fa-folder-open\"><\/i>\n        <strong>Gestionnaire pr\u00eat<\/strong>\n        <span>Choisis un dossier dans la colonne de gauche.<\/span>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div class=\"berf-fileviewer\" id=\"berfFileViewer\" aria-hidden=\"true\">\n  <div class=\"berf-fileviewer__backdrop\" data-fileviewer-close><\/div>\n  <div class=\"berf-fileviewer__dialog\" role=\"dialog\" aria-label=\"Visionneuse de fichier\">\n    <div class=\"berf-fileviewer__head\">\n      <div class=\"berf-fileviewer__title\" id=\"berfFileViewerTitle\">Visionneuse<\/div>\n      <div class=\"berf-fileviewer__actions\">\n        <button type=\"button\" class=\"berf-fileviewer__analyze\" id=\"berfFileViewerAnalyze\" style=\"display:none;\">\n          <i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser\n        <\/button>\n        <button type=\"button\" class=\"berf-fileviewer__analyze\" id=\"berfFileViewerCollect\" style=\"display:none;\">\n          <i class=\"fa-solid fa-download\"><\/i> Ajouter aux \u00e9l\u00e9ments collect\u00e9s\n        <\/button>\n        <button type=\"button\" class=\"berf-fileviewer__close\" data-fileviewer-close aria-label=\"Fermer\">\u00d7<\/button>\n      <\/div>\n    <\/div>\n    <div class=\"berf-fileviewer__body\" id=\"berfFileViewerBody\"><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"berf-filelockmodal\" id=\"berfFileLockModal\" aria-hidden=\"true\">\n  <div class=\"berf-filelockmodal__backdrop\" data-filelock-close><\/div>\n  <div class=\"berf-filelockmodal__dialog\" role=\"dialog\" aria-label=\"Verrouillage de dossier\">\n    <div class=\"berf-filelockmodal__head\">\n      <div class=\"berf-filelockmodal__title\" id=\"berfFileLockTitle\">Verrouillage du dossier<\/div>\n      <button type=\"button\" class=\"berf-filelockmodal__close\" data-filelock-close aria-label=\"Fermer\">\u00d7<\/button>\n    <\/div>\n    <div class=\"berf-filelockmodal__body\">\n      <p class=\"berf-filelockmodal__text\" id=\"berfFileLockText\">D\u00e9finis un mot de passe pour ce dossier.<\/p>\n\n      <div class=\"berf-filelockmodal__unlock\" id=\"berfFileUnlockWrap\" style=\"display:none;\">\n        <label>Mot de passe\n          <input type=\"password\" id=\"berfFileUnlockPassword\" autocomplete=\"off\" \/>\n        <\/label>\n      <\/div>\n\n      <div class=\"berf-filelockmodal__create\" id=\"berfFileCreateWrap\" style=\"display:none;\">\n        <label>Nouveau mot de passe\n          <input type=\"password\" id=\"berfFileCreatePassword\" autocomplete=\"new-password\" \/>\n        <\/label>\n        <label>Confirmation\n          <input type=\"password\" id=\"berfFileCreatePasswordConfirm\" autocomplete=\"new-password\" \/>\n        <\/label>\n      <\/div>\n\n      <div class=\"berf-filelockmodal__error\" id=\"berfFileLockError\" style=\"display:none;\"><\/div>\n\n      <div class=\"berf-filelockmodal__actions\">\n        <button type=\"button\" class=\"berf-filemanager__ghost\" id=\"berfFileLockRemove\" style=\"display:none;\">Retirer le mot de passe<\/button>\n        <button type=\"button\" class=\"berf-filemanager__ghost\" data-filelock-close>Annuler<\/button>\n        <button type=\"button\" class=\"berf-filemanager__primary\" id=\"berfFileLockSubmit\">Valider<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<div aria-hidden=\"true\" class=\"berf-oc\" id=\"berf-oc-calculator\">\n<div class=\"berf-oc__overlay\" data-close=\"\"><\/div>\n<div aria-label=\"Calculatrice s\u00e9curis\u00e9e\" class=\"berf-oc__main\" role=\"dialog\">\n<div class=\"berf-oc__top\">\n<div class=\"berf-oc__title\"><i class=\"fa-solid fa-calculator\"><\/i> Calculatrice s\u00e9curis\u00e9e<\/div>\n<button aria-label=\"Fermer\" class=\"berf-oc__close\" data-close=\"\" type=\"button\">\u00d7<\/button>\n<\/div>\n<div class=\"berf-oc__body\">\n  <div id=\"berfCalcTool\" class=\"berf-calc\">\n    <div class=\"berf-calc__screenWrap\">\n      <div class=\"berf-calc__label\"><\/div>\n      <input type=\"text\" id=\"berfCalcDisplay\" class=\"berf-calc__screen\" inputmode=\"decimal\" autocomplete=\"off\" placeholder=\"0\" \/>\n      <div class=\"berf-calc__status\" id=\"berfCalcStatus\"><\/div>\n    <\/div>\n    <div class=\"berf-calc__keys\">\n      <button type=\"button\" data-calc-key=\"7\">7<\/button>\n      <button type=\"button\" data-calc-key=\"8\">8<\/button>\n      <button type=\"button\" data-calc-key=\"9\">9<\/button>\n      <button type=\"button\" data-calc-action=\"clear\">C<\/button>\n      <button type=\"button\" data-calc-key=\"4\">4<\/button>\n      <button type=\"button\" data-calc-key=\"5\">5<\/button>\n      <button type=\"button\" data-calc-key=\"6\">6<\/button>\n      <button type=\"button\" data-calc-key=\"-\">\u2212<\/button>\n      <button type=\"button\" data-calc-key=\"1\">1<\/button>\n      <button type=\"button\" data-calc-key=\"2\">2<\/button>\n      <button type=\"button\" data-calc-key=\"3\">3<\/button>\n      <button type=\"button\" data-calc-key=\"+\">+<\/button>\n      <button type=\"button\" data-calc-key=\"0\">0<\/button>\n      <button type=\"button\" data-calc-key=\".\">.<\/button>\n      <button type=\"button\" data-calc-key=\"*\">\u00d7<\/button>\n      <button type=\"button\" class=\"is-equals\" data-calc-action=\"equals\">=<\/button>\n      <button type=\"button\" class=\"is-wide\" data-calc-key=\"\/\">\u00f7<\/button>\n      <button type=\"button\" class=\"is-wide\" data-calc-action=\"backspace\"><i class=\"fa-solid fa-delete-left\"><\/i><\/button>\n    <\/div>\n    <div class=\"berf-calc__hint\"><\/div>\n  <\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<!-- berf-oc -->\n\n<style>\n\/* ===== Desk shell ===== *\/\n#berfDesk{\n  position:relative; width:100%;\n  min-height:720px; height:min(86vh, 940px);\n  border-radius:22px; overflow:hidden;\n  border:1px solid rgba(255,255,255,0.08);\n  box-shadow:0 18px 60px rgba(0,0,0,0.55);\n  background:#000;\n  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n\n  z-index:999999; \/* keep above Elementor overlays *\/\n  pointer-events:auto;\n  isolation:isolate;\n}\n#berfDesk #berfSessionTransition{position:fixed;inset:0;z-index:2000000;background:#07100e;display:none;place-items:center;color:#fff;font-family:Roboto Mono,monospace}\n#berfDesk #berfSessionTransition.is-active{display:grid}\n#berfDesk .berf-session-card{display:grid;justify-items:center;gap:18px;text-align:center}\n#berfDesk .berf-session-spinner{width:46px;height:46px;border:3px solid rgba(255,255,255,.18);border-top-color:#af3232;border-radius:50%;animation:berfSessionSpin .8s linear infinite}\n@keyframes berfSessionSpin{to{transform:rotate(360deg)}}\n#berfDesk #berfSessionBadge{position:fixed;right:22px;top:18px;z-index:1000010;background:rgba(7,16,14,.92);border:1px solid rgba(175,50,50,.55);color:#fff;padding:9px 14px;border-radius:8px;font:700 12px\/1.3 Roboto Mono,monospace;letter-spacing:.04em}\n\n#berfDesk .berf-bg{\n  position:absolute; inset:0;\n  background:\n    radial-gradient(1200px 800px at 20% 10%, rgba(255,255,255,0.08), transparent 60%),\n    radial-gradient(900px 700px at 80% 30%, rgba(175,50,50,0.10), transparent 60%),\n    linear-gradient(120deg, #0b0f14, #0b111a 40%, #070a0f);\n\n  pointer-events:none;\n  pointer-events:none;\n}\n\n\/* ===== Left bar ===== *\/\n#berfDesk .berf-leftbar{\n  position:absolute; top:110px; left:22px;\n  display:flex; flex-direction:column; gap:14px;\n  z-index:5;\n}\n#berfDesk .berf-app{\n  width:60px; height:60px;\n  border-radius:16px;\n  border:1px solid rgba(255,255,255,0.10);\n  background: rgba(175,50,50,0.85);\n  box-shadow:0 10px 28px rgba(0,0,0,0.40);\n  color:white;\n  display:grid; place-items:center;\n  cursor:pointer;\n  position:relative;\n}\n#berfDesk .berf-app:disabled{ opacity:.45; cursor:not-allowed; }\n#berfDesk .berf-app i{ font-size:22px; }\n#berfDesk .berf-badge{\n  position:absolute; top:-8px; right:-8px;\n  min-width:24px; height:24px; padding:0 6px;\n  border-radius:999px;\n  background:#ffffff; color:#af3232;\n  font-weight:800; font-size:12px;\n  display:flex; align-items:center; justify-content:center;\n  box-shadow:0 10px 26px rgba(0,0,0,0.35);\n}\n#berfDesk .mail-widget[data-unread=\"0\"] .berf-badge{ display:none; }\n#berfDesk .evid-widget[data-unread=\"0\"] .berf-badge{ display:none; }\n#berfDesk .evid-taskbar-widget{ position:relative; }\n#berfDesk .evid-taskbar-widget .berf-badge{\n  top:-6px; right:-6px;\n  min-width:20px; height:20px; font-size:11px;\n}\n#berfDesk .evid-taskbar-widget[data-unread=\"0\"] .berf-badge{ display:none; }\n\n\/* ============================================================\nBARRE DU BAS + START MENU (scop\u00e9)\n============================================================ *\/\n#berfDesk .berf-taskbar{\n  position:absolute;\n  left:0; right:0; bottom:0;\n  height:64px;\n  display:flex;\n  align-items:center;\n  padding: 0 14px;\n  background: rgba(0,0,0,0.35);\n  border-top: 1px solid rgba(255,255,255,0.10);\n  backdrop-filter: blur(10px);\n  z-index: 50;\n}\n\n\/* ton Start menu (scop\u00e9) *\/\n#berfDesk .start-menu-container{ position: relative; display: flex; align-items: center; gap: 10px; }\n\n#berfDesk .start-button{\n  background-color: transparent !important;\n  color: #af3232 !important;\n  border: none;\n  padding: 0px 20px;\n  border-radius: 5px;\n  cursor: pointer;\n  font-size: 32px;\n  display: flex;\n  align-items: center;\n}\n#berfDesk .start-button i{ margin-right: 8px; }\n\n#berfDesk .start-menu{\n  display:none;\n  position:absolute;\n  bottom: 72px;\n  left: 0;\n  width: 240px;\n  background-color: #000;\n  border: 1px solid #7a7a7a33;\n  box-shadow: 0px 18px 50px rgba(0,0,0,0.55);\n  border-radius: 10px;\n  opacity: 0;\n  transform: scale(0.96);\n  transform-origin: bottom left;\n  transition: opacity 0.2s ease, transform 0.2s ease;\n  overflow:hidden;\n}\n#berfDesk .start-menu.show{\n  display:block;\n  opacity:1;\n  transform: scale(1);\n}\n#berfDesk .start-menu ul{ list-style:none; padding:0; margin:0; }\n\n#berfDesk .start-menu ul li{\n  padding: 10px 12px;\n  border-bottom: 1px solid #7a7a7a33;\n}\n#berfDesk .start-menu ul li a{\n  text-decoration:none;\n  color: #e9e9e9;\n  cursor:pointer;\n  display:flex;\n  align-items:center;\n  gap:10px;\n  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n  font-size: 14px;\n}\n#berfDesk .start-menu ul li:hover{ background-color: rgba(255,255,255,0.08); }\n\n#berfDesk .start-menu ul li.berf-sep{\n  padding:0; height:1px;\n  background: rgba(255,255,255,0.10);\n  border-bottom:none;\n}\n\n#berfDesk .menu-bottom-icons{\n  padding: 10px 12px;\n  display:flex;\n  justify-content:flex-end;\n  border-top: 1px solid #7a7a7a33;\n  background: rgba(255,255,255,0.02);\n}\n#berfDesk .icon-container{ cursor:pointer; }\n#berfDesk .icon-container i{ font-size: 20px; color: #e9e9e9; }\n#berfDesk .icon-container:hover i{ color:#af3232; }\n\n\/* ===== Off-canvas runtime ===== *\/\n#berfDesk .berf-oc{ position:fixed; inset:0; z-index:99990; display:none; }\n#berfDesk .berf-oc[data-open=\"true\"]{ display:block; }\n#berfDesk .berf-oc__overlay{ position:absolute; inset:0; background:rgba(0,0,0,0.65); }\n#berfDesk .berf-oc__main{\n  position:absolute; top:0; right:0;\n  height:100%; width:min(1100px, 96vw);\n  background: rgba(20,24,30,0.95);\n  border-left:1px solid rgba(255,255,255,0.10);\n  box-shadow:0 18px 60px rgba(0,0,0,0.55);\n  overflow:auto;\n}\n#berfDesk .berf-oc__top{\n  position:sticky; top:0;\n  display:flex; align-items:center; justify-content:space-between;\n  gap:12px;\n  padding:12px 14px;\n  background: rgba(0,0,0,0.35);\n  border-bottom:1px solid rgba(255,255,255,0.10);\n  backdrop-filter: blur(10px);\n  z-index:2;\n}\n#berfDesk .berf-oc__title{ color:rgba(255,255,255,0.92); font-weight:800; }\n#berfDesk .berf-oc__close{\n  width:40px; height:40px;\n  border-radius:12px;\n  border:1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color:rgba(255,255,255,0.92);\n  cursor:pointer;\n  font-size:20px;\n}\n\n\/* ===== MAIL TOOL (scop\u00e9) ===== *\/\n#berfMailTool *{ margin:0; padding:0; box-sizing:border-box; }\n#berfMailTool .date{ font-size:10px; }\n#berfMailTool span#sender-name{ color:black; font-weight:600; }\n#berfMailTool span#sender-email{ color:black; }\n#berfMailTool textarea#message, #berfMailTool textarea#replyMessage{ width:100% !important; }\n\n#berfMailTool .inbox-container{\n  display:flex; flex-direction:column;\n  max-width:100%; min-height:73vh;\n  margin:20px auto;\n  background:#fff; border:1px solid #ddd;\n  box-shadow:0 0 10px rgba(0,0,0,0.1);\n}\n#berfMailTool .email-list{\n  width:100%; max-width:100%;\n  border-right:1px solid #ddd;\n  padding:10px;\n  background:#f9f9f9;\n  display:flex; flex-direction:column;\n  overflow-y:auto; position:relative;\n}\n#berfMailTool .email-item{\n  display:flex; justify-content:space-between; align-items:center;\n  padding:10px; cursor:pointer;\n  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;\n  color:black;\n}\n#berfMailTool .email-item:hover{ background:#e0e0e0; }\n#berfMailTool .unread{ background:#f4f4f4; font-weight:bold; }\n#berfMailTool .new-indicator{ width:10px; height:10px; background:#af3232; border-radius:50%; }\n#berfMailTool .email-info .subject{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:200px; }\n\n#berfMailTool .email-details{ width:100%; padding:20px; color:black; min-height:50vh; display:block; }\n#berfMailTool .details-header{ display:flex; align-items:center; margin-bottom:10px; }\n#berfMailTool .avatar{\n  width:35px; height:35px; border-radius:50%;\n  display:flex; align-items:center; justify-content:center;\n  background:#af3232; color:#fff; font-weight:bold;\n  margin-right:10px;\n}\n#berfMailTool .details-avatar{\n  width:40px; height:40px; border-radius:50%;\n  display:flex; align-items:center; justify-content:center;\n  background:#af3232; color:#fff; font-weight:bold;\n  margin-right:10px;\n}\n#berfMailTool .sender-date{ margin:6px 0 14px; color:#222; font-size:13px; }\n#berfMailTool .message-body{\n  background:#e6e6e6; padding:15px; border-radius:5px; color:black;\n  overflow-wrap:break-word; margin-bottom:20px;\n  line-height:1.6; height:38vh; overflow-y:scroll;\n  white-space: pre-wrap;\n}\n#berfMailTool .message-body [data-berf-action=\"load-session\"]{\n  display:inline-flex !important;\n  width:auto !important;\n  max-width:100% !important;\n  min-height:44px !important;\n  box-sizing:border-box !important;\n  align-items:center !important;\n  justify-content:center !important;\n  padding:13px 20px !important;\n  margin:6px 0 !important;\n  border:1px solid rgba(255,255,255,.15) !important;\n  border-radius:6px !important;\n  background:#af3232 !important;\n  color:#fff !important;\n  font:700 15px\/1.2 \"Segoe UI\",Arial,sans-serif !important;\n  text-decoration:none !important;\n  white-space:normal !important;\n  cursor:pointer !important;\n}\n#berfMailTool .message-body [data-berf-action=\"load-session\"]:hover,\n#berfMailTool .message-body [data-berf-action=\"load-session\"]:focus-visible{\n  background:#c83e3e !important;\n  box-shadow:0 0 0 3px rgba(175,50,50,.25) !important;\n  outline:none !important;\n}\n#berfMailTool .attachments{ margin-top:20px; display:flex; gap:12px; flex-wrap:wrap; }\n#berfMailTool .attachment-element{ display:block; cursor:pointer; padding:5px; margin-bottom:5px; }\n#berfMailTool .attachment-icon{\n  color:#af3232; font-size:35px;\n  border:1px groove; width:54%; text-align:center;\n}\n#berfMailTool span.attachment-name{ font-size:12px; }\n\n#berfMailTool .modal{\n  display:none; position:fixed; inset:0;\n  background:rgba(0,0,0,0.5);\n  justify-content:center; align-items:center;\n  z-index: 100000;\n}\n#berfMailTool .modal-content{\n  position:relative;\n  background:#1E1E1E;\n  padding:20px; border-radius:5px;\n  width:min(700px, 92vw) !important; max-height:80%;\n  overflow:auto; color:#fff;\n}\n#berfMailTool .close{\n  position:absolute; top:10px; right:20px;\n  cursor:pointer; font-size:18px; color:#fff;\n}\n#berfMailTool #attachmentPreview iframe{ width:100%; height:500px; border:none; }\n@media (min-width:768px){\n  #berfMailTool .inbox-container{ flex-direction:row; }\n  #berfMailTool .email-list{ width:30%; }\n  #berfMailTool .email-details{ width:70%; }\n}\n#berfMailTool .email-list #newMailButton{\n  width:100%; padding:15px; background:#af3232; color:#fff;\n  border:none; cursor:pointer; font-size:16px;\n  position:absolute; bottom:0; left:0; margin-bottom:10px;\n}\n\n\/* ===== SUSPECTS TOOL (scop\u00e9) ===== *\/\n#berfSuspectsTool{ padding: 0 0 30px 0; }\n#berfSuspectsTool *{ box-sizing:border-box; }\n#berfSuspectsTool .container42X{\n  width:95%; max-width:1200px;\n  margin:20px auto; padding:20px;\n  background-color: rgba(30,30,30,0.8);\n  border-radius:10px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.5);\n  position:relative; overflow:hidden;\n}\n#berfSuspectsTool h1{\n  font-family:'Roboto Mono', monospace;\n  font-size:2em; text-align:center; margin-bottom:20px;\n  color:#eee;\n}\n#berfSuspectsTool .btn42X{\n  padding:10px 20px; background:#af3232; color:#fff;\n  border:none; border-radius:5px; cursor:pointer;\n  font-family:'Roboto Mono', monospace; font-size:0.9em;\n}\n#berfSuspectsTool .suspect-table42X{ width:100%; border-collapse:collapse; margin-top:20px; }\n#berfSuspectsTool .suspect-table42X th,#berfSuspectsTool .suspect-table42X td{\n  padding:12px 15px; text-align:left; border-bottom:1px solid #444;\n}\n#berfSuspectsTool .suspect-table42X th{ background:#333; color:#eee; font-family:'Roboto Mono', monospace; }\n#berfSuspectsTool .suspect-table42X td{ font-family:'Roboto Mono', monospace; font-size:0.85em; color:#eee; }\n#berfSuspectsTool .avatar42X{\n  width:40px; height:40px; border-radius:50%;\n  display:flex; align-items:center; justify-content:center;\n  font-weight:bold; color:#fff; background:#777;\n}\n#berfSuspectsTool .modal42X{\n  display:none; position:fixed; inset:0; z-index:100000;\n  background: rgba(0,0,0,0.7);\n  justify-content:center; align-items:center;\n}\n#berfSuspectsTool .modal-content42X{\n  background:#333; padding:20px; border-radius:10px;\n  width:min(650px, 92vw); color:#eee;\n}\n#berfSuspectsTool .form-control42X{\n  width:100%; padding:10px; background:#444; color:#eee;\n  border:1px solid #555; border-radius:5px;\n  font-family:'Roboto Mono', monospace;\n}\n#berfSuspectsTool .loader42X{\n  display:none; width:30px; height:30px;\n  border:4px solid #f3f3f3; border-top:4px solid #3498db;\n  border-radius:50%; animation: spin 1s linear infinite; margin: 10px auto 0;\n}\n@keyframes spin{ 0%{transform:rotate(0)} 100%{transform:rotate(360deg)} }\n#berfSuspectsTool .warning-message42X{ display:none; color:#ffc107; text-align:center; }\n#berfSuspectsTool .success-message42X{ display:none; background:#4CAF50; color:#fff; padding:10px; border-radius:5px; text-align:center; }\n#berfSuspectsTool .log-container42X{\n  position: sticky; bottom: 12px; width: 280px; margin-left: 14px;\n  background: rgba(0,0,0,0.8); color:#af3232;\n  font-family:'Roboto Mono', monospace; font-size:0.8em;\n  padding:10px; overflow-y:auto; max-height:150px;\n  border:1px solid #333; border-radius:5px;\n}\n#berfSuspectsTool .log-container42X p{ margin:0; padding:2px 0; white-space:pre-wrap; }\n\n\/* ===== CRYPTO TOOL (scop\u00e9) ===== *\/\n#berfCryptoTool{ padding: 20px 18px 40px; }\n#berfCryptoTool .container01{ display:flex; gap:20px; align-items:center; margin-top:20px; }\n#berfCryptoTool .column01{ width:100vw; }\n#berfCryptoTool textarea, #berfCryptoTool input{\n  width:100%;\n  padding:10px;\n  margin-bottom:10px;\n  border-radius:5px;\n  background-color:#7a7a7a33;\n  color:white;\n  border:1px solid rgba(255,255,255,0.12);\n}\n#berfCryptoTool #output01{ color:#af3232; font-size:1.7em; font-weight:700; position:relative; }\n#berfCryptoTool .copy-button01{\n  position:absolute;\n  bottom:10px; right:10px;\n  background-color:transparent !important;\n  border:none;\n  cursor:pointer;\n  color:#af3232;\n  font-size:1em;\n}\n#berfCryptoTool .center-button01{ display:flex; align-items:center; justify-content:center; }\n#berfCryptoTool .switch-button01{\n  padding:10px;\n  cursor:pointer;\n  border:none;\n  background-color:transparent !important;\n  color:white;\n  font-size:1.5em;\n  border-radius:50%;\n}\n#berfCryptoTool label{ color:white; font-weight:600; }\n\n#berfCryptoTool .mode-indicator01{\n  padding:10px 20px;\n  font-size:1.2em;\n  font-weight:bold;\n  border-radius:5px;\n  text-align:center;\n  margin-bottom:15px;\n  color:white;\n}\n#berfCryptoTool .encrypt-mode01{ background-color:#af3232; }\n#berfCryptoTool .decrypt-mode01{ background-color:#28a745; }\n\n#berfCryptoTool .toast{\n  visibility:hidden;\n  min-width:250px;\n  margin-left:-125px;\n  background-color:#333;\n  color:#fff;\n  text-align:center;\n  border-radius:5px;\n  padding:16px;\n  position:fixed;\n  z-index:100000;\n  left:50%;\n  bottom:30px;\n  font-size:17px;\n  opacity:0;\n  transition: opacity 0.5s, bottom 0.5s;\n}\n#berfCryptoTool .toast.show{\n  visibility:visible;\n  opacity:1;\n  bottom:50px;\n}\n\n\/* ===== TROMBI TOOL (scop\u00e9) ===== *\/\n#berfTrombiTool{\n  padding: 18px 16px 40px;\n  font-family: 'Roboto Mono', monospace;\n  color: rgba(255,255,255,0.92);\n}\n#berfTrombiTool .trombi77__header{\n  display:flex;\n  gap:12px;\n  align-items:center;\n  justify-content:space-between;\n  flex-wrap:wrap;\n  margin: 6px 0 16px;\n}\n#berfTrombiTool #search-bar-77{\n  flex: 1 1 420px;\n  width:100%;\n  padding: 12px 12px;\n  border-radius: 12px;\n  background: rgba(255,255,255,0.06);\n  border: 1px solid rgba(255,255,255,0.10);\n  color: white;\n  font-size: 14px;\n  outline: none;\n}\n#berfTrombiTool #search-bar-77:focus{\n  border-color: rgba(175,50,50,0.55);\n  box-shadow: 0 0 0 4px rgba(175,50,50,0.15);\n}\n#berfTrombiTool .trombi77__count{\n  padding: 10px 12px;\n  border-radius: 12px;\n  background: rgba(0,0,0,0.35);\n  border: 1px solid rgba(255,255,255,0.10);\n  font-size: 13px;\n  white-space:nowrap;\n}\n#berfTrombiTool .trombi77__grid{\n  display:grid;\n  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n  gap: 14px;\n}\n#berfTrombiTool .agent-77{\n  position:relative;\n  border-radius: 16px;\n  overflow:hidden;\n  cursor:pointer;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(0,0,0,0.30);\n  box-shadow: 0 12px 30px rgba(0,0,0,0.35);\n}\n#berfTrombiTool .agent-77 img{\n  width:100%;\n  aspect-ratio: 1 \/ 1;\n  object-fit: cover;\n  transform: scale(1.01);\n  transition: transform .25s ease;\n  display:block;\n}\n#berfTrombiTool .agent-77:hover img{\n  transform: scale(1.06);\n}\n#berfTrombiTool .info-77{\n  position:absolute;\n  inset: auto 0 0 0;\n  padding: 10px 10px 12px;\n  background: linear-gradient(180deg, transparent, rgba(0,0,0,0.75) 40%, rgba(0,0,0,0.92));\n  color:white;\n  opacity: 0;\n  transform: translateY(6px);\n  transition: opacity .2s ease, transform .2s ease;\n}\n#berfTrombiTool .agent-77:hover .info-77{\n  opacity:1;\n  transform: translateY(0);\n}\n#berfTrombiTool .info-77 .line1{ font-weight:800; font-size: 13px; }\n#berfTrombiTool .info-77 .line2{ font-size: 12px; opacity:.92; margin-top: 2px; }\n#berfTrombiTool .info-77 .line3{ font-size: 11px; opacity:.78; margin-top: 2px; }\n\n#berfTrombiTool .trombi77__modal{\n  display:none;\n  position:fixed;\n  inset:0;\n  background: rgba(0,0,0,0.72);\n  z-index: 100000;\n  align-items:center;\n  justify-content:center;\n  padding: 18px;\n}\n#berfTrombiTool .trombi77__modal[data-open=\"true\"]{ display:flex; }\n\n#berfTrombiTool .trombi77__modalCard{\n  width: min(820px, 96vw);\n  border-radius: 18px;\n  background: rgba(20,24,30,0.96);\n  border: 1px solid rgba(255,255,255,0.10);\n  box-shadow: 0 22px 80px rgba(0,0,0,0.65);\n  padding: 16px;\n  position:relative;\n}\n#berfTrombiTool .trombi77__close{\n  position:absolute;\n  top: 12px;\n  right: 12px;\n  width: 40px;\n  height: 40px;\n  border-radius: 12px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  cursor:pointer;\n  font-size: 20px;\n}\n#berfTrombiTool .trombi77__modalTop{\n  display:flex;\n  gap: 14px;\n  align-items:center;\n}\n#berfTrombiTool #modal-photo{\n  width: 110px;\n  height: 110px;\n  border-radius: 18px;\n  object-fit: cover;\n  border: 1px solid rgba(255,255,255,0.12);\n}\n#berfTrombiTool .trombi77__modalIdentity h2{\n  margin:0;\n  font-size: 18px;\n  font-weight: 900;\n}\n#berfTrombiTool .trombi77__sub{\n  margin-top: 6px;\n  font-size: 13px;\n  opacity: .85;\n}\n#berfTrombiTool .trombi77__pill{\n  display:inline-flex;\n  gap:8px;\n  align-items:center;\n  margin-top: 8px;\n  padding: 8px 10px;\n  border-radius: 999px;\n  border: 1px solid rgba(175,50,50,0.35);\n  background: rgba(175,50,50,0.12);\n  font-size: 12px;\n  font-weight: 800;\n  width: fit-content;\n}\n#berfTrombiTool .trombi77__fields{\n  display:grid;\n  grid-template-columns: repeat(2, minmax(0,1fr));\n  gap: 10px;\n  margin-top: 14px;\n}\n#berfTrombiTool .trombi77__field{\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.05);\n  padding: 10px 12px;\n}\n#berfTrombiTool .trombi77__field span{\n  display:block;\n  font-size: 11px;\n  opacity:.75;\n}\n#berfTrombiTool .trombi77__field b{\n  display:block;\n  margin-top: 4px;\n  font-size: 13px;\n  color: rgba(255,255,255,0.95);\n}\n@media (max-width: 560px){\n  #berfTrombiTool .trombi77__fields{ grid-template-columns: 1fr; }\n  #berfTrombiTool .trombi77__modalTop{ align-items:flex-start; }\n}\n\n\/* ===== FILE EXPLORER TOOL (scop\u00e9) ===== *\/\n#berfFilesTool{\n  padding: 18px 16px 40px;\n  font-family: 'Roboto Mono', monospace;\n  color: rgba(255,255,255,0.92);\n}\n#berfFilesTool *{ box-sizing: border-box; }\n#berfFilesTool #file-explorer573{\n  display:flex;\n  flex-direction:column;\n  align-items:center;\n  margin: 6px 0 0;\n}\n#berfFilesTool #folders-container928{\n  display:grid;\n  grid-template-columns: repeat(5, minmax(150px, 1fr));\n  gap: 20px;\n  width: min(1100px, 96vw);\n  margin-bottom: 20px;\n}\n@media (max-width: 980px){\n  #berfFilesTool #folders-container928{ grid-template-columns: repeat(3, minmax(150px, 1fr)); }\n}\n@media (max-width: 560px){\n  #berfFilesTool #folders-container928{ grid-template-columns: repeat(2, minmax(140px, 1fr)); }\n}\n\n#berfFilesTool .folder751{\n  display:flex;\n  flex-direction:column;\n  align-items:center;\n  cursor:pointer;\n  transition: transform 0.3s, box-shadow 0.3s;\n  grid-row: auto \/ span 1;\n  padding: 14px 10px;\n  border-radius: 16px;\n  border:1px solid rgba(255,255,255,0.10);\n  background: rgba(0,0,0,0.30);\n  box-shadow: 0 12px 30px rgba(0,0,0,0.35);\n}\n#berfFilesTool .folder751:hover{ transform: scale(1.05); }\n#berfFilesTool .folder751 i{ font-size: 60px; color: #f1c40f; }\n#berfFilesTool .folder751 span{ margin-top: 10px; text-align:center; font-weight:800; }\n\n#berfFilesTool .folder-content412{\n  display:none;\n  flex-wrap: wrap;\n  gap: 20px;\n  margin-top: 20px;\n  width: min(1100px, 96vw);\n  padding: 12px;\n  border-radius: 18px;\n  border:1px solid rgba(255,255,255,0.10);\n  background: rgba(0,0,0,0.25);\n}\n\n#berfFilesTool .file-thumb895{\n  display:inline-flex;\n  flex-direction:column;\n  align-items:center;\n  justify-content:center;\n  margin: 10px;\n  cursor:pointer;\n  padding: 10px;\n  border: 2px solid #ddd;\n  border-radius: 8px;\n  transition: border-color 0.3s;\n  text-align:center;\n  color: rgba(255,255,255,0.92);\n  background: rgba(255,255,255,0.04);\n  width: 170px;\n  min-height: 140px;\n}\n#berfFilesTool .file-thumb895:hover{\n  border-color:#af3232;\n  color:#af3232;\n}\n#berfFilesTool .file-thumb895 i{ font-size: 50px; margin-bottom: 10px; }\n\n#berfFilesTool div#media-content479{\n  height: calc(100% - 70px);\n  position: relative;\n}\n#berfFilesTool #media-viewer264{\n  display:none;\n  position: fixed;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  background-color: #222;\n  border: 1px solid #444;\n  padding: 15px;\n  border-radius: 12px;\n  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);\n  z-index: 100000;\n  width: 80%;\n  height: 80%;\n  overflow: hidden;\n  pointer-events: auto;\n}\n#berfFilesTool #media-viewer264 img,\n#berfFilesTool #media-viewer264 video,\n#berfFilesTool #media-viewer264 iframe{\n  width: 100%;\n  height: 100%;\n  object-fit: contain;\n}\n#berfFilesTool #media-viewer264 .close-btn193{\n  position: absolute;\n  top: 10px;\n  right: 10px;\n  background: none;\n  border: none;\n  color: #af3232;\n  font-size: 20px;\n  cursor: pointer;\n  z-index: 1010;\n}\n#berfFilesTool #download-btn{\n  position: absolute;\n  bottom: 10px;\n  right: 10px;\n  background-color: #af3232;\n  color: white;\n  padding: 8px 12px;\n  border: none;\n  border-radius: 5px;\n  cursor: pointer;\n  z-index: 1010;\n  display: none;\n}\n\n#berfFilesTool #password-modal307{\n  display:none;\n  position: fixed;\n  top: 0; left: 0;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.8);\n  justify-content: center;\n  align-items: center;\n  z-index: 100000;\n}\n#berfFilesTool #password-modal307 .modal-content874{\n  background-color: #333;\n  padding: 20px;\n  border-radius: 10px;\n  text-align: center;\n  width: min(420px, 92vw);\n  position: relative;\n}\n#berfFilesTool #password-modal307 input{\n  margin-top: 10px;\n  padding: 10px;\n  font-size: 16px;\n  border-radius: 5px;\n  color: white;\n  background-color: #7a7a7a33;\n  border: 0;\n  width: 100%;\n}\n#berfFilesTool #password-modal307 button{\n  margin-top: 10px;\n  padding: 10px 20px;\n  font-size: 16px;\n  border-radius: 5px;\n  background-color: #af3232;\n  color: white;\n  border: 0;\n  cursor: pointer;\n}\n#berfFilesTool #password-modal307 .close-modal-btn{\n  position: absolute;\n  top: 10px;\n  right: 10px;\n  font-size: 30px;\n  color: #af3232;\n  background: none;\n  border: none;\n  cursor: pointer;\n}\n\n\/* ===== FILES TOOLBAR (nav + lock) ===== *\/\n#berfFilesTool .files-toolbar883{\n  width: min(1100px, 96vw);\n  display:flex;\n  align-items:center;\n  gap: 10px;\n  margin: 4px 0 10px;\n}\n#berfFilesTool .files-toolbar-spacer883{ flex:1; }\n\n#berfFilesTool .files-navbtn883{\n  display:none; \/* affich\u00e9 uniquement quand un dossier est ouvert *\/\n  width: 42px;\n  height: 38px;\n  align-items:center;\n  justify-content:center;\n  border-radius: 12px;\n  border: 1px solid rgba(255,255,255,0.12);\n  background: rgba(0,0,0,0.35);\n  color: rgba(255,255,255,0.92);\n  cursor: pointer;\n  box-shadow: 0 10px 28px rgba(0,0,0,0.35);\n  transition: transform .18s ease, background .18s ease, border-color .18s ease;\n}\n#berfFilesTool .files-navbtn883:hover{\n  transform: translateY(-1px);\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.10);\n}\n#berfFilesTool .files-navbtn883:active{ transform: translateY(0px) scale(0.99); }\n#berfFilesTool .files-navbtn883 i{ font-size: 16px; }\n\n#berfFilesTool .files-lockbtn883{\n  display:none;\n  align-items:center;\n  gap: 10px;\n  padding: 10px 12px;\n  border-radius: 999px;\n  border: 1px solid rgba(175,50,50,0.40);\n  background: rgba(175,50,50,0.14);\n  color: rgba(255,255,255,0.95);\n  font: 800 13px\/1 'Roboto Mono', monospace;\n  cursor: pointer;\n  box-shadow: 0 10px 28px rgba(0,0,0,0.35);\n  transition: transform .18s ease, background .18s ease, border-color .18s ease, opacity .18s ease;\n  white-space: nowrap;\n}\n#berfFilesTool .files-lockbtn883 i{ font-size: 14px; }\n#berfFilesTool .files-lockbtn883:hover{\n  transform: translateY(-1px);\n  border-color: rgba(175,50,50,0.65);\n  background: rgba(175,50,50,0.22);\n}\n#berfFilesTool .files-lockbtn883:active{ transform: translateY(0px) scale(0.99); }\n#berfFilesTool .files-lockbtn883.is-locked{\n  border-color: rgba(255,255,255,0.14);\n  background: rgba(0,0,0,0.28);\n  opacity: .95;\n}\n\n\/* Dossier verrouill\u00e9 : petit badge cadenas + l\u00e9g\u00e8re variation d\u2019ic\u00f4ne *\/\n#berfFilesTool .folder751{ position: relative; }\n#berfFilesTool .folder751.folder751--locked i.fa-folder{ color: #d8b04a; filter: saturate(0.9) brightness(0.95); }\n#berfFilesTool .folder751.folder751--locked::after{\n  content: \"\\f023\";\n  font-family: \"Font Awesome 6 Free\";\n  font-weight: 900;\n  position: absolute;\n  top: 10px;\n  right: 10px;\n  width: 28px;\n  height: 28px;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  border-radius: 10px;\n  border: 1px solid rgba(255,255,255,0.14);\n  background: rgba(0,0,0,0.45);\n  color: rgba(255,255,255,0.92);\n  backdrop-filter: blur(6px);\n  box-shadow: 0 10px 22px rgba(0,0,0,0.35);\n  pointer-events:none;\n}\n\n\/* ============================================================\nAJOUT : TENNIS (scop\u00e9 #berfDesk)\n============================================================ *\/\n#berfDesk #bdd-modal{\n  display:none;\n  position: fixed;\n  inset: 0;\n  background-color: rgba(0,0,0,0.85);\n  z-index: 100005; \/* au-dessus des modales d\u2019outils *\/\n  justify-content: center;\n  align-items: center;\n  padding: 16px;\n}\n#berfDesk #bdd-modal[data-open=\"true\"]{ display:flex; }\n#berfDesk #bdd-modal[aria-hidden=\"false\"]{ display:flex; }\n\n#berfDesk #bdd-modal-content{\n  position: relative;\n  background: #0c0f14;\n  border: 1px solid rgba(255,255,255,0.10);\n  padding: 12px;\n  border-radius: 14px;\n  width: min(1100px, 96vw);\n  height: min(760px, 86vh);\n  overflow: hidden;\n  box-shadow: 0 22px 80px rgba(0,0,0,0.65);\n}\n\n#berfDesk #bdd-close-button{\n  position: absolute;\n  top: 10px;\n  right: 10px;\n  font-size: 26px;\n  cursor: pointer;\n  color: white;\n  background-color: #af3232;\n  padding: 0px 10px 2px 10px;\n  z-index: 5;\n  border-radius: 10px;\n  border: 0;\n  line-height: 1;\n}\n\n#berfDesk #bdd-hud{\n  position:absolute;\n  top: 10px;\n  left: 10px;\n  right: 56px;\n  z-index: 4;\n  display:flex;\n  justify-content:space-between;\n  gap: 10px;\n  pointer-events: none;\n  flex-wrap: wrap;\n}\n#berfDesk #bdd-hud .bdd-hud-left,\n#berfDesk #bdd-hud .bdd-hud-right{\n  display:flex;\n  gap: 8px;\n  align-items:center;\n  flex-wrap: wrap;\n}\n#berfDesk #bdd-hud .bdd-hud-right{ justify-content:flex-end; }\n#berfDesk #bdd-hud .bdd-pill{\n  pointer-events:none;\n  color: rgba(255,255,255,0.92);\n  font: 700 13px\/1 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n  padding: 8px 10px;\n  border-radius: 999px;\n  background: rgba(0,0,0,0.45);\n  border: 1px solid rgba(255,255,255,0.10);\n  backdrop-filter: blur(8px);\n}\n#berfDesk #bdd-hud .bdd-hint{\n  pointer-events:none;\n  color: rgba(255,255,255,0.78);\n  font: 600 12px\/1 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n  padding: 8px 10px;\n  border-radius: 999px;\n  background: rgba(0,0,0,0.25);\n  border: 1px solid rgba(255,255,255,0.08);\n}\n#berfDesk #bdd-hud .bdd-btn{\n  pointer-events:auto;\n  border: 1px solid rgba(255,255,255,0.12);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  border-radius: 999px;\n  padding: 8px 12px;\n  font-weight: 800;\n  font-size: 12px;\n  cursor: pointer;\n}\n#berfDesk #bdd-hud .bdd-btn:hover{\n  background: rgba(255,255,255,0.10);\n  border-color: rgba(175,50,50,0.35);\n}\n\n#berfDesk #bdd-canvas-wrap{\n  position:absolute;\n  inset: 0;\n  padding-top: 0;\n}\n#berfDesk #bdd-canvas{\n  background-color: #000;\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n\n#berfDesk #bdd-overlay{\n  position:absolute;\n  inset: 0;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  background: radial-gradient(900px 600px at 50% 40%, rgba(175,50,50,0.15), rgba(0,0,0,0.82));\n  z-index: 3;\n}\n#berfDesk #bdd-overlay[data-hidden=\"true\"]{ display:none; }\n#berfDesk .bdd-overlay-card{\n  width: min(520px, 92vw);\n  border-radius: 18px;\n  background: rgba(10,12,18,0.92);\n  border: 1px solid rgba(255,255,255,0.12);\n  box-shadow: 0 22px 80px rgba(0,0,0,0.65);\n  padding: 16px;\n  color: rgba(255,255,255,0.92);\n  text-align:center;\n}\n#berfDesk .bdd-overlay-title{\n  font: 900 20px\/1.1 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n  margin-bottom: 8px;\n}\n#berfDesk .bdd-overlay-text{\n  font: 600 13px\/1.5 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n  opacity: .88;\n  margin-bottom: 12px;\n}\n#berfDesk .bdd-btn-primary{\n  background: rgba(175,50,50,0.90) !important;\n  border-color: rgba(175,50,50,0.60) !important;\n}\n#berfDesk .bdd-btn-primary:hover{\n  filter: brightness(1.05);\n}\n\n\/* ============================================================\nAJOUT : TASKBAR APPS (ic\u00f4nes \u00e0 droite du Start)\n============================================================ *\/\n#berfDesk .berf-taskbar-apps{\n  display:inline-flex;\n  align-items:center;\n  gap:10px;\n  margin-left: 8px;\n}\n#berfDesk .berf-taskbar-app{\n  width:44px; height:44px;\n  border-radius: 14px;\n  border:1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  cursor:pointer;\n  display:grid;\n  place-items:center;\n  transition: transform .12s ease, background .2s ease, border-color .2s ease;\n}\n#berfDesk .berf-taskbar-app:hover{\n  transform: translateY(-1px);\n  background: rgba(255,255,255,0.10);\n  border-color: rgba(175,50,50,0.35);\n}\n#berfDesk .berf-taskbar-app i{ font-size:18px; color: #e9e9e9; }\n#berfDesk .berf-taskbar-app:hover i{ color:#af3232; }\n\n\/* ============================================================\nAJOUT : AGENDA (scop\u00e9) \u2014 look BERF\n============================================================ *\/\n#berfAgendaTool{ padding: 18px 16px 40px; }\n#berfAgendaTool *{ box-sizing:border-box; }\n#berfAgendaTool, #berfAgendaTool input, #berfAgendaTool button, #berfAgendaTool label, #berfAgendaTool select, #berfAgendaTool h3, #berfAgendaTool p, #berfAgendaTool span, #berfAgendaTool li{ font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; }\n#berfAgendaTool i.fa-solid, #berfAgendaTool i.fa-regular, #berfAgendaTool i.fa-brands{\n  font-family: \"Font Awesome 6 Free\";\n  font-weight: 900;\n}\n#berfAgendaTool i.fa-brands{ font-family: \"Font Awesome 6 Brands\"; font-weight: 400; }\n\n#berfAgendaTool .agenda_42_container{\n  width: min(1100px, 96vw);\n  margin: 6px auto 0;\n  background: rgba(0,0,0,0.28);\n  border: 1px solid rgba(255,255,255,0.10);\n  border-radius: 18px;\n  box-shadow: 0 18px 60px rgba(0,0,0,0.45);\n  overflow:hidden;\n}\n\n#berfAgendaTool .agenda_42_navigation{\n  display:flex;\n  gap: 8px;\n  padding: 10px;\n  background: rgba(0,0,0,0.35);\n  border-bottom: 1px solid rgba(255,255,255,0.10);\n  backdrop-filter: blur(10px);\n}\n#berfAgendaTool .agenda_42_navbtn{\n  flex: 1;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.78);\n  padding: 12px 12px;\n  border-radius: 14px;\n  cursor:pointer;\n  font-weight: 800;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  gap:10px;\n}\n#berfAgendaTool .agenda_42_navbtn.active,\n#berfAgendaTool .agenda_42_navbtn:hover{\n  color: rgba(255,255,255,0.92);\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.18);\n}\n\n#berfAgendaTool .agenda_42_content{ padding: 14px; }\n#berfAgendaTool .agenda_42_tab{ display:none; }\n#berfAgendaTool .agenda_42_tab.active{ display:block; }\n\n#berfAgendaTool .agenda_42_next{\n  border-radius: 16px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.05);\n  padding: 14px;\n}\n#berfAgendaTool .agenda_42_next h3{\n  margin:0 0 6px 0;\n  color: rgba(255,255,255,0.75);\n  font-size: 13px;\n  letter-spacing: .2px;\n}\n#berfAgendaTool #agenda_42_next_item{\n  margin:0;\n  color: rgba(255,255,255,0.92);\n  font-weight: 800;\n  line-height: 1.35;\n}\n\n#berfAgendaTool .agenda_42_calwrap{ margin-top: 12px; }\n\n#berfAgendaTool .agenda_42_controls{\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap: 10px;\n  padding: 10px;\n  border-radius: 16px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(0,0,0,0.25);\n}\n#berfAgendaTool .agenda_42_controls button{\n  width:44px; height:44px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.88);\n  cursor:pointer;\n}\n#berfAgendaTool .agenda_42_controls button:hover{\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.15);\n}\n#berfAgendaTool #agenda_42_current_month{\n  flex: 1;\n  text-align:center;\n  font-weight: 900;\n  color: rgba(255,255,255,0.92);\n}\n#berfAgendaTool .agenda_42_year{\n  padding: 10px 12px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n}\n\n#berfAgendaTool .agenda_42_calendar{\n  display:grid;\n  grid-template-columns: repeat(7, 1fr);\n  gap: 8px;\n  margin-top: 10px;\n}\n#berfAgendaTool .agenda_42_day{\n  padding: 12px 10px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.05);\n  color: rgba(255,255,255,0.92);\n  text-align:center;\n  cursor:pointer;\n  user-select:none;\n  transition: transform .12s ease, background .2s ease, border-color .2s ease;\n}\n#berfAgendaTool .agenda_42_day.header{\n  cursor: default;\n  opacity: .7;\n  font-weight: 900;\n}\n#berfAgendaTool .agenda_42_day:not(.header):hover{\n  transform: translateY(-1px);\n  border-color: rgba(175,50,50,0.35);\n  background: rgba(255,255,255,0.08);\n}\n#berfAgendaTool .agenda_42_day.hasAppt{\n  border-color: rgba(175,50,50,0.55);\n  background: rgba(175,50,50,0.22);\n}\n\n#berfAgendaTool .agenda_42_formgroup{ margin-top: 12px; }\n#berfAgendaTool .agenda_42_formgroup label{\n  display:block;\n  margin-bottom: 6px;\n  font-weight: 900;\n  color: rgba(255,255,255,0.88);\n  font-size: 13px;\n}\n#berfAgendaTool .agenda_42_formgroup input{\n  width:100%;\n  padding: 12px 12px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  outline:none;\n}\n#berfAgendaTool .agenda_42_formgroup input:focus{\n  border-color: rgba(175,50,50,0.55);\n  box-shadow: 0 0 0 4px rgba(175,50,50,0.15);\n}\n\n#berfAgendaTool .agenda_42_addbtn{\n  margin-top: 12px;\n  width: 100%;\n  padding: 12px 14px;\n  border-radius: 14px;\n  border: 1px solid rgba(175,50,50,0.55);\n  background: rgba(175,50,50,0.88);\n  color: white;\n  font-weight: 900;\n  cursor:pointer;\n}\n#berfAgendaTool .agenda_42_addbtn:hover{ filter: brightness(1.05); }\n\n\/* Modal *\/\n#berfAgendaTool .agenda_42_modal{\n  display:none;\n  position: fixed;\n  inset:0;\n  background: rgba(0,0,0,0.75);\n  z-index: 100000;\n  justify-content:center;\n  align-items:center;\n  padding: 16px;\n}\n#berfAgendaTool .agenda_42_modal[data-open=\"true\"]{ display:flex; }\n#berfAgendaTool .agenda_42_modalcontent{\n  width: min(720px, 96vw);\n  border-radius: 18px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(20,24,30,0.96);\n  box-shadow: 0 22px 80px rgba(0,0,0,0.65);\n  padding: 14px;\n  position: relative;\n}\n#berfAgendaTool .agenda_42_close{\n  position:absolute;\n  top: 10px;\n  right: 10px;\n  width: 44px; height:44px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  cursor:pointer;\n  font-size: 18px;\n}\n#berfAgendaTool .agenda_42_modalheader{\n  padding: 6px 6px 10px;\n  text-align:center;\n  color: rgba(255,255,255,0.92);\n  font-weight: 900;\n}\n#berfAgendaTool .agenda_42_modalappts{\n  margin-top: 4px;\n  border-top: 1px solid rgba(255,255,255,0.10);\n  padding-top: 10px;\n}\n#berfAgendaTool .agenda_42_modalappts h3{\n  margin:0 0 8px 0;\n  font-size: 13px;\n  opacity: .85;\n}\n#berfAgendaTool .agenda_42_list{ list-style:none; padding:0; margin:0; }\n#berfAgendaTool .agenda_42_list li{\n  display:flex;\n  justify-content:space-between;\n  align-items:center;\n  gap: 10px;\n  padding: 10px 10px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.05);\n  margin-bottom: 8px;\n}\n#berfAgendaTool .agenda_42_del{\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  padding: 8px 10px;\n  border-radius: 12px;\n  cursor:pointer;\n}\n#berfAgendaTool .agenda_42_del:hover{\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.16);\n}\n\n\/* ============================================================\nAJOUT : SEARCH BAR (taskbar) \u2014 scop\u00e9 #berfDesk\n============================================================ *\/\n#berfDesk .berf-taskbar-search{\n  flex: 1 1 360px;\n  max-width: 520px;\n  min-width: 220px;\n  position: relative;\n}\n\n#berfDesk .berf-taskbar-search #searchInput45{\n  width: 100%;\n  padding: 10px 14px;\n  font-size: 12px;\n  border: 1px solid rgba(255,255,255,0.10);\n  border-radius: 999px;\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  outline: none;\n}\n\n#berfDesk .berf-taskbar-search #searchInput45::placeholder{\n  color: rgba(255,255,255,0.55);\n}\n\n#berfDesk .berf-taskbar-search #searchInput45:focus{\n  border-color: rgba(175,50,50,0.55);\n  box-shadow: 0 0 0 4px rgba(175,50,50,0.15);\n}\n\n#berfDesk .berf-taskbar-search .search-results56{\n  position: absolute;\n  left: 0;\n  right: 0;\n  bottom: calc(100% + 10px);\n  border: 1px solid rgba(255,255,255,0.10);\n  border-radius: 14px;\n  max-height: 240px;\n  overflow-y: auto;\n  background: rgba(20,24,30,0.96);\n  box-shadow: 0 18px 60px rgba(0,0,0,0.55);\n  z-index: 100000;\n  display: none;\n  padding: 6px;\n}\n\n#berfDesk .berf-taskbar-search .result-item99{\n  padding: 10px 10px;\n  border-radius: 12px;\n  cursor: pointer;\n  color: rgba(255,255,255,0.88);\n  border: 1px solid transparent;\n}\n\n#berfDesk .berf-taskbar-search .result-item99:hover{\n  background: rgba(175,50,50,0.18);\n  border-color: rgba(175,50,50,0.45);\n  color: rgba(255,255,255,0.96);\n}\n\n\n\/* ============================================================\nAJOUT : NAVIGATEUR FICTIF \u2014 UI BERF (scop\u00e9 #berfBrowserTool)\n============================================================ *\/\n#berfBrowserTool{ padding: 18px 16px 40px; }\n#berfBrowserTool, #berfBrowserTool input, #berfBrowserTool button, #berfBrowserTool select, #berfBrowserTool h3, #berfBrowserTool p, #berfBrowserTool div{\n  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n  box-sizing: border-box;\n}\n\n#berfBrowserTool .berfBrowser{\n  width: min(1200px, 96vw);\n  margin: 0 auto;\n  background: rgba(0,0,0,0.28);\n  border: 1px solid rgba(255,255,255,0.10);\n  border-radius: 18px;\n  box-shadow: 0 18px 60px rgba(0,0,0,0.45);\n  overflow: hidden;\n}\n\n#berfBrowserTool .berfBrowser__top{\n  display:flex;\n  align-items:center;\n  gap: 10px;\n  padding: 10px;\n  background: rgba(0,0,0,0.35);\n  border-bottom: 1px solid rgba(255,255,255,0.10);\n  backdrop-filter: blur(10px);\n}\n\n#berfBrowserTool .berfBrowser__nav{ display:flex; gap:8px; }\n#berfBrowserTool .berfBrowser__btn{\n  width: 44px; height: 44px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  cursor:pointer;\n  display:grid;\n  place-items:center;\n  transition: transform .12s ease, background .2s ease, border-color .2s ease;\n}\n#berfBrowserTool .berfBrowser__btn:hover{\n  transform: translateY(-1px);\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.15);\n}\n\n#berfBrowserTool .berfBrowser__address{\n  flex: 1 1 auto;\n  padding: 10px 14px;\n  border-radius: 999px;\n  border: 1px solid rgba(255,255,255,0.10) !important;\n  background: rgba(255,255,255,0.06) !important;\n  color: rgba(255,255,255,0.92);\n  outline:none;\n  font-size: 13px;\n}\n#berfBrowserTool .berfBrowser__address::placeholder{ color: rgba(255,255,255,0.55); }\n#berfBrowserTool .berfBrowser__address:focus{\n  border-color: rgba(175,50,50,0.55) !important;\n  box-shadow: 0 0 0 4px rgba(175,50,50,0.15);\n}\n\n#berfBrowserTool .berfBrowser__tabs{\n  display:flex;\n  align-items:center;\n  gap: 8px;\n  padding: 10px;\n  background: rgba(0,0,0,0.28);\n  border-bottom: 1px solid rgba(255,255,255,0.10);\n  overflow-x:auto;\n}\n#berfBrowserTool .berfBrowser__tab{\n  position: relative;\n  padding: 10px 34px 10px 12px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.82);\n  cursor:pointer;\n  white-space: nowrap;\n  user-select:none;\n  font-weight: 800;\n  font-size: 12px;\n}\n#berfBrowserTool .berfBrowser__tab.active123{\n  border-color: rgba(175,50,50,0.55);\n  background: rgba(175,50,50,0.22);\n  color: rgba(255,255,255,0.95);\n}\n#berfBrowserTool #addTab123{\n  width: 44px;\n  padding: 10px 0;\n  text-align:center;\n  font-size: 16px;\n  border-radius: 14px;\n}\n#berfBrowserTool .berfBrowser__close{\n  position:absolute;\n  right: 8px;\n  top: 50%;\n  transform: translateY(-50%);\n  width: 22px; height: 22px;\n  border-radius: 8px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  cursor:pointer;\n  line-height: 18px;\n  font-weight: 900;\n}\n#berfBrowserTool .berfBrowser__close:hover{\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.18);\n}\n\n#berfBrowserTool .berfBrowser__content{\n  background: rgba(0,0,0,0.12);\n  padding: 12px;\n  min-height: 62vh;\n}\n#berfBrowserTool .berfBrowser__page{\n  width: 100%;\n  min-height: 60vh;\n}\n#berfBrowserTool .berfBrowser__page iframe{\n  width: 100%;\n  height: 60vh;\n  border: 0;\n  border-radius: 14px;\n  background: rgba(255,255,255,0.04);\n}\n.berf-browser-login-form{max-width:430px;margin:48px auto;padding:30px;border:1px solid #d8d8d0;border-radius:8px;background:#fff;box-shadow:0 12px 34px rgba(0,0,0,.12);font-family:Arial,sans-serif;color:#252820}\n.berf-browser-login-form h2{margin:0 0 24px;color:#5f7f42;font-size:26px}\n.berf-browser-login-form label{display:block;margin:0 0 17px;font-size:13px;font-weight:700}\n.berf-browser-login-form input{display:block;width:100%;box-sizing:border-box;margin-top:7px;padding:12px;border:1px solid #b9bdb3;border-radius:4px;background:#fff;color:#222;font-size:15px}\n.berf-browser-login-form button{width:100%;padding:12px 16px;border:0;border-radius:4px;background:#789a55;color:#fff;font-size:15px;font-weight:700;cursor:pointer}\n.berf-browser-login-form button:hover{background:#658448}\n.berf-browser-login-feedback{min-height:20px;margin:-4px 0 12px;color:#a52d2d;font-size:13px}\n.berf-browser-login-feedback.is-success,.berf-browser-login-ok{color:#4f7038}\n.berf-browser-login-ok,.berf-browser-login-error{max-width:430px;margin:48px auto;padding:24px;background:#fff;border:1px solid #d8d8d0;border-radius:8px;text-align:center;font-family:Arial,sans-serif}\n\n\/* History *\/\n#berfBrowserTool .berfBrowser__history{\n  position: fixed;\n  inset: auto 16px 80px auto;\n  width: min(360px, calc(100vw - 32px));\n  background: rgba(20,24,30,0.96);\n  border: 1px solid rgba(255,255,255,0.10);\n  border-radius: 18px;\n  box-shadow: 0 18px 60px rgba(0,0,0,0.55);\n  padding: 12px;\n  z-index: 100000;\n  display:none;\n}\n#berfBrowserTool .berfBrowser__history h3{\n  margin: 8px 0 10px;\n  font-size: 13px;\n  color: rgba(255,255,255,0.92);\n}\n#berfBrowserTool #historyList123 a{\n  display:block;\n  padding: 10px;\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.08);\n  background: rgba(255,255,255,0.05);\n  color: rgba(255,255,255,0.86);\n  text-decoration: none;\n  margin-bottom: 8px;\n  font-weight: 700;\n  font-size: 12px;\n}\n#berfBrowserTool #historyList123 a:hover{\n  border-color: rgba(175,50,50,0.45);\n  background: rgba(175,50,50,0.16);\n}\n\n\/* Easter egg overlay *\/\n#berfBrowserTool .berfBrowser__eggOverlay{\n  position: fixed;\n  inset:0;\n  background: rgba(0,0,0,0.65);\n  z-index: 100000;\n  display:none;\n}\n#berfBrowserTool .berfBrowser__egg{\n  position: fixed;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  width: min(520px, 92vw);\n  background: rgba(20,24,30,0.98);\n  color: rgba(255,255,255,0.95);\n  border-radius: 18px;\n  border: 1px solid rgba(255,255,255,0.10);\n  box-shadow: 0 22px 80px rgba(0,0,0,0.65);\n  z-index: 100001;\n  display:none;\n  text-align:center;\n  padding: 16px;\n}\n#berfBrowserTool .berfBrowser__eggClose{\n  margin-top: 10px;\n  width: 100%;\n  padding: 12px 14px;\n  border-radius: 14px;\n  border: 1px solid rgba(175,50,50,0.55);\n  background: rgba(175,50,50,0.88);\n  color: white;\n  font-weight: 900;\n  cursor:pointer;\n}\n\n\n\/* ============================================================\nFIX : Taskbar clicable + ic\u00f4nes\n============================================================ *\/\n#berfDesk .berf-taskbar{ pointer-events: auto; }\n#berfDesk .berf-taskbar *{ pointer-events: auto; }\n#berfDesk .berf-taskbar-apps{ display:flex; align-items:center; gap:10px; }\n\n\/* ============================================================\nHARDENING : clics en FRONT-END Elementor\nObjectif: emp\u00eacher un overlay Elementor (background overlay, sections)\nde capturer les clics au-dessus du bureau virtuel.\n============================================================ *\/\n\/* Si Elementor ajoute des overlays au-dessus (rare mais arrive) *\/\n.elementor-background-overlay,\n.elementor-widget-wrap > .elementor-background-overlay,\n.elementor-section > .elementor-background-overlay,\n.elementor-column > .elementor-background-overlay{\n  pointer-events: none !important;\n}\n\n\/* Le fond du bureau ne doit jamais intercepter les clics *\/\n#berfDesk .berf-bg,\n#berfDesk .berf-wallpaper,\n#berfDesk .berf-desktop,\n#berfDesk .berf-desktop *:not(.berf-leftbar):not(.berf-taskbar):not(.berf-oc):not(.berf-window):not(.berf-icon):not(button):not(a):not(input):not(textarea){\n  \/* on ne force pas partout; on couvre les cas de fond *\/\n}\n\n\/* Renforcer l'empilement des zones interactives *\/\n#berfDesk .berf-leftbar{ z-index: 1000000; }\n#berfDesk .berf-taskbar{ z-index: 1000001; }\n#berfDesk .berf-oc{ z-index: 1000002; }\n\n\n\n\/* =========================\nTRIANGULATION (scop\u00e9)\n========================= *\/\n#berfDesk #berfTriangulation77{\n  font-family: \"Roboto Mono\", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n  color: rgba(255,255,255,0.92);\n}\n\n#berfDesk #berfTriangulation77 .tri77__grid{\n  display: grid;\n  grid-template-columns: 280px minmax(0, 1fr) 280px;\n  gap: 14px;\n  align-items: stretch;\n}\n\n#berfDesk #berfTriangulation77 .tri77__col{\n  border-radius: 16px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(255,255,255,0.04);\n  backdrop-filter: blur(10px);\n  padding: 14px;\n  min-height: 520px;\n  overflow: auto;\n}\n\n#berfDesk #berfTriangulation77 .tri77__left h3,\n#berfDesk #berfTriangulation77 .tri77__right h3{\n  margin: 0 0 12px;\n  font-size: 14px;\n  letter-spacing: .3px;\n  text-transform: uppercase;\n  opacity: .9;\n}\n\n#berfDesk #berfTriangulation77 .tri77__field label{\n  display: block;\n  font-size: 12px;\n  opacity: .85;\n  margin-bottom: 6px;\n}\n\n#berfDesk #berfTriangulation77 select,\n#berfDesk #berfTriangulation77 input{\n  width: 100%;\n  border: 1px solid rgba(255,255,255,0.10);\n  border-radius: 14px;\n  padding: 10px 12px;\n  background: rgba(122,122,122,0.20);\n  color: rgba(255,255,255,0.92);\n  outline: none;\n}\n\n#berfDesk #berfTriangulation77 select:focus,\n#berfDesk #berfTriangulation77 input:focus{\n  border-color: rgba(175,50,50,0.75);\n  box-shadow: 0 0 0 3px rgba(175,50,50,0.20);\n}\n\n#berfDesk #berfTriangulation77 .tri77__hint{\n  margin-top: 12px;\n  padding: 12px;\n  border-radius: 14px;\n  border: 1px dashed rgba(255,255,255,0.18);\n  background: rgba(0,0,0,0.25);\n}\n\n#berfDesk #berfTriangulation77 .tri77__hintTitle{\n  display:flex;\n  align-items:center;\n  gap:8px;\n  font-weight: 800;\n  margin-bottom: 8px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__hint ul{\n  margin: 0;\n  padding-left: 18px;\n  opacity: .88;\n  line-height: 1.35;\n  font-size: 12px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__center{\n  background: rgba(0,0,0,0.35);\n}\n\n#berfDesk #berfTriangulation77 .tri77__card{\n  border-radius: 18px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(0,0,0,0.35);\n  padding: 14px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__card + .tri77__card{ margin-top: 12px; }\n\n#berfDesk #berfTriangulation77 .tri77__cardHead{\n  display:flex;\n  gap: 12px;\n  align-items:center;\n  margin-bottom: 12px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__badge{\n  width: 42px;\n  height: 42px;\n  border-radius: 16px;\n  display:grid;\n  place-items:center;\n  background: rgba(175,50,50,0.20);\n  border: 1px solid rgba(175,50,50,0.45);\n}\n\n#berfDesk #berfTriangulation77 .tri77__title{\n  font-weight: 950;\n  font-size: 16px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__sub{\n  font-size: 12px;\n  opacity: .85;\n}\n\n#berfDesk #berfTriangulation77 .tri77__inputs{\n  display:grid;\n  gap: 10px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__btn{\n  border: 0;\n  border-radius: 14px;\n  padding: 10px 12px;\n  cursor: pointer;\n  font-weight: 900;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  gap: 10px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__btnPrimary{\n  background: rgba(175,50,50,0.95);\n  color: white;\n}\n#berfDesk #berfTriangulation77 .tri77__btnPrimary:hover{\n  filter: brightness(1.05);\n  transform: translateY(-1px);\n}\n\n#berfDesk #berfTriangulation77 .tri77__btnGhost{\n  background: rgba(255,255,255,0.06);\n  color: rgba(255,255,255,0.92);\n  border: 1px solid rgba(255,255,255,0.10);\n}\n#berfDesk #berfTriangulation77 .tri77__btnGhost:hover{\n  background: rgba(255,255,255,0.09);\n}\n\n#berfDesk #berfTriangulation77 .tri77__resultText{\n  text-align:left;\n  line-height: 1.45;\n}\n\n#berfDesk #berfTriangulation77 .tri77__resultText .tri77__kv{\n  display:grid;\n  grid-template-columns: 120px 1fr;\n  gap: 8px 10px;\n  margin-top: 10px;\n  font-size: 13px;\n}\n#berfDesk #berfTriangulation77 .tri77__resultText .tri77__k{ opacity: .75; }\n#berfDesk #berfTriangulation77 .tri77__resultText .tri77__v{ font-weight: 800; }\n\n#berfDesk #berfTriangulation77 .tri77__map{\n  height: 320px;\n  width: 100%;\n  margin-top: 12px;\n  border-radius: 16px;\n  border: 1px solid rgba(255,255,255,0.10);\n  overflow: hidden;\n}\n\n#berfDesk #berfTriangulation77 .tri77__history{\n  display:flex;\n  flex-direction: column;\n  gap: 10px;\n}\n\n#berfDesk #berfTriangulation77 .tri77__historyItem{\n  border-radius: 14px;\n  border: 1px solid rgba(255,255,255,0.10);\n  background: rgba(0,0,0,0.28);\n  padding: 10px 12px;\n  font-size: 12px;\n  line-height: 1.35;\n}\n#berfDesk #berfTriangulation77 .tri77__historyItem b{ color: rgba(255,255,255,0.95); }\n\n@media (max-width: 980px){\n  #berfDesk #berfTriangulation77 .tri77__grid{\n    grid-template-columns: 1fr;\n  }\n  #berfDesk #berfTriangulation77 .tri77__col{\n    min-height: auto;\n  }\n}\n\n\/* ============================================================\nIMGTOOL 991 \u2014 UI (scop\u00e9)\n============================================================ *\/\n#berfDesk .berf-imgtool-wrap{ background: rgba(0,0,0,.32); border: 1px solid rgba(255,255,255,.08); border-radius: 18px; padding: 14px; }\n#berfDesk .imgtool991-grid{ display:grid; grid-template-columns: 260px minmax(0, 1fr) 260px; gap: 12px; width:100%; min-height: 70vh; }\n@media (max-width: 980px){ #berfDesk .imgtool991-grid{ grid-template-columns: 1fr; min-height:auto; } }\n#berfDesk .imgtool991-panel{ display:flex; flex-direction:column; gap:10px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08); border-radius: 16px; padding: 12px; }\n#berfDesk .imgtool991-slider{display:flex;flex-direction:column;gap:7px;padding:10px 11px;border-radius:13px;background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.09);font-size:12px;color:#f4f4f4}\n#berfDesk .imgtool991-slider span{display:flex;justify-content:space-between;gap:8px}.imgtool991-slider input{width:100%;accent-color:#af3232}\n#berfDesk .imgtool991-zoomline{display:flex;align-items:center;justify-content:space-between;padding:0 3px;color:#ddd;font-size:12px}\n#berfDesk .imgtool991-mini{border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.07);color:#fff;border-radius:8px;padding:5px 9px;cursor:pointer}\n#berfDesk #imgtool991-canvas.annotating{cursor:crosshair}\n#berfDesk #imgtool991-canvas.panning{cursor:grabbing}\n#berfDesk .imgtool991-btn.active{outline:2px solid #cf5454;background:rgba(175,50,50,.28)}\n#berfDesk .imgtool991-row{ display:flex; gap:10px; }\n#berfDesk .imgtool991-btn{ width:100%; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.10); color: rgba(255,255,255,0.92); padding: 10px 12px; border-radius: 14px; cursor:pointer; font-weight: 750; letter-spacing: .2px; transition: transform .12s ease, background .12s ease, border-color .12s ease; display:flex; align-items:center; justify-content:center; gap:8px; }\n#berfDesk .imgtool991-btn:hover{ transform: translateY(-1px); background: rgba(255,255,255,0.10); border-color: rgba(255,255,255,0.16); }\n#berfDesk .imgtool991-btn:active{ transform: translateY(0); }\n#berfDesk .imgtool991-btn--green{ background: rgba(76,175,80,0.20); border-color: rgba(76,175,80,0.35); }\n#berfDesk .imgtool991-btn--green:hover{ background: rgba(76,175,80,0.28); }\n#berfDesk .imgtool991-btn--danger{ background: rgba(231,76,60,0.20); border-color: rgba(231,76,60,0.40); }\n#berfDesk .imgtool991-btn--danger:hover{ background: rgba(231,76,60,0.30); }\n\n#berfDesk .imgtool991-canvas{ position:relative; background:#000; border: 2px solid #af3232; border-radius: 16px; overflow:hidden; display:flex; align-items:center; justify-content:center; min-height: 320px; }\n#berfDesk #imgtool991-canvas{ width:100%; height:auto; display:none; z-index:1; }\n#berfDesk .imgtool991-upload{ position:absolute; inset:0; display:flex; flex-direction:column; gap:6px; justify-content:center; align-items:center; cursor:pointer; color:#fff; z-index:5; background: linear-gradient(transparent, rgba(0,0,0,0.35)); text-align:center; padding: 18px; user-select:none; }\n#berfDesk .imgtool991-upload span{ opacity:.75; font-size: 13px; }\n#berfDesk #imgtool991-grainOverlay{ pointer-events:none; position:absolute; inset:0; opacity:0; mix-blend-mode:overlay; background-image:url(\"https:\/\/grainy-gradients.vercel.app\/noise.svg\"); background-size:200px 200px; transition:opacity .25s ease; z-index:4; }\n#berfDesk #imgtool991-modeOverlay{ pointer-events:none; position:absolute; inset:0; opacity:0; border-radius:16px; transition:opacity .25s ease, background .25s ease, mix-blend-mode .25s ease; z-index:3; }\n\n#berfDesk .imgtool991-notice{ background: rgba(255,204,204,0.95); padding: 10px 12px; border-radius: 12px; color:#800000; display:flex; justify-content:space-between; align-items:center; gap:10px; margin-bottom: 10px; border: 1px solid rgba(128,0,0,0.25); }\n#berfDesk #imgtool991-close-notice{ background: transparent; border: none; color:#800000; font-size: 18px; cursor:pointer; padding: 0 6px; border-radius:8px; }\n\n#berfDesk .imgtool991-color.active{ outline:2px solid rgba(255,255,255,.6); box-shadow:0 0 0 3px rgba(255,255,255,.12); }\n#berfDesk .imgtool991-mode.active{ outline:2px solid rgba(255,255,255,.6); box-shadow:0 0 0 3px rgba(175,50,50,.25); }\n\n.imgtool991-modal-overlay{ position: fixed; inset:0; background: rgba(0,0,0,0.70); display:flex; justify-content:center; align-items:center; visibility:hidden; opacity:0; transition: opacity .25s ease, visibility 0s linear .25s; z-index: 99999; }\n.imgtool991-modal-overlay.show{ visibility: visible; opacity: 1; transition: opacity .25s ease; }\n.imgtool991-modal{ background: #1f1f1f; border: 1px solid rgba(255,255,255,0.10); border-radius: 16px; width: min(560px, 92vw); max-height: calc(100% - 70px); overflow:auto; padding: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.55); color:#fff; }\n.imgtool991-modal-head{ font-weight: 900; letter-spacing:.2px; font-size: 18px; margin-bottom: 10px; }\n.imgtool991-modal-body{ font-size: 14px; line-height: 1.45; }\n.imgtool991-modal-body h4{ margin: 14px 0 6px; font-size: 15px; }\n.imgtool991-modal-body .kv{ margin: 2px 0; }\n.imgtool991-modal-body .kv b{ color: #ffd6d6; }\n.imgtool991-meta-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.imgtool991-meta-grid section{border:1px solid rgba(255,255,255,.10);border-radius:12px;padding:12px;background:rgba(255,255,255,.035)}\n.imgtool991-meta-grid section h4{margin:0 0 9px;color:#f4b0b0}.imgtool991-meta-grid .kv{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:8px;border-radius:8px;background:rgba(0,0,0,.22);margin:5px 0}.imgtool991-meta-grid .kv span{color:#aaa;font-size:11px}.imgtool991-meta-grid .kv b{font-size:12px;text-align:right;word-break:break-word;color:#fff}\n.imgtool991-meta-gps{grid-column:1\/-1}.imgtool991-extract{display:grid;place-items:center;text-align:center;min-height:190px;gap:10px}.imgtool991-extract small{color:#aaa}.imgtool991-extract-spinner{width:58px;height:58px;border:3px solid rgba(255,255,255,.12);border-top-color:#af3232;border-radius:50%;animation:imgtool991spin .8s linear infinite}.imgtool991-extract i{display:block;width:min(300px,80%);height:5px;background:linear-gradient(90deg,transparent,#af3232,transparent);border-radius:10px;animation:imgtool991scan 1.1s ease-in-out infinite}\n#imgtool991-copy-gps{margin-top:10px;width:100%;border:1px solid rgba(175,50,50,.55);background:#af3232;color:#fff;border-radius:9px;padding:9px 12px;font-weight:700;cursor:pointer}\n@keyframes imgtool991spin{to{transform:rotate(360deg)}}@keyframes imgtool991scan{0%{transform:translateX(-110%)}100%{transform:translateX(390%)}}\n@media(max-width:600px){.imgtool991-meta-grid{grid-template-columns:1fr}}\n\n\n\/* =========================\n   AUDIO TOOL (audiotool772)\n   ========================= *\/\n.berf-audiotool{ width:100%; }\n.audiotool772-grid{display:grid;grid-template-columns:1fr 2fr 1fr;gap:10px;width:100%;min-height:72vh;}\n.audiotool772-panel{display:flex;flex-direction:column;gap:14px;background-color:#7a7a7a33;padding:12px;border-radius:12px;min-width:180px;}\n.audiotool772-center{display:flex;flex-direction:column;align-items:center;gap:12px;background:#000;padding:12px;border-radius:12px;border:1px solid rgba(175,50,50,.85);box-shadow:inset 0 0 0 1px rgba(255,255,255,.06);}\n.audiotool772-wave{width:100%;height:160px;background:rgba(255,255,255,.06);border-radius:12px;overflow:hidden;box-shadow:inset 0 0 18px rgba(0,0,0,.55);}\n.audiotool772-upload{width:100%;text-align:center;padding:10px 14px;border-radius:10px;background-color:#7a7a7a33;border:1px solid rgba(255,255,255,.08);color:#fff;cursor:pointer;user-select:none;transition:transform .15s ease,background-color .2s ease,border-color .2s ease;}\n.audiotool772-upload:hover{background-color:#af3232;border-color:rgba(175,50,50,.9);transform:translateY(-1px);}#audiotool772-upload{display:none;}\n.audiotool772-actions{width:100%;display:flex;gap:10px;}\n#audiotool772-play,#audiotool772-reset{flex:1 1 0;padding:11px 12px;border:none;border-radius:10px;cursor:pointer;font-weight:600;color:#fff;background:#af3232;transition:transform .15s ease,filter .2s ease;}\n#audiotool772-play:disabled,#audiotool772-reset:disabled{opacity:.5;cursor:not-allowed;filter:saturate(.6);}#audiotool772-play:hover:not(:disabled),#audiotool772-reset:hover:not(:disabled){transform:translateY(-1px);filter:brightness(1.05);}\n.audiotool772-muted{background:#5a5a5a !important;}\n.audiotool772-slider label{display:block;color:#ddd;font-size:12px;margin:0 0 6px;}\n.audiotool772-slider input[type=range]{width:100%;}\n.audiotool772-status{width:100%;display:flex;justify-content:space-between;gap:10px;}\n.audiotool772-pill{background:#7a7a7a33;border:1px solid rgba(255,255,255,.08);color:#ddd;padding:6px 10px;border-radius:999px;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:50%;}\n.audiotool772-toggle{margin-top:2px;display:flex;justify-content:space-between;align-items:center;gap:10px;}\n.audiotool772-toggle__label{color:#ddd;font-size:12px;}\n.audiotool772-switch{position:relative;display:inline-block;width:44px;height:26px;}\n.audiotool772-switch input{opacity:0;width:0;height:0;}\n.audiotool772-switch__track{position:absolute;inset:0;background:#f5aeae;border-radius:999px;transition:background .2s ease;}\n.audiotool772-switch__knob{position:absolute;width:18px;height:18px;left:4px;top:4px;background:#af3232;border-radius:50%;transition:transform .2s ease,background .2s ease;}\n#audiotool772-reverse:checked ~ .audiotool772-switch__track{background:#9ed99c;}\n#audiotool772-reverse:checked ~ .audiotool772-switch__knob{transform:translateX(18px);background:#379237;}\n@media (max-width:980px){.audiotool772-grid{grid-template-columns:1fr;min-height:unset;}.audiotool772-pill{max-width:100%;}}\n\n\/* ============================\n   Evidence Tool (evidtool992)\n   ============================ *\/\n.evidtool992-wrap{width:100%;height:100%;display:flex;align-items:stretch;justify-content:center;}\n.evidtool992-app{\n  width: min(980px, 100%);\n  height: 100%;\n  margin: 0 auto;\n  display:flex;\n  flex-direction:column;\n  gap:12px;\n}\n.evidtool992-screen{display:none; height:100%;}\n.evidtool992-screen.is-active{display:block;}\n.evidtool992-topbar{\n  display:flex; align-items:center; justify-content:space-between;\n  padding:10px 10px 0;\n}\n.evidtool992-brand{display:flex; align-items:baseline; gap:10px;}\n.evidtool992-berf{color:#af3232; font-family: abegnale, system-ui, sans-serif; font-size:28px; font-weight:200; letter-spacing:.5px;}\n.evidtool992-sub{color:rgba(255,255,255,.72); font-size:13px;}\n.evidtool992-iconbtn{\n  appearance:none; border:none; background:rgba(255,255,255,.06);\n  color:#ddd; width:42px; height:42px; border-radius:12px;\n  display:inline-flex; align-items:center; justify-content:center;\n  cursor:pointer; transition:transform .15s ease, background .2s ease;\n  position:relative;\n}\n.evidtool992-iconbtn:hover{background:rgba(255,255,255,.10); transform:translateY(-1px);}\n.evidtool992-badge{\n  position:absolute; top:-6px; right:-6px;\n  background:#af3232; color:#fff; font-size:11px; font-weight:700;\n  padding:4px 7px; border-radius:999px;\n  border:2px solid rgba(0,0,0,.55);\n}\n.evidtool992-card{\n  background:rgba(20,20,20,.55);\n  border:1px solid rgba(255,255,255,.08);\n  border-radius:16px;\n  padding:14px;\n  box-shadow: 0 10px 24px rgba(0,0,0,.35);\n}\n.evidtool992-scanbar{position:relative;width:100%;height:4px;border-radius:999px;background:linear-gradient(to right, transparent, #b71c1c, transparent); overflow:hidden; margin-bottom:12px;}\n.evidtool992-scanline{position:absolute; top:0; left:-15%; width:15%; height:100%; background:#b71c1c; animation:evidtool992-scan 3s linear infinite;}\n@keyframes evidtool992-scan{0%{left:-15%}100%{left:100%}}\n.evidtool992-label{display:block; color:rgba(255,255,255,.75); font-size:12px; margin-bottom:8px;}\n.evidtool992-row{display:flex; gap:10px; align-items:center; flex-wrap:wrap;}\n.evidtool992-input{\n  flex:1 1 220px;\n  padding:12px 12px;\n  border-radius:12px;\n  border:1px solid rgba(255,255,255,.10);\n  background:#151515;\n  color:#eee;\n  outline:none;\n  box-shadow: inset 0 2px 6px rgba(0,0,0,.35);\n  text-transform:uppercase;\n}\n.evidtool992-input:focus{border-color:rgba(175,50,50,.55); box-shadow:0 0 0 3px rgba(175,50,50,.18), inset 0 2px 6px rgba(0,0,0,.35);}\n.evidtool992-btn{\n  appearance:none; border:none;\n  border-radius:12px;\n  padding:12px 14px;\n  cursor:pointer;\n  font-weight:700;\n  color:#fff;\n  display:inline-flex; align-items:center; gap:8px;\n  transition: transform .15s ease, background .2s ease, box-shadow .2s ease;\n  user-select:none;\n}\n.evidtool992-btn-primary{background:#af3232; box-shadow:0 10px 22px rgba(175,50,50,.18);}\n.evidtool992-btn-primary:hover{background:#c94545; transform:translateY(-1px);}\n.evidtool992-btn-ghost{\n  background:rgba(255,255,255,.06);\n  color:#ddd;\n  border:1px solid rgba(255,255,255,.10);\n}\n.evidtool992-btn-ghost:hover{background:rgba(255,255,255,.10); transform:translateY(-1px);}\n.evidtool992-actions{display:flex; gap:10px; margin-top:12px; flex-wrap:wrap;}\n.evidtool992-hint{margin-top:12px; font-size:12px; color:rgba(255,255,255,.62);}\n.evidtool992-detailhead{\n  display:flex; align-items:center; justify-content:space-between;\n  gap:10px;\n  padding:10px;\n  border-bottom:1px solid rgba(255,255,255,.08);\n  background:rgba(0,0,0,.25);\n  border-radius:14px;\n}\n.evidtool992-titlewrap{display:flex; align-items:center; gap:10px;}\n.evidtool992-title{margin:0; color:#eee; font-size:18px; font-weight:800;}\n.evidtool992-detailactions{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}\n.evidtool992-grid{\n  display:grid;\n  grid-template-columns: 1.15fr .85fr;\n  gap:12px;\n  padding:12px 0;\n}\n.evidtool992-mediaframe{\n  position:relative;\n  background:#000;\n  border:2px solid #af3232;\n  border-radius:16px;\n  overflow:hidden;\n  min-height:320px;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  padding:10px;\n}\n.evidtool992-mediaframe img,\n.evidtool992-mediaframe video,\n.evidtool992-mediaframe audio{\n  max-width:100%;\n  max-height:100%;\n  border-radius:12px;\n}\n.evidtool992-mediaframe img{cursor:pointer;}\n.evidtool992-medialabel{\n  position:absolute; inset:auto 12px 12px 12px;\n  background:rgba(0,0,0,.55);\n  border:1px solid rgba(255,255,255,.10);\n  border-radius:999px;\n  padding:8px 10px;\n  color:rgba(255,255,255,.75);\n  font-size:12px;\n  text-align:center;\n}\n.evidtool992-sectiontitle{color:rgba(255,255,255,.70); font-size:12px; margin:6px 0 10px;}\n.evidtool992-desc{\n  color:rgba(255,255,255,.82);\n  line-height:1.55;\n  background:rgba(255,255,255,.04);\n  border:1px solid rgba(255,255,255,.08);\n  border-radius:14px;\n  padding:12px;\n  min-height:220px;\n  white-space:pre-wrap;\n}\n.evidtool992-bottomactions{margin-top:10px; display:flex; justify-content:flex-end;}\n.evidtool992-textarea{\n  width:100%;\n  min-height:55vh;\n  resize:vertical;\n  padding:14px;\n  border-radius:14px;\n  border:1px solid rgba(255,255,255,.10);\n  background:#141414;\n  color:#eee;\n  outline:none;\n  box-shadow: inset 0 2px 6px rgba(0,0,0,.35);\n  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace;\n}\n.evidtool992-list{\n  margin-top:12px;\n  display:flex;\n  flex-direction:column;\n  gap:10px;\n  padding:0 2px 2px;\n}\n.evidtool992-item{\n  display:flex; justify-content:space-between; align-items:center;\n  gap:10px;\n  padding:12px 12px;\n  border-radius:14px;\n  background:rgba(255,255,255,.04);\n  border:1px solid rgba(255,255,255,.08);\n  color:rgba(255,255,255,.80);\n  cursor:pointer;\n  transition: transform .15s ease, background .2s ease;\n}\n.evidtool992-item:hover{background:rgba(255,255,255,.08); transform:translateY(-1px);}\n.evidtool992-item small{color:rgba(255,255,255,.55);}\n\n.evidtool992-viewer{\n  position:fixed; inset:0;\n  background:rgba(0,0,0,.86);\n  display:none;\n  align-items:center; justify-content:center;\n  z-index: 1000006; \/* above berf-oc *\/\n}\n.evidtool992-viewer.is-open{display:flex;}\n.evidtool992-viewerInner{\n  width:min(1100px, 92vw);\n  max-height: 90vh;\n  border-radius:18px;\n  background:rgba(20,20,20,.80);\n  border:1px solid rgba(255,255,255,.10);\n  box-shadow:0 14px 40px rgba(0,0,0,.55);\n  padding:14px;\n  display:flex; flex-direction:column; gap:10px;\n}\n.evidtool992-viewerMedia{\n  background:#000;\n  border:2px solid #af3232;\n  border-radius:16px;\n  padding:10px;\n  display:flex;\n  justify-content:center;\n  align-items:center;\n  min-height: 40vh;\n  overflow:hidden;\n}\n.evidtool992-viewerMedia img,\n.evidtool992-viewerMedia video,\n.evidtool992-viewerMedia audio{\n  max-width:100%;\n  max-height:100%;\n  border-radius:12px;\n}\n.evidtool992-viewerHint{font-size:12px;color:rgba(255,255,255,.65); text-align:center;}\n.evidtool992-viewerClose{\n  position:fixed;\n  top:14px; right:16px;\n  width:44px; height:44px;\n  border-radius:14px;\n  border:1px solid rgba(255,255,255,.10);\n  background:rgba(255,255,255,.06);\n  color:#fff;\n  font-size:26px;\n  cursor:pointer;\n  z-index:1000007;\n}\n    .evidtool992-viewer:not(.is-open) .evidtool992-viewerClose{ display:none; }\n\n.evidtool992-viewerClose:hover{background:rgba(255,255,255,.10);}\n\n@media (max-width: 980px){\n  .evidtool992-grid{grid-template-columns:1fr;}\n  .evidtool992-desc{min-height:unset;}\n  .evidtool992-mediaframe{min-height:240px;}\n}\n\n\n\/* === Evidencetool chrome fix === *\/\n.berf-oc--nochrome .berf-oc__top{ display:none !important; }\n.berf-oc--nochrome .berf-oc__body{ padding-top: 0 !important; height: 100% !important; }\n\n\n\/* Evidtool viewer max height *\/\n.evidtool992-viewer{ padding: 24px !important; }\n.evidtool992-viewer__content{ max-height: 85vh !important; }\n.evidtool992-viewer__media{ max-height: 80vh !important; }\n\n\n.evidtool992-iconbtn{ position:relative; z-index: 5; }\n\n\/* =========================\n   ROUTE TOOL 23 (scop\u00e9)\n   ========================= *\/\n.route23-wrap{ height:100%; }\n.route23-app{\n  height:100%;\n  display:grid;\n  grid-template-columns: 320px 1fr 320px;\n  gap:12px;\n  padding:12px;\n}\n.route23-panel{\n  background: rgba(30,30,30,.82);\n  border:1px solid rgba(255,255,255,.10);\n  border-radius:14px;\n  box-shadow: 0 10px 28px rgba(0,0,0,.35);\n  padding:12px;\n  display:flex;\n  flex-direction:column;\n  gap:10px;\n  min-height:0;\n}\n.route23-panelTitle{\n  font-family: \"Roboto Mono\", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n  font-size:12px;\n  letter-spacing:.16em;\n  text-transform:uppercase;\n  color: rgba(255,255,255,.78);\n}\n.route23-field{ display:flex; flex-direction:column; gap:6px; }\n.route23-label{ font-size:12px; color: rgba(255,255,255,.72); }\n.route23-input{\n  width:100%;\n  padding:10px 12px;\n  border-radius:10px;\n  border:1px solid rgba(255,255,255,.10);\n  background: rgba(0,0,0,.35);\n  color:#fff;\n  outline:none;\n}\n.route23-input:focus{ border-color: rgba(175,50,50,.55); box-shadow:0 0 0 3px rgba(175,50,50,.18); }\n.route23-row{ display:flex; gap:10px; align-items:center; }\n.route23-btn{\n  border:none;\n  border-radius:12px;\n  padding:10px 12px;\n  cursor:pointer;\n  font-weight:700;\n  letter-spacing:.02em;\n  transition: transform .12s ease, filter .12s ease, box-shadow .12s ease;\n  user-select:none;\n}\n.route23-btn:active{ transform: translateY(1px) scale(.99); }\n.route23-btn-primary{ background: linear-gradient(180deg, #cf4242, #af3232); color:#fff; box-shadow: 0 10px 18px rgba(175,50,50,.18); flex:1; }\n.route23-btn-primary:hover{ filter: brightness(1.05); }\n.route23-btn-danger{ background: rgba(175,50,50,.18); color:#ffd6d6; border:1px solid rgba(175,50,50,.35); }\n.route23-btn-danger:hover{ filter: brightness(1.06); }\n.route23-btn-ghost{ width:44px; background: rgba(255,255,255,.06); color:#fff; border:1px solid rgba(255,255,255,.10); }\n.route23-btn-ghost:hover{ filter: brightness(1.10); }\n.route23-hint{ font-size:12px; color: rgba(255,255,255,.65); line-height:1.35; padding-top:2px; }\n.route23-mini{\n  margin-top:auto;\n  padding:10px;\n  border-radius:12px;\n  border:1px dashed rgba(255,255,255,.14);\n  background: rgba(0,0,0,.18);\n}\n.route23-miniTitle{ font-size:12px; color:#ffd6d6; font-weight:700; margin-bottom:6px; }\n.route23-miniText{ font-size:12px; color: rgba(255,255,255,.62); line-height:1.35; }\n\n.route23-mapWrap{\n  background: rgba(0,0,0,.55);\n  border: 1px solid rgba(175,50,50,.45);\n  border-radius: 14px;\n  overflow:hidden;\n  box-shadow: 0 10px 28px rgba(0,0,0,.35);\n  min-height:0;\n}\n.route23-map{ width:100%; height:100%; }\n\n.route23-list{\n  border-radius:12px;\n  border:1px solid rgba(255,255,255,.10);\n  background: rgba(0,0,0,.18);\n  padding:8px;\n  overflow:auto;\n  min-height:0;\n}\n.route23-item{\n  display:flex;\n  gap:10px;\n  align-items:flex-start;\n  justify-content:space-between;\n  padding:10px 10px;\n  border-radius:12px;\n  border:1px solid rgba(255,255,255,.08);\n  background: rgba(0,0,0,.22);\n  margin-bottom:8px;\n}\n.route23-item:hover{ border-color: rgba(255,255,255,.14); background: rgba(0,0,0,.28); }\n.route23-itemName{ color:#fff; font-size:13px; line-height:1.25; flex:1; }\n.route23-itemMeta{ color: rgba(255,255,255,.55); font-size:11px; margin-top:4px; }\n.route23-itemBtns{ display:flex; gap:8px; }\n.route23-miniBtn{\n  width:34px; height:34px;\n  display:inline-flex; align-items:center; justify-content:center;\n  border-radius:10px;\n  border:1px solid rgba(255,255,255,.10);\n  background: rgba(255,255,255,.06);\n  color:#fff;\n  cursor:pointer;\n}\n.route23-miniBtn:hover{ filter: brightness(1.12); }\n.route23-empty{ color: rgba(255,255,255,.55); font-size:13px; padding:10px; }\n\n@media (max-width: 1100px){\n  .route23-app{ grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; }\n  .route23-panel--left{ order: 1; }\n  .route23-mapWrap{ order: 2; min-height: 52vh; }\n  .route23-panel--right{ order: 3; }\n}\n\n\n\/* ROUTE23 \u2014 sizing fix *\/\n\n#route23-root{height:72vh; max-height:72vh; min-height:420px;}\n#route23-root .route23-wrap{height:100%;} \n#route23-root .route23-app{height:100%;} \n#route23-root .route23-map{min-height:0;}\n#route23-root #map23{height:100% !important; width:100% !important; max-width:none !important; border-radius:12px;}\n#route23-root .leaflet-control-container{z-index:2;}\n\n\n\n\/* ===== POST-IT (desktop overlay) ===== *\/\n#postit23-container{position:absolute; inset:0; pointer-events:none; z-index:99999;}\n\/* Post-it \"sur le bureau\" (pas de fen\u00eatre) *\/\n#berf-oc-postit23{background:transparent !important; pointer-events:none;}\n#berf-oc-postit23[data-open=\"true\"]{pointer-events:none;} \/* les notes g\u00e8rent les events *\/\n.postit23-note{position:absolute; width:220px; min-height:200px; background:#fdfd96; border-radius:10px;\n  box-shadow:0 12px 30px rgba(0,0,0,.45); border:1px solid rgba(0,0,0,.22); overflow:hidden; pointer-events:auto;}\n.postit23-head{display:flex; align-items:center; justify-content:space-between; gap:8px;\n  padding:8px 10px; background:rgba(0,0,0,.10); cursor:grab; user-select:none;}\n.postit23-head:active{cursor:grabbing;}\n.postit23-title{font-size:12px; font-weight:700; color:#1b1b1b; opacity:.85;}\n.postit23-actions{display:flex; gap:6px; align-items:center;}\n.postit23-btn{border:none; background:transparent; cursor:pointer; width:26px; height:26px; border-radius:8px;\n  display:inline-flex; align-items:center; justify-content:center; color:#222; opacity:.85;}\n.postit23-btn:hover{background:rgba(0,0,0,.12); opacity:1;}\n.postit23-body{padding:10px;}\n.postit23-text{width:100%; height:130px; background:transparent; border:none; outline:none; resize:vertical;\n  font-size:13px; color:#222; font-family:inherit;}\n.postit23-save{width:100%; margin-top:8px; padding:10px 10px; border:none; border-radius:10px;\n  background:#af3232; color:#fff; font-weight:700; cursor:pointer;}\n.postit23-save:hover{filter:brightness(1.05);}\n.postit23-hud{position:absolute; right:16px; top:16px; display:flex; gap:10px; pointer-events:auto;\n  z-index:100000;}\n.postit23-pill{background:rgba(20,20,20,.72); border:1px solid rgba(255,255,255,.08); color:#eee;\n  padding:8px 10px; border-radius:999px; font-size:12px; display:flex; align-items:center; gap:8px;\n  box-shadow:0 10px 26px rgba(0,0,0,.45); backdrop-filter: blur(8px);}\n.postit23-pill button{all:unset; cursor:pointer; padding:4px 8px; border-radius:999px; background:rgba(255,255,255,.08);}\n.postit23-pill button:hover{background:rgba(255,255,255,.14);}\n\n#postit23-container .postit23{pointer-events:auto; position:absolute; width:240px; min-height:220px; background:linear-gradient(180deg,#fff6a6,#ffe66b); border:1px solid rgba(0,0,0,.15); border-radius:10px; box-shadow:0 14px 35px rgba(0,0,0,.35); padding:12px 12px 10px; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial; }\n#postit23-container .postit23:before{content:\"\"; position:absolute; top:0; left:0; right:0; height:26px; border-radius:10px 10px 0 0; background:rgba(0,0,0,.05);} \n#postit23-container .postit23 .p23-head{display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:8px; padding-top:2px; cursor:grab;}\n#postit23-container .postit23 .p23-title{font-size:12px; font-weight:700; letter-spacing:.08em; color:#503f00; text-transform:uppercase; opacity:.9;}\n#postit23-container .postit23 .p23-actions{display:flex; gap:8px;}\n#postit23-container .postit23 .p23-iconbtn{width:28px; height:28px; border:none; border-radius:8px; cursor:pointer; background:rgba(0,0,0,.08); color:#3a2f00; display:grid; place-items:center;}\n#postit23-container .postit23 .p23-iconbtn:hover{background:rgba(0,0,0,.14);}\n#postit23-container .postit23 textarea{width:100%; height:138px; border:none; outline:none; resize:vertical; background:transparent; font-size:14px; line-height:1.35; color:#2b2500;}\n#postit23-container .postit23 .p23-footer{display:flex; gap:8px; margin-top:8px;}\n#postit23-container .postit23 .p23-btn{flex:1; border:none; cursor:pointer; border-radius:10px; padding:10px 10px; font-weight:700; font-size:13px;}\n#postit23-container .postit23 .p23-save{background:#af3232; color:#fff;}\n#postit23-container .postit23 .p23-save:hover{filter:brightness(1.05);}\n#postit23-container .postit23 .p23-hide{background:rgba(0,0,0,.10); color:#3a2f00;}\n#postit23-container .postit23 .p23-hide:hover{background:rgba(0,0,0,.16);}\n\n\n\n\n\n\/* ===== Knowledge Base ===== *\/\n#berfDesk .kb901-shell{display:grid;grid-template-columns:320px minmax(0,1fr);gap:16px;min-height:calc(100vh - 90px);padding:16px}\n#berfDesk .kb901-side,#berfDesk .kb901-main{background:linear-gradient(180deg,rgba(255,255,255,.03),rgba(255,255,255,.015));border:1px solid rgba(255,255,255,.08);border-radius:18px;box-shadow:0 12px 34px rgba(0,0,0,.28)}\n#berfDesk .kb901-side{padding:14px;display:flex;flex-direction:column;gap:14px}\n#berfDesk .kb901-sideTop{display:flex;flex-direction:column;gap:10px}\n#berfDesk .kb901-brand{display:flex;flex-direction:column}\n#berfDesk .kb901-brandTop{font-size:12px;letter-spacing:.25em;color:#9ea9b7;text-transform:uppercase}\n#berfDesk .kb901-brandSub{font-size:20px;font-weight:700;color:#fff}\n#berfDesk .kb901-scan{height:4px;border-radius:999px;background:rgba(255,255,255,.06);overflow:hidden}\n#berfDesk .kb901-scan span{display:block;height:100%;width:26%;background:linear-gradient(90deg,transparent,#af3232,transparent);animation:kb901scan 3s linear infinite}\n@keyframes kb901scan{from{transform:translateX(-120%)}to{transform:translateX(420%)}}\n#berfDesk .kb901-search{width:100%;border-radius:12px;border:1px solid rgba(255,255,255,.1);background:rgba(0,0,0,.28);color:#f3f6fb;padding:12px 14px}\n#berfDesk .kb901-list{display:flex;flex-direction:column;gap:8px;overflow:auto;padding-right:4px}\n#berfDesk .kb901-item{width:100%;text-align:left;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03);color:#fff;border-radius:14px;padding:12px 13px;cursor:pointer}\n#berfDesk .kb901-item:hover,#berfDesk .kb901-item.is-active{border-color:rgba(175,50,50,.45);background:rgba(175,50,50,.12)}\n#berfDesk .kb901-itemTitle{font-weight:700}\n#berfDesk .kb901-itemMeta{font-size:12px;color:#a9b6c5;margin-top:4px}\n#berfDesk .kb901-main{padding:18px;position:relative}\n#berfDesk .kb901-empty{min-height:420px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:#b7c2cf;text-align:center}\n#berfDesk .kb901-empty i{font-size:44px;color:#af3232}\n#berfDesk .kb901-detailHead{display:flex;justify-content:space-between;gap:16px;margin-bottom:16px}\n#berfDesk .kb901-kicker{font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:#8e9bad}\n#berfDesk .kb901-title{font-size:30px;line-height:1.1;color:#fff;margin:6px 0}\n#berfDesk .kb901-meta{font-size:14px;color:#b7c2cf}\n#berfDesk .kb901-detailGrid{display:grid;grid-template-columns:minmax(280px,360px) minmax(0,1fr);gap:18px}\n#berfDesk .kb901-figureFrame{border-radius:18px;border:1px solid rgba(255,255,255,.08);background:rgba(0,0,0,.24);min-height:380px;display:flex;align-items:center;justify-content:center;overflow:hidden}\n#berfDesk .kb901-figureFrame img{max-width:100%;max-height:460px;display:block;cursor:zoom-in}\n#berfDesk .kb901-noimage{display:flex;flex-direction:column;align-items:center;gap:8px;color:#9ca9b6}\n#berfDesk .kb901-sectionTitle{font-size:13px;text-transform:uppercase;letter-spacing:.18em;color:#9aa6b4;margin-bottom:10px}\n#berfDesk .kb901-description{color:#edf2f7;font-size:15px;line-height:1.7;white-space:pre-wrap}\n#berfDesk .kb901-viewer{display:none;position:fixed;inset:0;z-index:999999;background:rgba(0,0,0,.92);align-items:center;justify-content:center}\n#berfDesk .kb901-viewer[aria-hidden=\"false\"]{display:flex}\n#berfDesk .kb901-viewerInner{max-width:92vw;max-height:92vh}\n#berfDesk .kb901-viewerInner img{max-width:92vw;max-height:92vh;display:block}\n#berfDesk .kb901-viewerClose{position:absolute;top:16px;right:18px;width:42px;height:42px;border-radius:999px;border:none;background:rgba(255,255,255,.12);color:#fff;font-size:28px;cursor:pointer}\n@media (max-width:980px){\n  #berfDesk .kb901-shell{grid-template-columns:1fr}\n  #berfDesk .kb901-detailGrid{grid-template-columns:1fr}\n}\n\n\n\/* ===== Global notifications ===== *\/\n#berfDesk .berf-toast-stack{position:fixed;right:18px;bottom:76px;z-index:999999;display:flex;flex-direction:column;gap:10px;pointer-events:none}\n#berfDesk .berf-toast{width:min(390px,calc(100vw - 36px));background:linear-gradient(180deg,rgba(18,23,29,.98),rgba(13,17,23,.98));border:1px solid rgba(175,50,50,.34);border-radius:16px;box-shadow:0 18px 40px rgba(0,0,0,.46);overflow:hidden;pointer-events:auto;cursor:pointer;transform:translateY(12px);opacity:0;animation:berfToastIn .26s ease forwards}\n#berfDesk .berf-toast__top{display:flex;align-items:center;gap:12px;padding:12px 14px 10px}\n#berfDesk .berf-toast__icon{width:34px;height:34px;border-radius:10px;display:flex;align-items:center;justify-content:center;background:rgba(175,50,50,.14);color:#ef9a9a;flex:0 0 auto}\n#berfDesk .berf-toast__body{min-width:0}\n#berfDesk .berf-toast__title{color:#fff;font-size:14px;font-weight:700;line-height:1.25}\n#berfDesk .berf-toast__text{color:#c4ced8;font-size:12px;line-height:1.45;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n#berfDesk .berf-toast__bar{height:3px;background:rgba(255,255,255,.06);position:relative}\n#berfDesk .berf-toast__bar::after{content:\"\";position:absolute;left:0;top:0;bottom:0;width:100%;background:linear-gradient(90deg,#af3232,#d84c4c,#f18282);transform-origin:left center;animation:berfToastTimer 6s linear forwards}\n@keyframes berfToastIn{to{opacity:1;transform:translateY(0)}}\n@keyframes berfToastOut{to{opacity:0;transform:translateY(12px)}}\n@keyframes berfToastTimer{to{transform:scaleX(0)}}\n#berfDesk .berf-notify-btn{position:relative}\n#berfDesk .berf-notify-btn .berf-badge{top:-7px;right:-7px;min-width:18px;height:18px;font-size:10px}\n#berfDesk .berf-notify-btn[data-unread=\"0\"] .berf-badge{display:none}\n#berfDesk .berf-notify-drawer{position:fixed;right:0;top:0;bottom:0;width:min(30vw,420px);min-width:320px;z-index:999998;background:linear-gradient(180deg,rgba(10,13,18,.99),rgba(14,18,24,.99));border-left:1px solid rgba(175,50,50,.28);box-shadow:-16px 0 42px rgba(0,0,0,.48);transform:translateX(100%);transition:transform .26s ease;display:flex;flex-direction:column}\n#berfDesk .berf-notify-drawer[data-open=\"true\"]{transform:translateX(0)}\n#berfDesk .berf-notify-drawer__head{display:flex;align-items:center;justify-content:space-between;padding:18px 18px 10px;border-bottom:1px solid rgba(255,255,255,.07)}\n#berfDesk .berf-notify-drawer__title{color:#fff;font-weight:700;font-size:18px;display:flex;align-items:center;gap:10px}\n#berfDesk .berf-notify-drawer__close{width:36px;height:36px;border:none;border-radius:999px;background:rgba(255,255,255,.08);color:#fff;font-size:24px;cursor:pointer}\n#berfDesk .berf-notify-drawer__sub{padding:10px 18px 14px;color:#9aa8b7;font-size:12px;letter-spacing:.1em;text-transform:uppercase}\n#berfDesk .berf-notify-drawer__list{padding:0 12px 12px;overflow:auto;display:flex;flex-direction:column;gap:10px}\n#berfDesk .berf-notify-item{width:100%;text-align:left;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);border-radius:16px;padding:14px 14px 12px;color:#fff;cursor:pointer}\n#berfDesk .berf-notify-item:hover{border-color:rgba(175,50,50,.34);background:rgba(175,50,50,.11)}\n#berfDesk .berf-notify-item__meta{display:flex;align-items:center;gap:10px;color:#ef9a9a;font-size:11px;text-transform:uppercase;letter-spacing:.12em;margin-bottom:6px}\n#berfDesk .berf-notify-item__title{font-size:14px;font-weight:700}\n#berfDesk .berf-notify-item__text{font-size:12px;line-height:1.45;color:#c5cfda;margin-top:3px}\n#berfDesk .berf-notify-empty{padding:16px;border:1px dashed rgba(255,255,255,.08);border-radius:16px;color:#98a5b3;text-align:center}\n@media (max-width:980px){#berfDesk .berf-notify-drawer{width:min(86vw,420px);min-width:0}}\n\n\n\/* ===== Global notifications (body-mounted fallback) ===== *\/\n.berf-toast-stack{position:fixed;right:18px;bottom:76px;z-index:2147483646;display:flex;flex-direction:column;gap:10px;pointer-events:none}\n.berf-toast{width:min(390px,calc(100vw - 36px));background:linear-gradient(180deg,rgba(18,23,29,.98),rgba(13,17,23,.98));border:1px solid rgba(175,50,50,.34);border-radius:16px;box-shadow:0 18px 40px rgba(0,0,0,.46);overflow:hidden;pointer-events:auto;cursor:pointer;transform:translateY(12px);opacity:0;animation:berfToastIn .26s ease forwards}\n.berf-toast__top{display:flex;align-items:center;gap:12px;padding:12px 14px 10px}\n.berf-toast__icon{width:34px;height:34px;border-radius:10px;display:flex;align-items:center;justify-content:center;background:rgba(175,50,50,.14);color:#ef9a9a;flex:0 0 auto}\n.berf-toast__body{min-width:0}\n.berf-toast__title{color:#fff;font-size:14px;font-weight:700;line-height:1.25}\n.berf-toast__text{color:#c4ced8;font-size:12px;line-height:1.45;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n.berf-toast__bar{height:3px;background:rgba(255,255,255,.06);position:relative}\n.berf-toast__bar::after{content:\"\";position:absolute;left:0;top:0;bottom:0;width:100%;background:linear-gradient(90deg,#af3232,#d84c4c,#f18282);transform-origin:left center;animation:berfToastTimer 6s linear forwards}\n.berf-notify-drawer{position:fixed;right:0;top:0;bottom:0;width:min(30vw,420px);min-width:320px;z-index:2147483645;background:linear-gradient(180deg,rgba(10,13,18,.99),rgba(14,18,24,.99));border-left:1px solid rgba(175,50,50,.28);box-shadow:-16px 0 42px rgba(0,0,0,.48);transform:translateX(100%);transition:transform .26s ease;display:flex;flex-direction:column}\n.berf-notify-drawer[data-open=\"true\"]{transform:translateX(0)}\n.berf-notify-drawer__head{display:flex;align-items:center;justify-content:space-between;padding:18px 18px 10px;border-bottom:1px solid rgba(255,255,255,.07)}\n.berf-notify-drawer__title{color:#fff;font-weight:700;font-size:18px;display:flex;align-items:center;gap:10px}\n.berf-notify-drawer__close{width:36px;height:36px;border:none;border-radius:999px;background:rgba(255,255,255,.08);color:#fff;font-size:24px;cursor:pointer}\n.berf-notify-drawer__sub{padding:10px 18px 14px;color:#9aa8b7;font-size:12px;letter-spacing:.1em;text-transform:uppercase}\n.berf-notify-drawer__list{padding:0 12px 12px;overflow:auto;display:flex;flex-direction:column;gap:10px}\n.berf-notify-item{width:100%;text-align:left;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);border-radius:16px;padding:14px 14px 12px;color:#fff;cursor:pointer}\n.berf-notify-item:hover{border-color:rgba(175,50,50,.34);background:rgba(175,50,50,.11)}\n.berf-notify-item__meta{display:flex;align-items:center;gap:10px;color:#ef9a9a;font-size:11px;text-transform:uppercase;letter-spacing:.12em;margin-bottom:6px}\n.berf-notify-item__title{font-size:14px;font-weight:700}\n.berf-notify-item__text{font-size:12px;line-height:1.45;color:#c5cfda;margin-top:3px}\n.berf-notify-empty{padding:16px;border:1px dashed rgba(255,255,255,.08);border-radius:16px;color:#98a5b3;text-align:center}\n@media (max-width:980px){.berf-notify-drawer{width:min(86vw,420px);min-width:0}}\n\n\n\/* =========================================================\n   TABLET RESPONSIVE PATCH\n   ========================================================= *\/\n@media (max-width: 1024px){\n  #berfDesk{\n    min-height: 100svh;\n    overflow: hidden;\n  }\n\n  #berfDesk .berf-leftbar{\n    position: fixed;\n    top: 10px;\n    left: 10px;\n    bottom: auto;\n    right: 10px;\n    width: auto;\n    max-width: calc(100vw - 20px);\n    display: flex;\n    gap: 8px;\n    padding: 8px;\n    border-radius: 18px;\n    background: rgba(8,10,14,0.72);\n    border: 1px solid rgba(255,255,255,0.08);\n    backdrop-filter: blur(10px);\n    overflow-x: auto;\n    z-index: 1000003;\n  }\n\n  #berfDesk .berf-leftbar .berf-app{\n    flex: 0 0 auto;\n    width: 46px;\n    height: 46px;\n    min-width: 46px;\n  }\n\n  #berfDesk .berf-taskbar{\n    height: 74px;\n    padding: 0 10px;\n    gap: 8px;\n  }\n\n  #berfDesk .start-menu-container{\n    gap: 8px;\n    min-width: 0;\n    flex: 1 1 auto;\n  }\n\n  #berfDesk .start-button{\n    font-size: 28px;\n    padding: 0 10px;\n    min-width: 48px;\n    height: 48px;\n  }\n\n  #berfDesk .berf-taskbar-search{\n    min-width: 0;\n    width: min(240px, 28vw);\n    max-width: 240px;\n  }\n\n  #berfDesk .berf-taskbar-apps{\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    flex: 1 1 auto;\n    min-width: 0;\n    overflow-x: auto;\n    overflow-y: hidden;\n    -webkit-overflow-scrolling: touch;\n    scrollbar-width: thin;\n    padding-bottom: 2px;\n  }\n\n  #berfDesk .berf-taskbar-app{\n    flex: 0 0 auto;\n    width: 46px;\n    height: 46px;\n    min-width: 46px;\n  }\n\n  #berfDesk .start-menu{\n    width: min(88vw, 320px);\n    bottom: 82px;\n    left: 0;\n  }\n\n  #berfDesk .berf-oc__main{\n    width: 100vw;\n  }\n\n  #berfDesk .berf-oc__top{\n    padding: 10px 12px;\n  }\n\n  #berfDesk .berf-oc__close{\n    width: 44px;\n    height: 44px;\n  }\n\n  #berfDesk .berf-oc__body{\n    padding-bottom: 88px;\n  }\n\n  #berfMailTool .inbox-container{\n    margin: 12px auto;\n    min-height: calc(100svh - 170px);\n  }\n\n  #berfMailTool .email-list,\n  #berfMailTool .email-details{\n    width: 100% !important;\n    max-width: 100%;\n  }\n\n  #berfMailTool .email-item{\n    min-height: 56px;\n    padding: 12px 10px;\n  }\n\n  #berfMailTool .email-list #newMailButton{\n    position: sticky;\n    bottom: 0;\n    margin-bottom: 0;\n  }\n\n  #berfSuspectsTool .container42X,\n  #berfDesk .tri77,\n  #berfDesk .route23,\n  #berfDesk #kb901-root{\n    width: 100%;\n    max-width: 100%;\n  }\n\n  #berfSuspectsTool .container42X{\n    padding: 14px;\n  }\n\n  #berfSuspectsTool .suspect-table42X{\n    display: block;\n    overflow-x: auto;\n    white-space: nowrap;\n  }\n\n  #berfDesk #berfTriangulation77 .tri77__grid{\n    grid-template-columns: 1fr;\n  }\n\n  #berfDesk #berfTriangulation77 .tri77__col{\n    min-height: auto;\n  }\n\n  #berfDesk #berfTriangulation77 #map77,\n  #berfDesk #berfTriangulation77 .tri77__map{\n    min-height: 320px;\n  }\n\n  #berfDesk .berf-notify-drawer{\n    width: min(82vw, 420px);\n    min-width: 0;\n  }\n\n  #postit23-container{\n    left: 14px !important;\n    right: 14px !important;\n    width: auto !important;\n    max-width: none !important;\n  }\n}\n\n@media (max-width: 820px){\n  #berfDesk .berf-leftbar{\n    top: 8px;\n    left: 8px;\n    right: 8px;\n  }\n\n  #berfDesk .berf-taskbar{\n    height: 70px;\n    padding: 0 8px;\n  }\n\n  #berfDesk .berf-taskbar-search{\n    width: min(180px, 32vw);\n    max-width: 180px;\n  }\n\n  #berfDesk .start-menu{\n    width: min(92vw, 320px);\n  }\n\n  #berfDesk .berf-oc__body{\n    padding-bottom: 82px;\n  }\n}\n\n\n\/* =========================================================\n   TABLET VIEWPORT + DESKTOP LAYOUT FIX\n   ========================================================= *\/\n#berfDesk{\n  position: relative;\n  width: 100%;\n  min-height: 100svh;\n  min-height: 100dvh;\n  height: auto;\n  overflow: hidden;\n}\n\n#berfDesk > .berf-bg{\n  position: absolute;\n  inset: 0;\n}\n\n#berfDesk .berf-oc__body{\n  min-height: calc(100svh - 64px);\n  min-height: calc(100dvh - 64px);\n}\n\n@media (max-width: 1024px){\n  #berfDesk{\n    min-height: 100svh !important;\n    min-height: 100dvh !important;\n    height: auto !important;\n  }\n\n  #berfDesk > .berf-bg{\n    position: absolute;\n    inset: 0;\n  }\n\n  #berfDesk .berf-leftbar{\n    position: fixed;\n    top: 10px;\n    left: 10px;\n    right: 10px;\n    bottom: auto;\n    width: auto;\n    max-width: calc(100vw - 20px);\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    padding: 8px;\n    border-radius: 18px;\n    background: rgba(8,10,14,0.72);\n    border: 1px solid rgba(255,255,255,0.08);\n    backdrop-filter: blur(10px);\n    overflow-x: auto;\n    overflow-y: hidden;\n    z-index: 1000003;\n  }\n\n  #berfDesk .berf-leftbar .berf-app{\n    flex: 0 0 auto;\n    width: 46px;\n    height: 46px;\n    min-width: 46px;\n  }\n\n  #berfDesk .berf-taskbar{\n    position: fixed;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    height: 74px;\n    padding: 0 10px;\n    gap: 8px;\n  }\n\n  #berfDesk .start-menu-container{\n    gap: 8px;\n    min-width: 0;\n    flex: 1 1 auto;\n  }\n\n  #berfDesk .start-button{\n    font-size: 28px;\n    padding: 0 10px;\n    min-width: 48px;\n    height: 48px;\n  }\n\n  #berfDesk .berf-taskbar-search{\n    min-width: 0;\n    width: min(220px, 32vw);\n    max-width: 220px;\n  }\n\n  #berfDesk .berf-taskbar-apps{\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    flex: 1 1 auto;\n    min-width: 0;\n    overflow-x: auto;\n    overflow-y: hidden;\n    -webkit-overflow-scrolling: touch;\n    scrollbar-width: thin;\n    padding-bottom: 2px;\n  }\n\n  #berfDesk .berf-taskbar-app{\n    flex: 0 0 auto;\n    width: 48px;\n    height: 48px;\n    min-width: 48px;\n  }\n\n  #berfDesk .berf-taskbar-app i{\n    font-size: 20px;\n  }\n\n  #berfDesk .start-menu{\n    width: min(92vw, 320px);\n    bottom: 82px;\n    left: 0;\n  }\n\n  #berfDesk .berf-oc{\n    position: fixed;\n    inset: 0;\n  }\n\n  #berfDesk .berf-oc__main{\n    width: 100vw !important;\n    max-width: 100vw !important;\n    min-height: 100svh;\n    min-height: 100dvh;\n    height: 100svh;\n    height: 100dvh;\n    border-left: none;\n    border-radius: 0;\n  }\n\n  #berfDesk .berf-oc__top{\n    padding: 10px 12px;\n  }\n\n  #berfDesk .berf-oc__close{\n    width: 44px;\n    height: 44px;\n  }\n\n  #berfDesk .berf-oc__body{\n    min-height: calc(100svh - 74px);\n    min-height: calc(100dvh - 74px);\n    padding-bottom: 96px;\n  }\n\n  #berfMailTool .inbox-container{\n    margin: 12px auto;\n    min-height: calc(100svh - 190px);\n    min-height: calc(100dvh - 190px);\n  }\n\n  #berfMailTool .email-list,\n  #berfMailTool .email-details{\n    width: 100% !important;\n    max-width: 100%;\n  }\n\n  #berfMailTool .email-item{\n    min-height: 56px;\n    padding: 12px 10px;\n  }\n\n  #berfMailTool .email-list #newMailButton{\n    position: sticky;\n    bottom: 0;\n    margin-bottom: 0;\n  }\n\n  #berfSuspectsTool .container42X{\n    width: calc(100% - 16px);\n    margin: 8px auto;\n    padding: 14px;\n  }\n\n  #berfSuspectsTool .suspect-table42X{\n    display: block;\n    overflow-x: auto;\n    white-space: nowrap;\n  }\n\n  #berfDesk #berfTriangulation77 .tri77__grid{\n    grid-template-columns: 1fr !important;\n  }\n\n  #berfDesk #berfTriangulation77 .tri77__col{\n    min-height: auto;\n  }\n\n  #berfDesk #berfTriangulation77 #map77,\n  #berfDesk #berfTriangulation77 .tri77__map{\n    min-height: 320px;\n  }\n\n  #berfDesk .berf-notify-drawer{\n    width: min(86vw, 420px);\n    min-width: 0;\n  }\n\n  #postit23-container{\n    left: 14px !important;\n    right: 14px !important;\n    width: auto !important;\n    max-width: none !important;\n  }\n}\n\n@media (max-width: 820px){\n  #berfDesk .berf-leftbar{\n    top: 8px;\n    left: 8px;\n    right: 8px;\n  }\n\n  #berfDesk .berf-taskbar{\n    height: 70px;\n    padding: 0 8px;\n  }\n\n  #berfDesk .berf-taskbar-search{\n    width: min(180px, 34vw);\n    max-width: 180px;\n  }\n\n  #berfDesk .berf-oc__body{\n    min-height: calc(100svh - 70px);\n    min-height: calc(100dvh - 70px);\n    padding-bottom: 90px;\n  }\n}\n\n\n\/* =========================================================\n   TABLET APP ICON GRID (iOS \/ Android style)\n   ========================================================= *\/\n@media (max-width: 1024px){\n  #berfDesk .berf-leftbar{\n    position: absolute !important;\n    top: 18px !important;\n    left: 16px !important;\n    right: 16px !important;\n    bottom: auto !important;\n    width: auto !important;\n    max-width: none !important;\n    display: grid !important;\n    grid-template-columns: repeat(5, minmax(110px, 1fr)) !important;\n    justify-items: center;\n    align-items: start;\n    gap: 24px 18px;\n    padding: 0 !important;\n    border: none !important;\n    border-radius: 0 !important;\n    background: transparent !important;\n    backdrop-filter: none !important;\n    overflow: visible !important;\n    box-shadow: none !important;\n  }\n\n  #berfDesk .berf-leftbar .berf-app{\n    width: 110px !important;\n    height: 110px !important;\n    min-width: 110px !important;\n    border-radius: 22px !important;\n    box-shadow: 0 10px 22px rgba(0,0,0,0.28);\n  }\n\n  #berfDesk .berf-app i{\n    font-size: 50px !important;\n  }\n\n  #berfDesk .berf-leftbar .berf-badge{\n    top: -5px !important;\n    right: -5px !important;\n  }\n}\n\n@media (max-width: 820px){\n  #berfDesk .berf-leftbar{\n    top: 14px !important;\n    left: 12px !important;\n    right: 12px !important;\n    grid-template-columns: repeat(4, minmax(110px, 1fr)) !important;\n    gap: 24px 18px;\n  }\n}\n\n\n\/* =========================================================\n   TABLET BALANCE FIXES\n   ========================================================= *\/\n@media (max-width: 1024px){\n  #berfDesk .berf-taskbar{\n    height: 84px !important;\n    padding: 0 10px !important;\n  }\n\n  #berfDesk .berf-taskbar-app{\n    width: 58px !important;\n    height: 58px !important;\n    min-width: 58px !important;\n    border-radius: 16px !important;\n  }\n\n  #berfDesk .berf-taskbar-app i{\n    font-size: 24px !important;\n  }\n\n  #berfDesk .berf-oc__body{\n    min-height: calc(100svh - 84px) !important;\n    min-height: calc(100dvh - 84px) !important;\n    padding-bottom: 104px !important;\n  }\n\n  #berfDesk[data-berf-oc-open=\"true\"] .berf-leftbar{\n    opacity: 0 !important;\n    pointer-events: none !important;\n    visibility: hidden !important;\n  }\n}\n\n@media (max-width: 820px){\n  #berfDesk .berf-taskbar{\n    height: 82px !important;\n  }\n\n  #berfDesk .berf-taskbar-app{\n    width: 56px !important;\n    height: 56px !important;\n    min-width: 56px !important;\n  }\n\n  #berfDesk .berf-taskbar-app i{\n    font-size: 23px !important;\n  }\n\n  #berfDesk .berf-oc__body{\n    min-height: calc(100svh - 82px) !important;\n    min-height: calc(100dvh - 82px) !important;\n    padding-bottom: 102px !important;\n  }\n}\n\n\n\/* ===== Analyze image buttons in viewers ===== *\/\n.berf-viewer-actionbar{\n  display:flex;\n  justify-content:center;\n  gap:10px;\n  margin-top:14px;\n  flex-wrap:wrap;\n}\n.berf-viewer-analyze-btn{\n  border:1px solid rgba(255,255,255,0.12);\n  background:rgba(175,50,50,0.92);\n  color:#fff;\n  border-radius:12px;\n  padding:10px 14px;\n  font-weight:700;\n  cursor:pointer;\n  box-shadow:0 10px 22px rgba(0,0,0,0.25);\n}\n.berf-viewer-analyze-btn:hover{\n  background:#c53b3b;\n}\n\n\n\/* ===== File manager viewer actions ===== *\/\n#berfFilesTool #media-viewer264 #media-content479 .berf-viewer-actionbar{\n  position:absolute;\n  left:12px;\n  right:12px;\n  bottom:12px;\n  display:flex;\n  justify-content:flex-end;\n  gap:10px;\n  z-index:1012;\n  pointer-events:auto;\n}\n#berfFilesTool #media-viewer264 #media-content479 .berf-viewer-actionbar button{\n  position:static !important;\n}\n#berfFilesTool #media-viewer264 #media-content479 #media-analyze-btn264-inline{\n  display:inline-flex;\n}\n\n\n\/* ===== Files viewer fixed action footer ===== *\/\n#berfFilesTool #media-viewer264{\n  display:none;\n  position:fixed;\n  top:50%;\n  left:50%;\n  transform:translate(-50%, -50%);\n  width:80%;\n  height:80%;\n  padding:15px;\n  border-radius:12px;\n  background:#222;\n  border:1px solid #444;\n  box-shadow:0 4px 8px rgba(0,0,0,.2);\n  z-index:100000;\n  overflow:hidden;\n  pointer-events:auto;\n}\n#berfFilesTool #media-viewer264 #media-content479{\n  position:absolute;\n  inset:15px 15px 78px 15px;\n  height:auto !important;\n}\n#berfFilesTool #media-viewer264 .files-viewer-actions264{\n  position:absolute;\n  left:15px;\n  right:15px;\n  bottom:15px;\n  display:flex;\n  justify-content:flex-end;\n  align-items:center;\n  gap:10px;\n  z-index:1015;\n  pointer-events:auto;\n}\n#berfFilesTool #media-viewer264 .files-viewer-actions264 button{\n  position:static !important;\n  display:inline-flex;\n  align-items:center;\n  justify-content:center;\n}\n#berfFilesTool #media-viewer264 #media-download-btn264{\n  background-color:#af3232;\n  color:#fff;\n  padding:8px 12px;\n  border:none;\n  border-radius:5px;\n  cursor:pointer;\n}\n#berfFilesTool #media-viewer264 #media-analyze-btn264{\n  display:none;\n}\n\n\n\/* ===== Files viewer emergency action buttons ===== *\/\n#berfFilesTool #media-viewer264 .berf-files-float-actions{\n  position:absolute;\n  right:15px;\n  bottom:15px;\n  display:flex;\n  gap:10px;\n  z-index:99999;\n}\n#berfFilesTool #media-viewer264 .berf-files-float-actions button{\n  display:inline-flex;\n  align-items:center;\n  justify-content:center;\n  position:static !important;\n  padding:10px 14px;\n  border:none;\n  border-radius:10px;\n  cursor:pointer;\n}\n#berfFilesTool #media-viewer264 .berf-files-download-btn{\n  background:#af3232;\n  color:#fff;\n}\n#berfFilesTool #media-viewer264 .berf-files-analyze-btn{\n  background:#af3232;\n  color:#fff;\n}\n\n\n\/* Preserve line breaks in mail body *\/\n#berfMailTool .email-details .message-body{\n  white-space: pre-wrap;\n}\n\n\n\/* KB tabs *\/\n#berfDesk .kb901-tabs{\n  display:flex;\n  flex-wrap:wrap;\n  gap:8px;\n  margin-bottom:14px;\n}\n#berfDesk .kb901-tab{\n  border:1px solid rgba(255,255,255,.12);\n  background:rgba(0,0,0,.25);\n  color:rgba(255,255,255,.88);\n  border-radius:10px;\n  padding:10px 12px;\n  cursor:pointer;\n}\n#berfDesk .kb901-tab.is-active{\n  background:#af3232;\n  color:#fff;\n  border-color:#af3232;\n}\n#berfDesk .kb901-tabPanel{ display:none; }\n#berfDesk .kb901-tabPanel.is-active{ display:block; }\n#berfDesk .kb901-generalMeta{\n  display:grid;\n  grid-template-columns:repeat(3,minmax(0,1fr));\n  gap:10px;\n  margin-bottom:14px;\n}\n#berfDesk .kb901-metaCard{\n  background:rgba(0,0,0,.22);\n  border:1px solid rgba(255,255,255,.08);\n  border-radius:12px;\n  padding:12px;\n}\n#berfDesk .kb901-metaCard span{\n  display:block;\n  font-size:12px;\n  opacity:.72;\n  margin-bottom:6px;\n}\n#berfDesk .kb901-metaCard strong{\n  font-size:15px;\n}\n#berfDesk .kb901-figureFrame{\n  background:#fff;\n}\n@media (max-width: 900px){\n  #berfDesk .kb901-generalMeta{ grid-template-columns:1fr; }\n}\n\n\n\/* ===== BERF KB UI UPGRADE ===== *\/\n#berfDesk .kb901-detailHead{\n  border-bottom:1px solid rgba(255,255,255,.08);\n  padding-bottom:10px;\n  margin-bottom:12px;\n}\n\n#berfDesk .kb901-title{\n  font-size:22px;\n  font-weight:700;\n  letter-spacing:.5px;\n}\n\n#berfDesk .kb901-meta{\n  opacity:.7;\n  font-size:13px;\n}\n\n#berfDesk .kb901-generalMeta{\n  display:flex;\n  gap:10px;\n  flex-wrap:wrap;\n}\n\n#berfDesk .kb901-metaCard{\n  background:#111;\n  border:1px solid rgba(255,255,255,.1);\n  padding:10px 14px;\n  border-radius:8px;\n  display:flex;\n  flex-direction:column;\n  min-width:120px;\n}\n\n#berfDesk .kb901-metaCard span{\n  font-size:11px;\n  opacity:.6;\n}\n\n#berfDesk .kb901-metaCard strong{\n  font-size:14px;\n  margin-top:4px;\n}\n\n#berfDesk .kb901-description{\n  background:rgba(0,0,0,.25);\n  border:1px solid rgba(255,255,255,.08);\n  padding:14px;\n  border-radius:10px;\n  line-height:1.5;\n  white-space:pre-line;\n}\n\n#berfDesk .kb901-tabs{\n  display:flex;\n  gap:6px;\n  margin-bottom:12px;\n}\n\n#berfDesk .kb901-tab{\n  font-size:13px;\n  padding:8px 10px;\n  border-radius:6px;\n}\n\n#berfDesk .kb901-tab.is-active{\n  background:#af3232;\n}\n\n#berfDesk .kb901-figureFrame{\n  background:#fff;\n  border-radius:10px;\n  padding:10px;\n  box-shadow:0 5px 20px rgba(0,0,0,.4);\n}\n\n\n\/* ===== KB UI OVERHAUL v1.8.3 ===== *\/\n#berfDesk #kb901-detail{\n  background: linear-gradient(180deg, rgba(20,22,28,.92) 0%, rgba(10,12,16,.95) 100%) !important;\n  border: 1px solid rgba(255,255,255,.08) !important;\n  border-radius: 18px !important;\n  padding: 18px !important;\n  box-shadow: 0 18px 42px rgba(0,0,0,.35) !important;\n}\n\n#berfDesk .kb901-detailHead{\n  display:flex !important;\n  align-items:flex-start !important;\n  justify-content:space-between !important;\n  gap:16px !important;\n  border-bottom:1px solid rgba(255,255,255,.08) !important;\n  padding-bottom:14px !important;\n  margin-bottom:16px !important;\n}\n\n#berfDesk .kb901-kicker{\n  display:inline-flex !important;\n  padding:6px 10px !important;\n  border-radius:999px !important;\n  background:rgba(175,50,50,.16) !important;\n  border:1px solid rgba(175,50,50,.38) !important;\n  color:#ffb0b0 !important;\n  text-transform:uppercase !important;\n  letter-spacing:.12em !important;\n  font-size:11px !important;\n  margin-bottom:8px !important;\n}\n\n#berfDesk .kb901-title{\n  font-size:28px !important;\n  line-height:1.05 !important;\n  font-weight:800 !important;\n  margin:0 0 8px 0 !important;\n  color:#fff !important;\n  letter-spacing:.01em !important;\n}\n\n#berfDesk .kb901-meta{\n  font-size:13px !important;\n  color:rgba(255,255,255,.72) !important;\n}\n\n#berfDesk .kb901-detailGrid{\n  display:grid !important;\n  grid-template-columns: 320px minmax(0,1fr) !important;\n  gap:20px !important;\n  align-items:start !important;\n}\n\n#berfDesk .kb901-figureWrap{\n  position:sticky !important;\n  top:0 !important;\n}\n\n#berfDesk .kb901-figureFrame{\n  background:#fff !important;\n  border-radius:18px !important;\n  padding:16px !important;\n  min-height:360px !important;\n  display:flex !important;\n  align-items:center !important;\n  justify-content:center !important;\n  box-shadow: 0 20px 40px rgba(0,0,0,.35) !important;\n  border: 1px solid rgba(255,255,255,.14) !important;\n}\n\n#berfDesk .kb901-figureFrame img{\n  max-width:100% !important;\n  max-height:330px !important;\n  object-fit:contain !important;\n}\n\n#berfDesk .kb901-noimage{\n  color:#3e4652 !important;\n}\n\n#berfDesk .kb901-content{\n  background:rgba(255,255,255,.03) !important;\n  border:1px solid rgba(255,255,255,.06) !important;\n  border-radius:16px !important;\n  padding:16px !important;\n}\n\n#berfDesk .kb901-tabs{\n  display:flex !important;\n  flex-wrap:wrap !important;\n  gap:8px !important;\n  margin-bottom:16px !important;\n}\n\n#berfDesk .kb901-tab{\n  border:1px solid rgba(255,255,255,.1) !important;\n  background:rgba(255,255,255,.04) !important;\n  color:rgba(255,255,255,.82) !important;\n  border-radius:12px !important;\n  padding:10px 14px !important;\n  font-size:13px !important;\n  font-weight:600 !important;\n  cursor:pointer !important;\n  transition:.2s ease !important;\n}\n\n#berfDesk .kb901-tab:hover{\n  transform:translateY(-1px) !important;\n  background:rgba(255,255,255,.08) !important;\n}\n\n#berfDesk .kb901-tab.is-active{\n  background:linear-gradient(180deg, #c44343 0%, #8f2323 100%) !important;\n  border-color:#c44343 !important;\n  color:#fff !important;\n  box-shadow:0 10px 22px rgba(175,50,50,.28) !important;\n}\n\n#berfDesk .kb901-tabPanel{\n  display:none !important;\n}\n\n#berfDesk .kb901-tabPanel.is-active{\n  display:block !important;\n}\n\n#berfDesk .kb901-generalMeta{\n  display:grid !important;\n  grid-template-columns:repeat(3,minmax(0,1fr)) !important;\n  gap:12px !important;\n  margin-bottom:14px !important;\n}\n\n#berfDesk .kb901-metaCard{\n  background:linear-gradient(180deg, rgba(255,255,255,.06) 0%, rgba(255,255,255,.03) 100%) !important;\n  border:1px solid rgba(255,255,255,.08) !important;\n  border-radius:14px !important;\n  padding:14px !important;\n  min-height:86px !important;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.04) !important;\n}\n\n#berfDesk .kb901-metaCard span{\n  display:block !important;\n  font-size:11px !important;\n  text-transform:uppercase !important;\n  letter-spacing:.08em !important;\n  color:rgba(255,255,255,.55) !important;\n  margin-bottom:8px !important;\n}\n\n#berfDesk .kb901-metaCard strong{\n  display:block !important;\n  font-size:15px !important;\n  color:#fff !important;\n}\n\n#berfDesk .kb901-description{\n  background:rgba(0,0,0,.22) !important;\n  border:1px solid rgba(255,255,255,.08) !important;\n  border-radius:14px !important;\n  padding:16px !important;\n  line-height:1.65 !important;\n  color:#eef2f7 !important;\n  min-height:180px !important;\n  white-space:pre-line !important;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.03) !important;\n}\n\n#berfDesk .kb901-description:empty::before{\n  content:\"Aucune donn\u00e9e disponible.\" !important;\n  color:rgba(255,255,255,.42) !important;\n}\n\n@media (max-width: 1100px){\n  #berfDesk .kb901-detailGrid{\n    grid-template-columns: 1fr !important;\n  }\n  #berfDesk .kb901-figureWrap{\n    position:static !important;\n  }\n}\n\n@media (max-width: 720px){\n  #berfDesk .kb901-title{\n    font-size:24px !important;\n  }\n  #berfDesk .kb901-generalMeta{\n    grid-template-columns:1fr !important;\n  }\n}\n\n\n\/* ===== KB meta cards hotfix v1.8.4 ===== *\/\n#berfDesk .kb901-generalMeta{\n  display:grid !important;\n  grid-template-columns:repeat(3,minmax(0,1fr)) !important;\n  gap:12px !important;\n  align-items:stretch !important;\n}\n\n#berfDesk .kb901-metaCard{\n  position:relative !important;\n  width:100% !important;\n  min-width:0 !important;\n  overflow:hidden !important;\n  display:flex !important;\n  flex-direction:column !important;\n  justify-content:flex-start !important;\n}\n\n#berfDesk .kb901-metaCard::before,\n#berfDesk .kb901-metaCard::after,\n#berfDesk .kb901-metaCard span::before,\n#berfDesk .kb901-metaCard span::after,\n#berfDesk .kb901-metaCard strong::before,\n#berfDesk .kb901-metaCard strong::after{\n  content:none !important;\n  display:none !important;\n}\n\n#berfDesk .kb901-metaCard span,\n#berfDesk .kb901-metaCard strong{\n  position:static !important;\n  inset:auto !important;\n  transform:none !important;\n  width:auto !important;\n  height:auto !important;\n  min-width:0 !important;\n  max-width:none !important;\n  background:none !important;\n  box-shadow:none !important;\n  border:none !important;\n  backdrop-filter:none !important;\n  filter:none !important;\n  border-radius:0 !important;\n  white-space:normal !important;\n  writing-mode:horizontal-tb !important;\n}\n\n#berfDesk .kb901-metaCard strong{\n  line-height:1.35 !important;\n}\n\n@media (max-width: 720px){\n  #berfDesk .kb901-generalMeta{\n    grid-template-columns:1fr !important;\n  }\n}\n\n\n\/* ===== KB desktop layout aligned with tablet ===== *\/\n#berfDesk .kb901-shell{\n  display:grid !important;\n  grid-template-columns: 190px minmax(0,1fr) !important;\n  gap:10px !important;\n  align-items:stretch !important;\n}\n\n#berfDesk .kb901-side{\n  min-width:0 !important;\n  width:auto !important;\n  max-width:none !important;\n}\n\n#berfDesk .kb901-main{\n  min-width:0 !important;\n}\n\n#berfDesk #kb901-detail{\n  max-width: none !important;\n}\n\n#berfDesk .kb901-detailGrid{\n  grid-template-columns: 1fr !important;\n  gap:14px !important;\n}\n\n#berfDesk .kb901-figureWrap{\n  position:static !important;\n}\n\n#berfDesk .kb901-figureFrame{\n  min-height: auto !important;\n  padding: 12px !important;\n}\n\n#berfDesk .kb901-figureFrame img{\n  max-height: 300px !important;\n}\n\n#berfDesk .kb901-content{\n  padding: 12px !important;\n}\n\n#berfDesk .kb901-tabs{\n  margin-bottom: 10px !important;\n}\n\n#berfDesk .kb901-description{\n  min-height: 0 !important;\n}\n\n@media (max-width: 1100px){\n  #berfDesk .kb901-shell{\n    grid-template-columns: 190px minmax(0,1fr) !important;\n  }\n}\n\n@media (max-width: 900px){\n  #berfDesk .kb901-shell{\n    grid-template-columns: 1fr !important;\n  }\n}\n\n\n\/* ===== Browser shortcode rendering fix ===== *\/\n#berfDesk #berfBrowserTool{\n  position:relative;\n  height:calc(100% - 48px);\n}\n#berfDesk .berfBrowser{\n  height:100%;\n  display:flex;\n  flex-direction:column;\n  min-height:0;\n}\n#berfDesk .berfBrowser__content{\n  position:relative;\n  flex:1 1 auto;\n  min-height:0;\n  overflow:auto;\n}\n#berfDesk .berfBrowser__page{\n  position:relative;\n  width:100%;\n  min-height:100%;\n  overflow:auto;\n}\n#berfDesk .berfBrowser__page > *{\n  max-width:100%;\n}\n\n\n\/* ===== FILE MANAGER (new clean tool) ===== *\/\n#berfDesk #berfFileManagerTool{\n  display:grid;\n  grid-template-columns: 260px minmax(0,1fr);\n  gap:18px;\n  height:100%;\n  min-height:540px;\n}\n#berfDesk #berf-oc-filemanager .berf-oc__body{\n  padding:18px;\n  overflow:hidden;\n}\n#berfDesk .berf-filemanager__sidebar,\n#berfDesk .berf-filemanager__main{\n  background:rgba(5,12,18,0.74);\n  border:1px solid rgba(255,255,255,0.08);\n  border-radius:16px;\n  min-height:0;\n}\n#berfDesk .berf-filemanager__sidebar{\n  display:flex;\n  flex-direction:column;\n  overflow:hidden;\n}\n#berfDesk .berf-filemanager__sidebarHead{\n  padding:16px 16px 10px;\n  border-bottom:1px solid rgba(255,255,255,0.08);\n}\n#berfDesk .berf-filemanager__sidebarTitle{\n  font-weight:800;\n  color:#fff;\n}\n#berfDesk .berf-filemanager__sidebarSub{\n  color:rgba(255,255,255,0.62);\n  font-size:12px;\n  margin-top:4px;\n}\n#berfDesk .berf-filemanager__folders{\n  padding:12px;\n  overflow:auto;\n  display:flex;\n  flex-direction:column;\n  gap:10px;\n}\n#berfDesk .berf-filemanager__folderbtn{\n  width:100%;\n  text-align:left;\n  padding:12px 14px;\n  border-radius:14px;\n  border:1px solid rgba(255,255,255,0.08);\n  background:rgba(255,255,255,0.03);\n  color:#fff;\n  cursor:pointer;\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:10px;\n}\n#berfDesk .berf-filemanager__folderbtn:hover,\n#berfDesk .berf-filemanager__folderbtn.is-active{\n  background:rgba(95,170,255,0.14);\n  border-color:rgba(95,170,255,0.34);\n}\n#berfDesk .berf-filemanager__foldermain{\n  display:flex;\n  align-items:center;\n  gap:10px;\n  min-width:0;\n}\n#berfDesk .berf-filemanager__foldername{\n  white-space:nowrap;\n  overflow:hidden;\n  text-overflow:ellipsis;\n}\n#berfDesk .berf-filemanager__foldermeta{\n  color:rgba(255,255,255,0.56);\n  font-size:12px;\n}\n#berfDesk .berf-filemanager__main{\n  display:flex;\n  flex-direction:column;\n  overflow:hidden;\n}\n#berfDesk .berf-filemanager__toolbar{\n  display:flex;\n  align-items:center;\n  gap:12px;\n  padding:14px 16px;\n  border-bottom:1px solid rgba(255,255,255,0.08);\n}\n#berfDesk .berf-filemanager__crumbs{\n  flex:1;\n  min-width:0;\n  color:rgba(255,255,255,0.78);\n  font-weight:700;\n  white-space:nowrap;\n  overflow:hidden;\n  text-overflow:ellipsis;\n}\n#berfDesk .berf-filemanager__ghost,\n#berfDesk .berf-filemanager__primary,\n#berfDesk .berf-fileviewer__analyze{\n  border:none;\n  border-radius:12px;\n  cursor:pointer;\n  font-weight:700;\n  padding:10px 14px;\n  display:inline-flex;\n  align-items:center;\n  gap:8px;\n}\n#berfDesk .berf-filemanager__ghost{\n  background:rgba(255,255,255,0.08);\n  color:#fff;\n}\n#berfDesk .berf-filemanager__primary,\n#berfDesk .berf-fileviewer__analyze{\n  background:#6eb6ff;\n  color:#081018;\n}\n#berfDesk .berf-filemanager__stage{\n  flex:1;\n  min-height:0;\n  overflow:auto;\n  padding:16px;\n}\n#berfDesk .berf-filemanager__grid{\n  display:grid;\n  grid-template-columns:repeat(auto-fill,minmax(170px,1fr));\n  gap:14px;\n}\n#berfDesk .berf-filemanager__card{\n  border:none;\n  border-radius:16px;\n  background:rgba(255,255,255,0.04);\n  border:1px solid rgba(255,255,255,0.08);\n  color:#fff;\n  min-height:150px;\n  padding:16px 14px;\n  cursor:pointer;\n  display:flex;\n  flex-direction:column;\n  align-items:flex-start;\n  gap:12px;\n  text-align:left;\n}\n#berfDesk .berf-filemanager__card:hover{\n  background:rgba(255,255,255,0.08);\n  border-color:rgba(110,182,255,0.34);\n}\n#berfDesk .berf-filemanager__card i{\n  font-size:34px;\n  opacity:.98;\n  color:#cb3000;\n  filter:drop-shadow(0 0 8px rgba(203,48,0,0.35));\n  text-shadow:0 0 10px rgba(203,48,0,0.28), 0 0 18px rgba(255,120,90,0.16);\n}\n#berfDesk .berf-filemanager__card--folder i{\n  color:#d8b65a;\n  filter:drop-shadow(0 0 8px rgba(216,182,90,0.28));\n  text-shadow:none;\n}\n#berfDesk .berf-filemanager__cardtitle{\n  font-size:8px;\n  font-weight:700;\n  line-height:1.2;\n  text-align:center;\n  overflow:hidden;\n  text-overflow:ellipsis;\n  white-space:nowrap;\n  max-width:100%;\n}\n#berfDesk #berfCalcTool{\n  width:min(420px, 100%);\n  margin:10px auto;\n  padding:18px;\n  border-radius:22px;\n  background:linear-gradient(180deg,#15191f 0%,#0f141a 100%);\n  border:1px solid rgba(175,50,50,.26);\n  box-shadow:0 20px 50px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.03);\n}\n#berfDesk .berf-calc__screenWrap{\n  padding:14px;\n  border-radius:18px;\n  background:linear-gradient(180deg,rgba(20,26,33,.96),rgba(10,14,19,.96));\n  border:1px solid rgba(255,255,255,.06);\n  margin-bottom:14px;\n}\n#berfDesk .berf-calc__label{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:#a8b2bf;margin-bottom:8px}\n#berfDesk .berf-calc__screen{\n  width:100%;border:none;outline:none;background:#e7ecef;color:#10161d;padding:14px 16px;border-radius:14px;\n  font:700 28px\/1.1 \"Roboto Mono\", monospace;text-align:right;box-sizing:border-box;\n}\n#berfDesk .berf-calc__status{min-height:20px;margin-top:10px;color:#cfd6de;font-size:12px}\n#berfDesk .berf-calc__status.is-error{color:#ff9a9a}\n#berfDesk .berf-calc__status.is-success{color:#ffcf90}\n#berfDesk .berf-calc__keys{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}\n#berfDesk .berf-calc__keys button{\n  border:none;outline:none;border-radius:14px;padding:16px 10px;background:#202833;color:#fff;\n  font:700 18px\/1 \"Roboto Mono\", monospace;cursor:pointer;transition:transform .14s ease, background .14s ease, box-shadow .14s ease;\n  box-shadow:0 8px 18px rgba(0,0,0,.24);\n}\n#berfDesk .berf-calc__keys button:hover{transform:translateY(-1px);background:#28313d}\n#berfDesk .berf-calc__keys button.is-equals{background:linear-gradient(180deg,#af3232,#842222)}\n#berfDesk .berf-calc__keys button.is-wide{grid-column:span 2}\n#berfDesk .berf-calc__hint{margin-top:12px;font-size:12px;color:#94a2b1;line-height:1.45}\n#berfDesk .berf-filemanager__cardmeta{\n  color:rgba(255,255,255,0.56);\n  font-size:12px;\n}\n#berfDesk .berf-filemanager__empty{\n  min-height:100%;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  flex-direction:column;\n  gap:10px;\n  text-align:center;\n  color:rgba(255,255,255,0.68);\n}\n#berfDesk .berf-filemanager__empty i{\n  font-size:42px;\n  color:rgba(110,182,255,0.8);\n}\n#berfDesk #berfFilesTool .berf-filemanager__textdoc,\n#berfDesk #berfFileManagerTool .berf-filemanager__textdoc,\n#berfFileViewer .berf-filemanager__textdoc{\n  width:min(760px, 92vw);\n  max-height:70vh;\n  overflow:auto;\n  background:#f4efe4;\n  color:#1e1b16;\n  border:1px solid rgba(40,30,20,.22);\n  border-radius:10px;\n  padding:22px;\n  box-shadow:0 18px 45px rgba(0,0,0,.35);\n}\n#berfDesk #berfFilesTool .berf-filemanager__textdoc pre,\n#berfDesk #berfFileManagerTool .berf-filemanager__textdoc pre,\n#berfFileViewer .berf-filemanager__textdoc pre{\n  margin:0;\n  white-space:pre-wrap;\n  font:500 15px\/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n}\n#berfDesk .berf-filemanager__folderhead{\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:12px;\n  margin-bottom:14px;\n}\n#berfDesk .berf-filemanager__folderhead h3{\n  margin:0;\n  color:#fff;\n}\n#berfDesk .berf-filemanager__folderhead p{\n  margin:4px 0 0;\n  color:rgba(255,255,255,0.56);\n  font-size:12px;\n}\n#berfDesk .berf-fileviewer,\n#berfDesk .berf-filelockmodal{\n  position:absolute;\n  inset:0;\n  display:none;\n  z-index:8;\n}\n#berfDesk .berf-fileviewer[data-open=\"true\"],\n#berfDesk .berf-filelockmodal[data-open=\"true\"]{\n  display:block;\n}\n#berfDesk .berf-fileviewer__backdrop,\n#berfDesk .berf-filelockmodal__backdrop{\n  position:absolute;\n  inset:0;\n  background:rgba(0,0,0,0.72);\n}\n#berfDesk .berf-fileviewer__dialog,\n#berfDesk .berf-filelockmodal__dialog{\n  position:absolute;\n  top:50%;\n  left:50%;\n  transform:translate(-50%,-50%);\n  width:min(900px, calc(100% - 40px));\n  max-height:calc(100% - 40px);\n  background:#081018;\n  border:1px solid rgba(255,255,255,0.12);\n  border-radius:18px;\n  overflow:hidden;\n  box-shadow:0 24px 90px rgba(0,0,0,0.45);\n}\n#berfDesk .berf-fileviewer__dialog{ width:min(1000px, calc(100% - 40px)); }\n#berfDesk .berf-fileviewer__head,\n#berfDesk .berf-filelockmodal__head{\n  padding:14px 16px;\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:12px;\n  border-bottom:1px solid rgba(255,255,255,0.08);\n}\n#berfDesk .berf-fileviewer__title,\n#berfDesk .berf-filelockmodal__title{\n  color:#fff;\n  font-weight:800;\n}\n#berfDesk .berf-fileviewer__actions{\n  display:flex;\n  align-items:center;\n  gap:10px;\n}\n#berfDesk .berf-fileviewer__close,\n#berfDesk .berf-filelockmodal__close{\n  width:38px;\n  height:38px;\n  border:none;\n  border-radius:12px;\n  background:rgba(255,255,255,0.08);\n  color:#fff;\n  cursor:pointer;\n  font-size:24px;\n}\n#berfDesk .berf-fileviewer__body{\n  padding:20px;\n  max-height:calc(100vh - 180px);\n  overflow:auto;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n}\n#berfDesk .berf-fileviewer__body img,\n#berfDesk .berf-fileviewer__body video,\n#berfDesk .berf-fileviewer__body audio,\n#berfDesk .berf-fileviewer__body iframe{\n  width:100%;\n  max-width:100%;\n  border:none;\n  border-radius:14px;\n  background:#000;\n}\n#berfDesk .berf-fileviewer__body img{\n  object-fit:contain;\n  max-height:70vh;\n}\n#berfDesk .berf-fileviewer__body video,\n#berfDesk .berf-fileviewer__body iframe{\n  min-height:60vh;\n}\n#berfDesk .berf-filelockmodal__body{\n  padding:18px 16px 16px;\n}\n#berfDesk .berf-filelockmodal__text{\n  margin:0 0 14px;\n  color:rgba(255,255,255,0.78);\n}\n#berfDesk .berf-filelockmodal__body label{\n  display:block;\n  color:#fff;\n  font-weight:700;\n  margin-bottom:12px;\n}\n#berfDesk .berf-filelockmodal__body input{\n  width:100%;\n  margin-top:6px;\n  border:1px solid rgba(255,255,255,0.12);\n  background:rgba(255,255,255,0.04);\n  color:#fff;\n  border-radius:12px;\n  padding:12px 14px;\n}\n#berfDesk .berf-filelockmodal__error{\n  margin-top:4px;\n  margin-bottom:12px;\n  padding:10px 12px;\n  border-radius:12px;\n  background:rgba(255,80,80,0.12);\n  color:#ffb2b2;\n  border:1px solid rgba(255,80,80,0.2);\n}\n#berfDesk .berf-filelockmodal__actions{\n  display:flex;\n  justify-content:flex-end;\n  gap:10px;\n  margin-top:18px;\n  flex-wrap:wrap;\n}\n@media (max-width: 900px){\n  #berfDesk #berfFileManagerTool{\n    grid-template-columns:1fr;\n  }\n  #berfDesk .berf-filemanager__sidebar{\n    max-height:220px;\n  }\n  #berfDesk .berf-filemanager__toolbar{\n    flex-wrap:wrap;\n  }\n}\n\n\n#berfDesk #berf-oc-drone .berf-oc__main{display:flex;flex-direction:column;overflow:hidden}\n#berfDesk #berf-oc-drone .berf-oc__body--drone{display:flex;flex:1 1 auto;min-height:0;padding:0;overflow:hidden}\n#berfDesk .berf-drone{display:grid;grid-template-columns:320px minmax(0,1fr);flex:1 1 auto;width:100%;height:100%;min-height:calc(100svh - 64px);min-height:calc(100dvh - 64px);background:#091118;color:#d8e7ef;overflow:hidden}\n#berfDesk .berf-drone__sidebar{padding:18px;border-right:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;gap:14px;background:linear-gradient(180deg,#0d1720,#091118);min-height:0;overflow:auto}\n#berfDesk .berf-drone__eyebrow{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:#7ca2b8}\n#berfDesk .berf-drone__name{font-size:24px;font-weight:700}\n#berfDesk .berf-drone__statusBadge{display:inline-flex;align-self:flex-start;padding:6px 10px;border-radius:999px;font-size:12px;font-weight:700;background:#26333d}\n#berfDesk .berf-drone__statusBadge[data-state=\"online\"]{background:#173b27;color:#97f0b4}\n#berfDesk .berf-drone__statusBadge[data-state=\"unstable\"]{background:#433518;color:#ffd37a}\n#berfDesk .berf-drone__statusBadge[data-state=\"offline\"]{background:#3a2020;color:#ffb1b1}\n#berfDesk .berf-drone__label{display:flex;flex-direction:column;gap:6px;font-size:13px;color:#9fb5c3}\n#berfDesk .berf-drone__label input{height:42px;border-radius:12px;border:1px solid rgba(255,255,255,.12);background:#0f1d28;color:#fff;padding:0 12px}\n#berfDesk .berf-drone__unlock{height:42px;border:none;border-radius:12px;background:#1a6a8d;color:#fff;font-weight:700;cursor:pointer}\n#berfDesk .berf-drone__meta{display:grid;grid-template-columns:1fr;gap:10px}\n#berfDesk .berf-drone__meta div{padding:10px 12px;border-radius:12px;background:rgba(255,255,255,.04);display:flex;justify-content:space-between;gap:12px}\n#berfDesk .berf-drone__meta span{color:#88a2b2;font-size:12px;text-transform:uppercase;letter-spacing:.08em}\n#berfDesk .berf-drone__notesTitle{font-size:12px;text-transform:uppercase;letter-spacing:.12em;color:#88a2b2}\n#berfDesk .berf-drone__notes{padding:12px;border-radius:14px;background:rgba(255,255,255,.04);line-height:1.45;white-space:pre-wrap}\n#berfDesk .berf-drone__viewer{position:relative;display:flex;align-items:stretch;justify-content:center;background:#02070a;min-width:0;min-height:420px;height:100%;overflow:hidden}\n#berfDesk .berf-drone__hud{position:absolute;top:16px;left:16px;right:16px;display:flex;gap:10px;z-index:2;flex-wrap:wrap}\n#berfDesk .berf-drone__hud span{padding:6px 10px;border-radius:999px;background:rgba(0,0,0,.45);backdrop-filter:blur(4px);font-size:12px;letter-spacing:.08em}\n#berfDesk .berf-drone__rec{color:#ff7b7b;font-weight:700}\n#berfDesk .berf-drone__feed{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:420px;background:radial-gradient(circle at center,#0f2430,#02070a 70%);overflow:hidden;border:1px solid rgba(255,255,255,.06)}\n#berfDesk .berf-drone__feed img,#berfDesk .berf-drone__feed video,#berfDesk .berf-drone__feed iframe{display:block;width:100%;height:100%;max-width:100%;max-height:100%;object-fit:contain;border:0;background:#000;flex:1 1 auto}\n#berfDesk .berf-drone-empty{padding:18px 22px;border:1px solid rgba(255,255,255,.12);border-radius:14px;background:rgba(255,255,255,.05);color:#c6d6df}\n@media (max-width: 980px){#berfDesk .berf-drone{grid-template-columns:1fr;min-height:calc(100svh - 64px);min-height:calc(100dvh - 64px)}#berfDesk .berf-drone__sidebar{border-right:none;border-bottom:1px solid rgba(255,255,255,.08);max-height:40svh;max-height:40dvh}#berfDesk .berf-drone__viewer{min-height:320px}}\n\n\/* ============================================================\n   BERF DARK IMMERSIVE SKIN - visual only, no feature changes\n============================================================ *\/\n#berfDesk{\n  --berf-ink:#161516;\n  --berf-ink-2:#232123;\n  --berf-panel:#211f20;\n  --berf-panel-2:#2b2729;\n  --berf-line:rgba(239,209,179,.18);\n  --berf-line-strong:rgba(239,209,179,.34);\n  --berf-red:#B03332;\n  --berf-red-dark:#6f2124;\n  --berf-parchment:#EFD1B3;\n  --berf-muted:#A3938D;\n  --berf-ash:#8A827E;\n  --berf-mauve:#53393E;\n  color:var(--berf-parchment) !important;\n  border-radius:6px !important;\n  border:1px solid rgba(239,209,179,.22) !important;\n  background:\n    linear-gradient(rgba(239,209,179,.025) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.022) 1px, transparent 1px),\n    radial-gradient(880px 420px at 18% 8%, rgba(176,51,50,.18), transparent 62%),\n    radial-gradient(740px 520px at 86% 22%, rgba(83,57,62,.30), transparent 66%),\n    linear-gradient(135deg,#111010 0%,#1b181a 46%,#0b0a0a 100%) !important;\n  background-size:36px 36px,36px 36px,auto,auto,auto !important;\n  box-shadow:0 28px 80px rgba(0,0,0,.72), inset 0 0 0 1px rgba(255,255,255,.025) !important;\n  font-family:\"Roboto Mono\",\"Segoe UI\",Arial,sans-serif !important;\n}\n#berfDesk .berf-bg{\n  background:\n    radial-gradient(circle at 48% 42%, rgba(239,209,179,.06), transparent 16%),\n    linear-gradient(rgba(255,255,255,.018) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(255,255,255,.014) 1px, transparent 1px),\n    linear-gradient(145deg, rgba(22,21,22,.20), rgba(0,0,0,.72)) !important;\n  background-size:auto,22px 22px,22px 22px,auto !important;\n}\n#berfDesk .berf-brandplate{\n  position:absolute;\n  top:18px;\n  left:20px;\n  z-index:6;\n  display:flex;\n  align-items:center;\n  gap:13px;\n  width:min(360px, calc(100% - 40px));\n  padding:10px 14px 10px 10px;\n  border:1px solid var(--berf-line);\n  background:linear-gradient(180deg, rgba(35,33,35,.92), rgba(18,17,18,.86));\n  box-shadow:0 18px 36px rgba(0,0,0,.36), inset 0 1px 0 rgba(239,209,179,.05);\n  pointer-events:none;\n}\n#berfDesk .berf-brandplate img{\n  width:58px;\n  height:58px;\n  object-fit:contain;\n  filter:drop-shadow(0 8px 14px rgba(0,0,0,.45));\n}\n#berfDesk .berf-brandplate strong{\n  display:block;\n  color:var(--berf-parchment);\n  font-size:22px;\n  letter-spacing:.18em;\n  line-height:1.1;\n}\n#berfDesk .berf-brandplate span{\n  display:block;\n  margin-top:5px;\n  color:var(--berf-muted);\n  font-size:11px;\n  letter-spacing:.08em;\n  text-transform:uppercase;\n}\n#berfDesk .berf-leftbar{\n  top:116px !important;\n  left:20px !important;\n  gap:9px !important;\n  width:96px;\n  padding:10px 8px;\n  border:1px solid var(--berf-line);\n  background:linear-gradient(180deg, rgba(20,19,20,.88), rgba(9,8,9,.78));\n  box-shadow:0 18px 42px rgba(0,0,0,.38);\n}\n#berfDesk .berf-app,\n#berfDesk .berf-taskbar-app,\n#berfDesk .start-button,\n#berfDesk .berf-oc__close,\n#berfDesk button{\n  transition:background .14s ease, border-color .14s ease, color .14s ease, transform .12s ease, box-shadow .14s ease;\n}\n#berfDesk .berf-app{\n  width:78px !important;\n  height:58px !important;\n  border-radius:2px !important;\n  color:var(--berf-parchment) !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.42), rgba(22,21,22,.72)) !important;\n  box-shadow:inset 3px 0 0 rgba(176,51,50,.0), 0 10px 24px rgba(0,0,0,.32) !important;\n}\n#berfDesk .berf-app:hover{\n  transform:translateX(2px);\n  border-color:rgba(239,209,179,.38) !important;\n  background:linear-gradient(180deg, rgba(83,57,62,.55), rgba(48,25,27,.76)) !important;\n  box-shadow:inset 3px 0 0 var(--berf-red), 0 14px 28px rgba(0,0,0,.42) !important;\n}\n#berfDesk .berf-app i,\n#berfDesk .berf-taskbar-app i{\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .berf-badge{\n  background:var(--berf-red) !important;\n  color:#fff !important;\n  border:1px solid rgba(239,209,179,.32) !important;\n  box-shadow:0 0 0 3px rgba(176,51,50,.18), 0 10px 22px rgba(0,0,0,.45) !important;\n}\n#berfDesk .berf-taskbar{\n  height:66px !important;\n  padding:0 16px 0 138px !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.92), rgba(10,9,10,.96)) !important;\n  border-top:1px solid var(--berf-line) !important;\n  box-shadow:0 -18px 42px rgba(0,0,0,.52), inset 0 1px 0 rgba(239,209,179,.035) !important;\n}\n#berfDesk .start-button{\n  width:48px !important;\n  height:46px !important;\n  padding:0 !important;\n  justify-content:center !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.20) !important;\n  background:rgba(176,51,50,.20) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .start-button:hover,\n#berfDesk .berf-taskbar-app:hover{\n  transform:translateY(-1px);\n  border-color:rgba(239,209,179,.42) !important;\n  background:rgba(176,51,50,.28) !important;\n}\n#berfDesk .berf-taskbar-app{\n  width:46px !important;\n  height:46px !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.16) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.36), rgba(22,21,22,.72)) !important;\n}\n#berfDesk .berf-taskbar-search #searchInput45{\n  height:46px !important;\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:rgba(10,9,10,.70) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .start-menu,\n#berfDesk .berf-taskbar-search .search-results56{\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.98), rgba(13,12,13,.98)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .start-menu ul li:hover,\n#berfDesk .berf-taskbar-search .result-item99:hover{\n  background:rgba(176,51,50,.22) !important;\n}\n#berfDesk .berf-oc__overlay{\n  background:rgba(0,0,0,.72) !important;\n  backdrop-filter:blur(3px);\n}\n#berfDesk .berf-oc__main{\n  width:min(1260px, 96vw) !important;\n  color:var(--berf-parchment) !important;\n  background:\n    linear-gradient(rgba(239,209,179,.018) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.014) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(35,33,35,.98), rgba(14,13,14,.98)) !important;\n  background-size:28px 28px,28px 28px,auto !important;\n  border-left:1px solid var(--berf-line-strong) !important;\n  box-shadow:-28px 0 70px rgba(0,0,0,.62), inset 1px 0 0 rgba(239,209,179,.04) !important;\n}\n#berfDesk .berf-oc__top{\n  min-height:64px !important;\n  padding:13px 18px !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.98), rgba(14,13,14,.96)) !important;\n  border-bottom:1px solid var(--berf-line) !important;\n}\n#berfDesk .berf-oc__title{\n  color:var(--berf-parchment) !important;\n  letter-spacing:.08em;\n  text-transform:uppercase;\n}\n#berfDesk .berf-oc__title i{\n  color:var(--berf-red) !important;\n}\n#berfDesk .berf-oc__close{\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:rgba(176,51,50,.16) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .berf-oc__body{\n  padding:16px !important;\n}\n#berfDesk input,\n#berfDesk textarea,\n#berfDesk select{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.20) !important;\n  background:rgba(11,10,11,.70) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk input::placeholder,\n#berfDesk textarea::placeholder{\n  color:rgba(239,209,179,.42) !important;\n}\n#berfDesk button{\n  border-radius:2px !important;\n}\n#berfDesk table{\n  color:var(--berf-parchment) !important;\n  border-color:var(--berf-line) !important;\n}\n#berfDesk th{\n  color:var(--berf-muted) !important;\n  background:rgba(176,51,50,.14) !important;\n}\n#berfDesk td{\n  border-color:rgba(239,209,179,.10) !important;\n}\n\n\/* Mail *\/\n#berfMailTool{\n  --berf-mail-bg:transparent !important;\n  --berf-mail-bg-2:transparent !important;\n  --berf-mail-panel:rgba(35,33,35,.88) !important;\n  --berf-mail-panel-2:rgba(83,57,62,.40) !important;\n  --berf-mail-line:rgba(239,209,179,.16) !important;\n  --berf-mail-line-strong:rgba(239,209,179,.32) !important;\n  --berf-mail-text:var(--berf-parchment) !important;\n  --berf-mail-muted:var(--berf-muted) !important;\n  --berf-mail-accent:var(--berf-red) !important;\n}\n#berfMailTool .inbox-container{\n  min-height:calc(100vh - 112px) !important;\n  margin:0 !important;\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.72), rgba(9,8,9,.68)) !important;\n  box-shadow:inset 0 1px 0 rgba(239,209,179,.035), 0 18px 42px rgba(0,0,0,.28) !important;\n}\n#berfMailTool .email-list{\n  background:rgba(11,10,11,.54) !important;\n  border-right:1px solid var(--berf-line) !important;\n}\n#berfMailTool .email-item{\n  border-radius:2px !important;\n  border-color:rgba(239,209,179,.14) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.34), rgba(20,18,20,.72)) !important;\n}\n#berfMailTool .email-item:hover,\n#berfMailTool .email-item.active{\n  border-color:rgba(176,51,50,.62) !important;\n  background:linear-gradient(180deg, rgba(83,57,62,.56), rgba(42,20,22,.74)) !important;\n}\n#berfMailTool .email-item.unread{\n  border-left:4px solid var(--berf-red) !important;\n}\n#berfMailTool .email-item .avatar,\n#berfMailTool .details-avatar,\n#berfMailTool #details-avatar{\n  background:linear-gradient(180deg, var(--berf-red), var(--berf-red-dark)) !important;\n  color:#fff !important;\n  border-radius:2px !important;\n}\n#berfMailTool span#sender-name,\n#berfMailTool span#sender-email,\n#berfMailTool .email-details,\n#berfMailTool .message-body{\n  color:var(--berf-parchment) !important;\n}\n#berfMailTool .message-body,\n#berfMailTool .attachment-element,\n#berfMailTool .modal-content{\n  border-radius:2px !important;\n  border-color:rgba(239,209,179,.16) !important;\n  background:rgba(11,10,11,.58) !important;\n}\n#berfMailTool #newMailButton,\n#berfMailTool #replyButton,\n#berfMailTool form button{\n  border:1px solid rgba(239,209,179,.24) !important;\n  background:linear-gradient(180deg, rgba(176,51,50,.52), rgba(111,33,36,.72)) !important;\n  color:var(--berf-parchment) !important;\n}\n\n\/* Evidence *\/\n#berfDesk #berf-oc-evidencetool .berf-oc__main{\n  width:min(1380px, 98vw) !important;\n}\n#berfDesk .evidtool992-app,\n#berfDesk .evidtool992-wrap{\n  color:var(--berf-parchment) !important;\n  background:transparent !important;\n}\n#berfDesk .evidtool992-topbar,\n#berfDesk .evidtool992-card,\n#berfDesk .evidtool992-analysis,\n#berfDesk .evidtool992-mediaframe,\n#berfDesk .evidtool992-item,\n#berfDesk .evidtool992-viewerInner{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.16) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.82), rgba(12,11,12,.74)) !important;\n  color:var(--berf-parchment) !important;\n  box-shadow:0 18px 36px rgba(0,0,0,.24) !important;\n}\n#berfDesk .evidtool992-berf,\n#berfDesk .evidtool992-title,\n#berfDesk .evidtool992-sectiontitle{\n  color:var(--berf-parchment) !important;\n  letter-spacing:.12em;\n  text-transform:uppercase;\n}\n#berfDesk .evidtool992-sub,\n#berfDesk .evidtool992-label,\n#berfDesk .evidtool992-desc,\n#berfDesk .evidtool992-hint,\n#berfDesk .evidtool992-item small{\n  color:var(--berf-muted) !important;\n}\n#berfDesk .evidtool992-input,\n#berfDesk .evidtool992-textarea{\n  background:rgba(9,8,9,.78) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .evidtool992-btn,\n#berfDesk .evidtool992-iconbtn{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.36), rgba(22,21,22,.74)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .evidtool992-btn-primary,\n#berfDesk .evidtool992-badge{\n  background:linear-gradient(180deg, rgba(176,51,50,.76), rgba(111,33,36,.84)) !important;\n  border-color:rgba(239,209,179,.28) !important;\n  color:#fff !important;\n}\n#berfDesk .evidtool992-scanline{\n  background:linear-gradient(90deg, transparent, rgba(176,51,50,.86), transparent) !important;\n}\n\n\/* File manager and shared archive panels *\/\n#berfDesk #berfFileManagerTool,\n#berfDesk .berf-filemanager{\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.76), rgba(10,9,10,.72)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .berf-filemanager__sidebar,\n#berfDesk .berf-filemanager__main,\n#berfDesk .berf-filemanager__toolbar,\n#berfDesk .berf-filemanager__empty,\n#berfDesk .berf-filemanager__folderhead,\n#berfDesk .berf-fileviewer__dialog,\n#berfDesk .berf-filelockmodal__dialog{\n  border-radius:2px !important;\n  border-color:rgba(239,209,179,.16) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.76), rgba(13,12,13,.78)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .berf-filemanager__folderbtn,\n#berfDesk .berf-filemanager__card{\n  border-radius:2px !important;\n  border-color:rgba(239,209,179,.14) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.36), rgba(22,21,22,.72)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .berf-filemanager__folderbtn:hover,\n#berfDesk .berf-filemanager__folderbtn.is-active,\n#berfDesk .berf-filemanager__card:hover{\n  border-color:rgba(176,51,50,.58) !important;\n  background:linear-gradient(180deg, rgba(83,57,62,.50), rgba(42,20,22,.72)) !important;\n}\n#berfDesk .berf-filemanager__primary,\n#berfDesk .berf-fileviewer__analyze{\n  border-radius:2px !important;\n  background:linear-gradient(180deg, rgba(176,51,50,.76), rgba(111,33,36,.84)) !important;\n  color:#fff !important;\n}\n#berfDesk .berf-filemanager__ghost,\n#berfDesk .berf-fileviewer__close,\n#berfDesk .berf-filelockmodal__close{\n  border-radius:2px !important;\n  border-color:rgba(239,209,179,.18) !important;\n  background:rgba(58,58,59,.34) !important;\n  color:var(--berf-parchment) !important;\n}\n\n\/* Agenda, knowledge, browser, analysis tools: harmonize legacy light areas *\/\n#berfAgendaTool .agenda_42_container,\n#berfDesk #berfTriangulation77,\n#berfDesk .berf-imgtool-wrap,\n#berfDesk #berfAudioTool,\n#berfDesk .berf-kb,\n#berfDesk .berf-browser,\n#berfDesk .container42X,\n#berfCryptoTool,\n#berfTrombiTool,\n#berfDesk .berf-calc{\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.76), rgba(10,9,10,.72)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .agenda_42_navbtn,\n#berfDesk .agenda_42_addbtn,\n#berfDesk .agenda_42_controls button,\n#berfDesk .btn42X,\n#berfDesk .tri77__btn,\n#berfDesk .imgtool991-btn,\n#berfDesk .berf-kb__btn,\n#berfDesk .berf-browser__btn,\n#berfDesk .berf-calc button{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.38), rgba(22,21,22,.76)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .agenda_42_navbtn.active,\n#berfDesk .agenda_42_addbtn,\n#berfDesk .tri77__btnPrimary,\n#berfDesk .imgtool991-btn--danger,\n#berfDesk .imgtool991-btn--green{\n  background:linear-gradient(180deg, rgba(176,51,50,.68), rgba(111,33,36,.82)) !important;\n  color:#fff !important;\n}\n#berfDesk .agenda_42_next,\n#berfDesk .agenda_42_day,\n#berfDesk .agenda_42_modalcontent,\n#berfDesk .tri77__card,\n#berfDesk .imgtool991-panel,\n#berfDesk .trombi77__modalCard,\n#berfDesk .modal-content42X,\n#berfDesk .modal-content,\n#berfDesk .container01,\n#berfDesk .column01,\n#berfDesk .berf-calc__panel{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.14) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.74), rgba(12,11,12,.72)) !important;\n  color:var(--berf-parchment) !important;\n}\n\n\/* Notifications *\/\n#berfDesk .berf-notify-drawer,\n#berfDesk .berf-toast,\n#berfDesk .berf-toast-stack > *{\n  border-radius:2px !important;\n  border:1px solid var(--berf-line) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.96), rgba(12,11,12,.96)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk .berf-notify-drawer__title,\n#berfDesk .berf-notify-drawer__title i{\n  color:var(--berf-parchment) !important;\n}\n\n@media (max-width: 760px){\n  #berfDesk{\n    min-height:760px !important;\n    height:88vh !important;\n  }\n  #berfDesk .berf-brandplate{\n    top:12px;\n    left:12px;\n    width:calc(100% - 24px);\n  }\n  #berfDesk .berf-brandplate img{\n    width:44px;\n    height:44px;\n  }\n  #berfDesk .berf-brandplate strong{\n    font-size:18px;\n  }\n  #berfDesk::after{\n    display:none;\n  }\n  #berfDesk .berf-leftbar{\n    top:92px !important;\n    left:12px !important;\n    width:64px;\n  }\n  #berfDesk .berf-app{\n    width:46px !important;\n    height:46px !important;\n  }\n  #berfDesk .berf-taskbar{\n    padding-left:8px !important;\n    overflow-x:auto;\n  }\n  #berfDesk .berf-taskbar-search{\n    display:none !important;\n  }\n  #berfDesk .berf-oc__main{\n    width:100vw !important;\n  }\n}\n\n\/* ============================================================\n   MAIL TOOL - dedicated mockup-inspired interface\n============================================================ *\/\n#berfDesk #berf-oc-mail .berf-oc__main{\n  width:min(1540px, 98vw) !important;\n  overflow:hidden !important;\n}\n#berfDesk #berf-oc-mail .berf-oc__top{\n  display:none !important;\n}\n#berfMailTool,\n#berfMailTool *{\n  box-sizing:border-box;\n}\n#berfMailTool{\n  width:100%;\n  height:100%;\n  min-height:100vh;\n  color:var(--berf-parchment) !important;\n  font-family:Georgia, \"Times New Roman\", serif !important;\n}\n#berfMailTool .inbox-container{\n  display:grid !important;\n  grid-template-columns:210px minmax(0,1fr) !important;\n  min-height:100vh !important;\n  height:100vh !important;\n  margin:0 !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  border-radius:0 !important;\n  overflow:hidden !important;\n  background:\n    linear-gradient(rgba(239,209,179,.018) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.014) 1px, transparent 1px),\n    #111010 !important;\n  background-size:24px 24px,24px 24px,auto !important;\n}\n#berfMailTool .berf-mail-nav{\n  display:flex;\n  flex-direction:column;\n  border-right:1px solid rgba(239,209,179,.18);\n  background:linear-gradient(180deg, rgba(12,12,12,.98), rgba(20,19,20,.94));\n  min-height:0;\n}\n#berfMailTool .berf-mail-logo{\n  height:170px;\n  display:grid;\n  place-items:center;\n  border-bottom:1px solid rgba(239,209,179,.18);\n}\n#berfMailTool .berf-mail-logo img{\n  width:128px;\n  height:128px;\n  object-fit:contain;\n}\n#berfMailTool .berf-mail-navitem{\n  height:86px;\n  display:flex;\n  align-items:center;\n  gap:18px;\n  width:100%;\n  padding:0 30px;\n  border:0 !important;\n  border-bottom:1px solid rgba(239,209,179,.12) !important;\n  border-left:4px solid transparent !important;\n  background:transparent !important;\n  color:var(--berf-parchment) !important;\n  text-transform:uppercase;\n  letter-spacing:.03em;\n  font-size:16px;\n  cursor:pointer;\n}\n#berfMailTool .berf-mail-navitem i{\n  width:24px;\n  color:var(--berf-parchment);\n  font-size:24px;\n}\n#berfMailTool .berf-mail-navitem:hover,\n#berfMailTool .berf-mail-navitem.is-active{\n  border-left-color:var(--berf-red) !important;\n  background:linear-gradient(90deg, rgba(176,51,50,.34), rgba(83,57,62,.12)) !important;\n  color:#fff !important;\n}\n#berfMailTool .berf-mail-navitem.is-active i{\n  color:#e05b4d !important;\n}\n#berfMailTool .berf-mail-clearance{\n  margin:auto 28px 34px;\n  padding:14px 12px;\n  border:1px solid rgba(176,51,50,.58);\n  color:#d65347;\n  text-align:center;\n  text-transform:uppercase;\n  letter-spacing:.06em;\n  line-height:1.45;\n  background:rgba(176,51,50,.08);\n}\n#berfMailTool .berf-mail-workspace{\n  display:grid;\n  grid-template-rows:94px minmax(0,1fr);\n  min-width:0;\n  min-height:0;\n}\n#berfMailTool .berf-mail-header{\n  display:grid;\n  grid-template-columns:320px 1fr 360px;\n  align-items:stretch;\n  border-bottom:1px solid rgba(239,209,179,.18);\n  background:rgba(10,9,10,.64);\n}\n#berfMailTool .berf-mail-case,\n#berfMailTool .berf-mail-status,\n#berfMailTool .berf-mail-agent{\n  display:flex;\n  flex-direction:column;\n  justify-content:center;\n  padding:0 28px;\n  border-right:1px solid rgba(239,209,179,.18);\n}\n#berfMailTool .berf-mail-case strong,\n#berfMailTool .berf-mail-status strong{\n  font-size:28px;\n  text-transform:uppercase;\n  letter-spacing:.04em;\n}\n#berfMailTool .berf-mail-case span,\n#berfMailTool .berf-mail-agent span{\n  color:var(--berf-muted);\n  font-size:12px;\n  text-transform:uppercase;\n  margin-top:7px;\n}\n#berfMailTool .berf-mail-status{\n  position:relative;\n  padding-left:56px;\n}\n#berfMailTool .berf-mail-status em{\n  color:#d65347;\n  font-style:normal;\n  text-transform:uppercase;\n  margin-top:8px;\n}\n#berfMailTool .berf-mail-dot{\n  position:absolute;\n  left:28px;\n  top:38px;\n  width:10px;\n  height:10px;\n  border-radius:50%;\n  background:#d65347;\n}\n#berfMailTool .berf-mail-agent{\n  flex-direction:row;\n  align-items:center;\n  justify-content:space-between;\n  gap:18px;\n  border-right:0;\n  position:relative;\n}\n#berfMailTool .berf-mail-agent > i{\n  font-size:28px;\n  color:var(--berf-parchment);\n}\n#berfMailTool .berf-mail-agent-badge{\n  position:absolute;\n  left:53px;\n  top:27px;\n  display:grid;\n  place-items:center;\n  width:24px;\n  height:24px;\n  border-radius:50%;\n  background:var(--berf-red);\n  color:#fff !important;\n  font:700 12px\/1 \"Roboto Mono\",monospace;\n}\n#berfMailTool .berf-mail-main{\n  display:grid;\n  grid-template-columns:360px minmax(420px,1fr) 390px;\n  min-height:0;\n}\n#berfMailTool .berf-mail-listpane,\n#berfMailTool .berf-mail-reader,\n#berfMailTool .berf-mail-attachments{\n  min-height:0;\n  border-right:1px solid rgba(239,209,179,.18);\n  background:rgba(15,14,15,.58);\n}\n#berfMailTool .berf-mail-listhead{\n  height:62px;\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  padding:0 20px;\n  border-bottom:1px solid rgba(239,209,179,.18);\n  text-transform:uppercase;\n}\n#berfMailTool .berf-mail-listhead h3,\n#berfMailTool .berf-mail-attachments-head h3{\n  margin:0;\n  font-size:16px;\n  letter-spacing:.05em;\n  font-weight:500;\n}\n#berfMailTool .berf-mail-listhead div{\n  display:flex;\n  align-items:center;\n  gap:18px;\n  color:var(--berf-muted);\n  font-size:12px;\n}\n#berfMailTool .email-list{\n  height:calc(100vh - 94px - 62px - 54px);\n  overflow:auto;\n  padding:0 !important;\n  border:0 !important;\n  background:transparent !important;\n}\n#berfMailTool .email-item{\n  position:relative !important;\n  display:grid !important;\n  grid-template-columns:1fr 24px;\n  gap:10px;\n  min-height:104px;\n  margin:0 !important;\n  padding:18px 18px 14px 34px !important;\n  border:0 !important;\n  border-bottom:1px solid rgba(239,209,179,.14) !important;\n  border-left:3px solid transparent !important;\n  border-radius:0 !important;\n  color:var(--berf-parchment) !important;\n  background:rgba(18,17,18,.36) !important;\n  cursor:pointer;\n}\n#berfMailTool .email-item:hover,\n#berfMailTool .email-item.active{\n  border-left-color:var(--berf-red) !important;\n  background:linear-gradient(90deg, rgba(176,51,50,.30), rgba(83,57,62,.08)) !important;\n}\n#berfMailTool .email-item.unread .berf-mail-unread-dot{\n  display:block;\n}\n#berfMailTool .berf-mail-unread-dot{\n  display:none;\n  position:absolute;\n  left:16px;\n  top:25px;\n  width:8px;\n  height:8px;\n  border-radius:50%;\n  background:#d65347;\n}\n#berfMailTool .email-info .sender{\n  color:var(--berf-parchment);\n  font-size:18px;\n  text-transform:uppercase;\n  margin-bottom:5px;\n}\n#berfMailTool .email-info .subject{\n  color:var(--berf-parchment) !important;\n  font-size:14px;\n  max-width:none !important;\n  white-space:nowrap;\n  overflow:hidden;\n  text-overflow:ellipsis;\n}\n#berfMailTool .email-info .snippet{\n  color:var(--berf-muted);\n  font-size:13px;\n  line-height:1.35;\n  margin-top:8px;\n}\n#berfMailTool .email-info .date{\n  position:absolute;\n  top:18px;\n  right:20px;\n  color:var(--berf-muted) !important;\n  font-size:12px !important;\n}\n#berfMailTool .berf-mail-clip{\n  align-self:center;\n  color:var(--berf-muted);\n}\n#berfMailTool .new-indicator{\n  display:none !important;\n}\n#berfMailTool .berf-mail-listfoot{\n  height:54px;\n  display:flex;\n  align-items:center;\n  padding:0 22px;\n  border-top:1px solid rgba(239,209,179,.14);\n  color:var(--berf-muted);\n  text-transform:uppercase;\n  font-size:12px;\n}\n#berfMailTool .berf-mail-readermount{\n  min-height:0;\n}\n#berfMailTool .berf-mail-reader{\n  display:grid !important;\n  grid-template-rows:62px auto minmax(0,1fr) 118px;\n  height:100%;\n  padding:0 !important;\n}\n#berfMailTool .berf-mail-reader[style*=\"none\"]{\n  display:none !important;\n}\n#berfMailTool .berf-mail-reader-head{\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  padding:0 22px;\n  border-bottom:1px solid rgba(239,209,179,.18);\n}\n#berfMailTool .details-subject{\n  margin:0 !important;\n  color:var(--berf-parchment) !important;\n  font-size:19px !important;\n  text-transform:uppercase;\n  letter-spacing:.04em;\n}\n#berfMailTool .berf-mail-star{\n  border:0 !important;\n  background:transparent !important;\n  color:var(--berf-parchment) !important;\n  font-size:20px;\n}\n#berfMailTool .berf-mail-meta{\n  display:grid;\n  grid-template-columns:92px minmax(0,1fr) 180px;\n  gap:18px;\n  padding:22px;\n  border-bottom:1px dashed rgba(239,209,179,.22);\n}\n#berfMailTool .details-avatar{\n  width:74px !important;\n  height:74px !important;\n  margin:0 !important;\n  border-radius:50% !important;\n  border:1px solid rgba(176,51,50,.60) !important;\n  background:rgba(176,51,50,.12) !important;\n  color:#d65347 !important;\n}\n#berfMailTool .berf-mail-meta-grid{\n  display:grid;\n  grid-template-columns:52px minmax(0,1fr);\n  gap:8px 12px;\n  align-content:start;\n  color:var(--berf-muted);\n  font-size:14px;\n}\n#berfMailTool .berf-mail-meta-grid strong,\n#berfMailTool .berf-mail-meta-grid em{\n  color:var(--berf-parchment);\n  font-style:normal;\n  overflow:hidden;\n  text-overflow:ellipsis;\n}\n#berfMailTool .berf-mail-stamp{\n  align-self:start;\n  padding:14px 12px;\n  border:1px solid rgba(176,51,50,.62);\n  color:#d65347;\n  text-transform:uppercase;\n  text-align:center;\n}\n#berfMailTool .berf-mail-stamp strong,\n#berfMailTool .berf-mail-stamp span,\n#berfMailTool .berf-mail-stamp small{\n  display:block;\n  margin:0 0 8px;\n}\n#berfMailTool .message-body{\n  height:auto !important;\n  min-height:0;\n  overflow:auto !important;\n  margin:0 !important;\n  padding:34px 28px !important;\n  border:0 !important;\n  border-radius:0 !important;\n  background:transparent !important;\n  color:var(--berf-parchment) !important;\n  font-size:17px;\n  line-height:1.72 !important;\n  white-space:pre-wrap;\n}\n#berfMailTool .berf-mail-actions{\n  display:grid;\n  grid-template-columns:repeat(4, minmax(0,1fr));\n  border-top:1px solid rgba(239,209,179,.18);\n  background:rgba(10,9,10,.56);\n}\n#berfMailTool .berf-mail-actions button{\n  display:flex;\n  flex-direction:column;\n  align-items:center;\n  justify-content:center;\n  gap:10px;\n  border:0 !important;\n  border-right:1px solid rgba(239,209,179,.18) !important;\n  border-radius:0 !important;\n  background:transparent !important;\n  color:var(--berf-parchment) !important;\n  text-transform:uppercase;\n  font-size:13px;\n  letter-spacing:.04em;\n  cursor:pointer;\n}\n#berfMailTool .berf-mail-actions button:hover{\n  background:rgba(176,51,50,.18) !important;\n}\n#berfMailTool .berf-mail-actions i{\n  font-size:28px;\n}\n#berfMailTool .berf-mail-attachments{\n  border-right:0;\n  display:grid;\n  grid-template-rows:62px minmax(0,1fr) auto;\n}\n#berfMailTool .berf-mail-attachments-head{\n  display:flex;\n  align-items:center;\n  gap:14px;\n  padding:0 22px;\n  border-bottom:1px solid rgba(239,209,179,.18);\n  text-transform:uppercase;\n}\n#berfMailTool .berf-mail-attachments-list{\n  overflow:auto;\n  padding:18px;\n}\n#berfMailTool .berf-mail-empty{\n  min-height:160px;\n  display:grid;\n  place-items:center;\n  gap:12px;\n  color:var(--berf-muted);\n  text-align:center;\n  border:1px dashed rgba(239,209,179,.18);\n}\n#berfMailTool .berf-mail-attachment-card{\n  display:grid;\n  grid-template-columns:132px minmax(0,1fr);\n  gap:18px;\n  padding:14px;\n  margin-bottom:16px;\n  border:1px solid rgba(239,209,179,.18);\n  background:rgba(12,11,12,.48);\n}\n#berfMailTool .berf-mail-attachment-preview{\n  min-height:132px;\n  border:1px solid rgba(239,209,179,.18);\n  background:rgba(0,0,0,.28);\n  display:grid;\n  place-items:center;\n  overflow:hidden;\n}\n#berfMailTool .berf-mail-attachment-preview img{\n  width:100%;\n  height:100%;\n  object-fit:cover;\n}\n#berfMailTool .berf-mail-attachment-file{\n  display:grid;\n  place-items:center;\n  gap:10px;\n  color:var(--berf-muted);\n}\n#berfMailTool .berf-mail-attachment-file i{\n  font-size:42px;\n  color:#d65347;\n}\n#berfMailTool .berf-mail-attachment-info{\n  position:relative;\n  min-width:0;\n}\n#berfMailTool .berf-mail-attachment-info strong{\n  display:block;\n  padding-right:24px;\n  color:var(--berf-parchment);\n  font-size:15px;\n  overflow:hidden;\n  text-overflow:ellipsis;\n  white-space:nowrap;\n}\n#berfMailTool .berf-mail-attachment-info span,\n#berfMailTool .berf-mail-attachment-info small{\n  display:block;\n  margin-top:9px;\n  color:var(--berf-muted);\n  font-size:12px;\n}\n#berfMailTool .berf-mail-attachment-menu{\n  position:absolute;\n  top:0;\n  right:0;\n  border:0 !important;\n  background:transparent !important;\n  color:var(--berf-muted) !important;\n}\n#berfMailTool .berf-mail-attachment-buttons{\n  display:flex;\n  gap:8px;\n  margin-top:14px;\n  flex-wrap:wrap;\n}\n#berfMailTool .berf-mail-attachment-open,\n#berfMailTool .berf-mail-attachment-analyze{\n  padding:9px 12px;\n  border:1px solid rgba(176,51,50,.62) !important;\n  border-radius:0 !important;\n  background:rgba(176,51,50,.14) !important;\n  color:var(--berf-parchment) !important;\n  text-transform:uppercase;\n  font-size:12px;\n}\n#berfMailTool .berf-mail-attachments-note{\n  display:flex;\n  gap:12px;\n  padding:16px 18px;\n  border-top:1px solid rgba(239,209,179,.14);\n  color:var(--berf-muted);\n  line-height:1.45;\n  font-size:13px;\n}\n#berfMailTool .modal-content{\n  border-radius:0 !important;\n  border:1px solid rgba(239,209,179,.20) !important;\n  background:linear-gradient(180deg, rgba(35,33,35,.98), rgba(12,11,12,.98)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfMailTool #attachmentPreview img,\n#berfMailTool #attachmentPreview video{\n  max-width:100%;\n  max-height:70vh;\n}\n\n@media (max-width: 1180px){\n  #berfMailTool .inbox-container{\n    grid-template-columns:86px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-logo{ height:104px; }\n  #berfMailTool .berf-mail-logo img{ width:68px; height:68px; }\n  #berfMailTool .berf-mail-navitem{ justify-content:center; padding:0; }\n  #berfMailTool .berf-mail-navitem span,\n  #berfMailTool .berf-mail-clearance{ display:none; }\n  #berfMailTool .berf-mail-header{ grid-template-columns:1fr 220px; }\n  #berfMailTool .berf-mail-agent{ display:none; }\n  #berfMailTool .berf-mail-main{ grid-template-columns:310px minmax(0,1fr); }\n  #berfMailTool .berf-mail-attachments{ display:none; }\n}\n\n@media (max-width: 760px){\n  #berfMailTool .inbox-container{\n    grid-template-columns:1fr !important;\n    height:auto !important;\n    min-height:100vh !important;\n  }\n  #berfMailTool .berf-mail-nav{ display:none; }\n  #berfMailTool .berf-mail-header{ grid-template-columns:1fr; min-height:120px; }\n  #berfMailTool .berf-mail-status{ display:none; }\n  #berfMailTool .berf-mail-main{ grid-template-columns:1fr; }\n  #berfMailTool .email-list{ height:260px; }\n  #berfMailTool .berf-mail-reader{ min-height:560px; }\n  #berfMailTool .berf-mail-meta{ grid-template-columns:1fr; }\n  #berfMailTool .details-avatar,\n  #berfMailTool .berf-mail-stamp{ display:none !important; }\n}\n\n\/* Mail polish pass - fixes cramped live rendering *\/\n#berfDesk #berf-oc-mail{\n  inset:0 !important;\n}\n#berfDesk #berf-oc-mail .berf-oc__main{\n  width:100vw !important;\n  max-width:none !important;\n  height:100dvh !important;\n  left:0 !important;\n  right:0 !important;\n}\n#berfMailTool{\n  height:100dvh !important;\n  min-height:0 !important;\n  overflow:hidden !important;\n}\n#berfMailTool .inbox-container{\n  grid-template-columns:260px minmax(0,1fr) !important;\n  height:100dvh !important;\n  min-height:0 !important;\n  width:100% !important;\n}\n#berfMailTool .berf-mail-logo{\n  height:176px !important;\n}\n#berfMailTool .berf-mail-logo img{\n  width:138px !important;\n  height:138px !important;\n  max-width:80% !important;\n  object-fit:contain !important;\n}\n#berfMailTool .berf-mail-navitem{\n  height:88px !important;\n  padding:0 34px !important;\n  font:600 18px\/1.1 \"Segoe UI\",Arial,sans-serif !important;\n}\n#berfMailTool .berf-mail-navitem i{\n  font-size:26px !important;\n}\n#berfMailTool .berf-mail-clearance{\n  margin:24px 32px 44px !important;\n  font-size:26px !important;\n  line-height:1.45 !important;\n}\n#berfMailTool .berf-mail-workspace{\n  grid-template-rows:118px minmax(0,1fr) !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-header{\n  grid-template-columns:minmax(330px, 1.2fr) minmax(300px, 1fr) minmax(380px, .95fr) !important;\n  min-width:0 !important;\n}\n#berfMailTool .berf-mail-case,\n#berfMailTool .berf-mail-status,\n#berfMailTool .berf-mail-agent{\n  min-width:0 !important;\n  padding:0 34px !important;\n}\n#berfMailTool .berf-mail-case strong,\n#berfMailTool .berf-mail-status strong{\n  font-size:34px !important;\n  line-height:1.05 !important;\n  white-space:nowrap !important;\n}\n#berfMailTool .berf-mail-case span,\n#berfMailTool .berf-mail-status em,\n#berfMailTool .berf-mail-agent span{\n  font-size:14px !important;\n}\n#berfMailTool .berf-mail-agent{\n  display:grid !important;\n  grid-template-columns:42px 1fr 42px !important;\n  gap:18px !important;\n}\n#berfMailTool .berf-mail-agent div{\n  min-width:0 !important;\n}\n#berfMailTool .berf-mail-agent strong{\n  display:block !important;\n  font-size:26px !important;\n  line-height:1.05 !important;\n  white-space:nowrap !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n}\n#berfMailTool .berf-mail-agent-badge{\n  left:62px !important;\n  top:36px !important;\n}\n#berfMailTool .berf-mail-main{\n  grid-template-columns:420px minmax(680px, 1fr) 420px !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-listpane,\n#berfMailTool .berf-mail-reader,\n#berfMailTool .berf-mail-attachments{\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-listhead,\n#berfMailTool .berf-mail-attachments-head{\n  height:78px !important;\n  padding:0 26px !important;\n}\n#berfMailTool .berf-mail-listhead h3,\n#berfMailTool .berf-mail-attachments-head h3{\n  font-size:20px !important;\n  white-space:nowrap !important;\n}\n#berfMailTool .email-list{\n  width:100% !important;\n  max-width:none !important;\n  height:calc(100dvh - 118px - 78px - 54px) !important;\n  overflow-y:auto !important;\n  overflow-x:hidden !important;\n  scrollbar-width:thin;\n  scrollbar-color:rgba(239,209,179,.26) rgba(0,0,0,.18);\n}\n#berfMailTool .email-list::-webkit-scrollbar{\n  width:8px;\n}\n#berfMailTool .email-list::-webkit-scrollbar-track{\n  background:rgba(0,0,0,.18);\n}\n#berfMailTool .email-list::-webkit-scrollbar-thumb{\n  background:rgba(239,209,179,.26);\n}\n#berfMailTool .email-item{\n  width:100% !important;\n  max-width:none !important;\n  min-height:128px !important;\n  grid-template-columns:minmax(0,1fr) 20px !important;\n  padding:22px 24px 18px 40px !important;\n  overflow:hidden !important;\n}\n#berfMailTool .email-info{\n  min-width:0 !important;\n  padding-right:76px !important;\n  position:relative !important;\n}\n#berfMailTool .email-info .sender{\n  font-size:22px !important;\n  line-height:1.1 !important;\n  white-space:nowrap !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n}\n#berfMailTool .email-info .subject{\n  font-size:15px !important;\n  line-height:1.25 !important;\n}\n#berfMailTool .email-info .snippet{\n  font-size:14px !important;\n  line-height:1.35 !important;\n  max-height:38px !important;\n  overflow:hidden !important;\n}\n#berfMailTool .email-info .date{\n  top:0 !important;\n  right:0 !important;\n  max-width:72px !important;\n  text-align:right !important;\n  white-space:normal !important;\n  line-height:1.2 !important;\n}\n#berfMailTool .berf-mail-reader{\n  width:100% !important;\n  max-width:none !important;\n  grid-template-rows:78px auto minmax(260px,1fr) 96px !important;\n}\n#berfMailTool .berf-mail-reader-head{\n  height:78px !important;\n  padding:0 28px !important;\n}\n#berfMailTool .details-subject{\n  font-size:26px !important;\n  line-height:1.1 !important;\n  white-space:nowrap !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n}\n#berfMailTool .berf-mail-meta{\n  grid-template-columns:78px minmax(0,1fr) 190px !important;\n  gap:18px !important;\n  padding:28px !important;\n  align-items:start !important;\n}\n#berfMailTool .details-avatar{\n  width:64px !important;\n  height:64px !important;\n  font-size:30px !important;\n}\n#berfMailTool .berf-mail-meta-grid{\n  grid-template-columns:56px minmax(0,1fr) !important;\n  gap:8px 12px !important;\n  font-size:15px !important;\n  line-height:1.25 !important;\n}\n#berfMailTool .berf-mail-stamp{\n  padding:14px 10px !important;\n  min-width:0 !important;\n  max-width:190px !important;\n}\n#berfMailTool .berf-mail-stamp strong{\n  font-size:15px !important;\n  line-height:1.2 !important;\n  margin-bottom:6px !important;\n}\n#berfMailTool .berf-mail-stamp span{\n  font-size:14px !important;\n  line-height:1.25 !important;\n  margin-bottom:8px !important;\n}\n#berfMailTool .berf-mail-stamp small{\n  font-size:11px !important;\n  line-height:1.25 !important;\n  overflow-wrap:anywhere !important;\n  margin-bottom:5px !important;\n}\n#berfMailTool .message-body{\n  padding:30px 34px !important;\n  font-size:18px !important;\n  line-height:1.72 !important;\n  overflow-y:auto !important;\n  overflow-x:hidden !important;\n}\n#berfMailTool .berf-mail-actions{\n  height:96px !important;\n}\n#berfMailTool .berf-mail-actions button{\n  min-width:0 !important;\n  gap:6px !important;\n  padding:8px 6px !important;\n  font-size:13px !important;\n  line-height:1.1 !important;\n}\n#berfMailTool .berf-mail-actions i{\n  font-size:25px !important;\n}\n#berfMailTool .berf-mail-attachments-list{\n  width:100% !important;\n  max-width:none !important;\n  padding:22px 24px !important;\n}\n#berfMailTool .berf-mail-empty{\n  min-height:200px !important;\n  font-size:20px !important;\n  padding:22px !important;\n}\n#berfMailTool .berf-mail-attachments-note{\n  padding:18px 24px !important;\n  font-size:15px !important;\n}\n\n@media (max-width: 1480px){\n  #berfMailTool .inbox-container{\n    grid-template-columns:220px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-main{\n    grid-template-columns:360px minmax(560px,1fr) 340px !important;\n  }\n  #berfMailTool .berf-mail-meta{\n    grid-template-columns:68px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-stamp{\n    grid-column:1 \/ -1 !important;\n    max-width:320px !important;\n  }\n  #berfMailTool .berf-mail-clearance{\n    font-size:20px !important;\n  }\n}\n\n\/* Mail UX V2 - final immersive workstation layout *\/\n#berfDesk #berf-oc-mail .berf-oc__main{\n  background:#0d0c0d !important;\n}\n#berfMailTool{\n  --mail-nav:230px;\n  --mail-list:390px;\n  --mail-side:360px;\n  --mail-head:104px;\n  --mail-row:118px;\n}\n#berfMailTool .inbox-container{\n  grid-template-columns:var(--mail-nav) minmax(0,1fr) !important;\n}\n#berfMailTool .berf-mail-workspace{\n  grid-template-rows:var(--mail-head) minmax(0,1fr) !important;\n}\n#berfMailTool .berf-mail-header{\n  grid-template-columns:minmax(360px, .95fr) minmax(260px, .75fr) minmax(320px, .72fr) !important;\n}\n#berfMailTool .berf-mail-case strong,\n#berfMailTool .berf-mail-status strong{\n  font-size:30px !important;\n}\n#berfMailTool .berf-mail-agent strong{\n  font-size:22px !important;\n}\n#berfMailTool .berf-mail-main{\n  grid-template-columns:var(--mail-list) minmax(620px, 1fr) var(--mail-side) !important;\n}\n#berfMailTool .berf-mail-listpane{\n  display:grid !important;\n  grid-template-rows:76px minmax(0,1fr) 48px !important;\n}\n#berfMailTool .berf-mail-listhead{\n  height:76px !important;\n  gap:14px !important;\n}\n#berfMailTool .berf-mail-listhead > div{\n  gap:10px !important;\n}\n#berfMailTool .berf-mail-listhead h3{\n  font-size:17px !important;\n}\n#berfMailTool .berf-mail-search{\n  display:flex !important;\n  align-items:center !important;\n  gap:8px !important;\n  width:132px !important;\n  height:34px !important;\n  padding:0 10px !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:rgba(0,0,0,.28) !important;\n  color:var(--berf-muted) !important;\n}\n#berfMailTool .berf-mail-search input{\n  width:100% !important;\n  min-width:0 !important;\n  height:100% !important;\n  border:0 !important;\n  padding:0 !important;\n  background:transparent !important;\n  color:var(--berf-parchment) !important;\n  font:600 12px\/1 \"Segoe UI\",Arial,sans-serif !important;\n  outline:0 !important;\n}\n#berfMailTool .email-list{\n  height:auto !important;\n  min-height:0 !important;\n  width:100% !important;\n  display:block !important;\n}\n#berfMailTool .email-item{\n  min-height:var(--mail-row) !important;\n  height:var(--mail-row) !important;\n  padding:20px 22px 16px 38px !important;\n}\n#berfMailTool .email-info .sender{\n  font-size:20px !important;\n}\n#berfMailTool .email-info .subject{\n  font-size:14px !important;\n}\n#berfMailTool .email-info .snippet{\n  font-family:\"Segoe UI\",Arial,sans-serif !important;\n  font-size:13px !important;\n}\n#berfMailTool .berf-mail-reader{\n  grid-template-rows:76px 176px minmax(0,1fr) 92px !important;\n  background:\n    linear-gradient(rgba(239,209,179,.012) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.010) 1px, transparent 1px),\n    rgba(13,12,13,.78) !important;\n  background-size:22px 22px,22px 22px,auto !important;\n}\n#berfMailTool .berf-mail-reader-head{\n  height:76px !important;\n}\n#berfMailTool .details-subject{\n  font-size:24px !important;\n  max-width:calc(100% - 44px) !important;\n}\n#berfMailTool .berf-mail-meta{\n  grid-template-columns:72px minmax(0,1fr) 174px !important;\n  padding:24px 28px !important;\n  min-height:176px !important;\n}\n#berfMailTool .berf-mail-meta-grid{\n  font-family:\"Segoe UI\",Arial,sans-serif !important;\n  font-size:14px !important;\n}\n#berfMailTool .berf-mail-stamp{\n  max-width:174px !important;\n  padding:12px 10px !important;\n}\n#berfMailTool .berf-mail-stamp strong,\n#berfMailTool .berf-mail-stamp span{\n  font-size:13px !important;\n}\n#berfMailTool .message-body{\n  font-size:17px !important;\n  padding:28px 38px !important;\n}\n#berfMailTool .berf-mail-actions{\n  height:92px !important;\n}\n#berfMailTool .berf-mail-actions button{\n  font-family:\"Segoe UI\",Arial,sans-serif !important;\n}\n#berfMailTool .berf-mail-attachments{\n  grid-template-rows:76px minmax(0,1fr) auto !important;\n}\n#berfMailTool .berf-mail-attachments-head{\n  height:76px !important;\n}\n#berfMailTool .berf-mail-attachments-head h3{\n  font-size:20px !important;\n}\n#berfMailTool .berf-mail-empty{\n  min-height:170px !important;\n  font-size:18px !important;\n}\n#berfMailTool .berf-mail-close{\n  width:42px !important;\n  height:42px !important;\n  display:grid !important;\n  place-items:center !important;\n  border:1px solid rgba(239,209,179,.22) !important;\n  background:rgba(176,51,50,.14) !important;\n  color:var(--berf-parchment) !important;\n  cursor:pointer !important;\n}\n#berfMailTool .berf-mail-close:hover{\n  background:rgba(176,51,50,.34) !important;\n}\n\n@media (max-width: 1500px){\n  #berfMailTool{\n    --mail-nav:210px;\n    --mail-list:350px;\n    --mail-side:320px;\n  }\n  #berfMailTool .berf-mail-main{\n    grid-template-columns:var(--mail-list) minmax(540px,1fr) var(--mail-side) !important;\n  }\n  #berfMailTool .berf-mail-meta{\n    grid-template-columns:64px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-stamp{\n    grid-column:2 !important;\n    max-width:320px !important;\n    display:grid !important;\n    grid-template-columns:repeat(4, auto) !important;\n    align-items:center !important;\n    gap:8px 12px !important;\n    text-align:left !important;\n  }\n  #berfMailTool .berf-mail-stamp *{\n    margin:0 !important;\n  }\n}\n\n@media (max-width: 1180px){\n  #berfMailTool{\n    --mail-nav:78px;\n    --mail-list:330px;\n  }\n  #berfMailTool .berf-mail-main{\n    grid-template-columns:var(--mail-list) minmax(0,1fr) !important;\n  }\n}\n\n\/* Mail rescue layout - stable, readable, no inherited flex widths *\/\n#berfDesk #berf-oc-mail,\n#berfDesk #berf-oc-mail[data-open=\"true\"]{\n  position:fixed !important;\n  inset:0 !important;\n  display:block !important;\n  overflow:hidden !important;\n}\n#berfDesk #berf-oc-mail .berf-oc__main{\n  position:absolute !important;\n  inset:0 !important;\n  width:100vw !important;\n  height:100dvh !important;\n  max-width:none !important;\n  overflow:hidden !important;\n  transform:none !important;\n}\n#berfMailTool{\n  width:100vw !important;\n  height:100dvh !important;\n  min-height:0 !important;\n  overflow:hidden !important;\n  background:#0c0b0c !important;\n  font-family:\"Segoe UI\", Arial, sans-serif !important;\n}\n#berfMailTool .inbox-container{\n  width:100vw !important;\n  height:100dvh !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-columns:240px minmax(0, 1fr) !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-workspace{\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-rows:104px minmax(0,1fr) !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-header{\n  min-width:0 !important;\n  height:104px !important;\n  display:grid !important;\n  grid-template-columns:minmax(300px, 1fr) 280px 330px !important;\n}\n#berfMailTool .berf-mail-case,\n#berfMailTool .berf-mail-status,\n#berfMailTool .berf-mail-agent{\n  min-width:0 !important;\n  padding:0 24px !important;\n}\n#berfMailTool .berf-mail-case strong,\n#berfMailTool .berf-mail-status strong{\n  font:700 28px\/1.05 Georgia, \"Times New Roman\", serif !important;\n  white-space:nowrap !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n}\n#berfMailTool .berf-mail-case span,\n#berfMailTool .berf-mail-status em,\n#berfMailTool .berf-mail-agent span{\n  font-size:12px !important;\n  line-height:1.2 !important;\n}\n#berfMailTool .berf-mail-agent{\n  display:grid !important;\n  grid-template-columns:34px minmax(0,1fr) 40px !important;\n  align-items:center !important;\n  gap:12px !important;\n}\n#berfMailTool .berf-mail-agent strong{\n  display:block !important;\n  font:700 22px\/1.1 Georgia, \"Times New Roman\", serif !important;\n  white-space:nowrap !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n}\n#berfMailTool .berf-mail-agent-badge{\n  left:44px !important;\n  top:28px !important;\n}\n#berfMailTool .berf-mail-main{\n  min-width:0 !important;\n  min-height:0 !important;\n  height:100% !important;\n  display:grid !important;\n  grid-template-columns:360px minmax(0,1fr) 360px !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-listpane{\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-rows:70px minmax(0,1fr) 44px !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-listhead{\n  min-width:0 !important;\n  height:70px !important;\n  padding:0 18px !important;\n}\n#berfMailTool .berf-mail-listhead h3{\n  font:700 18px\/1.1 Georgia, \"Times New Roman\", serif !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n  white-space:nowrap !important;\n}\n#berfMailTool .berf-mail-listhead > div span{\n  display:none !important;\n}\n#berfMailTool .berf-mail-search{\n  width:120px !important;\n}\n#berfMailTool .berf-mail-listmount{\n  min-width:0 !important;\n  min-height:0 !important;\n  position:relative !important;\n  overflow:hidden !important;\n}\n#berfMailTool .email-list{\n  position:absolute !important;\n  inset:0 !important;\n  width:auto !important;\n  height:auto !important;\n  max-width:none !important;\n  min-width:0 !important;\n  display:block !important;\n  overflow-y:auto !important;\n  overflow-x:hidden !important;\n  padding:0 !important;\n  margin:0 !important;\n}\n#berfMailTool .email-item{\n  width:100% !important;\n  min-width:0 !important;\n  max-width:none !important;\n  min-height:104px !important;\n  height:auto !important;\n  display:block !important;\n  padding:16px 18px 14px 28px !important;\n}\n#berfMailTool .email-info{\n  width:100% !important;\n  min-width:0 !important;\n  padding-right:82px !important;\n}\n#berfMailTool .email-info .sender{\n  font:700 17px\/1.15 Georgia, \"Times New Roman\", serif !important;\n}\n#berfMailTool .email-info .subject,\n#berfMailTool .email-info .snippet{\n  display:block !important;\n  width:100% !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n}\n#berfMailTool .email-info .snippet{\n  display:-webkit-box !important;\n  -webkit-line-clamp:2 !important;\n  -webkit-box-orient:vertical !important;\n}\n#berfMailTool .email-info .date{\n  top:16px !important;\n  right:16px !important;\n  width:72px !important;\n  max-width:72px !important;\n}\n#berfMailTool .berf-mail-readermount{\n  min-width:0 !important;\n  min-height:0 !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-reader{\n  width:100% !important;\n  height:100% !important;\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-rows:70px 128px minmax(0,1fr) 82px !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-reader-head{\n  height:70px !important;\n  min-width:0 !important;\n  padding:0 24px !important;\n}\n#berfMailTool .details-subject{\n  font:700 22px\/1.15 Georgia, \"Times New Roman\", serif !important;\n  max-width:100% !important;\n}\n#berfMailTool .berf-mail-meta{\n  min-width:0 !important;\n  min-height:0 !important;\n  grid-template-columns:56px minmax(0,1fr) !important;\n  padding:18px 24px !important;\n  gap:14px !important;\n}\n#berfMailTool .details-avatar{\n  width:48px !important;\n  height:48px !important;\n  font-size:24px !important;\n}\n#berfMailTool .berf-mail-meta-grid{\n  min-width:0 !important;\n  grid-template-columns:46px minmax(0,1fr) !important;\n  gap:5px 10px !important;\n  font-size:13px !important;\n}\n#berfMailTool .berf-mail-stamp{\n  display:none !important;\n}\n#berfMailTool .message-body{\n  min-width:0 !important;\n  min-height:0 !important;\n  padding:24px 30px !important;\n  font:600 16px\/1.65 Georgia, \"Times New Roman\", serif !important;\n  overflow:auto !important;\n}\n#berfMailTool .berf-mail-actions{\n  height:82px !important;\n  min-height:82px !important;\n}\n#berfMailTool .berf-mail-actions button{\n  font-size:12px !important;\n  gap:4px !important;\n}\n#berfMailTool .berf-mail-actions i{\n  font-size:21px !important;\n}\n#berfMailTool .berf-mail-attachments{\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-rows:70px minmax(0,1fr) auto !important;\n  overflow:hidden !important;\n}\n#berfMailTool .berf-mail-attachments-head{\n  height:70px !important;\n  padding:0 20px !important;\n}\n#berfMailTool .berf-mail-attachments-head h3{\n  font:700 18px\/1.1 Georgia, \"Times New Roman\", serif !important;\n}\n#berfMailTool .berf-mail-attachments-list{\n  min-height:0 !important;\n  padding:18px !important;\n  overflow:auto !important;\n}\n#berfMailTool .berf-mail-empty{\n  min-height:150px !important;\n  font-size:17px !important;\n}\n#berfMailTool .berf-mail-attachments-note{\n  font-size:13px !important;\n  padding:14px 18px !important;\n}\n\n@media (max-width: 1320px){\n  #berfMailTool .inbox-container{\n    grid-template-columns:88px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-logo{\n    height:98px !important;\n  }\n  #berfMailTool .berf-mail-logo img{\n    width:64px !important;\n    height:64px !important;\n  }\n  #berfMailTool .berf-mail-navitem{\n    justify-content:center !important;\n    padding:0 !important;\n  }\n  #berfMailTool .berf-mail-navitem span,\n  #berfMailTool .berf-mail-clearance{\n    display:none !important;\n  }\n  #berfMailTool .berf-mail-main{\n    grid-template-columns:330px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-attachments{\n    display:none !important;\n  }\n}\n\n@media (max-width: 900px){\n  #berfMailTool .inbox-container{\n    grid-template-columns:1fr !important;\n  }\n  #berfMailTool .berf-mail-nav{\n    display:none !important;\n  }\n  #berfMailTool .berf-mail-workspace{\n    width:100% !important;\n    grid-template-rows:78px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-header{\n    width:100% !important;\n    height:78px !important;\n    min-height:0 !important;\n    max-height:78px !important;\n    grid-template-columns:minmax(0,1fr) auto !important;\n    overflow:hidden !important;\n  }\n  #berfMailTool .berf-mail-case{\n    padding:0 16px !important;\n  }\n  #berfMailTool .berf-mail-case strong{\n    font-size:22px !important;\n  }\n  #berfMailTool .berf-mail-case span{\n    max-width:100% !important;\n    overflow:hidden !important;\n    text-overflow:ellipsis !important;\n    white-space:nowrap !important;\n  }\n  #berfMailTool .berf-mail-status{\n    display:none !important;\n  }\n  #berfMailTool .berf-mail-agent{\n    width:auto !important;\n    padding:0 12px !important;\n    grid-template-columns:34px 38px !important;\n    border-left:1px solid rgba(214,176,133,.18) !important;\n  }\n  #berfMailTool .berf-mail-agent > div{\n    display:none !important;\n  }\n  #berfMailTool .berf-mail-agent-badge{\n    left:30px !important;\n    top:18px !important;\n  }\n  #berfMailTool .berf-mail-main{\n    width:100% !important;\n    grid-template-columns:1fr !important;\n    grid-template-rows:218px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-listpane{\n    width:100% !important;\n    grid-template-rows:52px minmax(0,1fr) 30px !important;\n    border-right:0 !important;\n    border-bottom:1px solid rgba(214,176,133,.2) !important;\n  }\n  #berfMailTool .berf-mail-listhead{\n    height:52px !important;\n    padding:0 12px !important;\n  }\n  #berfMailTool .berf-mail-listhead h3{\n    font-size:15px !important;\n  }\n  #berfMailTool .berf-mail-search{\n    width:104px !important;\n    height:28px !important;\n  }\n  #berfMailTool .email-list{\n    display:flex !important;\n    align-items:stretch !important;\n    overflow-x:auto !important;\n    overflow-y:hidden !important;\n    scroll-snap-type:x mandatory !important;\n  }\n  #berfMailTool .email-item{\n    flex:0 0 280px !important;\n    width:280px !important;\n    height:100% !important;\n    min-height:0 !important;\n    max-height:136px !important;\n    padding:14px 16px !important;\n    scroll-snap-align:start !important;\n    border-right:1px solid rgba(214,176,133,.12) !important;\n  }\n  #berfMailTool .email-info{\n    padding-right:0 !important;\n  }\n  #berfMailTool .email-info .date{\n    position:static !important;\n    width:auto !important;\n    max-width:none !important;\n    margin-bottom:8px !important;\n    text-align:left !important;\n  }\n  #berfMailTool .berf-mail-reader{\n    grid-template-rows:48px 86px minmax(120px,1fr) 32px 58px !important;\n  }\n  #berfMailTool .berf-mail-reader-head{\n    height:48px !important;\n    padding:0 16px !important;\n  }\n  #berfMailTool .details-subject{\n    font-size:17px !important;\n  }\n  #berfMailTool .berf-mail-meta{\n    padding:10px 16px !important;\n    grid-template-columns:42px minmax(0,1fr) !important;\n  }\n  #berfMailTool .details-avatar{\n    width:38px !important;\n    height:38px !important;\n    font-size:20px !important;\n  }\n  #berfMailTool .berf-mail-meta-grid{\n    grid-template-columns:40px minmax(0,1fr) !important;\n    font-size:12px !important;\n  }\n  #berfMailTool .message-body{\n    padding:14px 18px !important;\n    font-size:14px !important;\n    line-height:1.55 !important;\n  }\n  #berfMailTool .berf-mail-reader > .attachments{\n    min-height:0 !important;\n    height:32px !important;\n    padding:0 16px !important;\n    overflow:hidden !important;\n  }\n  #berfMailTool .berf-mail-actions{\n    height:58px !important;\n    min-height:58px !important;\n  }\n  #berfMailTool .berf-mail-actions button span{\n    display:none !important;\n  }\n  #berfMailTool .berf-mail-actions i{\n    font-size:20px !important;\n  }\n}\n\n\/* Mail window final behavior: contained overlay, no left rail, no top header *\/\n#berfDesk #berf-oc-mail{\n  position:fixed !important;\n  inset:0 !important;\n  display:none !important;\n  overflow:hidden !important;\n  background:rgba(3,3,4,.42) !important;\n  backdrop-filter:blur(2px) !important;\n}\n#berfDesk #berf-oc-mail[data-open=\"true\"]{\n  display:block !important;\n}\n#berfDesk #berf-oc-mail .berf-oc__main{\n  position:absolute !important;\n  left:50% !important;\n  top:50% !important;\n  width:86vw !important;\n  max-width:1540px !important;\n  min-width:min(980px, 92vw) !important;\n  height:84dvh !important;\n  max-height:900px !important;\n  transform:translate(-50%, -50%) !important;\n  overflow:hidden !important;\n  border:1px solid rgba(214,176,133,.32) !important;\n  box-shadow:0 28px 90px rgba(0,0,0,.72), 0 0 0 1px rgba(170,54,46,.18) inset !important;\n  background:#0b0a0a !important;\n}\n#berfMailTool{\n  width:100% !important;\n  height:100% !important;\n}\n#berfMailTool .inbox-container{\n  width:100% !important;\n  height:100% !important;\n  grid-template-columns:1fr !important;\n}\n#berfMailTool .berf-mail-nav,\n#berfMailTool .berf-mail-header{\n  display:none !important;\n}\n#berfMailTool .berf-mail-workspace{\n  width:100% !important;\n  height:100% !important;\n  grid-template-rows:minmax(0,1fr) !important;\n}\n#berfMailTool .berf-mail-main{\n  width:100% !important;\n  height:100% !important;\n  grid-template-columns:340px minmax(0,1fr) 340px !important;\n}\n#berfMailTool .berf-mail-listpane{\n  height:100% !important;\n}\n#berfMailTool .berf-mail-reader{\n  grid-template-rows:70px 128px minmax(0,1fr) auto 82px !important;\n}\n#berfMailTool #archiveMailButton{\n  display:none !important;\n}\n\n@media (max-width: 1180px){\n  #berfDesk #berf-oc-mail .berf-oc__main{\n    width:90vw !important;\n    min-width:0 !important;\n    height:86dvh !important;\n  }\n  #berfMailTool .berf-mail-main{\n    grid-template-columns:320px minmax(0,1fr) !important;\n  }\n  #berfMailTool .berf-mail-attachments{\n    display:none !important;\n  }\n}\n\n@media (max-width: 760px){\n  #berfDesk #berf-oc-mail .berf-oc__main{\n    width:92vw !important;\n    height:88dvh !important;\n  }\n  #berfMailTool .berf-mail-main{\n    grid-template-columns:1fr !important;\n    grid-template-rows:210px minmax(0,1fr) !important;\n  }\n}\n\n\/* Mail action bar and compose\/reply modals *\/\n#berfMailTool .berf-mail-actions{\n  display:grid !important;\n  grid-template-columns:repeat(2, minmax(0, 1fr)) !important;\n  height:74px !important;\n  min-height:74px !important;\n  border-top:1px solid rgba(214,176,133,.24) !important;\n  background:linear-gradient(180deg, rgba(20,18,18,.94), rgba(9,8,8,.96)) !important;\n}\n#berfMailTool .berf-mail-actions button{\n  min-width:0 !important;\n  height:100% !important;\n  display:flex !important;\n  flex-direction:row !important;\n  align-items:center !important;\n  justify-content:center !important;\n  gap:12px !important;\n  padding:0 18px !important;\n  border:0 !important;\n  border-right:1px solid rgba(214,176,133,.18) !important;\n  border-radius:0 !important;\n  background:transparent !important;\n  color:#efd8bd !important;\n  font:700 13px\/1.1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.08em !important;\n  text-transform:uppercase !important;\n}\n#berfMailTool .berf-mail-actions button:last-child{\n  border-right:0 !important;\n}\n#berfMailTool .berf-mail-actions button:hover,\n#berfMailTool .berf-mail-actions button:focus-visible{\n  background:rgba(176,51,50,.22) !important;\n  color:#fff2df !important;\n  outline:1px solid rgba(214,83,71,.52) !important;\n  outline-offset:-1px !important;\n}\n#berfMailTool .berf-mail-actions i{\n  font-size:22px !important;\n  line-height:1 !important;\n}\n#berfMailTool #flagMailButton,\n#berfMailTool #archiveMailButton{\n  display:none !important;\n}\n\n#berfMailTool #newMailModal,\n#berfMailTool #replyModal{\n  position:fixed !important;\n  inset:0 !important;\n  display:none;\n  align-items:center !important;\n  justify-content:center !important;\n  padding:28px !important;\n  background:rgba(2,2,3,.58) !important;\n  backdrop-filter:blur(3px) !important;\n  z-index:100200 !important;\n}\n#berfMailTool #newMailModal .modal-content,\n#berfMailTool #replyModal .modal-content{\n  width:min(680px, 92vw) !important;\n  max-height:min(760px, 86dvh) !important;\n  overflow:auto !important;\n  padding:0 !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.34) !important;\n  background:\n    linear-gradient(90deg, rgba(214,176,133,.05) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(214,176,133,.045) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(28,24,23,.98), rgba(10,9,9,.98)) !important;\n  background-size:36px 36px, 36px 36px, auto !important;\n  box-shadow:0 30px 90px rgba(0,0,0,.74), 0 0 0 1px rgba(174,49,45,.20) inset !important;\n  color:#efd8bd !important;\n}\n#berfMailTool #newMailModal .modal-content::before,\n#berfMailTool #replyModal .modal-content::before{\n  content:\"Transmission securisee BERF\";\n  display:flex;\n  align-items:center;\n  height:54px;\n  padding:0 24px;\n  border-bottom:1px solid rgba(214,176,133,.22);\n  color:#d65347;\n  font:800 12px\/1 \"Segoe UI\", Arial, sans-serif;\n  letter-spacing:.16em;\n  text-transform:uppercase;\n}\n#berfMailTool #newMailModal h2,\n#berfMailTool #replyModal h2{\n  margin:0 !important;\n  padding:24px 24px 8px !important;\n  color:#f6dec0 !important;\n  font:700 25px\/1.1 Georgia, \"Times New Roman\", serif !important;\n  letter-spacing:.04em !important;\n  text-transform:uppercase !important;\n}\n#berfMailTool #newMailForm,\n#berfMailTool #replyForm{\n  display:grid !important;\n  gap:10px !important;\n  padding:14px 24px 24px !important;\n}\n#berfMailTool #newMailForm label,\n#berfMailTool #replyForm label{\n  margin-top:10px !important;\n  color:#b8a899 !important;\n  font:800 11px\/1.2 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfMailTool #newMailForm input,\n#berfMailTool #replyForm input,\n#berfMailTool #newMailForm textarea,\n#berfMailTool #replyForm textarea{\n  width:100% !important;\n  min-width:0 !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  border-radius:0 !important;\n  background:rgba(5,5,6,.74) !important;\n  color:#f6dec0 !important;\n  padding:13px 14px !important;\n  font:600 14px\/1.35 \"Segoe UI\", Arial, sans-serif !important;\n  outline:none !important;\n}\n#berfMailTool #newMailForm textarea,\n#berfMailTool #replyForm textarea{\n  min-height:154px !important;\n  resize:vertical !important;\n}\n#berfMailTool #newMailForm input:focus,\n#berfMailTool #replyForm input:focus,\n#berfMailTool #newMailForm textarea:focus,\n#berfMailTool #replyForm textarea:focus{\n  border-color:rgba(214,83,71,.7) !important;\n  box-shadow:0 0 0 2px rgba(214,83,71,.12) !important;\n}\n#berfMailTool #replyForm input[readonly]{\n  color:#b8a899 !important;\n  background:rgba(255,255,255,.04) !important;\n}\n#berfMailTool #newMailForm input[type=\"file\"],\n#berfMailTool #replyForm input[type=\"file\"]{\n  color:#b8a899 !important;\n  border-style:dashed !important;\n  cursor:pointer !important;\n}\n#berfMailTool #newMailForm button[type=\"submit\"],\n#berfMailTool #replyForm button[type=\"submit\"]{\n  justify-self:end !important;\n  min-width:180px !important;\n  margin-top:14px !important;\n  border:1px solid rgba(214,83,71,.7) !important;\n  border-radius:0 !important;\n  background:linear-gradient(180deg, rgba(121,33,31,.96), rgba(78,19,19,.96)) !important;\n  color:#fff2df !important;\n  padding:13px 20px !important;\n  font:800 12px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.14em !important;\n  text-transform:uppercase !important;\n  cursor:pointer !important;\n}\n#berfMailTool #newMailForm button[type=\"submit\"]:hover,\n#berfMailTool #replyForm button[type=\"submit\"]:hover{\n  background:linear-gradient(180deg, rgba(154,45,40,.98), rgba(101,25,23,.98)) !important;\n}\n#berfMailTool #newMailModal .close,\n#berfMailTool #replyModal .close{\n  top:14px !important;\n  right:18px !important;\n  width:32px !important;\n  height:32px !important;\n  display:grid !important;\n  place-items:center !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  color:#efd8bd !important;\n  background:rgba(0,0,0,.2) !important;\n  font-size:20px !important;\n  line-height:1 !important;\n  z-index:2 !important;\n}\n#berfMailTool #newMailModal .close:hover,\n#berfMailTool #replyModal .close:hover{\n  border-color:rgba(214,83,71,.7) !important;\n  color:#fff2df !important;\n}\n\n\/* Mail viewer refinement: attachments only live in the right column *\/\n#berfMailTool .berf-mail-reader > .attachments,\n#berfMailTool .email-details > .attachments{\n  display:none !important;\n}\n#berfMailTool .berf-mail-reader{\n  grid-template-rows:70px 128px minmax(0,1fr) 82px !important;\n}\n#berfMailTool #attachmentModal{\n  position:fixed !important;\n  inset:0 !important;\n  display:none;\n  align-items:center !important;\n  justify-content:center !important;\n  padding:28px !important;\n  background:rgba(2,2,3,.72) !important;\n  backdrop-filter:blur(4px) !important;\n  z-index:100300 !important;\n}\n#berfMailTool #attachmentModal .berf-mail-viewer{\n  width:min(1180px, 92vw) !important;\n  height:min(860px, 88dvh) !important;\n  max-height:88dvh !important;\n  padding:0 !important;\n  display:grid !important;\n  grid-template-rows:76px minmax(0,1fr) 64px !important;\n  overflow:hidden !important;\n  border:1px solid rgba(214,176,133,.36) !important;\n  border-radius:0 !important;\n  background:\n    linear-gradient(90deg, rgba(214,176,133,.04) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(214,176,133,.035) 1px, transparent 1px),\n    #090808 !important;\n  background-size:34px 34px, 34px 34px, auto !important;\n  box-shadow:0 36px 110px rgba(0,0,0,.78), 0 0 0 1px rgba(176,51,50,.18) inset !important;\n}\n#berfMailTool .berf-mail-viewer-head{\n  display:flex !important;\n  align-items:center !important;\n  justify-content:space-between !important;\n  gap:18px !important;\n  padding:0 22px !important;\n  border-bottom:1px solid rgba(214,176,133,.24) !important;\n  background:linear-gradient(180deg, rgba(24,21,20,.98), rgba(11,10,10,.96)) !important;\n}\n#berfMailTool .berf-mail-viewer-kicker{\n  display:block !important;\n  color:#d65347 !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.16em !important;\n  text-transform:uppercase !important;\n}\n#berfMailTool .berf-mail-viewer-head h2{\n  margin:8px 0 0 !important;\n  color:#f6dec0 !important;\n  font:700 21px\/1.1 Georgia, \"Times New Roman\", serif !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n  white-space:nowrap !important;\n}\n#berfMailTool .berf-mail-viewer-head p{\n  margin:6px 0 0 !important;\n  color:#b8a899 !important;\n  font-size:12px !important;\n}\n#berfMailTool #attachmentModal .close{\n  position:static !important;\n  flex:0 0 auto !important;\n  width:36px !important;\n  height:36px !important;\n  display:grid !important;\n  place-items:center !important;\n  border:1px solid rgba(214,176,133,.26) !important;\n  background:rgba(0,0,0,.28) !important;\n  color:#efd8bd !important;\n  cursor:pointer !important;\n}\n#berfMailTool #attachmentModal .close:hover{\n  border-color:rgba(214,83,71,.78) !important;\n  color:#fff2df !important;\n}\n#berfMailTool #attachmentPreview{\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  place-items:center !important;\n  overflow:hidden !important;\n  background:rgba(0,0,0,.35) !important;\n}\n#berfMailTool #attachmentPreview iframe{\n  width:100% !important;\n  height:100% !important;\n  border:0 !important;\n  background:#111 !important;\n}\n#berfMailTool #attachmentPreview img,\n#berfMailTool #attachmentPreview video{\n  max-width:100% !important;\n  max-height:100% !important;\n  object-fit:contain !important;\n}\n#berfMailTool #attachmentPreview audio{\n  width:min(620px, 86%) !important;\n}\n#berfMailTool #attachmentModal .berf-viewer-actionbar{\n  height:64px !important;\n  display:flex !important;\n  align-items:center !important;\n  justify-content:flex-end !important;\n  gap:12px !important;\n  padding:0 22px !important;\n  border-top:1px solid rgba(214,176,133,.22) !important;\n  background:rgba(10,9,9,.96) !important;\n}\n#berfMailTool .berf-viewer-open-btn,\n#berfMailTool .berf-viewer-analyze-btn{\n  min-height:38px !important;\n  display:inline-flex !important;\n  align-items:center !important;\n  justify-content:center !important;\n  gap:9px !important;\n  padding:0 14px !important;\n  border:1px solid rgba(214,83,71,.64) !important;\n  border-radius:0 !important;\n  background:rgba(176,51,50,.16) !important;\n  color:#f6dec0 !important;\n  text-decoration:none !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.11em !important;\n  text-transform:uppercase !important;\n  cursor:pointer !important;\n}\n#berfMailTool .berf-viewer-open-btn:hover,\n#berfMailTool .berf-viewer-analyze-btn:hover{\n  background:rgba(176,51,50,.28) !important;\n  color:#fff2df !important;\n}\n#berfMailTool .berf-viewer-analyze-btn[hidden]{display:none !important}\n#berfMailTool .berf-viewer-collect-btn{border-color:rgba(96,154,112,.68) !important;background:rgba(64,125,82,.18) !important}\n#berfMailTool .berf-viewer-collect-btn:hover{background:rgba(64,125,82,.32) !important}\n\n\/* Mail action bar final sizing *\/\n#berfMailTool .berf-mail-reader{\n  grid-template-rows:70px 128px minmax(0,1fr) 56px !important;\n}\n#berfMailTool .berf-mail-actions{\n  height:56px !important;\n  min-height:56px !important;\n  display:flex !important;\n  align-items:center !important;\n  justify-content:center !important;\n  gap:10px !important;\n  padding:0 16px !important;\n  border-top:1px solid rgba(214,176,133,.22) !important;\n  background:rgba(10,9,9,.92) !important;\n}\n#berfMailTool .berf-mail-actions button{\n  flex:0 0 178px !important;\n  width:178px !important;\n  height:36px !important;\n  min-height:36px !important;\n  display:grid !important;\n  grid-template-columns:18px minmax(0,1fr) !important;\n  align-items:center !important;\n  justify-items:center !important;\n  gap:8px !important;\n  padding:0 12px !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  border-radius:0 !important;\n  background:rgba(18,15,15,.74) !important;\n  color:#efd8bd !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.09em !important;\n  text-transform:uppercase !important;\n}\n#berfMailTool .berf-mail-actions button:last-child{\n  border-right:1px solid rgba(214,176,133,.24) !important;\n}\n#berfMailTool .berf-mail-actions button i{\n  width:18px !important;\n  height:18px !important;\n  display:grid !important;\n  place-items:center !important;\n  font-size:16px !important;\n  line-height:1 !important;\n}\n#berfMailTool .berf-mail-actions button span{\n  display:block !important;\n  width:100% !important;\n  overflow:hidden !important;\n  text-align:center !important;\n  white-space:nowrap !important;\n}\n#berfMailTool .berf-mail-actions button:hover,\n#berfMailTool .berf-mail-actions button:focus-visible{\n  background:rgba(176,51,50,.22) !important;\n  border-color:rgba(214,83,71,.6) !important;\n  outline:0 !important;\n}\n\n@media (max-width: 760px){\n  #berfMailTool .berf-mail-actions{\n    gap:8px !important;\n    padding:0 10px !important;\n  }\n  #berfMailTool .berf-mail-actions button{\n    flex:1 1 0 !important;\n    width:auto !important;\n    max-width:180px !important;\n  }\n}\n\n\/* Mail action buttons hard alignment *\/\n#berfMailTool .berf-mail-actions{\n  display:grid !important;\n  grid-template-columns:170px 170px !important;\n  grid-auto-rows:34px !important;\n  align-content:center !important;\n  justify-content:center !important;\n  align-items:center !important;\n  justify-items:stretch !important;\n  gap:10px !important;\n  height:52px !important;\n  min-height:52px !important;\n  padding:0 !important;\n}\n#berfMailTool .berf-mail-actions #newMailButton,\n#berfMailTool .berf-mail-actions #replyButton{\n  position:static !important;\n  inset:auto !important;\n  top:auto !important;\n  right:auto !important;\n  bottom:auto !important;\n  left:auto !important;\n  transform:none !important;\n  margin:0 !important;\n  float:none !important;\n  box-sizing:border-box !important;\n  width:170px !important;\n  min-width:170px !important;\n  max-width:170px !important;\n  height:34px !important;\n  min-height:34px !important;\n  max-height:34px !important;\n  display:grid !important;\n  grid-template-columns:18px 1fr !important;\n  align-items:center !important;\n  justify-items:center !important;\n  align-self:center !important;\n  justify-self:center !important;\n  gap:8px !important;\n  padding:0 12px !important;\n  line-height:1 !important;\n  vertical-align:middle !important;\n}\n#berfMailTool .berf-mail-actions #newMailButton i,\n#berfMailTool .berf-mail-actions #replyButton i{\n  width:18px !important;\n  height:18px !important;\n  margin:0 !important;\n  display:grid !important;\n  place-items:center !important;\n  line-height:1 !important;\n}\n#berfMailTool .berf-mail-actions #newMailButton span,\n#berfMailTool .berf-mail-actions #replyButton span{\n  margin:0 !important;\n  padding:0 !important;\n  display:block !important;\n  line-height:1 !important;\n}\n\n@media (max-width: 760px){\n  #berfMailTool .berf-mail-actions{\n    grid-template-columns:minmax(0, 1fr) minmax(0, 1fr) !important;\n    padding:0 10px !important;\n  }\n  #berfMailTool .berf-mail-actions #newMailButton,\n  #berfMailTool .berf-mail-actions #replyButton{\n    width:100% !important;\n    min-width:0 !important;\n    max-width:170px !important;\n  }\n}\n\n\/* Suspects tool immersive BERF UI *\/\n#berfDesk #berf-oc-suspects .berf-oc__main{\n  width:min(1420px, 90vw) !important;\n  height:86dvh !important;\n  max-height:920px !important;\n  top:50% !important;\n  right:auto !important;\n  left:50% !important;\n  transform:translate(-50%, -50%) !important;\n  overflow:hidden !important;\n  border:1px solid rgba(214,176,133,.32) !important;\n  background:#0b0a0a !important;\n  box-shadow:0 28px 90px rgba(0,0,0,.72), 0 0 0 1px rgba(170,54,46,.18) inset !important;\n}\n#berfDesk #berf-oc-suspects .berf-oc__top{\n  height:58px !important;\n  min-height:58px !important;\n  padding:0 18px !important;\n  border-bottom:1px solid rgba(214,176,133,.22) !important;\n  background:linear-gradient(180deg, rgba(24,21,20,.98), rgba(11,10,10,.96)) !important;\n}\n#berfDesk #berf-oc-suspects .berf-oc__title{\n  color:#f6dec0 !important;\n  font:800 14px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfDesk #berf-oc-suspects .berf-oc__title i{\n  color:#d65347 !important;\n  margin-right:10px !important;\n}\n#berfDesk #berf-oc-suspects .berf-oc__close{\n  width:34px !important;\n  height:34px !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.26) !important;\n  background:rgba(0,0,0,.24) !important;\n  color:#efd8bd !important;\n}\n#berfSuspectsTool{\n  height:calc(86dvh - 58px) !important;\n  min-height:0 !important;\n  padding:0 !important;\n  overflow:hidden !important;\n  color:#efd8bd !important;\n  background:\n    linear-gradient(90deg, rgba(214,176,133,.035) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(214,176,133,.028) 1px, transparent 1px),\n    radial-gradient(circle at 15% 0%, rgba(176,51,50,.16), transparent 32%),\n    #0b0a0a !important;\n  background-size:34px 34px, 34px 34px, auto, auto !important;\n}\n#berfSuspectsTool .container42X{\n  width:100% !important;\n  max-width:none !important;\n  height:100% !important;\n  margin:0 !important;\n  padding:0 !important;\n  display:grid !important;\n  grid-template-rows:92px minmax(0,1fr) !important;\n  overflow:hidden !important;\n  border:0 !important;\n  border-radius:0 !important;\n  background:transparent !important;\n  box-shadow:none !important;\n}\n#berfSuspectsTool .container42X h1{\n  margin:0 !important;\n  padding:0 220px 0 24px !important;\n  height:92px !important;\n  display:flex !important;\n  align-items:center !important;\n  border-bottom:1px solid rgba(214,176,133,.20) !important;\n  color:#f6dec0 !important;\n  font:700 28px\/1.05 Georgia, \"Times New Roman\", serif !important;\n  letter-spacing:.03em !important;\n  text-align:left !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool .container42X h1::before{\n  content:\"Dossier D-174\";\n  position:absolute;\n  left:24px;\n  top:14px;\n  color:#d65347;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif;\n  letter-spacing:.16em;\n}\n#berfSuspectsTool #btnNewSuspect42X{\n  position:absolute !important;\n  top:28px !important;\n  right:24px !important;\n  height:38px !important;\n  min-width:172px !important;\n  padding:0 16px !important;\n  border:1px solid rgba(214,83,71,.68) !important;\n  border-radius:0 !important;\n  background:linear-gradient(180deg, rgba(121,33,31,.96), rgba(78,19,19,.96)) !important;\n  color:#fff2df !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.13em !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool .suspect-table42X{\n  width:calc(100% - 48px) !important;\n  height:auto !important;\n  margin:24px !important;\n  border-collapse:separate !important;\n  border-spacing:0 !important;\n  table-layout:fixed !important;\n  overflow:hidden !important;\n  border:1px solid rgba(214,176,133,.18) !important;\n  background:rgba(11,10,10,.58) !important;\n}\n#berfSuspectsTool .suspect-table42X thead{\n  position:sticky !important;\n  top:0 !important;\n  z-index:1 !important;\n}\n#berfSuspectsTool .suspect-table42X th{\n  height:46px !important;\n  padding:0 14px !important;\n  border:0 !important;\n  border-bottom:1px solid rgba(214,176,133,.24) !important;\n  background:rgba(22,19,18,.96) !important;\n  color:#d65347 !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool .suspect-table42X td{\n  height:74px !important;\n  padding:12px 14px !important;\n  border:0 !important;\n  border-bottom:1px solid rgba(214,176,133,.13) !important;\n  color:#efd8bd !important;\n  font:600 13px\/1.35 \"Segoe UI\", Arial, sans-serif !important;\n  overflow:hidden !important;\n  text-overflow:ellipsis !important;\n  vertical-align:middle !important;\n}\n#berfSuspectsTool .suspect-table42X tr:hover td{\n  background:rgba(176,51,50,.10) !important;\n}\n#berfSuspectsTool .suspect-table42X th:nth-child(1),\n#berfSuspectsTool .suspect-table42X td:nth-child(1){\n  width:76px !important;\n  text-align:center !important;\n}\n#berfSuspectsTool .suspect-table42X th:nth-child(2),\n#berfSuspectsTool .suspect-table42X td:nth-child(2){\n  width:18% !important;\n  font-family:Georgia, \"Times New Roman\", serif !important;\n  font-size:17px !important;\n  font-weight:700 !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool .suspect-table42X th:nth-child(3),\n#berfSuspectsTool .suspect-table42X td:nth-child(3){\n  width:130px !important;\n}\n#berfSuspectsTool .suspect-table42X th:nth-child(7),\n#berfSuspectsTool .suspect-table42X td:nth-child(7){\n  width:136px !important;\n  text-align:right !important;\n}\n#berfSuspectsTool .avatar42X{\n  width:42px !important;\n  height:42px !important;\n  margin:0 auto !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.26) !important;\n  background:linear-gradient(180deg, #8e2625, #441313) !important;\n  color:#fff2df !important;\n  font:800 13px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.05em !important;\n}\n#berfSuspectsTool .action-btn42X{\n  width:32px !important;\n  height:32px !important;\n  display:inline-grid !important;\n  place-items:center !important;\n  margin-left:5px !important;\n  border:1px solid rgba(214,176,133,.20) !important;\n  border-radius:0 !important;\n  background:rgba(0,0,0,.20) !important;\n  color:#efd8bd !important;\n  cursor:pointer !important;\n}\n#berfSuspectsTool .action-btn42X:hover{\n  border-color:rgba(214,83,71,.70) !important;\n  background:rgba(176,51,50,.20) !important;\n  color:#fff2df !important;\n}\n#berfSuspectsTool .report-icon42X{\n  color:#d65347 !important;\n}\n#berfSuspectsTool .modal42X{\n  position:fixed !important;\n  inset:0 !important;\n  z-index:100200 !important;\n  display:none;\n  align-items:center !important;\n  justify-content:center !important;\n  padding:28px !important;\n  background:rgba(2,2,3,.64) !important;\n  backdrop-filter:blur(3px) !important;\n}\n#berfSuspectsTool .modal-content42X{\n  width:min(700px, 92vw) !important;\n  max-height:86dvh !important;\n  overflow:auto !important;\n  padding:0 !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.34) !important;\n  background:\n    linear-gradient(90deg, rgba(214,176,133,.045) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(214,176,133,.035) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(28,24,23,.98), rgba(10,9,9,.98)) !important;\n  background-size:36px 36px, 36px 36px, auto !important;\n  box-shadow:0 30px 90px rgba(0,0,0,.74), 0 0 0 1px rgba(174,49,45,.20) inset !important;\n  color:#efd8bd !important;\n}\n#berfSuspectsTool .modal-header42X{\n  margin:0 !important;\n  padding:24px 24px 10px !important;\n  border-bottom:1px solid rgba(214,176,133,.18) !important;\n  color:#f6dec0 !important;\n  font:700 24px\/1.1 Georgia, \"Times New Roman\", serif !important;\n  letter-spacing:.04em !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool form{\n  display:grid !important;\n  gap:10px !important;\n  padding:18px 24px 24px !important;\n}\n#berfSuspectsTool .form-group42X{\n  margin:0 !important;\n}\n#berfSuspectsTool label{\n  display:block !important;\n  margin:10px 0 7px !important;\n  color:#b8a899 !important;\n  font:800 11px\/1.2 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool .form-control42X{\n  width:100% !important;\n  min-width:0 !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  border-radius:0 !important;\n  background:rgba(5,5,6,.74) !important;\n  color:#f6dec0 !important;\n  padding:12px 14px !important;\n  font:600 14px\/1.35 \"Segoe UI\", Arial, sans-serif !important;\n  outline:none !important;\n}\n#berfSuspectsTool textarea.form-control42X{\n  min-height:118px !important;\n  resize:vertical !important;\n}\n#berfSuspectsTool .evidence-picker-open42X{width:auto;justify-content:flex-start;margin-top:4px}\n#berfSuspectsTool .evidence-selection42X{display:flex;flex-wrap:wrap;gap:7px;min-height:45px;margin-top:9px;padding:9px;border:1px dashed rgba(255,255,255,.16);border-radius:10px;background:rgba(0,0,0,.20);color:#aaa;font:12px 'Roboto Mono',monospace}\n#berfSuspectsTool .evidence-chip42X{display:inline-flex;align-items:center;gap:7px;max-width:100%;padding:7px 9px;border:1px solid rgba(175,50,50,.38);border-radius:9px;background:rgba(175,50,50,.14);color:#eee;cursor:pointer}\n#berfSuspectsTool .evidence-chip42X span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#berfSuspectsTool .evidence-chip42X button{border:0;background:transparent;color:#f4b0b0;cursor:pointer;padding:0}\n#berfSuspectsTool .evidence-table42X{display:flex;flex-wrap:wrap;gap:5px}#berfSuspectsTool .evidence-table42X button{border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.06);color:#eee;border-radius:7px;padding:5px 7px;cursor:pointer;font-size:11px}\n#berfSuspectsTool .evidence-picker42X{position:fixed;inset:0;z-index:2147483646;display:none;align-items:center;justify-content:center}#berfSuspectsTool .evidence-picker42X[data-open=\"true\"]{display:flex}#berfSuspectsTool .evidence-picker42X__backdrop{position:absolute;inset:0;background:rgba(0,0,0,.78);backdrop-filter:blur(3px)}\n#berfSuspectsTool .evidence-picker42X__dialog{position:relative;display:flex;flex-direction:column;width:min(920px,94vw);height:min(680px,88vh);overflow:hidden;border:1px solid rgba(255,255,255,.15);border-radius:15px;background:#181818;color:#eee;box-shadow:0 26px 80px rgba(0,0,0,.7)}\n#berfSuspectsTool .evidence-picker42X__head,#berfSuspectsTool .evidence-picker42X__foot{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:14px 17px;border-bottom:1px solid rgba(255,255,255,.1)}#berfSuspectsTool .evidence-picker42X__head strong{display:block;font:700 18px 'Roboto Mono',monospace}#berfSuspectsTool .evidence-picker42X__head span{display:block;margin-top:3px;color:#999;font-size:12px}#berfSuspectsTool .evidence-picker42X__head button{border:0;background:transparent;color:#fff;font-size:25px;cursor:pointer}\n#berfSuspectsTool .evidence-picker42X__body{display:grid;grid-template-columns:245px 1fr;min-height:0;flex:1}#berfSuspectsTool .evidence-picker42X__body aside{overflow:auto;padding:12px;border-right:1px solid rgba(255,255,255,.1);background:#111}#berfSuspectsTool .evidence-picker42X__body main{overflow:auto;padding:14px}\n#berfSuspectsTool .evidence-picker-folder42X{display:flex;width:100%;align-items:center;gap:8px;margin:3px 0;padding:9px 10px;border:0;border-radius:8px;background:transparent;color:#ccc;text-align:left;cursor:pointer}#berfSuspectsTool .evidence-picker-folder42X:hover,#berfSuspectsTool .evidence-picker-folder42X.active{background:rgba(175,50,50,.22);color:#fff}\n#berfSuspectsTool .evidence-picker-files42X{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px}#berfSuspectsTool .evidence-picker-file42X{position:relative;display:flex;align-items:center;gap:10px;min-height:70px;padding:11px;border:1px solid rgba(255,255,255,.1);border-radius:10px;background:rgba(255,255,255,.04);cursor:pointer}#berfSuspectsTool .evidence-picker-file42X:has(input:checked){border-color:#af3232;background:rgba(175,50,50,.17)}#berfSuspectsTool .evidence-picker-file42X input{accent-color:#af3232}#berfSuspectsTool .evidence-picker-file42X i{font-size:22px;color:#d06a6a}#berfSuspectsTool .evidence-picker-file42X span{min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:12px}\n#berfSuspectsTool .evidence-picker42X__foot{border-top:1px solid rgba(255,255,255,.1);border-bottom:0}#berfSuspectsTool .evidence-picker42X__foot>span{color:#bbb;font-size:12px}#berfSuspectsTool .evidence-picker42X__foot>div{display:flex;gap:8px}\n@media(max-width:700px){#berfSuspectsTool .evidence-picker42X__body{grid-template-columns:1fr;grid-template-rows:auto 1fr}#berfSuspectsTool .evidence-picker42X__body aside{display:flex;gap:5px;border-right:0;border-bottom:1px solid rgba(255,255,255,.1)}#berfSuspectsTool .evidence-picker-folder42X{width:auto;white-space:nowrap}}\n#berfSuspectsTool .form-control42X:focus{\n  border-color:rgba(214,83,71,.70) !important;\n  box-shadow:0 0 0 2px rgba(214,83,71,.12) !important;\n}\n#berfSuspectsTool .modal-footer42X{\n  display:flex !important;\n  justify-content:flex-end !important;\n  gap:10px !important;\n  margin-top:14px !important;\n}\n#berfSuspectsTool .modal-footer42X .btn42X{\n  min-width:136px !important;\n  height:38px !important;\n  padding:0 14px !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  border-radius:0 !important;\n  background:rgba(18,15,15,.74) !important;\n  color:#efd8bd !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.11em !important;\n  text-transform:uppercase !important;\n}\n#berfSuspectsTool .modal-footer42X .btn42X[type=\"submit\"],\n#berfSuspectsTool .modal-footer42X .btn42X:last-child{\n  border-color:rgba(214,83,71,.70) !important;\n  background:linear-gradient(180deg, rgba(121,33,31,.96), rgba(78,19,19,.96)) !important;\n  color:#fff2df !important;\n}\n#berfSuspectsTool .warning-message42X{\n  margin-top:8px !important;\n  color:#d65347 !important;\n  font-size:12px !important;\n  text-align:left !important;\n}\n#berfSuspectsTool .success-message42X,\n#berfSuspectsTool .error-message42X{\n  border-radius:0 !important;\n  margin-top:10px !important;\n  padding:10px 12px !important;\n  font:700 12px\/1.3 \"Segoe UI\", Arial, sans-serif !important;\n}\n#berfSuspectsTool .loader42X{\n  border:3px solid rgba(214,176,133,.22) !important;\n  border-top-color:#d65347 !important;\n}\n#berfSuspectsTool .log-container42X{\n  position:absolute !important;\n  right:24px !important;\n  bottom:18px !important;\n  width:min(420px, 36vw) !important;\n  max-height:112px !important;\n  margin:0 !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.18) !important;\n  background:rgba(0,0,0,.46) !important;\n  color:#d65347 !important;\n  font:600 11px\/1.35 \"Segoe UI\", Arial, sans-serif !important;\n}\n\n@media (max-width: 980px){\n  #berfDesk #berf-oc-suspects .berf-oc__main{\n    width:94vw !important;\n    height:88dvh !important;\n  }\n  #berfSuspectsTool .container42X h1{\n    padding-right:24px !important;\n    font-size:20px !important;\n  }\n  #berfSuspectsTool #btnNewSuspect42X{\n    position:static !important;\n    width:calc(100% - 48px) !important;\n    margin:12px 24px 0 !important;\n  }\n  #berfSuspectsTool .container42X{\n    grid-template-rows:132px minmax(0,1fr) !important;\n  }\n  #berfSuspectsTool .suspect-table42X{\n    display:block !important;\n    overflow:auto !important;\n  }\n  #berfSuspectsTool .log-container42X{\n    display:none !important;\n  }\n}\n\n\/* Crypto tool immersive BERF UI *\/\n#berfDesk #berf-oc-crypto .berf-oc__main{\n  width:min(1240px, 86vw) !important;\n  height:78dvh !important;\n  max-height:820px !important;\n  top:50% !important;\n  right:auto !important;\n  left:50% !important;\n  transform:translate(-50%, -50%) !important;\n  overflow:hidden !important;\n  border:1px solid rgba(214,176,133,.32) !important;\n  background:#0b0a0a !important;\n  box-shadow:0 28px 90px rgba(0,0,0,.72), 0 0 0 1px rgba(170,54,46,.18) inset !important;\n}\n#berfDesk #berf-oc-crypto .berf-oc__top{\n  height:58px !important;\n  min-height:58px !important;\n  padding:0 18px !important;\n  border-bottom:1px solid rgba(214,176,133,.22) !important;\n  background:linear-gradient(180deg, rgba(24,21,20,.98), rgba(11,10,10,.96)) !important;\n}\n#berfDesk #berf-oc-crypto .berf-oc__title{\n  color:#f6dec0 !important;\n  font:800 14px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfDesk #berf-oc-crypto .berf-oc__title i{\n  color:#d65347 !important;\n  margin-right:10px !important;\n}\n#berfDesk #berf-oc-crypto .berf-oc__close{\n  width:34px !important;\n  height:34px !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.26) !important;\n  background:rgba(0,0,0,.24) !important;\n  color:#efd8bd !important;\n}\n#berfCryptoTool{\n  height:calc(78dvh - 58px) !important;\n  min-height:0 !important;\n  padding:0 !important;\n  overflow:hidden !important;\n  display:grid !important;\n  grid-template-rows:86px minmax(0,1fr) !important;\n  color:#efd8bd !important;\n  background:\n    linear-gradient(90deg, rgba(214,176,133,.035) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(214,176,133,.028) 1px, transparent 1px),\n    radial-gradient(circle at 50% 0%, rgba(176,51,50,.18), transparent 36%),\n    #0b0a0a !important;\n  background-size:34px 34px, 34px 34px, auto, auto !important;\n}\n#berfCryptoTool .mode-indicator01{\n  height:86px !important;\n  margin:0 !important;\n  padding:22px 28px 0 !important;\n  display:flex !important;\n  align-items:flex-start !important;\n  justify-content:space-between !important;\n  border-radius:0 !important;\n  border-bottom:1px solid rgba(214,176,133,.20) !important;\n  background:transparent !important;\n  color:#f6dec0 !important;\n  font:700 28px\/1.05 Georgia, \"Times New Roman\", serif !important;\n  letter-spacing:.03em !important;\n  text-align:left !important;\n  text-transform:uppercase !important;\n}\n#berfCryptoTool .mode-indicator01::before{\n  content:\"Transmission D-174\";\n  position:absolute;\n  left:28px;\n  top:18px;\n  color:#d65347;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif;\n  letter-spacing:.16em;\n}\n#berfCryptoTool .mode-indicator01::after{\n  content:\"Cle alphabetique BERF - 3 caracteres\";\n  align-self:flex-start;\n  margin-top:8px;\n  color:#b8a899;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif;\n  letter-spacing:.12em;\n}\n#berfCryptoTool .encrypt-mode01{\n  box-shadow:inset 4px 0 0 #d65347 !important;\n}\n#berfCryptoTool .decrypt-mode01{\n  box-shadow:inset 4px 0 0 #72b37b !important;\n}\n#berfCryptoTool .container01{\n  min-height:0 !important;\n  margin:0 !important;\n  padding:24px 28px 28px !important;\n  display:grid !important;\n  grid-template-columns:minmax(0,1fr) 70px minmax(0,1fr) !important;\n  gap:18px !important;\n  align-items:stretch !important;\n}\n#berfCryptoTool .column01{\n  width:auto !important;\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-rows:auto 42px auto minmax(0,1fr) !important;\n  gap:10px !important;\n  padding:18px !important;\n  border:1px solid rgba(214,176,133,.18) !important;\n  background:rgba(11,10,10,.58) !important;\n}\n#berfCryptoTool .column01:first-child::before,\n#berfCryptoTool .column01:last-child::before{\n  display:block !important;\n  margin-bottom:2px !important;\n  color:#d65347 !important;\n  font:800 11px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.16em !important;\n  text-transform:uppercase !important;\n}\n#berfCryptoTool .column01:first-child::before{\n  content:\"Message source\";\n}\n#berfCryptoTool .column01:last-child::before{\n  content:\"Sortie calculee\";\n}\n#berfCryptoTool label{\n  margin:0 !important;\n  color:#b8a899 !important;\n  font:800 11px\/1.2 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfCryptoTool input,\n#berfCryptoTool textarea{\n  width:100% !important;\n  min-width:0 !important;\n  margin:0 !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  border-radius:0 !important;\n  background:rgba(5,5,6,.74) !important;\n  color:#f6dec0 !important;\n  padding:12px 14px !important;\n  font:600 14px\/1.45 \"Segoe UI\", Arial, sans-serif !important;\n  outline:none !important;\n  resize:none !important;\n}\n#berfCryptoTool input:focus,\n#berfCryptoTool textarea:focus{\n  border-color:rgba(214,83,71,.70) !important;\n  box-shadow:0 0 0 2px rgba(214,83,71,.12) !important;\n}\n#berfCryptoTool #key01{\n  height:42px !important;\n  max-width:180px !important;\n  color:#fff2df !important;\n  font:800 18px\/1 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.28em !important;\n  text-transform:uppercase !important;\n}\n#berfCryptoTool #message01,\n#berfCryptoTool #output01{\n  min-height:0 !important;\n  height:100% !important;\n  overflow:auto !important;\n}\n#berfCryptoTool #output01{\n  padding-right:52px !important;\n  color:#f6dec0 !important;\n  font:700 16px\/1.55 \"Segoe UI\", Arial, sans-serif !important;\n  background:\n    linear-gradient(180deg, rgba(94,24,23,.16), transparent 34%),\n    rgba(5,5,6,.78) !important;\n}\n#berfCryptoTool .center-button01{\n  min-width:0 !important;\n  min-height:0 !important;\n  display:grid !important;\n  place-items:center !important;\n}\n#berfCryptoTool .switch-button01{\n  width:54px !important;\n  height:54px !important;\n  display:grid !important;\n  place-items:center !important;\n  padding:0 !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,83,71,.66) !important;\n  background:linear-gradient(180deg, rgba(121,33,31,.96), rgba(78,19,19,.96)) !important;\n  color:#fff2df !important;\n  font-size:19px !important;\n  box-shadow:0 14px 28px rgba(0,0,0,.32) !important;\n}\n#berfCryptoTool .switch-button01:hover{\n  background:linear-gradient(180deg, rgba(154,45,40,.98), rgba(101,25,23,.98)) !important;\n}\n#berfCryptoTool .copy-button01{\n  right:12px !important;\n  bottom:12px !important;\n  width:36px !important;\n  height:36px !important;\n  display:grid !important;\n  place-items:center !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  border-radius:0 !important;\n  background:rgba(0,0,0,.32) !important;\n  color:#efd8bd !important;\n  font-size:15px !important;\n}\n#berfCryptoTool .copy-button01:hover{\n  border-color:rgba(214,83,71,.70) !important;\n  color:#fff2df !important;\n}\n#berfCryptoTool .toast{\n  min-width:220px !important;\n  border-radius:0 !important;\n  border:1px solid rgba(214,176,133,.24) !important;\n  background:rgba(9,8,8,.96) !important;\n  color:#f6dec0 !important;\n  font:800 12px\/1.35 \"Segoe UI\", Arial, sans-serif !important;\n  letter-spacing:.05em !important;\n  box-shadow:0 18px 50px rgba(0,0,0,.50) !important;\n}\n\n@media (max-width: 900px){\n  #berfDesk #berf-oc-crypto .berf-oc__main{\n    width:94vw !important;\n    height:88dvh !important;\n  }\n  #berfCryptoTool{\n    height:calc(88dvh - 58px) !important;\n  }\n  #berfCryptoTool .mode-indicator01{\n    font-size:20px !important;\n  }\n  #berfCryptoTool .mode-indicator01::after{\n    display:none !important;\n  }\n  #berfCryptoTool .container01{\n    grid-template-columns:1fr !important;\n    grid-template-rows:minmax(0,1fr) 54px minmax(0,1fr) !important;\n  }\n  #berfCryptoTool .center-button01{\n    place-items:center !important;\n  }\n}\n\n\/* File manager immersive BERF UI *\/\n#berfDesk #berf-oc-filemanager .berf-oc__main{\n  width:min(1320px, 88vw) !important;\n  height:min(780px, 86dvh) !important;\n  max-height:86dvh !important;\n  margin:auto !important;\n  inset:0 !important;\n  border-radius:4px !important;\n  border:1px solid rgba(239,209,179,.28) !important;\n  background:\n    linear-gradient(rgba(239,209,179,.026) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.02) 1px, transparent 1px),\n    radial-gradient(circle at 22% 0%, rgba(176,51,50,.18), transparent 34%),\n    linear-gradient(180deg, rgba(22,21,22,.98), rgba(8,8,9,.98)) !important;\n  background-size:32px 32px,32px 32px,100% 100%,100% 100% !important;\n  box-shadow:0 30px 90px rgba(0,0,0,.66), inset 0 1px 0 rgba(239,209,179,.08) !important;\n  overflow:hidden !important;\n}\n#berfDesk #berf-oc-filemanager .berf-oc__top{\n  min-height:58px !important;\n  padding:0 20px !important;\n  border-bottom:1px solid rgba(239,209,179,.18) !important;\n  background:linear-gradient(90deg, rgba(176,51,50,.16), rgba(11,10,11,.42)) !important;\n}\n#berfDesk #berf-oc-filemanager .berf-oc__title{\n  font-family:Georgia, \"Times New Roman\", serif !important;\n  font-size:22px !important;\n  letter-spacing:.055em !important;\n  text-transform:uppercase !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk #berf-oc-filemanager .berf-oc__title i{\n  color:var(--berf-red) !important;\n  filter:drop-shadow(0 0 10px rgba(176,51,50,.34)) !important;\n}\n#berfDesk #berf-oc-filemanager .berf-oc__body{\n  height:calc(100% - 58px) !important;\n  padding:16px !important;\n  overflow:hidden !important;\n}\n#berfDesk #berfFileManagerTool.berf-filemanager{\n  height:100% !important;\n  min-height:0 !important;\n  display:grid !important;\n  grid-template-columns:300px minmax(0, 1fr) !important;\n  gap:0 !important;\n  border:1px solid rgba(239,209,179,.20) !important;\n  border-radius:3px !important;\n  background:\n    linear-gradient(rgba(239,209,179,.02) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.018) 1px, transparent 1px),\n    rgba(10,9,10,.84) !important;\n  background-size:28px 28px !important;\n  overflow:hidden !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__sidebar,\n#berfDesk #berfFileManagerTool .berf-filemanager__main{\n  border:0 !important;\n  border-radius:0 !important;\n  min-height:0 !important;\n  background:transparent !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__sidebar{\n  border-right:1px solid rgba(239,209,179,.18) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__sidebarHead{\n  padding:18px !important;\n  border-bottom:1px solid rgba(239,209,179,.14) !important;\n  background:linear-gradient(180deg, rgba(239,209,179,.045), rgba(0,0,0,.08)) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__sidebarTitle,\n#berfDesk #berfFileManagerTool .berf-filemanager__folderhead h3,\n#berfDesk #berfFileManagerTool .berf-filemanager__crumbs,\n#berfDesk .berf-fileviewer__title,\n#berfDesk .berf-filelockmodal__title{\n  font-family:Georgia, \"Times New Roman\", serif !important;\n  font-weight:800 !important;\n  letter-spacing:.04em !important;\n  text-transform:uppercase !important;\n  color:#fff !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__sidebarTitle{\n  font-size:20px !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__sidebarSub{\n  margin-top:6px !important;\n  font-size:11px !important;\n  letter-spacing:.16em !important;\n  text-transform:uppercase !important;\n  color:var(--berf-muted) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__folders{\n  padding:12px !important;\n  gap:8px !important;\n  scrollbar-color:rgba(239,209,179,.42) rgba(239,209,179,.08) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__folderbtn{\n  min-height:64px !important;\n  padding:11px 12px !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.12) !important;\n  border-left:3px solid transparent !important;\n  background:linear-gradient(90deg, rgba(239,209,179,.045), rgba(22,21,22,.50)) !important;\n  color:var(--berf-parchment) !important;\n  transition:border-color .16s ease, background .16s ease, transform .16s ease !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__folderbtn:hover,\n#berfDesk #berfFileManagerTool .berf-filemanager__folderbtn.is-active{\n  transform:translateX(2px) !important;\n  border-color:rgba(176,51,50,.56) !important;\n  border-left-color:var(--berf-red) !important;\n  background:linear-gradient(90deg, rgba(176,51,50,.24), rgba(42,20,22,.58)) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__foldermain i{\n  width:28px !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__foldername{\n  font-size:14px !important;\n  font-weight:800 !important;\n  letter-spacing:.02em !important;\n  color:#fff !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__foldermeta{\n  flex:0 0 auto !important;\n  margin-left:auto !important;\n  padding:4px 7px !important;\n  border:1px solid rgba(239,209,179,.14) !important;\n  background:rgba(0,0,0,.20) !important;\n  color:var(--berf-muted) !important;\n  font-size:10px !important;\n  letter-spacing:.08em !important;\n  text-transform:uppercase !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__toolbar{\n  min-height:64px !important;\n  padding:0 18px !important;\n  border:0 !important;\n  border-bottom:1px solid rgba(239,209,179,.16) !important;\n  border-radius:0 !important;\n  background:linear-gradient(180deg, rgba(239,209,179,.032), rgba(0,0,0,.12)) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__crumbs{\n  font-size:22px !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__ghost,\n#berfDesk #berfFileManagerTool .berf-filemanager__primary,\n#berfDesk .berf-fileviewer__analyze,\n#berfDesk .berf-filelockmodal .berf-filemanager__ghost,\n#berfDesk .berf-filelockmodal .berf-filemanager__primary{\n  min-height:36px !important;\n  padding:0 13px !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.20) !important;\n  font-size:12px !important;\n  font-weight:800 !important;\n  letter-spacing:.06em !important;\n  text-transform:uppercase !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__ghost,\n#berfDesk .berf-filelockmodal .berf-filemanager__ghost{\n  background:rgba(239,209,179,.06) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__primary,\n#berfDesk .berf-fileviewer__analyze,\n#berfDesk .berf-filelockmodal .berf-filemanager__primary{\n  background:linear-gradient(180deg, rgba(176,51,50,.86), rgba(111,33,36,.92)) !important;\n  color:#fff !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__stage{\n  padding:18px !important;\n  scrollbar-color:rgba(239,209,179,.44) rgba(239,209,179,.08) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__folderhead{\n  margin:0 0 16px !important;\n  padding:0 0 14px !important;\n  border:0 !important;\n  border-bottom:1px dashed rgba(239,209,179,.18) !important;\n  border-radius:0 !important;\n  background:transparent !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__folderhead h3{\n  margin:0 !important;\n  font-size:26px !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__folderhead p{\n  margin:5px 0 0 !important;\n  font-size:12px !important;\n  letter-spacing:.10em !important;\n  text-transform:uppercase !important;\n  color:var(--berf-muted) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__grid{\n  grid-template-columns:repeat(auto-fill, minmax(155px, 1fr)) !important;\n  gap:12px !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__card{\n  position:relative !important;\n  min-height:164px !important;\n  padding:16px 13px 14px !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.16) !important;\n  background:\n    linear-gradient(180deg, rgba(239,209,179,.06), rgba(0,0,0,.10)),\n    linear-gradient(145deg, rgba(35,33,35,.88), rgba(13,12,13,.88)) !important;\n  color:var(--berf-parchment) !important;\n  align-items:center !important;\n  justify-content:center !important;\n  text-align:center !important;\n  gap:10px !important;\n  overflow:hidden !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__card:before{\n  content:\"\" !important;\n  position:absolute !important;\n  inset:0 !important;\n  border-top:3px solid rgba(176,51,50,.68) !important;\n  opacity:.35 !important;\n  pointer-events:none !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__card:hover{\n  transform:translateY(-2px) !important;\n  border-color:rgba(176,51,50,.72) !important;\n  background:\n    linear-gradient(180deg, rgba(176,51,50,.18), rgba(0,0,0,.04)),\n    linear-gradient(145deg, rgba(53,36,39,.92), rgba(15,13,14,.92)) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__card i{\n  font-size:42px !important;\n  color:var(--berf-parchment) !important;\n  filter:drop-shadow(0 0 12px rgba(176,51,50,.28)) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__cardtitle{\n  width:100% !important;\n  max-width:100% !important;\n  font-family:Georgia, \"Times New Roman\", serif !important;\n  font-size:15px !important;\n  font-weight:800 !important;\n  line-height:1.2 !important;\n  letter-spacing:.02em !important;\n  color:#fff !important;\n  white-space:normal !important;\n  display:-webkit-box !important;\n  -webkit-line-clamp:2 !important;\n  -webkit-box-orient:vertical !important;\n  overflow:hidden !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__cardmeta{\n  padding:4px 8px !important;\n  border:1px solid rgba(239,209,179,.14) !important;\n  background:rgba(0,0,0,.24) !important;\n  color:var(--berf-muted) !important;\n  font-size:10px !important;\n  letter-spacing:.12em !important;\n  text-transform:uppercase !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__empty{\n  min-height:100% !important;\n  border:1px dashed rgba(239,209,179,.18) !important;\n  border-radius:2px !important;\n  background:rgba(0,0,0,.14) !important;\n  color:var(--berf-muted) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__empty i{\n  color:var(--berf-red) !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__empty strong{\n  font-family:Georgia, \"Times New Roman\", serif !important;\n  font-size:22px !important;\n  color:#fff !important;\n  text-transform:uppercase !important;\n  letter-spacing:.04em !important;\n}\n#berfDesk .berf-fileviewer,\n#berfDesk .berf-filelockmodal{\n  position:absolute !important;\n  inset:0 !important;\n  z-index:80 !important;\n}\n#berfDesk .berf-fileviewer__backdrop,\n#berfDesk .berf-filelockmodal__backdrop{\n  background:rgba(0,0,0,.74) !important;\n  backdrop-filter:blur(6px) !important;\n}\n#berfDesk .berf-fileviewer__dialog{\n  width:min(1120px, calc(100% - 48px)) !important;\n  height:min(760px, calc(100% - 48px)) !important;\n  max-height:calc(100% - 48px) !important;\n  border-radius:3px !important;\n  border:1px solid rgba(239,209,179,.26) !important;\n  background:\n    linear-gradient(rgba(239,209,179,.024) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.018) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(22,21,22,.98), rgba(7,7,8,.98)) !important;\n  background-size:30px 30px,30px 30px,100% 100% !important;\n  box-shadow:0 30px 90px rgba(0,0,0,.70) !important;\n}\n#berfDesk .berf-fileviewer__head,\n#berfDesk .berf-filelockmodal__head{\n  min-height:58px !important;\n  padding:0 16px 0 20px !important;\n  border-bottom:1px solid rgba(239,209,179,.18) !important;\n  background:linear-gradient(90deg, rgba(176,51,50,.16), rgba(239,209,179,.025)) !important;\n}\n#berfDesk .berf-fileviewer__title,\n#berfDesk .berf-filelockmodal__title{\n  font-size:21px !important;\n}\n#berfDesk .berf-fileviewer__body{\n  height:calc(100% - 58px) !important;\n  max-height:none !important;\n  padding:18px !important;\n  align-items:stretch !important;\n  justify-content:center !important;\n  background:rgba(0,0,0,.12) !important;\n}\n#berfDesk .berf-fileviewer__body iframe,\n#berfDesk .berf-fileviewer__body video,\n#berfDesk .berf-fileviewer__body img{\n  min-height:0 !important;\n  width:100% !important;\n  height:100% !important;\n  max-height:none !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.16) !important;\n  background:#050505 !important;\n  object-fit:contain !important;\n}\n#berfDesk .berf-fileviewer__body audio{\n  align-self:center !important;\n  max-width:620px !important;\n  border-radius:2px !important;\n  background:rgba(239,209,179,.08) !important;\n}\n#berfDesk .berf-fileviewer__close,\n#berfDesk .berf-filelockmodal__close{\n  width:38px !important;\n  height:38px !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.20) !important;\n  background:rgba(239,209,179,.06) !important;\n  color:var(--berf-parchment) !important;\n  line-height:1 !important;\n}\n#berfDesk .berf-filelockmodal__dialog{\n  width:min(520px, calc(100% - 48px)) !important;\n  border-radius:3px !important;\n  border:1px solid rgba(239,209,179,.26) !important;\n  background:linear-gradient(180deg, rgba(28,25,26,.98), rgba(9,8,9,.98)) !important;\n  box-shadow:0 30px 90px rgba(0,0,0,.72) !important;\n}\n#berfDesk .berf-filelockmodal__body{\n  padding:20px !important;\n}\n#berfDesk .berf-filelockmodal__text{\n  margin-bottom:16px !important;\n  color:var(--berf-muted) !important;\n  line-height:1.5 !important;\n}\n#berfDesk .berf-filelockmodal__body label{\n  color:var(--berf-parchment) !important;\n  font-size:12px !important;\n  letter-spacing:.10em !important;\n  text-transform:uppercase !important;\n}\n#berfDesk .berf-filelockmodal__body input{\n  height:42px !important;\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:rgba(0,0,0,.28) !important;\n  color:#fff !important;\n}\n#berfDesk .berf-filelockmodal__error{\n  border-radius:2px !important;\n  border:1px solid rgba(176,51,50,.45) !important;\n  background:rgba(176,51,50,.16) !important;\n  color:#ffd1ca !important;\n}\n#berfDesk #berfFileManagerTool .berf-filemanager__textdoc,\n#berfDesk .berf-fileviewer__body .berf-filemanager__textdoc{\n  width:min(820px, 100%) !important;\n  max-height:100% !important;\n  border-radius:2px !important;\n  border:1px solid rgba(67,45,30,.24) !important;\n  background:#efe1cc !important;\n  color:#191312 !important;\n}\n@media (max-width: 980px){\n  #berfDesk #berf-oc-filemanager .berf-oc__main{\n    width:94vw !important;\n    height:88dvh !important;\n  }\n  #berfDesk #berfFileManagerTool.berf-filemanager{\n    grid-template-columns:1fr !important;\n    grid-template-rows:220px minmax(0, 1fr) !important;\n  }\n  #berfDesk #berfFileManagerTool .berf-filemanager__sidebar{\n    border-right:0 !important;\n    border-bottom:1px solid rgba(239,209,179,.18) !important;\n  }\n  #berfDesk #berfFileManagerTool .berf-filemanager__folders{\n    flex-direction:row !important;\n    overflow-x:auto !important;\n  }\n  #berfDesk #berfFileManagerTool .berf-filemanager__folderbtn{\n    min-width:260px !important;\n  }\n  #berfDesk #berfFileManagerTool .berf-filemanager__toolbar{\n    flex-wrap:wrap !important;\n    padding:10px 12px !important;\n  }\n  #berfDesk #berfFileManagerTool .berf-filemanager__crumbs{\n    flex-basis:100% !important;\n    order:-1 !important;\n    font-size:18px !important;\n  }\n}\n\n\/* Calculator standalone opening *\/\n#berfDesk #berf-oc-calculator{\n  pointer-events:none !important;\n}\n#berfDesk #berf-oc-calculator[data-open=\"true\"]{\n  display:flex !important;\n  align-items:center !important;\n  justify-content:center !important;\n  pointer-events:auto !important;\n}\n#berfDesk #berf-oc-calculator .berf-oc__overlay{\n  background:rgba(0,0,0,.28) !important;\n  backdrop-filter:blur(2px) !important;\n}\n#berfDesk #berf-oc-calculator .berf-oc__main{\n  position:relative !important;\n  top:auto !important;\n  right:auto !important;\n  bottom:auto !important;\n  left:auto !important;\n  width:auto !important;\n  height:auto !important;\n  min-width:0 !important;\n  max-width:none !important;\n  max-height:none !important;\n  border:0 !important;\n  border-radius:0 !important;\n  background:transparent !important;\n  box-shadow:none !important;\n  transform:none !important;\n  overflow:visible !important;\n  pointer-events:none !important;\n}\n#berfDesk #berf-oc-calculator .berf-oc__top{\n  position:absolute !important;\n  top:-14px !important;\n  right:-14px !important;\n  z-index:2 !important;\n  width:auto !important;\n  height:auto !important;\n  min-height:0 !important;\n  padding:0 !important;\n  border:0 !important;\n  background:transparent !important;\n}\n#berfDesk #berf-oc-calculator .berf-oc__title{\n  display:none !important;\n}\n#berfDesk #berf-oc-calculator .berf-oc__close{\n  width:34px !important;\n  height:34px !important;\n  border-radius:50% !important;\n  border:1px solid rgba(239,209,179,.36) !important;\n  background:linear-gradient(180deg, rgba(176,51,50,.94), rgba(111,33,36,.96)) !important;\n  color:#fff !important;\n  box-shadow:0 10px 28px rgba(0,0,0,.45) !important;\n  pointer-events:auto !important;\n}\n#berfDesk #berf-oc-calculator .berf-oc__body{\n  width:auto !important;\n  height:auto !important;\n  min-height:0 !important;\n  padding:0 !important;\n  overflow:visible !important;\n  background:transparent !important;\n  pointer-events:none !important;\n}\n#berfDesk #berf-oc-calculator #berfCalcTool{\n  width:360px !important;\n  max-width:calc(100vw - 44px) !important;\n  margin:0 !important;\n  padding:16px !important;\n  border-radius:4px !important;\n  border:1px solid rgba(239,209,179,.28) !important;\n  background:\n    linear-gradient(rgba(239,209,179,.026) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.02) 1px, transparent 1px),\n    linear-gradient(180deg, rgba(29,27,28,.98), rgba(8,8,9,.98)) !important;\n  background-size:28px 28px,28px 28px,100% 100% !important;\n  box-shadow:0 26px 70px rgba(0,0,0,.68), inset 0 1px 0 rgba(239,209,179,.08) !important;\n  pointer-events:auto !important;\n}\n#berfDesk #berf-oc-calculator #berfCalcTool:before{\n  content:\"Calculatrice securisee\";\n  display:block;\n  margin:0 0 12px;\n  color:var(--berf-parchment);\n  font:800 12px\/1 \"Segoe UI\", Arial, sans-serif;\n  letter-spacing:.14em;\n  text-transform:uppercase;\n}\n#berfDesk #berf-oc-calculator .berf-calc__screenWrap{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:rgba(0,0,0,.26) !important;\n}\n#berfDesk #berf-oc-calculator .berf-calc__screen{\n  border-radius:2px !important;\n  background:#efe1cc !important;\n  color:#151111 !important;\n}\n#berfDesk #berf-oc-calculator .berf-calc__keys button{\n  border-radius:2px !important;\n  border:1px solid rgba(239,209,179,.18) !important;\n  background:linear-gradient(180deg, rgba(58,58,59,.56), rgba(22,21,22,.86)) !important;\n  color:var(--berf-parchment) !important;\n}\n#berfDesk #berf-oc-calculator .berf-calc__keys button:hover{\n  border-color:rgba(239,209,179,.32) !important;\n  background:linear-gradient(180deg, rgba(83,57,62,.62), rgba(42,20,22,.86)) !important;\n}\n#berfDesk #berf-oc-calculator .berf-calc__keys button.is-equals{\n  border-color:rgba(239,209,179,.28) !important;\n  background:linear-gradient(180deg, rgba(176,51,50,.86), rgba(111,33,36,.92)) !important;\n  color:#fff !important;\n}\n@media (max-width: 560px){\n  #berfDesk #berf-oc-calculator #berfCalcTool{\n    width:calc(100vw - 34px) !important;\n  }\n}\n\n\/* Triangulation local fallback map *\/\n#berfDesk #berfTriangulation77 .tri77__map--fallback{\n  background:#080707 !important;\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackMap{\n  position:relative;\n  width:100%;\n  height:100%;\n  min-height:320px;\n  overflow:hidden;\n  background:\n    radial-gradient(circle at 50% 50%, rgba(176,51,50,.20), transparent 28%),\n    linear-gradient(rgba(239,209,179,.045) 1px, transparent 1px),\n    linear-gradient(90deg, rgba(239,209,179,.035) 1px, transparent 1px),\n    #080707;\n  background-size:100% 100%, 34px 34px, 34px 34px, 100% 100%;\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackGrid{\n  position:absolute;\n  inset:-40%;\n  opacity:.28;\n  background:\n    repeating-radial-gradient(circle at 50% 50%, transparent 0 58px, rgba(239,209,179,.28) 59px 60px),\n    linear-gradient(30deg, transparent 48%, rgba(239,209,179,.20) 49%, rgba(239,209,179,.20) 51%, transparent 52%),\n    linear-gradient(150deg, transparent 48%, rgba(239,209,179,.16) 49%, rgba(239,209,179,.16) 51%, transparent 52%);\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackScan{\n  position:absolute;\n  left:50%;\n  top:50%;\n  width:42%;\n  height:2px;\n  transform-origin:left center;\n  background:linear-gradient(90deg, rgba(176,51,50,.9), transparent);\n  animation:tri77Scan 3.6s linear infinite;\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackPulse{\n  position:absolute;\n  left:50%;\n  top:50%;\n  width:120px;\n  height:120px;\n  margin:-60px 0 0 -60px;\n  border:1px solid rgba(176,51,50,.75);\n  border-radius:999px;\n  animation:tri77Pulse 2.4s ease-out infinite;\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackPulse--two{\n  animation-delay:.75s;\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackPin{\n  position:absolute;\n  left:50%;\n  top:50%;\n  transform:translate(-50%, -100%);\n  color:#ff6a5e;\n  font-size:34px;\n  filter:drop-shadow(0 0 14px rgba(176,51,50,.78));\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackReadout{\n  position:absolute;\n  left:16px;\n  right:16px;\n  bottom:14px;\n  display:grid;\n  gap:4px;\n  padding:12px 14px;\n  border:1px solid rgba(239,209,179,.20);\n  background:rgba(8,7,7,.78);\n  color:var(--berf-parchment);\n  backdrop-filter:blur(5px);\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackReadout b{\n  color:#fff;\n  font:800 13px\/1.2 \"Segoe UI\", Arial, sans-serif;\n  letter-spacing:.10em;\n  text-transform:uppercase;\n}\n#berfDesk #berfTriangulation77 .tri77__fallbackReadout span,\n#berfDesk #berfTriangulation77 .tri77__fallbackReadout em{\n  color:var(--berf-muted);\n  font-size:12px;\n  font-style:normal;\n}\n@keyframes tri77Scan{\n  from{ transform:rotate(0deg); }\n  to{ transform:rotate(360deg); }\n}\n@keyframes tri77Pulse{\n  0%{ transform:scale(.45); opacity:.9; }\n  100%{ transform:scale(2.6); opacity:0; }\n}\n\n<\/style>\n<script src=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.js\"><\/script>\n<script>\n(function(){\n  const desk = document.getElementById(\"berfDesk\");\n  if(!desk) return;\n\n  \/* =========================================================\n     START MENU (taskbar) \u2014 toggle + liens vers outils\n     ========================================================= *\/\n  (function(){\n    if(window.__BERF_STARTMENU_INIT__) return;\n    window.__BERF_STARTMENU_INIT__ = true;\n\n    const startButton = desk.querySelector(\"#startButton\");\n    const startMenu   = desk.querySelector(\"#startMenu\");\n    const powerButton = desk.querySelector(\"#powerButton\");\n    if(!startButton || !startMenu) return;\n\n    function showMenu(){\n      startMenu.style.display = \"block\";\n      startMenu.setAttribute(\"aria-hidden\",\"false\");\n      requestAnimationFrame(()=> startMenu.classList.add(\"show\"));\n    }\n    function hideMenu(){\n      startMenu.classList.remove(\"show\");\n      startMenu.setAttribute(\"aria-hidden\",\"true\");\n      setTimeout(()=>{ startMenu.style.display = \"none\"; }, 220);\n    }\n    function toggleMenu(){\n      if(startMenu.classList.contains(\"show\")) hideMenu();\n      else showMenu();\n    }\n\n    startButton.addEventListener(\"click\", (e)=>{\n      e.stopPropagation();\n      toggleMenu();\n    });\n\n    \/\/ Fermer si clic en dehors\n    window.addEventListener(\"click\", (e)=>{\n      if(!startButton.contains(e.target) && !startMenu.contains(e.target)){\n        if(startMenu.classList.contains(\"show\")) hideMenu();\n      }\n    });\n\n    \/\/ ESC ferme le start menu uniquement s\u2019il est ouvert\n    window.addEventListener(\"keydown\",(e)=>{\n      if(e.key === \"Escape\" && startMenu.classList.contains(\"show\")){\n        hideMenu();\n      }\n    });\n\n    \/\/ Liens Start => ouvre tes off-canvas via le bouton correspondant\n    startMenu.querySelectorAll(\"[data-berf-open]\").forEach(link=>{\n      link.addEventListener(\"click\", ()=>{\n        const name = link.getAttribute(\"data-berf-open\");\n        hideMenu();\n        const btn = desk.querySelector(`[data-open-oc=\"${name}\"]`);\n        if(btn) btn.click();\n      });\n    });\n\n    \/\/ Bouton power\n    if(powerButton){\n      powerButton.addEventListener(\"click\", ()=>{\n        const confirmation = confirm(\"Voulez-vous vraiment arr\u00eater l'enqu\u00eate ?\");\n        if(confirmation){\n          window.location.href = \"https:\/\/lultime-frisson.com\/\";\n        }else{\n          alert(\"L'enqu\u00eate continue !\");\n        }\n      });\n    }\n\n    \/\/ Expose un petit helper interne pour Tennis (sans changer le reste)\n    window.__BERF_HIDE_START_MENU = hideMenu;\n  })();\n\n  \/* ===== Off-canvas open\/close ===== *\/\n  function syncOCState(){\n    try{\n      const hasOpen = !!desk.querySelector('.berf-oc[data-open=\"true\"], .berf-oc[aria-hidden=\"false\"]');\n      if(hasOpen){\n        desk.setAttribute('data-berf-oc-open', 'true');\n      }else{\n        desk.removeAttribute('data-berf-oc-open');\n      }\n    }catch(e){ console.warn(e); }\n  }\n\n  function openOC(name){\n    const oc = desk.querySelector(\"#berf-oc-\" + name);\n    if(!oc) return;\n    oc.setAttribute(\"data-open\",\"true\");\n    oc.setAttribute(\"aria-hidden\",\"false\");\n    syncOCState();\n    if(name === \"filemanager\"){\n      try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger(\"open_file_manager\", \"filemanager\", { id:\"filemanager\" }); }catch(e){}\n    }\n  }\n  function closeOC(oc){\n    oc.removeAttribute(\"data-open\");\n    oc.setAttribute(\"aria-hidden\",\"true\");\n    syncOCState();\n  }\n  desk.querySelectorAll(\"[data-open-oc]\").forEach(btn=>{\n    btn.addEventListener(\"click\", ()=> openOC(btn.getAttribute(\"data-open-oc\")));\n  });\n  desk.querySelectorAll(\".berf-oc\").forEach(oc=>{\n    oc.querySelectorAll(\"[data-close]\").forEach(el=>{\n      el.addEventListener(\"click\", ()=> closeOC(oc));\n    });\n  });\n\n  window.BERF_ANALYZE_IMAGE_FROM_URL = async function(url, name){\n    try{\n      if(!url) return false;\n      try{\n        desk.querySelectorAll('.berf-oc[data-open=\"true\"], .berf-oc[aria-hidden=\"false\"]').forEach(oc=>{\n          try{ closeOC(oc); }catch(_){}\n        });\n      }catch(_){}\n      if(typeof openOC === 'function') openOC('imgtool');\n      if(window.BERF_IMGTOOL_IMPORT_URL){\n        await window.BERF_IMGTOOL_IMPORT_URL(url, name || 'evidence-image');\n        return true;\n      }\n      return false;\n    }catch(e){\n      console.warn('BERF_ANALYZE_IMAGE_FROM_URL failed', e);\n      return false;\n    }\n  };\n  window.addEventListener(\"keydown\",(e)=>{\n    if(e.key === \"Escape\"){\n      const open = desk.querySelector('.berf-oc[data-open=\"true\"]');\n      if(open) closeOC(open);\n    }\n  });\n\n  syncOCState();\n\n  try{\n    const ocObserver = new MutationObserver(() => syncOCState());\n    desk.querySelectorAll('.berf-oc').forEach(oc => {\n      ocObserver.observe(oc, { attributes: true });\n    });\n  }catch(e){ console.warn(e); }\n\n  try{\n    window.addEventListener('click', () => { window.setTimeout(syncOCState, 40); }, { passive: true });\n    window.addEventListener('touchend', () => { window.setTimeout(syncOCState, 40); }, { passive: true });\n    window.setInterval(syncOCState, 400);\n  }catch(e){ console.warn(e); }\n\n\n  \/* ===== Tablet viewport fix ===== *\/\n  (function(){\n    try{\n      const applyViewportVars = function(){\n        const h = window.innerHeight || document.documentElement.clientHeight || 0;\n        document.documentElement.style.setProperty('--berf-vh', (h * 0.01) + 'px');\n        if(window.innerWidth <= 1024){\n          desk.setAttribute('data-berf-tablet', 'true');\n        }else{\n          desk.removeAttribute('data-berf-tablet');\n        }\n      };\n      applyViewportVars();\n      window.addEventListener('resize', applyViewportVars, { passive: true });\n      window.addEventListener('orientationchange', applyViewportVars, { passive: true });\n    }catch(e){ console.warn(e); }\n  })();\n\n\n  \/* ===== Tablet runtime helper ===== *\/\n  (function(){\n    try{\n      const applyTabletClass = function(){\n        if(window.innerWidth <= 1024){\n          desk.setAttribute('data-berf-tablet', 'true');\n        }else{\n          desk.removeAttribute('data-berf-tablet');\n        }\n      };\n      applyTabletClass();\n      window.addEventListener('resize', applyTabletClass, { passive: true });\n      window.addEventListener('orientationchange', applyTabletClass, { passive: true });\n    }catch(e){ console.warn(e); }\n  })();\n\n\n\n\n  \/* =========================================================\n     GLOBAL NOTIFICATION CENTER\n     ========================================================= *\/\n  (function(){\n    const KEY = 'berf_notifications_center_v1';\n\n    function load(){\n      try{\n        const raw = localStorage.getItem(KEY);\n        const parsed = raw ? JSON.parse(raw) : null;\n        if(parsed && typeof parsed === 'object'){\n          if(!Array.isArray(parsed.items)) parsed.items = [];\n          return parsed;\n        }\n      }catch(e){}\n      return { items: [] };\n    }\n    function save(state){ localStorage.setItem(KEY, JSON.stringify(state)); }\n\n    const btn = document.getElementById('berfNotifyBtn');\n    const badge = document.getElementById('berfNotifyBadge');\n    const drawer = document.getElementById('berfNotifyDrawer');\n    const closeBtn = document.getElementById('berfNotifyClose');\n    const list = document.getElementById('berfNotifyList');\n    const stack = document.getElementById('berfToastStack');\n\n    try{\n      if(drawer && drawer.parentNode !== document.body) document.body.appendChild(drawer);\n      if(stack && stack.parentNode !== document.body) document.body.appendChild(stack);\n    }catch(e){ console.warn(e); }\n\n    function iconFor(app){\n      if(app === 'mail') return 'fa-envelope';\n      if(app === 'evidencetool') return 'fa-layer-group';\n      if(app === 'knowledge') return 'fa-book-skull';\n      if(app === 'imgtool') return 'fa-image';\n      if(app === 'audiotool') return 'fa-wave-square';\n      if(app === 'route23') return 'fa-route';\n      return 'fa-bell';\n    }\n\n    function unreadCount(){\n      return (load().items || []).filter(x => x && !x.read).length;\n    }\n\n    function refreshBadge(){\n      const n = unreadCount();\n      if(btn) btn.setAttribute('data-unread', String(n));\n      if(badge){\n        badge.textContent = String(n);\n        badge.style.display = n > 0 ? 'flex' : 'none';\n      }\n    }\n\n    function openTarget(item){\n      if(!item) return;\n      if(item.app && typeof openOC === 'function'){\n        try{ openOC(item.app); }catch(e){}\n      }\n      setTimeout(()=>{\n        try{\n          if(item.app === 'mail' && item.targetId && window.BERF_MAIL && window.BERF_MAIL.openById){\n            window.BERF_MAIL.openById(item.targetId);\n          } else if(item.app === 'evidencetool' && item.targetId && window.BERF_EVID_OPEN){\n            window.BERF_EVID_OPEN(item.targetId);\n          } else if(item.app === 'knowledge' && item.targetId && window.BERF_KB_OPEN){\n            window.BERF_KB_OPEN(item.targetId);\n          }\n        }catch(e){ console.warn(e); }\n      }, 120);\n    }\n\n    function removeNotification(id){\n      const s = load();\n      s.items = (s.items || []).filter(x => x.id !== id);\n      save(s);\n      renderList();\n      refreshBadge();\n    }\n\n    function removeByTargets(targetIds){\n      const targets = new Set((Array.isArray(targetIds) ? targetIds : []).map(String));\n      if(!targets.size) return;\n      const s = load();\n      s.items = (s.items || []).filter(item => !item || !targets.has(String(item.targetId || '')));\n      save(s);\n      if(stack) stack.innerHTML = '';\n      renderList();\n      refreshBadge();\n    }\n\n    function clickNotification(id){\n      const s = load();\n      const item = (s.items || []).find(x => x.id === id);\n      if(!item) return;\n      openTarget(item);\n      removeNotification(id);\n      if(drawer) drawer.setAttribute('data-open', 'false');\n    }\n\n    function renderList(){\n      if(!list) return;\n      const items = (load().items || []).slice().reverse();\n      list.innerHTML = '';\n      if(!items.length){\n        list.innerHTML = '<div class=\"berf-notify-empty\">Aucune notification en attente.<\/div>';\n        return;\n      }\n      items.forEach(item => {\n        const el = document.createElement('button');\n        el.type = 'button';\n        el.className = 'berf-notify-item';\n        el.innerHTML = `\n          <div class=\"berf-notify-item__meta\"><i class=\"fa-solid ${iconFor(item.app)}\"><\/i><span>${item.source || 'BERF'}<\/span><\/div>\n          <div class=\"berf-notify-item__title\">${item.title || 'Notification'}<\/div>\n          <div class=\"berf-notify-item__text\">${item.text || ''}<\/div>\n        `;\n        el.addEventListener('click', ()=> clickNotification(item.id));\n        list.appendChild(el);\n      });\n    }\n\n    function showToast(item){\n      if(!stack) return;\n      const toast = document.createElement('div');\n      toast.className = 'berf-toast';\n      toast.innerHTML = `\n        <div class=\"berf-toast__top\">\n          <div class=\"berf-toast__icon\"><i class=\"fa-solid ${iconFor(item.app)}\"><\/i><\/div>\n          <div class=\"berf-toast__body\">\n            <div class=\"berf-toast__title\">${item.title || 'Notification'}<\/div>\n            <div class=\"berf-toast__text\">${item.text || ''}<\/div>\n          <\/div>\n        <\/div>\n        <div class=\"berf-toast__bar\"><\/div>\n      `;\n      let closed = false;\n      toast.addEventListener('click', ()=>{\n        if(closed) return;\n        closed = true;\n        clickNotification(item.id);\n        if(toast.parentNode) toast.remove();\n      });\n      stack.appendChild(toast);\n      setTimeout(()=>{\n        if(closed) return;\n        toast.style.animation = 'berfToastOut .22s ease forwards';\n        setTimeout(()=>{ if(toast.parentNode) toast.remove(); }, 220);\n      }, 6000);\n    }\n\n    function push(payload){\n      const s = load();\n      const item = {\n        id: payload.id || ('ntf_' + Date.now() + '_' + Math.random().toString(36).slice(2,7)),\n        app: payload.app || '',\n        targetId: payload.targetId || '',\n        source: payload.source || 'BERF',\n        title: payload.title || 'Notification',\n        text: payload.text || '',\n        read: false,\n        createdAt: Date.now()\n      };\n      s.items.push(item);\n      save(s);\n      renderList();\n      refreshBadge();\n      showToast(item);\n      return item;\n    }\n\n    if(btn){\n      btn.addEventListener('click', ()=>{\n        if(!drawer) return;\n        drawer.setAttribute('data-open', drawer.getAttribute('data-open') === 'true' ? 'false' : 'true');\n      });\n    }\n    if(closeBtn && drawer){\n      closeBtn.addEventListener('click', ()=> drawer.setAttribute('data-open', 'false'));\n    }\n    document.addEventListener('click', (e)=>{\n      if(!drawer || drawer.getAttribute('data-open') !== 'true') return;\n      if(drawer.contains(e.target)) return;\n      if(btn && btn.contains(e.target)) return;\n      drawer.setAttribute('data-open', 'false');\n    });\n\n    window.BERF_NOTIFY = { push, remove: removeNotification, removeByTargets, openTarget, render: renderList, refresh: refreshBadge };\n    renderList();\n    refreshBadge();\n  })();\n\n\n  \/* =========================================================\n     GLOBAL EVENT ENGINE\n     ========================================================= *\/\n  (function(){\n    const KEY = 'berf_events_state_v1';\n\n    function load(){\n      try{\n        const raw = localStorage.getItem(KEY);\n        const parsed = raw ? JSON.parse(raw) : null;\n        if(parsed && typeof parsed === 'object') return parsed;\n      }catch(e){}\n      return { flags:{}, triggered:{}, rules:[] };\n    }\n    function save(state){\n      localStorage.setItem(KEY, JSON.stringify(state));\n    }\n    function state(){\n      const s = load();\n      if(!s.flags) s.flags = {};\n      if(!s.triggered) s.triggered = {};\n      if(!Array.isArray(s.rules)) s.rules = [];\n      return s;\n    }\n    function matchRule(rule, type, target, s){\n      if(!rule || rule.trigger_type !== type) return false;\n\n      if(type === 'crypto_decryption_success'){\n        const expected = String(rule.trigger_target || '').trim().toLowerCase();\n        const received = String(target || '').trim().toLowerCase();\n        return expected === '' || expected === received;\n      }\n\n      if(type === 'flags_all'){\n        const list = String(rule.trigger_target || '')\n          .split(',')\n          .map(x => String(x || '').trim())\n          .filter(Boolean);\n        if(!list.length) return false;\n        return list.every(flag => !!(s.flags && s.flags[flag]));\n      }\n\n      if(type === 'browser_navigate'){\n        const normalizeBrowserTarget = value => String(value || '')\n          .trim()\n          .toLowerCase()\n          .replace(\/^https?:\\\/\\\/\/, '')\n          .replace(\/^www\\.\/, '')\n          .replace(\/[?#].*$\/, '')\n          .replace(\/\\\/+$\/, '');\n        return normalizeBrowserTarget(rule.trigger_target) === normalizeBrowserTarget(target);\n      }\n\n      return String(rule.trigger_target || '') === String(target || '');\n    }\n\n    function trigger(type, target, payload){\n      const s = state();\n      const rules = Array.isArray(s.rules) ? s.rules : [];\n      let dirty = false;\n\n      if(!s.triggered) s.triggered = {};\n\n      rules.forEach(rule => {\n        if(!matchRule(rule, type, target, s)) return;\n        if(rule.once !== false && s.triggered && s.triggered[rule.id]) return;\n\n        const effects = Array.isArray(rule.effects) ? rule.effects : [];\n        effects.forEach(effect => applyEffect(effect, payload));\n\n        if(rule.once !== false){\n          s.triggered[rule.id] = true;\n        }\n\n        dirty = true;\n      });\n\n      if(dirty) save(s);\n    }\n    function parseDelaySpec(target){\n      const parts = String(target || '').split('|');\n      return {\n        delay: Math.max(0, parseInt(parts[0] || '0', 10) || 0),\n        type: String(parts[1] || '').trim(),\n        target: parts.slice(2).join('|').trim()\n      };\n    }\n\n    function parseProbabilitySpec(target){\n      const parts = String(target || '').split('|');\n      let raw = String(parts[0] || '').trim();\n      let probability = 0;\n      if(raw.endsWith('%')){\n        probability = parseFloat(raw.replace('%','')) \/ 100;\n      } else {\n        probability = parseFloat(raw || '0');\n      }\n      if(!isFinite(probability)) probability = 0;\n      probability = Math.max(0, Math.min(1, probability));\n      return {\n        probability,\n        type: String(parts[1] || '').trim(),\n        target: parts.slice(2).join('|').trim()\n      };\n    }\n\n    function parseRandomSpec(target){\n      return String(target || '')\n        .split('||')\n        .map(x => String(x || '').trim())\n        .filter(Boolean)\n        .map(part => {\n          const bits = part.split('|');\n          return {\n            type: String(bits[0] || '').trim(),\n            target: bits.slice(1).join('|').trim()\n          };\n        })\n        .filter(x => x.type);\n    }\n\n    function applyEffect(effect, payload){\n      if(!effect || !effect.type) return;\n      const type = String(effect.type);\n      const target = String(effect.target || '');\n      const msg = String(effect.message || '');\n\n      if(type === 'unlock_index'){\n        if(window.BERF_EVID_ADD_ENTRY && window.BERFDB && window.BERFDB.INDEX_ALL && window.BERFDB.INDEX_ALL[target]){\n          window.BERF_EVID_ADD_ENTRY(target, window.BERFDB.INDEX_ALL[target]);\n        }\n      } else if(type === 'unlock_mail'){\n        if(window.BERF_MAIL && window.BERF_MAIL.unlockById) window.BERF_MAIL.unlockById(target);\n      } else if(type === 'receive_mail'){\n        if(window.BERF_MAIL && window.BERF_MAIL.unlockById) window.BERF_MAIL.unlockById(target);\n        if(window.BERF_NOTIFY){\n          window.BERF_NOTIFY.push({\n            app: 'mail',\n            targetId: target,\n            source: 'Bo\u00eete mail',\n            title: 'Nouveau mail re\u00e7u',\n            text: msg || 'Clique pour ouvrir la bo\u00eete mail.'\n          });\n        }\n      } else if(type === 'load_session'){\n        if(window.BERF_SESSION && window.BERF_SESSION.load) window.BERF_SESSION.load(target, msg);\n      } else if(type === 'reveal_locked_file_folder'){\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.lockFolder) window.BERF_FILE_MANAGER.lockFolder(target);\n      } else if(type === 'unlock_file_folder'){\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.unlockFolder) window.BERF_FILE_MANAGER.unlockFolder(target);\n      } else if(type === 'lock_file_folder'){\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.lockFolder) window.BERF_FILE_MANAGER.lockFolder(target);\n      } else if(type === 'open_file_manager'){\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.open) window.BERF_FILE_MANAGER.open();\n      } else if(type === 'open_file_folder'){\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.openFolder) window.BERF_FILE_MANAGER.openFolder(target, { reveal:true, unlock:false });\n      } else if(type === 'open_calculator'){\n        try{ if(typeof openOC === 'function') openOC('calculator'); }catch(e){}\n      } else if(type === 'unlock_agenda_entry'){\n        if(window.BERF_AGENDA_UNLOCK) window.BERF_AGENDA_UNLOCK(target);\n      } else if(type === 'delay_event'){\n        const spec = parseDelaySpec(target);\n        if(spec.type){\n          window.setTimeout(() => applyEffect({ type: spec.type, target: spec.target, message: msg }, payload), spec.delay);\n        }\n      } else if(type === 'probability_event'){\n        const spec = parseProbabilitySpec(target);\n        if(spec.type && Math.random() <= spec.probability){\n          applyEffect({ type: spec.type, target: spec.target, message: msg }, payload);\n        }\n      } else if(type === 'random_event'){\n        const choices = parseRandomSpec(target);\n        if(choices.length){\n          const pick = choices[Math.floor(Math.random() * choices.length)];\n          applyEffect({ type: pick.type, target: pick.target, message: msg }, payload);\n        }\n      } else if(type === 'unlock_kb_entry'){\n        try{\n          const key = 'berf_kb_unlocked_v1';\n          const current = JSON.parse(localStorage.getItem(key) || '[]');\n          const arr = Array.isArray(current) ? current : [];\n          if(!arr.includes(target)){\n            arr.push(target);\n            localStorage.setItem(key, JSON.stringify(arr));\n          }\n        }catch(e){}\n        if(window.BERF_KB_UNLOCK) window.BERF_KB_UNLOCK(target);\n      } else if(type === 'add_notification'){\n        const notifTarget = target || (payload && payload.id) || 'INFO';\n        if(window.BERF_EVID_PUSH_NOTIFICATION){\n          window.BERF_EVID_PUSH_NOTIFICATION({\n            id: notifTarget,\n            message: msg || 'Nouvelle mise \u00e0 jour disponible'\n          });\n        }\n        if(window.BERF_NOTIFY){\n          window.BERF_NOTIFY.push({\n            app: 'evidencetool',\n            targetId: notifTarget,\n            source: 'Base d\u2019indices',\n            title: 'Mise \u00e0 jour d\u00e9tect\u00e9e',\n            text: msg || 'Nouvelle mise \u00e0 jour disponible'\n          });\n        }\n      } else if(type === 'subscribe_index'){\n        if(window.BERF_EVID_SUBSCRIBE) window.BERF_EVID_SUBSCRIBE(target);\n      } else if(type === 'mark_flag'){\n        const s = state();\n        const wasSet = !!(s.flags && s.flags[target]);\n        s.flags[target] = true;\n        save(s);\n\n        if(!wasSet){\n          trigger('flag_set', target, { flag: target });\n          trigger('flags_all', '', { flag: target });\n        }\n      } else if(type === 'browser_open_tab'){\n        \/\/ Ouvre (ou cr\u00e9e) l'onglet dont l'ID ou le link = target\n        if(window.BERF_BROWSER && window.BERF_BROWSER.openConfigured) window.BERF_BROWSER.openConfigured(target);\n      } else if(type === 'browser_close_tab'){\n        if(window.BERF_BROWSER && window.BERF_BROWSER.close) window.BERF_BROWSER.close(target);\n      } else if(type === 'browser_unlock_tab'){\n        \/\/ D\u00e9bloque un onglet invisible : le cr\u00e9e s'il n'existe pas encore\n        if(window.BERF_BROWSER && window.BERF_BROWSER.unlock) window.BERF_BROWSER.unlock(target);\n      } else if(type === 'browser_lock_tab'){\n        if(window.BERF_BROWSER && window.BERF_BROWSER.lock) window.BERF_BROWSER.lock(target);\n      }\n    }\n\n    window.BERF_EVENTS = {\n      trigger: function(type, target, payload){\n        if(type === 'mark_flag'){\n          const s = state();\n          s.flags[String(target || '')] = true;\n          save(s);\n          return;\n        }\n        trigger(type, target, payload || {});\n      },\n      getState: state,\n      setFlag: function(flag, value){\n        const s = state();\n        s.flags[String(flag || '')] = !!value;\n        save(s);\n      }\n    };\n  })();\n\n  \/* =========================================================\n     FICTITIOUS SESSION TRANSITION\n     Effect target: SESSION_ID|MAIL_ID_1,MAIL_ID_2\n     Effect message: visible session label\n     ========================================================= *\/\n  (function(){\n    const overlay=document.getElementById('berfSessionTransition'), step=document.getElementById('berfSessionStep'), badge=document.getElementById('berfSessionBadge');\n    const storageKey='berf_active_session_v1';\n    function applyStoredSession(data){\n      if(!data||!data.id)return;\n      document.getElementById('berfDesk')?.setAttribute('data-session',data.id);\n      if(badge){badge.hidden=false;badge.textContent='SESSION : '+(data.label||data.id)+' \u2014 ACC\u00c8S EN LECTURE SEULE';}\n      if(window.BERF_MAIL && window.BERF_MAIL.removeByIds) window.BERF_MAIL.removeByIds(data.removeMails||[]);\n      if(window.BERF_NOTIFY && window.BERF_NOTIFY.removeByTargets) window.BERF_NOTIFY.removeByTargets(data.removeMails||[]);\n    }\n    async function load(target,message){\n      const parts=String(target||'').split('|'), id=String(parts[0]||'').trim();\n      if(!id)return;\n      const data={id,label:String(message||id).trim(),removeMails:String(parts[1]||'').split(',').map(x=>x.trim()).filter(Boolean)};\n      if(overlay){overlay.classList.add('is-active');overlay.setAttribute('aria-hidden','false');}\n      const stages=['Fermeture de la session actuelle\u2026','Authentification temporaire\u2026','Chargement du profil '+data.label+'\u2026','Restauration de l\u2019environnement\u2026'];\n      for(const text of stages){if(step)step.textContent=text;await new Promise(resolve=>setTimeout(resolve,650));}\n      localStorage.setItem(storageKey,JSON.stringify(data));\n      applyStoredSession(data);\n      document.querySelectorAll('#berfDesk .berf-oc[data-open=\"true\"], #berfDesk .berf-oc[aria-hidden=\"false\"]').forEach(el=>{el.removeAttribute('data-open');el.setAttribute('aria-hidden','true');});\n      if(overlay){overlay.classList.remove('is-active');overlay.setAttribute('aria-hidden','true');}\n    }\n    window.BERF_SESSION={load,apply:applyStoredSession};\n    try{const saved=JSON.parse(localStorage.getItem(storageKey)||'null');if(saved)setTimeout(()=>applyStoredSession(saved),0);}catch(e){}\n  })();\n\n\n  \/* =========================================================\n     TOOL : KNOWLEDGE BASE\n     ========================================================= *\/\n  (function(){\n    const root = document.getElementById('kb901-root');\n    if(!root) return;\n\n    const db = Array.isArray(window.BERFDB && window.BERFDB.KB) ? window.BERFDB.KB.slice() : [];\n    const dbAll = Array.isArray(window.BERFDB && window.BERFDB.KB_ALL) ? window.BERFDB.KB_ALL : [];\n\n    try{\n      const unlocked = JSON.parse(localStorage.getItem('berf_kb_unlocked_v1') || '[]');\n      if(Array.isArray(unlocked)){\n        unlocked.forEach(id=>{\n          if(!db.find(x=>x.id===id)){\n            const item = dbAll.find(x=>x.id===id);\n            if(item) db.push(item);\n          }\n        });\n      }\n    }catch(e){}\n    const searchInput = document.getElementById('kb901-search');\n    const list = document.getElementById('kb901-list');\n    const empty = document.getElementById('kb901-empty');\n    const detail = document.getElementById('kb901-detail');\n    const titleEl = document.getElementById('kb901-title');\n    const metaEl = document.getElementById('kb901-meta');\n    const classEl = document.getElementById('kb901-classification');\n    const threatEl = document.getElementById('kb901-threat');\n    const statusEl = document.getElementById('kb901-status');\n    const generalDescEl = document.getElementById('kb901-general-description');\n    const supposedOriginEl = document.getElementById('kb901-supposed-origin');\n    const capabilitiesEl = document.getElementById('kb901-capabilities');\n    const zonesEl = document.getElementById('kb901-zones');\n    const behaviorEl = document.getElementById('kb901-behavior');\n    const internalNoteEl = document.getElementById('kb901-internal-note');\n    const tabsEl = document.getElementById('kb901-tabs');\n    const imgEl = document.getElementById('kb901-image');\n    const noImgEl = document.getElementById('kb901-noimage');\n    const viewer = document.getElementById('kb901-viewer');\n    const viewerImg = document.getElementById('kb901-viewerImg');\n    const viewerClose = document.getElementById('kb901-viewerClose');\n    const analyzeBtn = document.getElementById('kb901-analyzeBtn');\n\n    let activeId = null;\n\n    function normalize(s){\n      return String(s || '').toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g, '');\n    }\n\n    function matches(item, q){\n      if(!q) return true;\n      const hay = [\n        item.title || '',\n        item.origin || '',\n        item.aliases || '',\n        item.classification || '',\n        item.threat_level || '',\n        item.status || '',\n        item.general_description || '',\n        item.supposed_origin || '',\n        item.identified_capabilities || '',\n        item.activity_zones || '',\n        item.behavioral_analysis || '',\n        item.internal_note || '',\n        item.description || '',\n        item.id || ''\n      ].join(' | ');\n      return normalize(hay).includes(q);\n    }\n\n    function renderList(){\n      const q = normalize(searchInput.value || '');\n      const rows = db.filter(item => matches(item, q));\n      list.innerHTML = '';\n      if(!rows.length){\n        const div = document.createElement('div');\n        div.className = 'kb901-item';\n        div.innerHTML = '<div class=\"kb901-itemTitle\">Aucun r\u00e9sultat<\/div><div class=\"kb901-itemMeta\">Aucune l\u00e9gende ne correspond \u00e0 cette recherche.<\/div>';\n        div.style.cursor = 'default';\n        list.appendChild(div);\n        return;\n      }\n      rows.forEach(item => {\n        const btn = document.createElement('button');\n        btn.type = 'button';\n        btn.className = 'kb901-item' + (item.id === activeId ? ' is-active' : '');\n        btn.innerHTML = `<div class=\"kb901-itemTitle\">${item.title || item.id || 'Entr\u00e9e'}<\/div><div class=\"kb901-itemMeta\">${item.origin || 'Origine inconnue'}${item.aliases ? ' \u2022 ' + item.aliases : ''}<\/div>`;\n        btn.addEventListener('click', ()=> showItem(item.id));\n        list.appendChild(btn);\n      });\n    }\n\n    function setActiveTab(name){\n      root.querySelectorAll('.kb901-tab').forEach(btn => btn.classList.toggle('is-active', btn.getAttribute('data-kb-tab') === name));\n      root.querySelectorAll('.kb901-tabPanel').forEach(panel => panel.classList.toggle('is-active', panel.getAttribute('data-kb-panel') === name));\n    }\n\n    function textOrFallback(value, fallback){\n      const s = String(value || '').trim();\n      return s || fallback;\n    }\n\n    function showItem(id){\n      const item = db.find(x => x.id === id);\n      if(!item) return;\n      activeId = id;\n      try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('open_kb_entry', id, { id, item }); }catch(e){}\n      renderList();\n      empty.style.display = 'none';\n      detail.style.display = '';\n      titleEl.textContent = item.title || item.id || 'Entr\u00e9e';\n      metaEl.textContent = [item.origin || '', item.aliases ? ('Alias : ' + item.aliases) : ''].filter(Boolean).join(' \u2022 ');\n      classEl.textContent = textOrFallback(item.classification, 'Non class\u00e9');\n      threatEl.textContent = textOrFallback(item.threat_level, 'Non \u00e9valu\u00e9');\n      statusEl.textContent = textOrFallback(item.status, 'Non d\u00e9fini');\n      generalDescEl.textContent = textOrFallback(item.general_description || item.description, 'Aucune description g\u00e9n\u00e9rale disponible.');\n      supposedOriginEl.textContent = textOrFallback(item.supposed_origin || item.origin, 'Origine suppos\u00e9e non renseign\u00e9e.');\n      capabilitiesEl.textContent = textOrFallback(item.identified_capabilities, 'Aucune capacit\u00e9 identifi\u00e9e.');\n      zonesEl.textContent = textOrFallback(item.activity_zones, 'Zones d\u2019activit\u00e9 non renseign\u00e9es.');\n      behaviorEl.textContent = textOrFallback(item.behavioral_analysis, 'Aucune analyse comportementale disponible.');\n      internalNoteEl.textContent = textOrFallback(item.internal_note, 'Aucune note interne.');\n      setActiveTab('general');\n      if(item.image){\n        imgEl.src = item.image;\n        imgEl.style.display = 'block';\n        noImgEl.style.display = 'none';\n      }else{\n        imgEl.removeAttribute('src');\n        imgEl.style.display = 'none';\n        noImgEl.style.display = 'flex';\n      }\n    }\n\n    if(tabsEl){\n      tabsEl.addEventListener('click', (e)=>{\n        const btn = e.target.closest('.kb901-tab');\n        if(!btn) return;\n        setActiveTab(btn.getAttribute('data-kb-tab') || 'general');\n      });\n    }\n\n    searchInput.addEventListener('input', renderList);\n    imgEl.addEventListener('click', ()=>{\n      if(!imgEl.src) return;\n      viewerImg.src = imgEl.src;\n      viewer.setAttribute('aria-hidden', 'false');\n    });\n    viewerClose.addEventListener('click', ()=> viewer.setAttribute('aria-hidden', 'true'));\n    viewer.addEventListener('click', (e)=>{ if(e.target === viewer) viewer.setAttribute('aria-hidden', 'true'); });\n    if(analyzeBtn){\n      analyzeBtn.addEventListener('click', async ()=>{\n        if(!viewerImg.src) return;\n        try{\n          viewer.setAttribute('aria-hidden', 'true');\n          await window.BERF_ANALYZE_IMAGE_FROM_URL?.(viewerImg.src, 'knowledge-image');\n        }catch(e){ console.warn(e); }\n      });\n    }\n\n\n    window.BERF_KB_OPEN = function(id){\n      if(!id) return false;\n      const item = db.find(x=>x.id===id);\n      if(!item) return false;\n      try{ if(typeof openOC === 'function') openOC('knowledge'); }catch(e){}\n      showItem(id);\n      return true;\n    };\n\n    window.BERF_KB_UNLOCK = function(id){\n      if(!id) return;\n      if(db.find(x=>x.id===id)) return;\n      const item = dbAll.find(x=>x.id===id);\n      if(item){\n        db.push(item);\n        renderList();\n      }\n    };\n\n    renderList();\n  })();\n\n\n  \/* =========================================================\n     TOOL #1 : MAIL (API => window.BERF_MAIL.addEmail)\n     ========================================================= *\/\n  (function(){\n    const scope = document.getElementById(\"berfMailTool\");\n    if(!scope) return;\n\n    const EMAIL_EXPIRATION_TIME = 45 * 60 * 1000;\n    let selectedMail = null;\n\n    const replyModal = scope.querySelector('#replyModal');\n    const newMailModal = scope.querySelector('#newMailModal');\n    const attachmentModal = scope.querySelector('#attachmentModal');\n    const attachmentPreview = scope.querySelector('#attachmentPreview');\n    const attachmentAnalyzeBtn = scope.querySelector('#attachmentAnalyzeBtn');\n    const attachmentCollectBtn = scope.querySelector('#attachmentCollectBtn');\n    const attachmentViewerTitle = scope.querySelector('#attachmentViewerTitle');\n    const attachmentViewerMeta = scope.querySelector('#attachmentViewerMeta');\n    const attachmentOpenExternal = scope.querySelector('#attachmentOpenExternal');\n    let currentAttachmentUrl = '';\n    let currentAttachmentType = '';\n    let currentAttachment = null;\n    const emailDetailsSection = scope.querySelector('.email-details');\n    const closeModalElements = scope.querySelectorAll('.close');\n\n    const mailWidget = desk.querySelector('.mail-widget');\n    const mailBadge = mailWidget ? mailWidget.querySelector('.berf-badge') : null;\n\n    function buildImmersiveMailLayout(){\n      if(scope.dataset.berfMailLayout === 'immersive') return;\n      const frame = scope.querySelector('.inbox-container');\n      const list = scope.querySelector('.email-list');\n      const details = scope.querySelector('.email-details');\n      const newBtn = scope.querySelector('#newMailButton');\n      const replyBtn = scope.querySelector('#replyButton');\n      if(!frame || !list || !details || !newBtn || !replyBtn) return;\n\n      scope.dataset.berfMailLayout = 'immersive';\n      list.querySelectorAll('#newMailButton').forEach(btn => btn.remove());\n\n      details.classList.add('berf-mail-reader');\n      details.innerHTML = `\n        <div class=\"berf-mail-reader-head\">\n          <h2 class=\"details-subject\" id=\"email-subject\">Selectionne un mail<\/h2>\n          <button type=\"button\" class=\"berf-mail-star\" aria-label=\"Marquer le mail\"><i class=\"fa-regular fa-star\"><\/i><\/button>\n        <\/div>\n        <div class=\"berf-mail-meta\">\n          <div class=\"details-avatar\" id=\"details-avatar\">B<\/div>\n          <div class=\"berf-mail-meta-grid\">\n            <span>De :<\/span><strong id=\"sender-name\"><\/strong>\n            <span>&nbsp;<\/span><em id=\"sender-email\"><\/em>\n            <span>A :<\/span><strong id=\"mail-recipient-display\">MOREAU, L.<\/strong>\n            <span>Date :<\/span><strong id=\"email-date-display\">-<\/strong>\n            <span>Objet :<\/span><strong id=\"mail-object-display\">-<\/strong>\n          <\/div>\n          <div class=\"berf-mail-stamp\">\n            <strong>Confidentiel<\/strong>\n            <span>Diffusion restreinte<\/span>\n            <small>Ref. : <b id=\"mail-ref-display\">D-174-MAIL<\/b><\/small>\n            <small>Niv. : 3<\/small>\n          <\/div>\n        <\/div>\n        <div class=\"message-body\">Corps du message...<\/div>\n        <div aria-label=\"Pieces jointes\" class=\"attachments\" hidden><\/div>\n        <div class=\"berf-mail-actions\"><\/div>\n      `;\n      const actions = details.querySelector('.berf-mail-actions');\n      newBtn.type = 'button';\n      newBtn.innerHTML = '<i class=\"fa-regular fa-pen-to-square\"><\/i><span>Nouveau message<\/span>';\n      replyBtn.type = 'button';\n      replyBtn.innerHTML = '<i class=\"fa-solid fa-reply\"><\/i><span>Repondre<\/span>';\n      actions.append(newBtn, replyBtn);\n\n      const workspace = document.createElement('section');\n      workspace.className = 'berf-mail-workspace';\n      workspace.innerHTML = `\n        <div class=\"berf-mail-main\">\n          <section class=\"berf-mail-listpane\">\n            <div class=\"berf-mail-listhead\"><h3>Boite de reception<\/h3><div><span>Tri : date<\/span><i class=\"fa-solid fa-filter\"><\/i><\/div><\/div>\n            <div class=\"berf-mail-listmount\"><\/div>\n            <div class=\"berf-mail-listfoot\"><span id=\"berfMailCount\">0 message(s)<\/span><\/div>\n          <\/section>\n          <div class=\"berf-mail-readermount\"><\/div>\n          <aside class=\"berf-mail-attachments\" aria-label=\"Pieces jointes du mail\">\n            <div class=\"berf-mail-attachments-head\"><i class=\"fa-solid fa-paperclip\"><\/i><h3>Pieces jointes <span id=\"mailAttachmentCount\">(0)<\/span><\/h3><\/div>\n            <div class=\"berf-mail-attachments-list\" id=\"mailAttachmentPanel\">\n              <div class=\"berf-mail-empty\"><i class=\"fa-solid fa-folder-open\"><\/i><span>Aucune piece jointe selectionnee.<\/span><\/div>\n            <\/div>\n            <div class=\"berf-mail-attachments-note\"><i class=\"fa-solid fa-circle-info\"><\/i><span>Certains fichiers peuvent necessiter une autorisation supplementaire pour etre consultes ou analyses.<\/span><\/div>\n          <\/aside>\n        <\/div>\n      `;\n\n      frame.innerHTML = '';\n      frame.append(workspace);\n      workspace.querySelector('.berf-mail-listmount').appendChild(list);\n      workspace.querySelector('.berf-mail-readermount').appendChild(details);\n\n      const oc = document.getElementById('berf-oc-mail');\n      if(oc && !oc.dataset.berfMailOutsideClose){\n        oc.dataset.berfMailOutsideClose = 'true';\n        oc.addEventListener('pointerdown', (event) => {\n          if(event.target.closest && event.target.closest('#berf-oc-mail .berf-oc__main')) return;\n          oc.removeAttribute('data-open');\n          oc.setAttribute('aria-hidden', 'true');\n        });\n      }\n    }\n\n    buildImmersiveMailLayout();\n\n    function escapeHTML(text){\n      const el = document.createElement('div');\n      el.innerText = text;\n      return el.innerHTML;\n    }\n    function sanitizeMailHtml(html){\n      const raw = normalizeTextUtf8(html || '');\n      if(!raw) return '';\n      const tpl = document.createElement('template');\n      tpl.innerHTML = raw;\n\n      tpl.content.querySelectorAll('script, iframe, object, embed, form, input, button, textarea, select, link').forEach(el => el.remove());\n\n      tpl.content.querySelectorAll('*').forEach(el => {\n        Array.from(el.attributes).forEach(attr => {\n          const name = attr.name.toLowerCase();\n          const value = String(attr.value || '');\n          if(name.startsWith('on')){\n            el.removeAttribute(attr.name);\n            return;\n          }\n          if((name === 'src' || name === 'href') && \/^\\s*javascript:\/i.test(value)){\n            el.removeAttribute(attr.name);\n            return;\n          }\n        });\n      });\n\n      return tpl.innerHTML;\n    }\n    function normalizeTextUtf8(value){\n      if(value == null) return '';\n      let s = String(value);\n\n      \/\/ restore unicode escapes that lost their backslash, e.g. \"pru00eat\" => \"pr\u00eat\"\n      try{\n        s = s.replace(\/(^|[^\\\\])u([0-9a-fA-F]{4})\/g, function(_, prefix, hex){\n          return prefix + String.fromCharCode(parseInt(hex, 16));\n        });\n        s = s.replace(\/\\\\u([0-9a-fA-F]{4})\/g, function(_, hex){\n          return String.fromCharCode(parseInt(hex, 16));\n        });\n      }catch(e){}\n\n      try{\n        \/\/ common mojibake repair: UTF-8 bytes interpreted as Latin-1\n        if(\/[\u00c3\u00c2\u00e2\u20ac\u2122\u00e2\u20ac\u0153\u00e2\u20ac\u009d]\/.test(s)){\n          s = decodeURIComponent(Array.prototype.map.call(s, function(ch){\n            return '%' + ch.charCodeAt(0).toString(16).padStart(2, '0');\n          }).join(''));\n        }\n      }catch(e){}\n      \/\/ restore literal escaped line breaks coming from serialized content\n      s = s.replace(\/\\\\r\\\\n\/g, '\\n').replace(\/\\\\n\/g, '\\n').replace(\/\\\\r\/g, '\\n');\n      \/\/ repair older corrupted mails where \\n became literal \"n\"\n      s = s.replace(\/([,.;:!?])nn(?=[A-Z\u00c0-\u00d6\u00d8-\u00de])\/g, '$1\\n\\n');\n      s = s.replace(\/([,.;:!?])n(?=[A-Z\u00c0-\u00d6\u00d8-\u00de])\/g, '$1\\n');\n      return s;\n    }\n\n\n    closeModalElements.forEach(close=>{\n      close.addEventListener('click', ()=>{\n        replyModal.style.display = 'none';\n        newMailModal.style.display = 'none';\n        attachmentModal.style.display = 'none';\n      });\n    });\n\n    window.addEventListener('click', (event)=>{\n      if(event.target === replyModal || event.target === newMailModal || event.target === attachmentModal){\n        replyModal.style.display = 'none';\n        newMailModal.style.display = 'none';\n        attachmentModal.style.display = 'none';\n      }\n    });\n\n    scope.querySelector('#newMailButton').addEventListener('click', ()=>{ newMailModal.style.display = 'flex'; });\n\n    scope.querySelector('#replyButton').addEventListener('click', ()=>{\n      if(!selectedMail) return;\n      replyModal.style.display = 'flex';\n      scope.querySelector('#replyRecipient').value = selectedMail.sender;\n      scope.querySelector('#replySubject').value = `Re: ${selectedMail.subject}`;\n    });\n\n    function getAttachmentIcon(type){\n      switch(type){\n        case 'pdf': return 'fa-solid fa-file-pdf';\n        case 'mp3':\n        case 'audio': return 'fa-solid fa-music';\n        case 'image': return 'fa-regular fa-image';\n        case 'video': return 'fa-solid fa-video';\n        default: return 'fa-solid fa-file';\n      }\n    }\n\n    function getMailAttachmentMap(){\n      const map = window.BERFDB && window.BERFDB.MAIL_ATTACHMENT_MAP;\n      return (map && typeof map === 'object') ? map : {};\n    }\n\n    function normalizeMailAttachment(att){\n      if(att == null) return null;\n      const map = getMailAttachmentMap();\n\n      if(typeof att === 'number' || (typeof att === 'string' && \/^\\d+$\/.test(att.trim()))){\n        const key = String(parseInt(att, 10));\n        const found = map[key];\n        if(found && found.url){\n          return {\n            id: found.id ?? parseInt(key, 10),\n            name: found.name ?? ('Pi\u00e8ce jointe #' + key),\n            type: found.type ?? 'file',\n            url: found.url\n          };\n        }\n        return null;\n      }\n\n      if(typeof att === 'object'){\n        const id = att.id ?? att.attachment_id ?? null;\n        const key = (id !== null && id !== undefined && String(id) !== '' && !Number.isNaN(parseInt(id, 10))) ? String(parseInt(id, 10)) : '';\n        const found = key ? map[key] : null;\n        const url = att.url || (found && found.url) || null;\n        if(!url) return null;\n        return {\n          id: id ?? (found && found.id) ?? null,\n          name: att.name || att.filename || att.title || (found && found.name) || 'Pi\u00e8ce jointe',\n          type: att.type || (found && found.type) || 'file',\n          url: url\n        };\n      }\n\n      return null;\n    }\n\n    function normalizeAttachmentType(type){\n      const t = String(type || '').toLowerCase();\n      if(t === 'mp3') return 'audio';\n      if(t.indexOf('image') !== -1) return 'image';\n      if(t.indexOf('audio') !== -1) return 'audio';\n      if(t.indexOf('video') !== -1) return 'video';\n      if(t.indexOf('pdf') !== -1) return 'pdf';\n      return t || 'file';\n    }\n\n    function attachmentLabel(type){\n      const t = normalizeAttachmentType(type);\n      if(t === 'image') return 'IMAGE';\n      if(t === 'audio') return 'AUDIO';\n      if(t === 'video') return 'VIDEO';\n      if(t === 'pdf') return 'PDF';\n      return 'FICHIER';\n    }\n\n    function renderAttachmentPanel(attachments, email){\n      const panel = scope.querySelector('#mailAttachmentPanel');\n      const count = scope.querySelector('#mailAttachmentCount');\n      if(!panel) return;\n      const list = Array.isArray(attachments) ? attachments : [];\n      if(count) count.textContent = '(' + list.length + ')';\n      panel.innerHTML = '';\n      if(!list.length){\n        panel.innerHTML = '<div class=\"berf-mail-empty\"><i class=\"fa-solid fa-folder-open\"><\/i><span>Aucune piece jointe pour ce mail.<\/span><\/div>';\n        return;\n      }\n\n      list.forEach((att, idx) => {\n        const type = normalizeAttachmentType(att.type);\n        const card = document.createElement('article');\n        card.className = 'berf-mail-attachment-card';\n        const isPreviewImage = type === 'image';\n        const preview = isPreviewImage\n          ? '<img decoding=\"async\" src=\"' + att.url + '\" alt=\"\">'\n          : '<div class=\"berf-mail-attachment-file\"><i class=\"' + getAttachmentIcon(type) + '\"><\/i><span>' + attachmentLabel(type) + '<\/span><\/div>';\n        const ref = (email && email.id ? String(email.id).replace(\/^MAIL_\/i, '') : 'D174') + '-' + String(idx + 1).padStart(2, '0');\n        card.innerHTML = `\n          <div class=\"berf-mail-attachment-preview\">${preview}<\/div>\n          <div class=\"berf-mail-attachment-info\">\n            <button type=\"button\" class=\"berf-mail-attachment-menu\" aria-label=\"Options\"><i class=\"fa-solid fa-ellipsis-vertical\"><\/i><\/button>\n            <strong>${escapeHTML(att.name || 'Piece jointe')}<\/strong>\n            <span>${attachmentLabel(type)} \u00b7 Ref. ${escapeHTML(ref)}<\/span>\n            <small>Ajoute au dossier D-174<\/small>\n            <small>Niveau : 3 - Confidentiel<\/small>\n            <div class=\"berf-mail-attachment-buttons\"><\/div>\n          <\/div>\n        `;\n        const buttons = card.querySelector('.berf-mail-attachment-buttons');\n        const openBtn = document.createElement('button');\n        openBtn.type = 'button';\n        openBtn.className = 'berf-mail-attachment-open';\n        openBtn.innerHTML = '<i class=\"fa-solid fa-magnifying-glass\"><\/i> Ouvrir';\n        openBtn.addEventListener('click', () => openAttachmentModal(type, att.url, att, ref));\n        buttons.appendChild(openBtn);\n        if(type === 'image'){\n          const analyzeBtn = document.createElement('button');\n          analyzeBtn.type = 'button';\n          analyzeBtn.className = 'berf-mail-attachment-analyze';\n          analyzeBtn.innerHTML = '<i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser';\n          analyzeBtn.addEventListener('click', async () => {\n            try{ await window.BERF_ANALYZE_IMAGE_FROM_URL?.(att.url, att.name || 'mail-attachment'); }catch(e){ console.warn(e); }\n          });\n          buttons.appendChild(analyzeBtn);\n        }\n        panel.appendChild(card);\n      });\n    }\n\n    function openAttachmentModal(type, url, attachment, ref){\n      type = normalizeAttachmentType(type);\n      const allowedTypes = ['image','video','audio','mp3','pdf'];\n      if(!allowedTypes.includes(type)) return;\n      currentAttachmentUrl = url || '';\n      currentAttachmentType = type || '';\n      currentAttachment = attachment ? normalizeMailAttachment(attachment) : null;\n      attachmentPreview.innerHTML = '';\n      const name = attachment && attachment.name ? normalizeTextUtf8(attachment.name) : 'Piece jointe';\n      if(attachmentViewerTitle) attachmentViewerTitle.textContent = name;\n      if(attachmentViewerMeta) attachmentViewerMeta.textContent = attachmentLabel(type) + ' - Dossier D-174' + (ref ? ' - Ref. ' + ref : '');\n      if(attachmentOpenExternal){\n        attachmentOpenExternal.href = url || '#';\n        attachmentOpenExternal.style.display = url ? 'inline-flex' : 'none';\n      }\n      if(type === 'image'){\n        const img = document.createElement('img'); img.src = url; attachmentPreview.appendChild(img);\n      }else if(type === 'video'){\n        const v = document.createElement('video'); v.src = url; v.controls = true; attachmentPreview.appendChild(v);\n      }else if(type === 'audio' || type === 'mp3'){\n        const a = document.createElement('audio'); a.src = url; a.controls = true; attachmentPreview.appendChild(a);\n      }else if(type === 'pdf'){\n        const f = document.createElement('iframe');\n        f.title = name;\n        f.src = url;\n        attachmentPreview.appendChild(f);\n      }\n      if(attachmentAnalyzeBtn){\n        attachmentAnalyzeBtn.hidden = type !== 'image';\n        attachmentAnalyzeBtn.style.display = type === 'image' ? 'inline-flex' : 'none';\n      }\n      if(attachmentCollectBtn){\n        const canCollect=['image','video','audio','pdf'].includes(type) && !!currentAttachment;\n        const already=canCollect && window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.isCollected && window.BERF_FILE_MANAGER.isCollected(currentAttachment);\n        attachmentCollectBtn.hidden=!canCollect;\n        attachmentCollectBtn.style.display=canCollect?'inline-flex':'none';\n        attachmentCollectBtn.disabled=!!already;\n        attachmentCollectBtn.innerHTML=already?'<i class=\"fa-solid fa-check\"><\/i> D\u00e9j\u00e0 dans les \u00e9l\u00e9ments collect\u00e9s':'<i class=\"fa-solid fa-download\"><\/i> Ajouter aux \u00e9l\u00e9ments collect\u00e9s';\n      }\n      attachmentModal.style.display = 'flex';\n    }\n\n    if(attachmentAnalyzeBtn){\n      attachmentAnalyzeBtn.addEventListener('click', async ()=>{\n        if(currentAttachmentType !== 'image' || !currentAttachmentUrl) return;\n        try{\n          attachmentModal.style.display = 'none';\n          await window.BERF_ANALYZE_IMAGE_FROM_URL?.(currentAttachmentUrl, 'mail-attachment');\n        }catch(e){ console.warn(e); }\n      });\n    }\n    if(attachmentCollectBtn){\n      attachmentCollectBtn.addEventListener('click',()=>{\n        if(!currentAttachment || !window.BERF_FILE_MANAGER || !window.BERF_FILE_MANAGER.collectFile) return;\n        const mailId=selectedMail&&selectedMail.id?String(selectedMail.id):'mail';\n        window.BERF_FILE_MANAGER.collectFile(currentAttachment,'mail:'+mailId);\n        attachmentCollectBtn.disabled=true;\n        attachmentCollectBtn.innerHTML='<i class=\"fa-solid fa-check\"><\/i> Ajout\u00e9 aux \u00e9l\u00e9ments collect\u00e9s';\n      });\n    }\n\n\n\n    function getEmailStateFromLocalStorage(){\n      const emailState = localStorage.getItem('emailState');\n      return emailState ? JSON.parse(emailState) : {};\n    }\n    function emailStateKey(email, index){\n      return email && email.id ? ('id:' + String(email.id)) : ('legacy:' + String(index));\n    }\n    function markEmailAsRead(email, index){\n      const emailState = getEmailStateFromLocalStorage();\n      emailState[emailStateKey(email, index)] = { read:true, timestamp: Date.now() };\n      localStorage.setItem('emailState', JSON.stringify(emailState));\n    }\n    function isEmailRead(email, index){\n      const emailState = getEmailStateFromLocalStorage();\n      const s = emailState[emailStateKey(email, index)];\n      if(s && s.read){\n        if(Date.now() - s.timestamp < EMAIL_EXPIRATION_TIME) return true;\n      }\n      return false;\n    }\n    function countUnreadMails(){\n      return scope.querySelectorAll('.email-item.unread').length;\n    }\n    function updateUnreadMailCount(){\n      const unread = countUnreadMails();\n      if(mailWidget){\n        mailWidget.setAttribute('data-unread', String(unread));\n        if(mailBadge) mailBadge.textContent = String(unread);\n      }\n      const agentBadge = scope.querySelector('.berf-mail-agent-badge');\n      if(agentBadge) agentBadge.textContent = String(unread);\n      const count = scope.querySelector('#berfMailCount');\n      if(count) count.textContent = String(emailData.length) + ' message(s)';\n    }\n\n    function formatMailDateTime(email){\n      const raw = (email && (email.date_iso || email.date || '')) ? String(email.date_iso || email.date || '').trim() : '';\n      if(!raw) return '';\n\n      const normalized = \/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$\/.test(raw) ? (raw + ':00') : raw;\n      const d = new Date(normalized);\n      if(!isNaN(d.getTime())){\n        return d.toLocaleString('fr-FR', {\n          day:'2-digit', month:'2-digit', year:'numeric',\n          hour:'2-digit', minute:'2-digit'\n        });\n      }\n\n      return raw;\n    }\n\n    function displayEmailDetails(index, emailItem){\n      const email = emailData[index];\n      selectedMail = email;\n\n      emailDetailsSection.style.display = 'block';\n      scope.querySelector('#email-subject').innerText = normalizeTextUtf8(email.subject);\n      const __mailSender = normalizeTextUtf8(email.sender);\n      scope.querySelector('#details-avatar').innerText = (__mailSender.charAt(0) || 'A').toUpperCase();\n      scope.querySelector('#sender-name').innerText = __mailSender.split('@')[0];\n      scope.querySelector('#sender-email').innerText = __mailSender;\n      const __mailDate = formatMailDateTime(email);\n      const __mailDateNode = scope.querySelector('#email-date-display');\n      if(__mailDateNode) __mailDateNode.innerText = __mailDate || '\u2014';\n\n      const __mailObjectNode = scope.querySelector('#mail-object-display');\n      if(__mailObjectNode) __mailObjectNode.innerText = normalizeTextUtf8(email.subject || '');\n      const __mailRefNode = scope.querySelector('#mail-ref-display');\n      if(__mailRefNode) __mailRefNode.innerText = normalizeTextUtf8(email.id || ('MAIL-' + (index + 1)));\n\n      const mailHtml = sanitizeMailHtml(email.body);\n      scope.querySelector('.email-details .message-body').innerHTML = mailHtml || escapeHTML(normalizeTextUtf8(email.body));\n\n      scope.querySelectorAll('.email-list .email-item.active').forEach(item => item.classList.remove('active'));\n      if(emailItem) emailItem.classList.add('active');\n      emailItem.classList.remove('unread');\n      const dot = emailItem.querySelector('.new-indicator');\n      if(dot) dot.style.display = 'none';\n      markEmailAsRead(email, index);\n      updateUnreadMailCount();\n\n      const attachmentsSection = scope.querySelector('.attachments');\n      if(attachmentsSection){\n        attachmentsSection.innerHTML = '';\n        attachmentsSection.hidden = true;\n      }\n      const normalizedAttachments = Array.isArray(email.attachments) ? email.attachments.map(normalizeMailAttachment).filter(Boolean) : [];\n      renderAttachmentPanel(normalizedAttachments, email);\n\n      window.dispatchEvent(new CustomEvent(\"berf:mail:selected\", { detail: email }));\n      try{ if(window.BERF_EVENTS && email.id) window.BERF_EVENTS.trigger(\"open_mail\", email.id, email); }catch(e){}\n    }\n\n    function displayEmail(email, index){\n      const emailList = scope.querySelector('.email-list');\n      email.subject = normalizeTextUtf8(email.subject || '');\n      email.sender = normalizeTextUtf8(email.sender || '');\n      email.body = normalizeTextUtf8(email.body || '');\n      const emailItem = document.createElement('div');\n      emailItem.classList.add('email-item');\n      emailItem.dataset.mailIndex = String(index);\n      if(!isEmailRead(email, index)) emailItem.classList.add('unread');\n\n      const displayDate = formatMailDateTime(email) || '\u2014';\n      emailItem.dataset.search = [email.sender, email.subject, email.body, displayDate].map(v => normalizeTextUtf8(v || '')).join(' ');\n\n      const senderLabel = normalizeTextUtf8(email.sender || '').split('@')[0] || 'BERF';\n      const snippet = normalizeTextUtf8(String(email.body || '').replace(\/<[^>]+>\/g, ' ')).replace(\/\\s+\/g, ' ').trim().slice(0, 92);\n      const hasAttachments = Array.isArray(email.attachments) && email.attachments.length;\n      emailItem.innerHTML = `\n        <span class=\"berf-mail-unread-dot\"><\/span>\n        <div class=\"email-info\">\n          <div class=\"sender\">${escapeHTML(senderLabel)}<\/div>\n          <div class=\"subject\">${escapeHTML(email.subject)}<\/div>\n          <div class=\"snippet\">${escapeHTML(snippet || 'Message BERF confidentiel.')}<\/div>\n          <div class=\"date\">${escapeHTML(displayDate)}<\/div>\n        <\/div>\n        ${hasAttachments ? '<i class=\"fa-solid fa-paperclip berf-mail-clip\"><\/i>' : ''}\n        <div class=\"new-indicator\" style=\"${isEmailRead(email, index) ? 'display:none;' : ''}\"><\/div>\n      `;\n      emailItem.addEventListener('click', ()=> displayEmailDetails(index, emailItem));\n      emailList.insertBefore(emailItem, emailList.firstChild);\n      updateUnreadMailCount();\n    }\n\n    function saveEmailsToLocalStorage(){ localStorage.setItem('emails', JSON.stringify(emailData)); }\n\n    function loadEmailsFromLocalStorage(){\n      const stored = localStorage.getItem('emails');\n      if(stored){\n        emailData = JSON.parse(stored);\n      }\n      emailData.forEach((e,i)=> displayEmail(e,i));\n      updateUnreadMailCount();\n      \/\/ Ne pas ouvrir automatiquement le premier mail : le joueur doit le s\u00e9lectionner lui-m\u00eame.\n    }\n\n    function simulateEmailReception(email){\n      const newIndex = emailData.length;\n      displayEmail(email, newIndex);\n      emailData.push(email);\n      saveEmailsToLocalStorage();\n      updateUnreadMailCount();\n      localStorage.setItem('mailReceivedTime', String(Date.now()));\n    }\n\n    scope.querySelector('#newMailForm').addEventListener('submit', (e)=>{\n      e.preventDefault();\n      const recipient = scope.querySelector('#recipient').value.trim();\n      const subject = scope.querySelector('#subject').value.trim();\n      const message = scope.querySelector('#message').value;\n      if(!recipient || !subject || !message) return;\n\n      simulateEmailReception({\n        sender: 'vous@berf-nat.fr',\n        subject: subject,\n        body: `\u00c0: ${recipient}\\n\\n${message}`,\n        attachments: []\n      });\n\n      newMailModal.style.display = 'none';\n      e.target.reset();\n    });\n\n    scope.querySelector('#replyForm').addEventListener('submit', (e)=>{\n      e.preventDefault();\n      const recipient = scope.querySelector('#replyRecipient').value;\n      const subject = scope.querySelector('#replySubject').value;\n      const message = scope.querySelector('#replyMessage').value;\n      if(!recipient || !subject || !message) return;\n\n      simulateEmailReception({\n        sender: 'vous@berf-nat.fr',\n        subject: subject,\n        body: `\u00c0: ${recipient}\\n\\n${message}`,\n        attachments: []\n      });\n\n      replyModal.style.display = 'none';\n      e.target.reset();\n    });\n\n    let emailData = [];\n            loadEmailsFromLocalStorage();\n\n    setInterval(()=>{\n      const testMailRequest = localStorage.getItem('test_mail_request');\n      if(testMailRequest){\n        const requestData = JSON.parse(testMailRequest);\n        if(Date.now() - requestData.timestamp >= 5000){\n          simulateEmailReception({\n            sender:'eta974@berf-nat.fr',\n            subject:'Re: Rapport de suspect - Amaury Delacroix',\n            body:'Je suis un mail test, remplacez moi',\n            attachments:[]\n          });\n          localStorage.removeItem('test_mail_request');\n        }\n      }\n    }, 1000);\n\n    window.BERF_MAIL = window.BERF_MAIL || {};\n\n    window.BERF_MAIL.openById = function(id){\n      if(!id) return false;\n      const idx = emailData.findIndex(e => e && e.id === id);\n      if(idx === -1) return false;\n      const item = scope.querySelector('.email-list .email-item[data-mail-index=\"' + idx + '\"]') || null;\n      if(!item) return false;\n      displayEmailDetails(idx, item);\n      return true;\n    };\n\n    window.BERF_MAIL.unlockById = function(id){\n      if(!id) return false;\n      const exists = emailData.find(e => e && e.id === id);\n      if(exists) return true;\n\n      const boot = window.BERFDB && window.BERFDB.BOOT;\n      const all = boot && boot.data && boot.data.mails && Array.isArray(boot.data.mails.inbox) ? boot.data.mails.inbox : [];\n      const raw = all.find(e => e && e.id === id);\n      if(!raw) return false;\n\n      const rawAtt = Array.isArray(raw.attachments) ? raw.attachments : [];\n      const atts = rawAtt.map(normalizeMailAttachment).filter(Boolean);\n\n      const mail = {\n        sender: normalizeTextUtf8(raw.from_email || raw.sender || ''),\n        subject: normalizeTextUtf8(raw.subject || ''),\n        body: normalizeTextUtf8((raw.body_html || raw.body || '').toString()),\n        attachments: atts,\n        folder: 'inbox',\n        date_iso: raw.date_iso || '',\n        date: raw.date || raw.date_iso || '',\n        id: raw.id || ('mail_' + Date.now())\n      };\n\n      simulateEmailReception(mail);\n      return true;\n    };\n\n    window.BERF_MAIL.addEmail = simulateEmailReception;\n\n    window.BERF_MAIL.removeByIds = function(ids){\n      const remove = new Set((Array.isArray(ids) ? ids : []).map(String));\n      emailData = emailData.filter(mail => !mail || !remove.has(String(mail.id || '')));\n      saveEmailsToLocalStorage();\n      const list = scope.querySelector('.email-list');\n      if(list) list.innerHTML = '';\n      emailDetailsSection.style.display = 'none';\n      selectedMail = null;\n      emailData.forEach((mail,index)=>displayEmail(mail,index));\n      updateUnreadMailCount();\n      return true;\n    };\n\n    scope.addEventListener('click', event=>{\n      const action = event.target.closest && event.target.closest('[data-berf-action=\"load-session\"]');\n      if(!action) return;\n      event.preventDefault();\n      const target = action.getAttribute('data-target') || '';\n      try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('mail_action', target, { target, mail:selectedMail }); }catch(e){}\n    });\n\n    updateUnreadMailCount();\n  })();\n\n  \/* =========================================================\n     TOOL #2 : SUSPECTS (envoi vers MAIL)\n     ========================================================= *\/\n  (function(){\n    const scope = document.getElementById(\"berfSuspectsTool\");\n    if(!scope) return;\n\n    let suspects = JSON.parse(localStorage.getItem('suspects')) || [];\n    let editIndex = null;\n    let selectedSuspectIndex = null;\n    let suspectEvidenceDraft42X = [];\n    let reportEvidenceDraft42X = [];\n    let pickerContext42X = 'suspect';\n    let pickerSelection42X = [];\n    let pickerFolders42X = [];\n    let pickerFolderId42X = '';\n\n    const emails = [\"eta974@berf-nat.fr\", \"rho887@berf-nat.fr\", \"pixel@berf-nat.fr\", \"theta005@berf-nat.fr\", \"sigma009@berf-nat.fr\", \"mu021@berf-nat.fr\", \"nu333@berf-nat.fr\", \"xi012@berf-nat.fr\", \"gamma107@berf-nat.fr\", \"beta002@berf-nat.fr\", \"psi099@berf-nat.fr\", \"delta014@berf-nat.fr\", \"omega323@berf-nat.fr\", \"alpha011@berf-nat.fr\", \"lambda045@berf-nat.fr\", \"zeta501@berf-nat.fr\", \"kappa023@berf-nat.fr\", \"theta004@berf-nat.fr\", \"epsilon075@berf-nat.fr\", \"epsilon103@berf-nat.fr\", \"rho077@berf-nat.fr\", \"xi045@berf-nat.fr\", \"phi033@berf-nat.fr\", \"chi012@berf-nat.fr\", \"eta005@berf-nat.fr\", \"iota019@berf-nat.fr\", \"pi007@berf-nat.fr\", \"omega033@berf-nat.fr\", \"sigma011@berf-nat.fr\", \"tau022@berf-nat.fr\", \"beta006@berf-nat.fr\", \"xi099@berf-nat.fr\"];\n\n    const tableBody = scope.querySelector(\"#suspect-table-body42X\");\n    const modalSuspect = scope.querySelector(\"#suspectModal42X\");\n    const modalTitle = scope.querySelector(\"#modal-title42X\");\n    const formSuspect = scope.querySelector(\"#suspect-form42X\");\n\n    const modalReport = scope.querySelector(\"#reportModal42X\");\n    const formReport = scope.querySelector(\"#report-form42X\");\n    const reportEmailSelect = scope.querySelector(\"#report-email42X\");\n    const reportReason = scope.querySelector(\"#report-reason42X\");\n    const reportDetails = scope.querySelector(\"#report-details42X\");\n    const fileWarn = scope.querySelector(\"#file-limit-warning42X\");\n    const loader = scope.querySelector(\"#report-loader42X\");\n    const successMessage = scope.querySelector(\"#report-success42X\");\n    const logContainer = scope.querySelector(\"#log-container42X\");\n    const suspectEvidenceList = scope.querySelector('#suspect-evidence-list42X');\n    const reportEvidenceList = scope.querySelector('#report-evidence-list42X');\n    const picker = scope.querySelector('#evidencePicker42X');\n    const pickerFolders = scope.querySelector('#evidencePickerFolders42X');\n    const pickerFiles = scope.querySelector('#evidencePickerFiles42X');\n    const pickerCount = scope.querySelector('#evidencePickerCount42X');\n\n    function escape42X(value){return String(value||'').replace(\/[&<>\"']\/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#039;'}[ch]));}\n    function evidenceKey42X(file){return String(file&&(file.id||file.attachment_id||file.url||file.label||file.name)||'');}\n    function evidenceName42X(file){return String(file&&(file.label||file.name)||'Fichier');}\n    function evidenceIcon42X(file){const value=String(file&&(file.type||file.mime||file.name||file.url)||'').toLowerCase();if(\/image|png|jpe?g|webp|gif\/.test(value))return 'fa-file-image';if(\/audio|mp3|wav|m4a|ogg\/.test(value))return 'fa-file-audio';if(\/pdf\/.test(value))return 'fa-file-pdf';if(\/video|mp4|mov|webm\/.test(value))return 'fa-file-video';return 'fa-file-lines';}\n    function normalizeEvidence42X(list){const seen=new Set();return (Array.isArray(list)?list:[]).filter(file=>{const key=evidenceKey42X(file);if(!key||seen.has(key))return false;seen.add(key);return true;});}\n    function renderEvidenceSelection42X(host,list,empty,removable){\n      const files=normalizeEvidence42X(list); if(!files.length){host.innerHTML='<span>'+escape42X(empty)+'<\/span>';return;}\n      host.innerHTML=files.map(file=>'<span class=\"evidence-chip42X\" data-evidence-open=\"'+escape42X(evidenceKey42X(file))+'\"><i class=\"fa-solid '+evidenceIcon42X(file)+'\"><\/i><span>'+escape42X(evidenceName42X(file))+'<\/span>'+(removable?'<button type=\"button\" data-evidence-remove=\"'+escape42X(evidenceKey42X(file))+'\" aria-label=\"Retirer\">\u00d7<\/button>':'')+'<\/span>').join('');\n      host.querySelectorAll('[data-evidence-open]').forEach(el=>el.addEventListener('click',event=>{if(event.target.closest('[data-evidence-remove]'))return;const file=files.find(item=>evidenceKey42X(item)===el.dataset.evidenceOpen);if(file&&window.BERF_FILE_MANAGER)window.BERF_FILE_MANAGER.openFile(file);}));\n      host.querySelectorAll('[data-evidence-remove]').forEach(btn=>btn.addEventListener('click',()=>{const key=btn.dataset.evidenceRemove;if(host===suspectEvidenceList)suspectEvidenceDraft42X=suspectEvidenceDraft42X.filter(item=>evidenceKey42X(item)!==key);else reportEvidenceDraft42X=reportEvidenceDraft42X.filter(item=>evidenceKey42X(item)!==key);renderEvidenceSelection42X(host,host===suspectEvidenceList?suspectEvidenceDraft42X:reportEvidenceDraft42X,empty,removable);try{if(window.BERF_EVENTS)window.BERF_EVENTS.trigger('suspect_evidence_removed',key,{fileKey:key,suspectName:scope.querySelector('#suspect-name42X').value||((suspects[selectedSuspectIndex]||{}).name)||''});}catch(e){}}));\n    }\n    function updatePickerCount42X(){pickerCount.textContent=pickerSelection42X.length+' fichier(s) s\u00e9lectionn\u00e9(s)';}\n    function renderPickerFiles42X(){\n      const folder=pickerFolders42X.find(item=>String(item.id)===String(pickerFolderId42X));const files=folder&&Array.isArray(folder.files)?folder.files:[];\n      if(!files.length){pickerFiles.innerHTML='<div class=\"evidence-selection42X\"><span>Ce dossier ne contient aucun fichier s\u00e9lectionnable.<\/span><\/div>';return;}\n      pickerFiles.innerHTML='<div class=\"evidence-picker-files42X\">'+files.map(file=>{const key=evidenceKey42X(file),checked=pickerSelection42X.some(item=>evidenceKey42X(item)===key);return '<label class=\"evidence-picker-file42X\"><input type=\"checkbox\" value=\"'+escape42X(key)+'\" '+(checked?'checked':'')+'><i class=\"fa-solid '+evidenceIcon42X(file)+'\"><\/i><span title=\"'+escape42X(evidenceName42X(file))+'\">'+escape42X(evidenceName42X(file))+'<\/span><\/label>';}).join('')+'<\/div>';\n      pickerFiles.querySelectorAll('input[type=\"checkbox\"]').forEach(input=>input.addEventListener('change',()=>{const file=files.find(item=>evidenceKey42X(item)===input.value);if(!file)return;if(input.checked){if(!pickerSelection42X.some(item=>evidenceKey42X(item)===input.value))pickerSelection42X.push(file);}else pickerSelection42X=pickerSelection42X.filter(item=>evidenceKey42X(item)!==input.value);if(pickerContext42X==='report'&&pickerSelection42X.length>10){pickerSelection42X=pickerSelection42X.slice(0,10);input.checked=false;fileWarn.style.display='block';}else fileWarn.style.display='none';updatePickerCount42X();}));\n    }\n    function renderPickerFolders42X(){pickerFolders.innerHTML=pickerFolders42X.map(folder=>'<button type=\"button\" class=\"evidence-picker-folder42X '+(String(folder.id)===String(pickerFolderId42X)?'active':'')+'\" data-picker-folder=\"'+escape42X(folder.id)+'\"><i class=\"fa-solid '+(folder.virtual?'fa-download':'fa-folder')+'\"><\/i><span>'+escape42X(folder.name)+'<\/span><\/button>').join('');pickerFolders.querySelectorAll('[data-picker-folder]').forEach(btn=>btn.addEventListener('click',()=>{pickerFolderId42X=btn.dataset.pickerFolder;renderPickerFolders42X();renderPickerFiles42X();}));}\n    function openEvidencePicker42X(context){\n      pickerContext42X=context;pickerFolders42X=window.BERF_FILE_MANAGER&&window.BERF_FILE_MANAGER.listAccessibleFolders?window.BERF_FILE_MANAGER.listAccessibleFolders():[];pickerSelection42X=normalizeEvidence42X(context==='report'?reportEvidenceDraft42X:suspectEvidenceDraft42X).slice();\n      const collected=pickerFolders42X.find(item=>item.virtual);pickerFolderId42X=String((collected||pickerFolders42X[0]||{}).id||'');scope.querySelector('#evidencePickerConfirm42X').textContent=context==='report'?'Joindre au rapport':'Associer au dossier';renderPickerFolders42X();renderPickerFiles42X();updatePickerCount42X();picker.setAttribute('data-open','true');picker.setAttribute('aria-hidden','false');\n      try{if(window.BERF_EVENTS)window.BERF_EVENTS.trigger('evidence_picker_opened',context,{context,suspectName:scope.querySelector('#suspect-name42X').value||''});}catch(e){}\n    }\n    function closeEvidencePicker42X(){picker.removeAttribute('data-open');picker.setAttribute('aria-hidden','true');}\n\n    function logMessage42X(message){\n      const p = document.createElement(\"p\");\n      p.textContent = `> ${message}`;\n      logContainer.appendChild(p);\n      logContainer.scrollTop = logContainer.scrollHeight;\n    }\n\n    function generateAvatar42X(name){\n      const initials = name.split(\" \").map(w => w.charAt(0)).join(\"\");\n      const color = `#${Math.floor(Math.random()*16777215).toString(16).padStart(6,'0')}`;\n      return { initials, color };\n    }\n\n    function saveSuspectsToLocalStorage42X(){ localStorage.setItem(\"suspects\", JSON.stringify(suspects)); }\n\n    function openModal42X(index=null){\n      editIndex = index;\n      if(index !== null){\n        modalTitle.textContent = \"Modifier le Suspect\";\n        scope.querySelector(\"#suspect-name42X\").value = suspects[index].name;\n        scope.querySelector(\"#suspect-mobile42X\").value = suspects[index].mobile;\n        scope.querySelector(\"#suspect-alibi42X\").value = suspects[index].alibi;\n        scope.querySelector(\"#suspect-relation42X\").value = suspects[index].relation;\n        suspectEvidenceDraft42X = normalizeEvidence42X(suspects[index].evidenceFiles);\n      }else{\n        modalTitle.textContent = \"Ajouter un Suspect\";\n        formSuspect.reset();\n        suspectEvidenceDraft42X = [];\n      }\n      renderEvidenceSelection42X(suspectEvidenceList,suspectEvidenceDraft42X,'Aucun fichier associ\u00e9.',true);\n      modalSuspect.style.display = \"flex\";\n    }\n    function closeModal42X(){ modalSuspect.style.display = \"none\"; }\n\n    function deleteSuspect42X(index){\n      suspects.splice(index, 1);\n      saveSuspectsToLocalStorage42X();\n      renderTable42X();\n    }\n\n    function openReportModal42X(index){\n      selectedSuspectIndex = index;\n      reportEvidenceDraft42X = normalizeEvidence42X((suspects[index]||{}).evidenceFiles).slice(0,10);\n      renderEvidenceSelection42X(reportEvidenceList,reportEvidenceDraft42X,'Aucun fichier s\u00e9lectionn\u00e9.',true);\n      reportEmailSelect.innerHTML = '<option value=\"\">Choisir un email...<\/option>';\n      emails.forEach(email=>{\n        const opt = document.createElement(\"option\");\n        opt.value = email;\n        opt.textContent = email;\n        reportEmailSelect.appendChild(opt);\n      });\n      modalReport.style.display = \"flex\";\n    }\n    function closeReportModal42X(){ modalReport.style.display = \"none\"; }\n\n    scope.querySelector(\"#btnNewSuspect42X\").addEventListener(\"click\", ()=> openModal42X(null));\n    scope.querySelector(\"#btnCancelSuspect42X\").addEventListener(\"click\", closeModal42X);\n    scope.querySelector(\"#btnCancelReport42X\").addEventListener(\"click\", closeReportModal42X);\n    scope.querySelector('#suspect-evidence-open42X').addEventListener('click',()=>openEvidencePicker42X('suspect'));\n    scope.querySelector('#report-evidence-open42X').addEventListener('click',()=>openEvidencePicker42X('report'));\n    scope.querySelectorAll('[data-evidence-picker-close]').forEach(btn=>btn.addEventListener('click',closeEvidencePicker42X));\n    scope.querySelector('#evidencePickerConfirm42X').addEventListener('click',()=>{\n      const previous=pickerContext42X==='report'?reportEvidenceDraft42X:suspectEvidenceDraft42X;\n      const added=pickerSelection42X.filter(item=>!previous.some(old=>evidenceKey42X(old)===evidenceKey42X(item)));\n      if(pickerContext42X==='report'){reportEvidenceDraft42X=normalizeEvidence42X(pickerSelection42X).slice(0,10);renderEvidenceSelection42X(reportEvidenceList,reportEvidenceDraft42X,'Aucun fichier s\u00e9lectionn\u00e9.',true);}else{suspectEvidenceDraft42X=normalizeEvidence42X(pickerSelection42X);renderEvidenceSelection42X(suspectEvidenceList,suspectEvidenceDraft42X,'Aucun fichier associ\u00e9.',true);}\n      added.forEach(file=>{try{if(window.BERF_EVENTS)window.BERF_EVENTS.trigger('suspect_evidence_attached',evidenceKey42X(file),{file,context:pickerContext42X,suspectName:scope.querySelector('#suspect-name42X').value||((suspects[selectedSuspectIndex]||{}).name)||''});}catch(e){}});closeEvidencePicker42X();\n    });\n\n    function renderTable42X(){\n      tableBody.innerHTML = \"\";\n      suspects.forEach((suspect, index)=>{\n        const row = document.createElement(\"tr\");\n        const av = generateAvatar42X(suspect.name);\n\n        row.innerHTML = `\n          <td><div class=\"avatar42X\" style=\"background-color:${av.color}\">${av.initials}<\/div><\/td>\n          <td>${suspect.name}<\/td>\n          <td>${suspect.mobile}<\/td>\n          <td>${suspect.alibi}<\/td>\n          <td>${suspect.relation || \"\"}<\/td>\n          <td><div class=\"evidence-table42X\">${normalizeEvidence42X(suspect.evidenceFiles).length?normalizeEvidence42X(suspect.evidenceFiles).map(file=>'<button type=\"button\" data-table-evidence=\"'+escape42X(evidenceKey42X(file))+'\" data-suspect-index=\"'+index+'\"><i class=\"fa-solid '+evidenceIcon42X(file)+'\"><\/i> '+escape42X(evidenceName42X(file))+'<\/button>').join(''):(suspect.indices?'<span>'+escape42X(suspect.indices)+'<\/span>':'<span>\u2014<\/span>')}<\/div><\/td>\n          <td>\n            <button class=\"action-btn42X edit-icon42X\" data-edit=\"${index}\"><i class=\"fa-solid fa-pencil-alt\"><\/i><\/button>\n            <button class=\"action-btn42X delete-icon42X\" data-del=\"${index}\"><i class=\"fa-solid fa-trash-alt\"><\/i><\/button>\n            <button class=\"action-btn42X report-icon42X\" data-report=\"${index}\"><i class=\"fa-regular fa-file-lines\"><\/i><\/button>\n          <\/td>\n        `;\n        tableBody.appendChild(row);\n      });\n\n      tableBody.querySelectorAll(\"[data-edit]\").forEach(b=> b.addEventListener(\"click\", ()=> openModal42X(Number(b.dataset.edit))));\n      tableBody.querySelectorAll(\"[data-del]\").forEach(b=> b.addEventListener(\"click\", ()=> deleteSuspect42X(Number(b.dataset.del))));\n      tableBody.querySelectorAll(\"[data-report]\").forEach(b=> b.addEventListener(\"click\", ()=> openReportModal42X(Number(b.dataset.report))));\n      tableBody.querySelectorAll('[data-table-evidence]').forEach(btn=>btn.addEventListener('click',()=>{const suspect=suspects[Number(btn.dataset.suspectIndex)]||{};const file=normalizeEvidence42X(suspect.evidenceFiles).find(item=>evidenceKey42X(item)===btn.dataset.tableEvidence);if(file&&window.BERF_FILE_MANAGER)window.BERF_FILE_MANAGER.openFile(file);}));\n    }\n\n    formSuspect.addEventListener(\"submit\", (event)=>{\n      event.preventDefault();\n      const suspect = {\n        name: scope.querySelector(\"#suspect-name42X\").value,\n        mobile: scope.querySelector(\"#suspect-mobile42X\").value,\n        alibi: scope.querySelector(\"#suspect-alibi42X\").value,\n        relation: scope.querySelector(\"#suspect-relation42X\").value,\n        indices: editIndex !== null ? String(suspects[editIndex].indices || '') : '',\n        evidenceFiles: normalizeEvidence42X(suspectEvidenceDraft42X)\n      };\n      if(editIndex !== null) suspects[editIndex] = suspect;\n      else suspects.push(suspect);\n\n      saveSuspectsToLocalStorage42X();\n      renderTable42X();\n      closeModal42X();\n    });\n\n    window.addEventListener(\"click\", (event)=>{\n      if(event.target === modalSuspect) closeModal42X();\n      if(event.target === modalReport) closeReportModal42X();\n      if(event.target === picker) closeEvidencePicker42X();\n    });\n\n    formReport.addEventListener(\"submit\", function(event){\n      event.preventDefault();\n      const email = reportEmailSelect.value;\n      const reason = reportReason.value;\n      const details = reportDetails.value;\n\n      if(!email){ alert(\"Veuillez s\u00e9lectionner un email.\"); return; }\n\n      if(email === \"eta974@berf-nat.fr\"){\n        localStorage.setItem(\"test_mail_request\", JSON.stringify({ timestamp: Date.now() }));\n        formReport.reset(); closeReportModal42X();\n        return;\n      }\n\n      loader.style.display = \"block\";\n      logMessage42X(\"D\u00e9but de la proc\u00e9dure d'envoi du rapport...\");\n\n      setTimeout(()=>{\n        logMessage42X(`Envoi du rapport \u00e0 ${email}...`);\n        setTimeout(()=>{\n          loader.style.display = \"none\";\n          successMessage.style.display = \"block\";\n          logMessage42X(\"Rapport envoy\u00e9 avec succ\u00e8s!\");\n\n          const suspect = suspects[selectedSuspectIndex] || { name:\"Suspect\" };\n          const mail = {\n            sender: \"system@berf-nat.fr\",\n            subject: `Rapport suspect \u2013 ${suspect.name} \u2013 ${reason}`,\n            body:\n`Rapport g\u00e9n\u00e9r\u00e9 depuis le Dossier Suspects.\n\nDESTINATAIRE : ${email}\nSUSPECT      : ${suspect.name}\nMOBILE       : ${suspect.mobile || \"-\"}\nALIBI        : ${suspect.alibi || \"-\"}\nACTES        : ${suspect.relation || \"-\"}\nPI\u00c8CES       : ${reportEvidenceDraft42X.length ? reportEvidenceDraft42X.map(evidenceName42X).join(', ') : \"-\"}\n\nMOTIF        : ${reason}\n\nD\u00c9TAILS :\n${details || \"(Aucun)\"}\n`,\n            attachments: reportEvidenceDraft42X.map(file=>({name:evidenceName42X(file),filename:evidenceName42X(file),url:file.url||'',type:file.type||file.mime||''}))\n          };\n\n          if(window.BERF_MAIL && typeof window.BERF_MAIL.addEmail === \"function\"){\n            window.BERF_MAIL.addEmail(mail);\n          }\n\n          setTimeout(()=>{ successMessage.style.display = \"none\"; closeReportModal42X(); }, 2500);\n          formReport.reset();\n        }, 1000);\n      }, 500);\n    });\n\n    logMessage42X(\"Initialisation du syst\u00e8me...\");\n    setTimeout(()=>logMessage42X(\"Connexion \u00e0 la base de donn\u00e9es des suspects...\"), 700);\n    setTimeout(()=>logMessage42X(\"Syst\u00e8me op\u00e9rationnel.\"), 1400);\n\n    renderTable42X();\n  })();\n\n  \/* =========================================================\n     TOOL #3 : CRYPTO (scop\u00e9 + API)\n     ========================================================= *\/\n  (function(){\n    const scope = document.getElementById(\"berfCryptoTool\");\n    if(!scope) return;\n\n    let isEncryptMode = true;\n    let lastCryptoSuccessFingerprint = '';\n\n    const keyEl = scope.querySelector(\"#key01\");\n    const msgEl = scope.querySelector(\"#message01\");\n    const outEl = scope.querySelector(\"#output01\");\n    const btnToggle = scope.querySelector(\"#btnToggleMode01\");\n    const btnCopy = scope.querySelector(\"#btnCopy01\");\n    const modeIndicator = scope.querySelector(\"#modeIndicator01\");\n    const labelMessage = scope.querySelector(\"#message-label01\");\n    const labelOutput = scope.querySelector(\"#output-label01\");\n    const toast = scope.querySelector(\"#toast\");\n\n    function cleanKey(key){\n      return key.toUpperCase().replace(\/[^A-Z]\/g,'').slice(0,3);\n    }\n\n    function applyTransformation(message, key, encrypt=true){\n      const keyLength = key.length;\n      let transformed = '';\n      let keyIndex = 0;\n\n      for(let i=0; i<message.length; i++){\n        const char = message[i];\n        const charCode = message.charCodeAt(i);\n\n        if(\/[A-Za-z]\/.test(char)){\n          const base = char >= 'a' ? 97 : 65;\n          const keyCode = key.charCodeAt(keyIndex % keyLength) - 65;\n\n          const newCharCode = encrypt\n            ? (charCode - base + keyCode) % 26 + base\n            : (charCode - base - keyCode + 26) % 26 + base;\n\n          transformed += String.fromCharCode(newCharCode);\n          keyIndex++;\n        }else{\n          transformed += char;\n        }\n      }\n      return transformed;\n    }\n\n    function normalizeCryptoValue(value){\n      return String(value || '')\n        .normalize('NFD')\n        .replace(\/[\\u0300-\\u036f]\/g, '')\n        .toLowerCase()\n        .replace(\/[^a-z0-9]+\/g, '');\n    }\n\n    function validateConfiguredSolution(key, message, output){\n      if(isEncryptMode){ lastCryptoSuccessFingerprint=''; return; }\n      const solutions = Array.isArray(window.BERFDB && window.BERFDB.CRYPTO_SOLUTIONS) ? window.BERFDB.CRYPTO_SOLUTIONS : [];\n      let matched = false;\n      solutions.forEach(solution=>{\n        if(!solution || !solution.id) return;\n        const keyOk = cleanKey(solution.key || '') === key;\n        const expectedCipher = normalizeCryptoValue(solution.cipher_text);\n        const expectedPlain = normalizeCryptoValue(solution.plain_text);\n        const cipherOk = !expectedCipher || expectedCipher === normalizeCryptoValue(message);\n        const plainOk = !expectedPlain || expectedPlain === normalizeCryptoValue(output);\n        if(keyOk && cipherOk && plainOk){\n          matched = true;\n          const solutionId=String(solution.id).trim();\n          const fingerprint=[solutionId,key,normalizeCryptoValue(message),normalizeCryptoValue(output)].join('|');\n          if(fingerprint===lastCryptoSuccessFingerprint) return;\n          lastCryptoSuccessFingerprint=fingerprint;\n          try{\n            const payload={ solution, solutionId, key, message, output };\n            if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('crypto_decryption_success', solutionId, payload);\n            window.dispatchEvent(new CustomEvent('berf:crypto-decryption-success',{detail:payload}));\n          }catch(e){}\n        }\n      });\n      if(!matched) lastCryptoSuccessFingerprint='';\n    }\n\n    function autoTransform(){\n      const key = cleanKey(keyEl.value);\n      if(keyEl.value !== key) keyEl.value = key;\n      const message = msgEl.value;\n\n      if(key && message){\n        outEl.value = applyTransformation(message, key, isEncryptMode);\n        validateConfiguredSolution(key, message, outEl.value);\n      }else{\n        outEl.value = \"\";\n      }\n    }\n\n    function showToast(message){\n      toast.textContent = message;\n      toast.className = \"toast show\";\n      setTimeout(()=>{ toast.className = toast.className.replace(\"show\",\"\"); }, 3000);\n    }\n\n    function toggleMode(){\n      isEncryptMode = !isEncryptMode;\n      labelMessage.textContent = isEncryptMode ? \"Message \u00e0 crypter :\" : \"Message \u00e0 d\u00e9crypter :\";\n      labelOutput.textContent = isEncryptMode ? \"Message crypt\u00e9 :\" : \"Message d\u00e9crypt\u00e9 :\";\n\n      if(isEncryptMode){\n        modeIndicator.textContent = \"Mode : Crypteur\";\n        modeIndicator.classList.add(\"encrypt-mode01\");\n        modeIndicator.classList.remove(\"decrypt-mode01\");\n      }else{\n        modeIndicator.textContent = \"Mode : D\u00e9crypteur\";\n        modeIndicator.classList.add(\"decrypt-mode01\");\n        modeIndicator.classList.remove(\"encrypt-mode01\");\n      }\n      autoTransform();\n    }\n\n    async function copyText(){\n      const textToCopy = outEl.value;\n      if(!textToCopy) return;\n      try{\n        if(navigator.clipboard && typeof navigator.clipboard.writeText === 'function'){\n          await navigator.clipboard.writeText(textToCopy);\n        }else{\n          outEl.focus();\n          outEl.select();\n          outEl.setSelectionRange(0, textToCopy.length);\n          const copied = document.execCommand && document.execCommand('copy');\n          if(!copied) throw new Error('copie non autorisee par le navigateur');\n          if(window.getSelection) window.getSelection().removeAllRanges();\n        }\n        showToast(isEncryptMode ? \"Texte crypt\u00e9 copi\u00e9 dans le presse-papiers !\" : \"Texte d\u00e9crypt\u00e9 copi\u00e9 dans le presse-papiers !\");\n      }catch(err){\n        showToast(\"Erreur lors de la copie : \" + err);\n      }\n    }\n\n    keyEl.addEventListener(\"input\", autoTransform);\n    msgEl.addEventListener(\"input\", autoTransform);\n    btnToggle.addEventListener(\"click\", toggleMode);\n    btnCopy.addEventListener(\"click\", copyText);\n\n    window.BERF_CRYPTO = window.BERF_CRYPTO || {};\n    window.BERF_CRYPTO.encrypt = (key, text) => applyTransformation(String(text||\"\"), cleanKey(String(key||\"\")), true);\n    window.BERF_CRYPTO.decrypt = (key, text) => applyTransformation(String(text||\"\"), cleanKey(String(key||\"\")), false);\n  })();\n\n  \/* =========================================================\n     TOOL #4 : TROMBI (scop\u00e9)\n     ========================================================= *\/\n  (function(){\n    const scope = document.getElementById(\"berfTrombiTool\");\n    if(!scope) return;\n\n    const input = scope.querySelector(\"#search-bar-77\");\n    const grid = scope.querySelector(\"#trombinoscope-77\");\n    const countEl = scope.querySelector(\"#trombiCount77\");\n\n    const modal = scope.querySelector(\"#modal-77\");\n    const btnClose = scope.querySelector(\"#trombiClose77\");\n\n    const elNom = scope.querySelector(\"#modal-nom\");\n    const elPhoto = scope.querySelector(\"#modal-photo\");\n    const elDOB = scope.querySelector(\"#modal-date_naissance\");\n    const elPOB = scope.querySelector(\"#modal-lieu-naissance\");\n    const elEntry = scope.querySelector(\"#modal-date-entree\");\n    const elSpec = scope.querySelector(\"#modal-specialite\");\n    const elCode = scope.querySelector(\"#modal-nom-de-code\");\n    const elPhone = scope.querySelector(\"#modal-phone\");\n    const elEmail = scope.querySelector(\"#modal-email\");\n\n    const legacyAgents = [\n      { nom: 'Belhair', prenom: 'V\u00e9rril', date_naissance: '12\/05\/1978', lieu_naissance: 'Paris', date_entree: '15\/06\/2005', specialite: 'Cryptozoologie', nom_de_code: 'Eta974', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Eta974.webp', phone: '07 42 23 65 87', email: 'eta974@berf-nat.fr' },\n      { nom: 'Dufort', prenom: 'Paul', date_naissance: '23\/07\/1956', lieu_naissance: 'Lyon', date_entree: '03\/08\/1989', specialite: 'Mythologie', nom_de_code: 'Le Sage', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Le-sage.webp', phone: '07 42 34 12 98', email: 'rho887@berf-nat.fr' },\n      { nom: 'Gamerault', prenom: 'Claire', date_naissance: '15\/03\/2001', lieu_naissance: 'Marseille', date_entree: '12\/11\/2021', specialite: 'Technologie et analyse de donn\u00e9es', nom_de_code: 'Pixel', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Pixel.webp', phone: '07 42 45 78 21', email: 'pixel@berf-nat.fr' },\n      { nom: 'Lemaitre', prenom: 'Madeleine', date_naissance: '10\/02\/1960', lieu_naissance: 'Toulouse', date_entree: '25\/04\/1990', specialite: 'Folklore et l\u00e9gendes', nom_de_code: 'Theta005', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-31.webp', phone: '07 42 56 89 32', email: 'theta005@berf-nat.fr' },\n      { nom: 'Dubois', prenom: 'Catherine', date_naissance: '22\/11\/1965', lieu_naissance: 'Nice', date_entree: '14\/06\/1995', specialite: 'Arch\u00e9ologie myst\u00e9rieuse', nom_de_code: 'Sigma009', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-24.webp', phone: '07 42 67 12 43', email: 'sigma009@berf-nat.fr' },\n      { nom: 'Ali', prenom: 'Leila', date_naissance: '19\/04\/1976', lieu_naissance: 'Nantes', date_entree: '08\/07\/2002', specialite: 'L\u00e9gendes maritimes', nom_de_code: 'Mu021', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-22.webp', phone: '07 42 78 34 54', email: 'mu021@berf-nat.fr' },\n      { nom: 'Moreau', prenom: 'Elena', date_naissance: '07\/08\/1983', lieu_naissance: 'Montpellier', date_entree: '03\/05\/2009', specialite: 'Cryptozoologie urbaine', nom_de_code: 'Nu333', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-20.webp', phone: '07 42 89 45 65', email: 'nu333@berf-nat.fr' },\n      { nom: 'Benoit', prenom: 'Isabelle', date_naissance: '28\/12\/1975', lieu_naissance: 'Bordeaux', date_entree: '27\/09\/2001', specialite: 'Investigations paranormales', nom_de_code: 'Xi012', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-19.webp', phone: '07 42 90 56 76', email: 'xi012@berf-nat.fr' },\n      { nom: 'Durand', prenom: 'Sylvie', date_naissance: '05\/01\/1960', lieu_naissance: 'Rennes', date_entree: '12\/04\/1985', specialite: 'Mythologie ancienne', nom_de_code: 'Gamma107', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-18.webp', phone: '07 42 11 67 87', email: 'gamma107@berf-nat.fr' },\n      { nom: 'Patel', prenom: 'Anjali', date_naissance: '14\/09\/1990', lieu_naissance: 'Paris', date_entree: '06\/08\/2015', specialite: 'Entit\u00e9s surnaturelles', nom_de_code: 'Beta002', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-14.webp', phone: '07 42 22 78 98', email: 'beta002@berf-nat.fr' },\n      { nom: 'Leroy', prenom: 'Marie', date_naissance: '03\/05\/1957', lieu_naissance: 'Lille', date_entree: '11\/11\/1980', specialite: 'Folklore europ\u00e9en', nom_de_code: 'Psi099', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-9.webp', phone: '07 42 33 89 09', email: 'psi099@berf-nat.fr' },\n      { nom: 'Martin', prenom: 'Camille', date_naissance: '22\/10\/1959', lieu_naissance: 'Paris', date_entree: '15\/05\/1982', specialite: 'L\u00e9gendes oubli\u00e9es', nom_de_code: 'Delta014', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-8.webp', phone: '07 42 44 90 10', email: 'delta014@berf-nat.fr' },\n      { nom: 'Tremblay', prenom: 'Louise', date_naissance: '12\/06\/1980', lieu_naissance: 'Lyon', date_entree: '22\/10\/2007', specialite: 'Enqu\u00eates paranormales', nom_de_code: 'Omega323', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-7.webp', phone: '07 42 55 01 21', email: 'omega323@berf-nat.fr' },\n      { nom: 'Ngono', prenom: 'Jean', date_naissance: '18\/11\/1953', lieu_naissance: 'Toulouse', date_entree: '07\/04\/1978', specialite: 'Mythes anciens', nom_de_code: 'Alpha011', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-1.webp', phone: '07 42 66 12 32', email: 'alpha011@berf-nat.fr' },\n      { nom: 'Kawasaki', prenom: 'Takeshi', date_naissance: '15\/04\/1981', lieu_naissance: 'Tokyo', date_entree: '30\/06\/2005', specialite: 'Mythes asiatiques', nom_de_code: 'Lambda045', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent2.webp', phone: '07 42 77 23 43', email: 'lambda045@berf-nat.fr' },\n      { nom: 'Hoshino', prenom: 'Akira', date_naissance: '23\/05\/1943', lieu_naissance: 'Kyoto', date_entree: '12\/08\/1975', specialite: 'Cryptides marins', nom_de_code: 'Zeta501', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-3.webp', phone: '07 42 88 34 54', email: 'zeta501@berf-nat.fr' },\n      { nom: 'Dubois', prenom: 'Michel', date_naissance: '06\/07\/1961', lieu_naissance: 'Nice', date_entree: '24\/10\/1986', specialite: 'L\u00e9gendes urbaines', nom_de_code: 'Kappa023', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-4.webp', phone: '07 42 99 45 65', email: 'kappa023@berf-nat.fr' },\n      { nom: 'Delacroix', prenom: 'Amaury', date_naissance: '11\/09\/1985', lieu_naissance: 'Marseille', date_entree: '09\/02\/2010', specialite: 'Cr\u00e9atures mythiques', nom_de_code: 'Theta004', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-5.webp', phone: '07 42 10 56 76', email: 'theta004@berf-nat.fr' },\n      { nom: 'Morel', prenom: 'Thibault', date_naissance: '24\/08\/1982', lieu_naissance: 'Strasbourg', date_entree: '14\/07\/2008', specialite: 'Investigations paranormales', nom_de_code: 'Delta006', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-6.webp', phone: '07 42 21 67 87', email: 'epsilon075@berf-nat.fr' },\n      { nom: 'Lefebvre', prenom: 'Henri', date_naissance: '17\/11\/1964', lieu_naissance: 'Bordeaux', date_entree: '05\/05\/1989', specialite: 'Entit\u00e9s surnaturelles', nom_de_code: 'Epsilon103', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-10.webp', phone: '07 42 32 78 98', email: 'epsilon103@berf-nat.fr' },\n      { nom: 'Giraud', prenom: 'Claude', date_naissance: '14\/02\/1952', lieu_naissance: 'Paris', date_entree: '07\/07\/1976', specialite: 'Mythologie grecque', nom_de_code: 'Rho077', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-11.webp', phone: '07 42 43 89 09', email: 'rho077@berf-nat.fr' },\n      { nom: 'Boussif', prenom: 'Nadir', date_naissance: '29\/03\/1989', lieu_naissance: 'Oran', date_entree: '25\/03\/2014', specialite: 'Mythes du d\u00e9sert', nom_de_code: 'Xi045', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-12.webp', phone: '07 42 54 90 10', email: 'xi045@berf-nat.fr' },\n      { nom: 'Smith', prenom: 'Louis', date_naissance: '18\/07\/1953', lieu_naissance: 'Londres', date_entree: '15\/02\/1980', specialite: 'L\u00e9gendes britanniques', nom_de_code: 'Phi033', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-13.webp', phone: '07 42 65 01 21', email: 'phi033@berf-nat.fr' },\n      { nom: 'Fournier', prenom: 'Jacques', date_naissance: '30\/08\/1962', lieu_naissance: 'Lille', date_entree: '10\/06\/1987', specialite: 'L\u00e9gendes anciennes', nom_de_code: 'Chi012', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-15.webp', phone: '07 42 76 12 32', email: 'chi012@berf-nat.fr' },\n      { nom: 'Lemoine', prenom: 'Georges', date_naissance: '05\/11\/1966', lieu_naissance: 'Bruxelles', date_entree: '20\/08\/1991', specialite: 'Mythologie nordique', nom_de_code: 'Eta005', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2025\/01\/Agent-LM.webp', phone: '07 42 87 23 43', email: 'eta005@berf-nat.fr' },\n      { nom: 'Martin', prenom: 'G\u00e9rard', date_naissance: '11\/12\/1963', lieu_naissance: 'Gen\u00e8ve', date_entree: '19\/04\/1989', specialite: 'Fant\u00f4mes et esprits', nom_de_code: 'Iota019', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-17.webp', phone: '07 42 98 34 54', email: 'iota019@berf-nat.fr' },\n      { nom: 'Redfeather', prenom: 'Talon', date_naissance: '25\/06\/1973', lieu_naissance: 'Phoenix', date_entree: '09\/07\/1998', specialite: 'Mythes am\u00e9rindiens', nom_de_code: 'Pi007', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-21.webp', phone: '07 42 09 45 65', email: 'pi007@berf-nat.fr' },\n      { nom: 'Guerrero', prenom: 'Manuel', date_naissance: '14\/04\/1964', lieu_naissance: 'Mexico', date_entree: '06\/01\/1989', specialite: 'Mythologie sud-am\u00e9ricaine', nom_de_code: 'Omega033', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-23.webp', phone: '07 42 10 56 76', email: 'omega033@berf-nat.fr' },\n      { nom: 'Peters', prenom: 'William', date_naissance: '02\/10\/1974', lieu_naissance: 'Los Angeles', date_entree: '22\/12\/2000', specialite: 'Mythes modernes', nom_de_code: 'Sigma011', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-25.webp', phone: '07 42 11 67 87', email: 'sigma011@berf-nat.fr' },\n      { nom: 'Johnson', prenom: 'David', date_naissance: '21\/09\/1970', lieu_naissance: 'New York', date_entree: '14\/02\/1995', specialite: 'Enqu\u00eates myst\u00e9rieuses', nom_de_code: 'Tau022', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-26.webp', phone: '07 42 12 78 98', email: 'tau022@berf-nat.fr' },\n      { nom: 'Lambert', prenom: 'Alain', date_naissance: '07\/01\/1961', lieu_naissance: 'Marseille', date_entree: '20\/04\/1986', specialite: 'Esprits vengeurs', nom_de_code: 'Beta006', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-29.webp', phone: '07 42 43 89 09', email: 'beta006@berf-nat.fr' },\n      { nom: 'Harrison', prenom: 'James', date_naissance: '05\/05\/1943', lieu_naissance: 'Londres', date_entree: '11\/11\/1967', specialite: 'Fant\u00f4mes et esprits', nom_de_code: 'Xi099', photo: 'https:\/\/lultime-frisson.com\/wp-content\/uploads\/2024\/09\/Agent-30.webp', phone: '07 42 54 90 10', email: 'xi099@berf-nat.fr' }\n    ];\n    const configuredAgents = window.BERFDB && window.BERFDB.BOOT && window.BERFDB.BOOT.data && window.BERFDB.BOOT.data.mission_registry && Array.isArray(window.BERFDB.BOOT.data.mission_registry.agents)\n      ? window.BERFDB.BOOT.data.mission_registry.agents : [];\n    const agents = configuredAgents.length ? configuredAgents.map(a=>({\n      nom:a.last_name||'', prenom:a.first_name||'', nom_de_code:a.code||'', specialite:a.specialty||a.role||'',\n      date_naissance:a.birth_date||'', lieu_naissance:a.birth_place||'', date_entree:a.entry_date||'',\n      phone:a.phone||'', email:a.email||'', photo:a.photo||'', statut:a.status||'available', fonction:a.role||''\n    })) : legacyAgents;\n\n    function normalize(str){\n      return String(str || \"\")\n        .normalize(\"NFD\")\n        .replace(\/[\\u0300-\\u036f]\/g, \"\")\n        .toLowerCase()\n        .trim();\n    }\n\n    function agentMatches(agent, q){\n      if(!q) return true;\n      const hay = normalize([\n        agent.nom, agent.prenom, agent.nom_de_code, agent.specialite, agent.email\n      ].join(\" \"));\n      return hay.includes(q);\n    }\n\n    function render(list){\n      grid.innerHTML = \"\";\n      const frag = document.createDocumentFragment();\n\n      list.forEach(agent=>{\n        const card = document.createElement(\"div\");\n        card.className = \"agent-77\";\n        card.innerHTML = `\n          <img decoding=\"async\" src=\"${agent.photo}\" alt=\"Agent ${agent.nom}\">\n          <div class=\"info-77\">\n            <div class=\"line1\">${agent.prenom} ${agent.nom}<\/div>\n            <div class=\"line2\">${agent.nom_de_code}<\/div>\n            <div class=\"line3\">${agent.specialite}<\/div>\n          <\/div>\n        `;\n        card.addEventListener(\"click\", ()=> openModal(agent));\n        frag.appendChild(card);\n      });\n\n      grid.appendChild(frag);\n      countEl.textContent = String(list.length);\n    }\n\n    function openModal(agent){\n      elNom.textContent = `${agent.prenom} ${agent.nom}`;\n      elPhoto.src = agent.photo;\n      scope.querySelector(\"#modal-date-naissance\").textContent = agent.date_naissance;\n      elPOB.textContent = agent.lieu_naissance;\n      elEntry.textContent = agent.date_entree;\n      elSpec.textContent = agent.specialite;\n      elCode.textContent = agent.nom_de_code;\n      elPhone.textContent = agent.phone;\n      elEmail.textContent = agent.email;\n\n      modal.setAttribute(\"data-open\",\"true\");\n      modal.setAttribute(\"aria-hidden\",\"false\");\n    }\n\n    function closeModal(){\n      modal.removeAttribute(\"data-open\");\n      modal.setAttribute(\"aria-hidden\",\"true\");\n    }\n\n    btnClose.addEventListener(\"click\", closeModal);\n    modal.addEventListener(\"click\", (e)=>{\n      if(e.target === modal) closeModal();\n    });\n\n    window.addEventListener(\"keydown\",(e)=>{\n      if(e.key === \"Escape\" && modal.getAttribute(\"data-open\")===\"true\"){\n        closeModal();\n      }\n    });\n\n    let t = null;\n    input.addEventListener(\"input\", ()=>{\n      clearTimeout(t);\n      t = setTimeout(()=>{\n        const q = normalize(input.value);\n        render(agents.filter(a => agentMatches(a, q)));\n      }, 60);\n    });\n\n    render(agents);\n  })();\n\n  \/* =========================================================\n     AJOUT : TENNIS (am\u00e9lior\u00e9) \u2014 click sur #colision\n     ========================================================= *\/\n  (function(){\n    \/\/ \u00e9vite double init si Elementor rejoue les scripts\n    if(window.__BERF_TENNIS_INIT) return;\n    window.__BERF_TENNIS_INIT = true;\n\n    const modal = desk.querySelector(\"#bdd-modal\");\n    const modalContent = desk.querySelector(\"#bdd-modal-content\");\n    const canvas = desk.querySelector(\"#bdd-canvas\");\n    const ctx = canvas.getContext(\"2d\");\n\n    const btnOpen = desk.querySelector(\"#colision\");\n    const btnClose = desk.querySelector(\"#bdd-close-button\");\n    const btnRestart = desk.querySelector(\"#bdd-restart\");\n    const overlay = desk.querySelector(\"#bdd-overlay\");\n    const btnPlay = desk.querySelector(\"#bdd-play\");\n\n    const scoreEl = desk.querySelector(\"#bdd-score\");\n    const levelEl = desk.querySelector(\"#bdd-level\");\n\n    if(!modal || !canvas || !btnOpen || !btnClose) return;\n\n    \/\/ --- \u00e9tat ---\n    let rafId = null;\n    let running = false;\n    let paused = false;\n\n    \/\/ contr\u00f4le\n    let leftPressed = false;\n    let rightPressed = false;\n    let targetX = null; \/\/ souris\/tactile: position cible\n\n    \/\/ dimensions & objets\n    const state = {\n      score: 0,\n      level: 1,\n      speedMul: 1.0,\n\n      paddle: { w: 120, h: 12, x: 0, y: 0, speed: 9 },\n      opp:    { w: 120, h: 12, x: 0, y: 0 },\n      ball:   { r: 10, x: 0, y: 0, vx: 3.2, vy: 3.2 },\n    };\n\n    function clamp(v, min, max){ return Math.max(min, Math.min(max, v)); }\n\n    function setOpen(isOpen){\n      if(isOpen){\n        modal.style.display = \"flex\";\n        modal.setAttribute(\"data-open\",\"true\");\n        modal.setAttribute(\"aria-hidden\",\"false\");\n\n        \/\/ ferme le start menu si ouvert (sans modifier son code)\n        if(typeof window.__BERF_HIDE_START_MENU === \"function\"){\n          window.__BERF_HIDE_START_MENU();\n        }\n\n        \/\/ on affiche l\u2019overlay \"Jouer\" au premier open\n        overlay.removeAttribute(\"data-hidden\");\n        paused = true;\n        running = false;\n\n        fitCanvas();\n        renderFrame(); \/\/ affiche un frame propre\n\n        \/\/ focus pour accessibilit\u00e9 (ESC, space)\n        btnClose.focus({ preventScroll:true });\n      }else{\n        modal.style.display = \"none\";\n        modal.removeAttribute(\"data-open\");\n        modal.setAttribute(\"aria-hidden\",\"true\");\n        stopLoop();\n      }\n    }\n\n    function stopLoop(){\n      running = false;\n      paused = false;\n      if(rafId) cancelAnimationFrame(rafId);\n      rafId = null;\n    }\n\n    function startLoop(){\n      if(running) return;\n      running = true;\n      paused = false;\n      overlay.setAttribute(\"data-hidden\",\"true\");\n      tick();\n    }\n\n    function fitCanvas(){\n      \/\/ canvas full size du container\n      const rect = modalContent.getBoundingClientRect();\n      const w = Math.floor(rect.width);\n      const h = Math.floor(rect.height);\n\n      \/\/ on r\u00e9serve un peu d\u2019espace au HUD sans casser le layout\n      const devicePixelRatio = Math.max(1, Math.min(2, window.devicePixelRatio || 1));\n      canvas.width  = Math.floor(w * devicePixelRatio);\n      canvas.height = Math.floor(h * devicePixelRatio);\n      canvas.style.width = w + \"px\";\n      canvas.style.height = h + \"px\";\n      ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);\n\n      \/\/ recalage\n      state.paddle.y = h - state.paddle.h - 18;\n      state.opp.y = 18;\n\n      \/\/ clamp positions\n      state.paddle.x = clamp(state.paddle.x, 0, w - state.paddle.w);\n      state.opp.x = clamp(state.opp.x, 0, w - state.opp.w);\n      state.ball.x = clamp(state.ball.x, state.ball.r, w - state.ball.r);\n      state.ball.y = clamp(state.ball.y, state.ball.r, h - state.ball.r);\n    }\n\n    function resetGame(full=true){\n      const w = parseInt(canvas.style.width || \"800\", 10);\n      const h = parseInt(canvas.style.height || \"600\", 10);\n\n      state.score = 0;\n      state.level = 1;\n      state.speedMul = 1.0;\n\n      state.paddle.w = clamp(Math.round(w * 0.18), 90, 160);\n      state.paddle.h = 12;\n      state.paddle.x = (w - state.paddle.w) \/ 2;\n      state.paddle.y = h - state.paddle.h - 18;\n\n      state.opp.w = state.paddle.w;\n      state.opp.h = 12;\n      state.opp.x = (w - state.opp.w) \/ 2;\n      state.opp.y = 18;\n\n      state.ball.r = 10;\n      state.ball.x = w \/ 2;\n      state.ball.y = h \/ 2;\n\n      \/\/ direction pseudo al\u00e9atoire\n      const dir = Math.random() < 0.5 ? -1 : 1;\n      state.ball.vx = 3.2 * dir;\n      state.ball.vy = 3.2;\n\n      updateHud();\n\n      if(full){\n        paused = true;\n        running = false;\n        overlay.removeAttribute(\"data-hidden\");\n        renderFrame();\n      }\n    }\n\n    function updateHud(){\n      scoreEl.textContent = \"Score: \" + state.score;\n      levelEl.textContent = \"Level: \" + state.level;\n    }\n\n    function drawCourt(w,h){\n      ctx.clearRect(0,0,w,h);\n\n      \/\/ ligne centrale\n      ctx.save();\n      ctx.globalAlpha = 0.25;\n      ctx.strokeStyle = \"#ffffff\";\n      ctx.setLineDash([10, 10]);\n      ctx.beginPath();\n      ctx.moveTo(w\/2, 0);\n      ctx.lineTo(w\/2, h);\n      ctx.stroke();\n      ctx.restore();\n    }\n\n    function drawPaddle(x,y,w,h,color){\n      ctx.fillStyle = color;\n      ctx.fillRect(x, y, w, h);\n    }\n\n    function drawBall(x,y,r){\n      ctx.beginPath();\n      ctx.arc(x, y, r, 0, Math.PI*2);\n      ctx.fillStyle = \"#ff0\";\n      ctx.fill();\n      ctx.closePath();\n    }\n\n    function renderFrame(){\n      const w = parseInt(canvas.style.width || \"800\", 10);\n      const h = parseInt(canvas.style.height || \"600\", 10);\n\n      drawCourt(w,h);\n      \/\/ adversaire (rouge)\n      drawPaddle(state.opp.x, state.opp.y, state.opp.w, state.opp.h, \"#f00\");\n      \/\/ balle\n      drawBall(state.ball.x, state.ball.y, state.ball.r);\n      \/\/ joueur (blanc)\n      drawPaddle(state.paddle.x, state.paddle.y, state.paddle.w, state.paddle.h, \"#fff\");\n\n      \/\/ texte pause\n      if(paused && running){\n        ctx.save();\n        ctx.fillStyle = \"rgba(255,255,255,0.85)\";\n        ctx.font = \"700 20px system-ui, -apple-system, Segoe UI, Roboto, Arial\";\n        ctx.textAlign = \"center\";\n        ctx.fillText(\"PAUSE\", w\/2, Math.max(40, h*0.18));\n        ctx.restore();\n      }\n    }\n\n    function tick(){\n      if(!running){\n        return;\n      }\n      rafId = requestAnimationFrame(tick);\n      if(paused) return;\n\n      const w = parseInt(canvas.style.width || \"800\", 10);\n      const h = parseInt(canvas.style.height || \"600\", 10);\n\n      \/\/ input paddle\n      if(targetX !== null){\n        \/\/ suit la souris\/tactile avec lissage l\u00e9ger\n        const desired = clamp(targetX - state.paddle.w\/2, 0, w - state.paddle.w);\n        state.paddle.x += (desired - state.paddle.x) * 0.22;\n      }else{\n        if(rightPressed) state.paddle.x += state.paddle.speed;\n        if(leftPressed)  state.paddle.x -= state.paddle.speed;\n        state.paddle.x = clamp(state.paddle.x, 0, w - state.paddle.w);\n      }\n\n      \/\/ IA adversaire (simple + un peu d'erreur selon level)\n      const aim = state.ball.x - state.opp.w\/2;\n      const maxMove = 5 + state.level * 0.35;\n      state.opp.x += clamp(aim - state.opp.x, -maxMove, maxMove);\n      state.opp.x = clamp(state.opp.x, 0, w - state.opp.w);\n\n      \/\/ balle\n      state.ball.x += state.ball.vx * state.speedMul;\n      state.ball.y += state.ball.vy * state.speedMul;\n\n      \/\/ murs\n      if(state.ball.x + state.ball.r > w || state.ball.x - state.ball.r < 0){\n        state.ball.vx *= -1;\n        state.ball.x = clamp(state.ball.x, state.ball.r, w - state.ball.r);\n      }\n\n      \/\/ rebond haut = point\n      if(state.ball.y - state.ball.r <= 0){\n        state.ball.vy *= -1;\n        state.ball.y = state.ball.r;\n        state.score++;\n        if(state.score > 0 && state.score % 10 === 0){\n          state.level++;\n          \/\/ l\u00e9g\u00e8re mont\u00e9e de difficult\u00e9\n          state.speedMul = Math.min(1.65, state.speedMul * 1.06);\n        }\n        updateHud();\n      }\n\n      \/\/ collision joueur (bas)\n      const paddleTop = state.paddle.y;\n      const paddleLeft = state.paddle.x;\n      const paddleRight = state.paddle.x + state.paddle.w;\n\n      if(\n        state.ball.y + state.ball.r >= paddleTop &&\n        state.ball.y + state.ball.r <= paddleTop + state.paddle.h + 6 &&\n        state.ball.x >= paddleLeft &&\n        state.ball.x <= paddleRight &&\n        state.ball.vy > 0\n      ){\n        \/\/ rebond + angle selon impact\n        const hit = (state.ball.x - (paddleLeft + state.paddle.w\/2)) \/ (state.paddle.w\/2);\n        state.ball.vy *= -1;\n        state.ball.vx += hit * 0.9;\n\n        \/\/ acc\u00e9l\u00e9ration douce\n        state.speedMul = Math.min(1.85, state.speedMul * 1.01);\n      }\n\n      \/\/ game over (sortie bas)\n      if(state.ball.y - state.ball.r > h){\n        paused = true;\n        running = false;\n        overlay.removeAttribute(\"data-hidden\");\n        \/\/ message dans l\u2019overlay\n        overlay.querySelector(\".bdd-overlay-title\").textContent = \"GAME OVER\";\n        overlay.querySelector(\".bdd-overlay-text\").innerHTML =\n          `Score: <b>${state.score}<\/b> \u2022 Level: <b>${state.level}<\/b><br>Rejouer ?`;\n        btnPlay.textContent = \"Rejouer\";\n        renderFrame();\n        return;\n      }\n\n      renderFrame();\n    }\n\n    function togglePause(){\n      if(!running) return;\n      paused = !paused;\n      renderFrame();\n    }\n\n    \/\/ --- Events ouverture\/fermeture ---\n    btnOpen.addEventListener(\"click\", (e)=>{\n      e.preventDefault();\n      setOpen(true);\n      \/\/ reset overlay texte \"Tennis\"\n      overlay.querySelector(\".bdd-overlay-title\").textContent = \"Tennis\";\n      overlay.querySelector(\".bdd-overlay-text\").innerHTML =\n        `D\u00e9place la raquette en bas et renvoie la balle.<br><b>\u2190 \u2192<\/b> (ou souris\/tactile) \u2022 <b>Espace<\/b> pause \u2022 <b>Esc<\/b> fermer`;\n      btnPlay.textContent = \"Jouer\";\n      resetGame(true);\n    });\n\n    btnClose.addEventListener(\"click\", ()=>{\n      setOpen(false);\n      \/\/ reset overlay pour la prochaine fois\n      btnPlay.textContent = \"Jouer\";\n    });\n\n    \/\/ clic en dehors du contenu = fermer\n    modal.addEventListener(\"click\", (e)=>{\n      if(e.target === modal){\n        setOpen(false);\n        btnPlay.textContent = \"Jouer\";\n      }\n    });\n\n    btnPlay.addEventListener(\"click\", ()=>{\n      \/\/ au play, on r\u00e9initialise proprement si game over\n      if(!running && !paused){\n        \/\/ s\u00e9curit\u00e9\n      }\n      if(!running){\n        \/\/ on repart d\u2019un reset quand on clique Jouer\/Rejouer\n        resetGame(false);\n        startLoop();\n      }else{\n        paused = false;\n        overlay.setAttribute(\"data-hidden\",\"true\");\n      }\n    });\n\n    btnRestart.addEventListener(\"click\", ()=>{\n      resetGame(false);\n      if(!running){\n        startLoop();\n      }\n    });\n\n    \/\/ --- input clavier (uniquement si modale ouverte) ---\n    window.addEventListener(\"keydown\", (e)=>{\n      if(modal.getAttribute(\"aria-hidden\") !== \"false\") return;\n\n      if(e.key === \"Escape\"){\n        e.preventDefault();\n        setOpen(false);\n        btnPlay.textContent = \"Jouer\";\n        return;\n      }\n      if(e.key === \" \" || e.code === \"Space\"){\n        e.preventDefault();\n        \/\/ si overlay visible et pas en cours => play\n        if(overlay.getAttribute(\"data-hidden\") !== \"true\" && !running){\n          resetGame(false);\n          startLoop();\n          return;\n        }\n        togglePause();\n        return;\n      }\n      if(e.key === \"ArrowRight\" || e.key === \"Right\"){\n        rightPressed = true; targetX = null;\n      }\n      if(e.key === \"ArrowLeft\" || e.key === \"Left\"){\n        leftPressed = true; targetX = null;\n      }\n    });\n\n    window.addEventListener(\"keyup\", (e)=>{\n      if(modal.getAttribute(\"aria-hidden\") !== \"false\") return;\n      if(e.key === \"ArrowRight\" || e.key === \"Right\") rightPressed = false;\n      if(e.key === \"ArrowLeft\" || e.key === \"Left\") leftPressed = false;\n    });\n\n    \/\/ --- souris\/tactile : suivre la position ---\n    function pointerToTarget(clientX){\n      const rect = canvas.getBoundingClientRect();\n      const x = clientX - rect.left;\n      targetX = clamp(x, 0, rect.width);\n    }\n\n    canvas.addEventListener(\"mousemove\", (e)=>{\n      if(modal.getAttribute(\"aria-hidden\") !== \"false\") return;\n      pointerToTarget(e.clientX);\n    });\n\n    canvas.addEventListener(\"touchstart\", (e)=>{\n      if(modal.getAttribute(\"aria-hidden\") !== \"false\") return;\n      if(e.touches && e.touches[0]){\n        pointerToTarget(e.touches[0].clientX);\n      }\n      \/\/ si touch sur overlay => ignore (overlay a son bouton)\n      e.preventDefault();\n    }, { passive:false });\n\n    canvas.addEventListener(\"touchmove\", (e)=>{\n      if(modal.getAttribute(\"aria-hidden\") !== \"false\") return;\n      if(e.touches && e.touches[0]){\n        pointerToTarget(e.touches[0].clientX);\n      }\n      e.preventDefault();\n    }, { passive:false });\n\n    \/\/ resize\n    window.addEventListener(\"resize\", ()=>{\n      if(modal.getAttribute(\"aria-hidden\") !== \"false\") return;\n      fitCanvas();\n      renderFrame();\n    });\n\n    \/\/ init \u201cferm\u00e9\u201d\n    setOpen(false);\n  })();\n\n})();\n\n\/* =========================================================\n   AJOUT : AGENDA (scop\u00e9 #berfAgendaTool)\n========================================================= *\/\n(function(){\n  const desk = document.getElementById(\"berfDesk\");\n  const scope = document.getElementById(\"berfAgendaTool\");\n  if(!desk || !scope) return;\n\n  const LS_KEY = \"berf_agenda_appointments_v1\";\n\n  let appointments = [];\n  let currentDate = new Date();\n  let selectedDateISO = null;\n\n  const moisFrancais = [\"Janvier\",\"F\u00e9vrier\",\"Mars\",\"Avril\",\"Mai\",\"Juin\",\"Juillet\",\"Ao\u00fbt\",\"Septembre\",\"Octobre\",\"Novembre\",\"D\u00e9cembre\"];\n\n  \/\/ Tabs\n  const navBtns = scope.querySelectorAll(\".agenda_42_navbtn\");\n  const tabs = scope.querySelectorAll(\".agenda_42_tab\");\n  navBtns.forEach(btn=>{\n    btn.addEventListener(\"click\", ()=>{\n      navBtns.forEach(b=>b.classList.remove(\"active\"));\n      tabs.forEach(t=>t.classList.remove(\"active\"));\n      btn.classList.add(\"active\");\n      const id = btn.getAttribute(\"data-tab\");\n      const tab = scope.querySelector(\"#\"+id);\n      if(tab) tab.classList.add(\"active\");\n    });\n  });\n\n  \/\/ Elements\n  const nextItem = scope.querySelector(\"#agenda_42_next_item\");\n  const cal = scope.querySelector(\"#agenda_42_calendar\");\n  const currentMonthEl = scope.querySelector(\"#agenda_42_current_month\");\n  const yearSelect = scope.querySelector(\"#agenda_42_year_select\");\n\n  const prevBtn = scope.querySelector(\"#agenda_42_prev\");\n  const nextBtn = scope.querySelector(\"#agenda_42_next\");\n\n  const addTitle = scope.querySelector(\"#agenda_42_title\");\n  const addDate = scope.querySelector(\"#agenda_42_date\");\n  const addBtn = scope.querySelector(\"#agenda_42_add_btn\");\n\n  const modal = scope.querySelector(\"#agenda_42_modal\");\n  const modalClose = scope.querySelector(\"#agenda_42_modal_close\");\n  const modalDateTitle = scope.querySelector(\"#agenda_42_modal_date_title\");\n  const modalList = scope.querySelector(\"#agenda_42_modal_list\");\n  const modalTitle = scope.querySelector(\"#agenda_42_modal_title\");\n  const modalDate = scope.querySelector(\"#agenda_42_modal_date\");\n  const modalAdd = scope.querySelector(\"#agenda_42_modal_add\");\n\n  function save(){\n    localStorage.setItem(LS_KEY, JSON.stringify(appointments));\n  }\n  function load(){\n    const raw = localStorage.getItem(LS_KEY);\n    if(raw){\n      try{ appointments = JSON.parse(raw) || []; }\n      catch(e){ appointments = []; }\n      return;\n    }\n\n    \/\/ Preferred seed: backend scenario data\n    try{\n      const boot = window.BERFDB && window.BERFDB.BOOT;\n      const hasSeed = !!(boot && boot.data && boot.data.agenda && Array.isArray(boot.data.agenda.seed));\n      const seed = hasSeed ? boot.data.agenda.seed : null;\n      if(hasSeed){\n        appointments = (seed || []).map(a => ({\n          id: a.id || '',\n          title: a.title || '',\n          date: a.date || '',\n          note: a.note || ''\n        }));\n        localStorage.setItem(LS_KEY, JSON.stringify(appointments));\n        return;\n      }\n    }catch(e){ appointments = []; }\n\n    \/\/ No legacy fallback on this builder version: backend seed or player-local data only.\n    appointments = [];\n    save();\n  }\n\n  function sortAppts(){\n    appointments.sort((a,b)=> new Date(a.date) - new Date(b.date));\n  }\n\n  function displayNext(){\n    if(!nextItem) return;\n    if(!appointments.length){\n      nextItem.textContent = \"Aucun rdv pr\u00e9vu prochainement\";\n      return;\n    }\n    const now = new Date();\n    const upcoming = appointments.filter(a => new Date(a.date) >= now).sort((a,b)=> new Date(a.date) - new Date(b.date));\n    if(!upcoming.length){\n      nextItem.textContent = \"Aucun rdv pr\u00e9vu prochainement\";\n      return;\n    }\n    const n = upcoming[0];\n    nextItem.textContent = `${n.title} \u2014 ${new Date(n.date).toLocaleString('fr-FR')}`;\n    if(n.note){ nextItem.title = n.note; } else { nextItem.removeAttribute('title'); }\n  }\n\n  function openModal(dateISO){\n    selectedDateISO = dateISO;\n    modal.setAttribute(\"data-open\",\"true\");\n    modal.setAttribute(\"aria-hidden\",\"false\");\n    modalDate.value = dateISO;\n\n    const formattedDate = new Date(dateISO).toLocaleDateString('fr-FR', { weekday:'long', year:'numeric', month:'long', day:'numeric' });\n    modalDateTitle.textContent = formattedDate;\n\n    renderModalList(dateISO);\n  }\n  function closeModal(){\n    modal.removeAttribute(\"data-open\");\n    modal.setAttribute(\"aria-hidden\",\"true\");\n    selectedDateISO = null;\n    modalTitle.value = \"\";\n  }\n\n  function renderModalList(dateISO){\n    modalList.innerHTML = \"\";\n    const dayAppts = appointments.filter(a => new Date(a.date).toDateString() === new Date(dateISO).toDateString());\n    if(!dayAppts.length){\n      const li = document.createElement(\"li\");\n      li.textContent = \"Aucun rendez-vous pour cette journ\u00e9e.\";\n      li.style.opacity = \".85\";\n      modalList.appendChild(li);\n      return;\n    }\n    dayAppts.forEach((a, idx)=>{\n      const li = document.createElement(\"li\");\n\n      const left = document.createElement(\"div\");\n      left.className = \"agenda_42_itemmain\";\n\n      const title = document.createElement(\"span\");\n      title.className = \"agenda_42_itemtitle\";\n      title.textContent = `${a.title} \u2014 ${new Date(a.date).toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'})}`;\n      left.appendChild(title);\n\n      if(a.note){\n        const note = document.createElement(\"div\");\n        note.className = \"agenda_42_itemnote\";\n        note.textContent = a.note;\n        left.appendChild(note);\n      }\n\n      const del = document.createElement(\"button\");\n      del.className = \"agenda_42_del\";\n      del.type = \"button\";\n      del.textContent = \"Supprimer\";\n      del.addEventListener(\"click\", ()=>{\n        const ref = dayAppts[idx];\n        appointments = appointments.filter(x => x !== ref);\n        save(); sortAppts(); displayNext(); renderCalendar();\n        renderModalList(dateISO);\n      });\n\n      li.appendChild(left);\n      li.appendChild(del);\n      modalList.appendChild(li);\n    });\n  }\n\n  function addAppointment(title, date, note='', id=''){\n    if(!title || !date) return false;\n    appointments.push({ title, date, note: note || '', id: id || '' });\n    save(); sortAppts(); displayNext(); renderCalendar();\n    return true;\n  }\n\n  window.BERF_AGENDA_UNLOCK = function(id){\n    if(!id) return false;\n    const exists = appointments.find(a => a && a.id === id);\n    if(exists) return true;\n    const all = Array.isArray(window.BERFDB && window.BERFDB.AGENDA_ALL) ? window.BERFDB.AGENDA_ALL : [];\n    const src = all.find(a => a && a.id === id);\n    if(!src) return false;\n    appointments.push({ title: src.title || '', date: src.date || '', note: src.note || '', id: src.id || '' });\n    save(); sortAppts(); displayNext(); renderCalendar();\n    return true;\n  };\n\n  function renderCalendar(){\n    cal.innerHTML = \"\";\n\n    const year = currentDate.getFullYear();\n    const month = currentDate.getMonth();\n\n    const firstDay = new Date(year, month, 1).getDay();\n    const daysInMonth = new Date(year, month + 1, 0).getDate();\n\n    const headerDays = ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'];\n    headerDays.forEach(d=>{\n      const el = document.createElement(\"div\");\n      el.className = \"agenda_42_day header\";\n      el.textContent = d;\n      cal.appendChild(el);\n    });\n\n    for(let i=0;i<firstDay;i++){\n      const pad = document.createElement(\"div\");\n      pad.style.opacity = \"0\";\n      cal.appendChild(pad);\n    }\n\n    for(let day=1; day<=daysInMonth; day++){\n      const dayDate = new Date(year, month, day);\n\n      const el = document.createElement(\"div\");\n      el.className = \"agenda_42_day\";\n      el.textContent = String(day);\n\n      const has = appointments.some(a => new Date(a.date).toDateString() === dayDate.toDateString());\n      if(has) el.classList.add(\"hasAppt\");\n\n      el.addEventListener(\"click\", ()=>{\n        const y = dayDate.getFullYear();\n        const m = String(dayDate.getMonth()+1).padStart(2,'0');\n        const dd = String(dayDate.getDate()).padStart(2,'0');\n        openModal(`${y}-${m}-${dd}T00:00`);\n      });\n\n      cal.appendChild(el);\n    }\n\n    currentMonthEl.textContent = `${moisFrancais[month]} ${year}`;\n\n    yearSelect.innerHTML = \"\";\n    for(let y=year-10; y<=year+10; y++){\n      const opt = document.createElement(\"option\");\n      opt.value = String(y);\n      opt.textContent = String(y);\n      if(y===year) opt.selected = true;\n      yearSelect.appendChild(opt);\n    }\n  }\n\n  \/\/ Controls\n  prevBtn.addEventListener(\"click\", ()=>{\n    currentDate.setMonth(currentDate.getMonth() - 1);\n    renderCalendar();\n  });\n  nextBtn.addEventListener(\"click\", ()=>{\n    currentDate.setMonth(currentDate.getMonth() + 1);\n    renderCalendar();\n  });\n  yearSelect.addEventListener(\"change\", ()=>{\n    currentDate.setFullYear(parseInt(yearSelect.value,10));\n    renderCalendar();\n  });\n\n  addBtn.addEventListener(\"click\", ()=>{\n    const ok = addAppointment(addTitle.value.trim(), addDate.value, '');\n    if(!ok){ alert(\"Veuillez remplir tous les champs.\"); return; }\n    addTitle.value = \"\"; addDate.value = \"\";\n    \/\/ revenir sur RDV\n    scope.querySelector('.agenda_42_navbtn[data-tab=\"agenda_42_tab_rdv\"]').click();\n  });\n\n  modalAdd.addEventListener(\"click\", ()=>{\n    const ok = addAppointment(modalTitle.value.trim(), modalDate.value, '');\n    if(!ok){ alert(\"Veuillez remplir tous les champs.\"); return; }\n    modalTitle.value = \"\";\n    renderModalList(modalDate.value);\n  });\n\n  modalClose.addEventListener(\"click\", closeModal);\n  modal.addEventListener(\"click\", (e)=>{\n    if(e.target === modal) closeModal();\n  });\n\n  \/\/ Init\n  load();\n  sortAppts();\n  renderCalendar();\n  displayNext();\n})();\n\n\n\n\/* =========================================================\n   AJOUT : SEARCH BAR (taskbar)\n========================================================= *\/\n(function(){\n  const input = document.getElementById('searchInput45');\n  const results = document.getElementById('searchResults78');\n  if(!input || !results) return;\n\n  \/\/ Exemple : branche ici tes commandes (tu pourras les remplacer ensuite)\n  const actions45 = {\n    \"agenda\": () => document.querySelector('[data-open-oc=\"agenda\"]')?.click(),\n    \"mail\": () => document.querySelector('[data-open-oc=\"mail\"]')?.click(),\n    \"suspects\": () => document.querySelector('[data-open-oc=\"suspects\"]')?.click(),\n    \"crypto\": () => document.querySelector('[data-open-oc=\"crypto\"]')?.click(),\n    \"trombi\": () => document.querySelector('[data-open-oc=\"registry\"]')?.click(),\n    \"registry\": () => document.querySelector('[data-open-oc=\"registry\"]')?.click(),\n  };\n\n  const data45 = Object.keys(actions45);\n\n  function hide(){ results.style.display = \"none\"; results.innerHTML = \"\"; }\n  function show(){ results.style.display = \"block\"; }\n\n  input.addEventListener(\"input\", function(){\n    const searchTerm = input.value.toLowerCase().trim();\n    if(searchTerm.length < 3){ hide(); return; }\n\n    results.innerHTML = \"\";\n    const filtered = data45.filter(item => item.toLowerCase().includes(searchTerm));\n    if(!filtered.length){ hide(); return; }\n\n    show();\n    filtered.forEach(result => {\n      const div = document.createElement(\"div\");\n      div.className = \"result-item99\";\n      div.textContent = result;\n      div.addEventListener(\"click\", () => {\n        actions45[result]?.();\n        hide();\n        input.blur();\n      });\n      results.appendChild(div);\n    });\n  });\n\n  document.addEventListener(\"click\", function(event){\n    if(!input.contains(event.target) && !results.contains(event.target)) hide();\n  });\n\n  \/\/ ESC to close\n  input.addEventListener(\"keydown\", (e)=>{\n    if(e.key === \"Escape\"){ input.value = \"\"; hide(); input.blur(); }\n  });\n})();\n\n\n\n\n\/* =========================================================\n   FIX : ouverture Navigateur (fallback)\n========================================================= *\/\n(function(){\n  const desk = document.getElementById(\"berfDesk\");\n  if(!desk) return;\n  const btn = desk.querySelector('[data-open-oc=\"browser\"]');\n  const oc  = desk.querySelector('#berf-oc-browser');\n  if(!btn || !oc) return;\n  btn.addEventListener('click', ()=>{\n    oc.setAttribute('data-open','true');\n    oc.setAttribute('aria-hidden','false');\n  });\n})();\n\n\n\n\/* =========================================================\n   NAVIGATEUR FICTIF \u2014 logique (scop\u00e9 #berfBrowserTool)\n   - Tabs: ouvrir \/ fermer \/ +\n   - Address bar:\n       * URLs autoris\u00e9es -> shortcodes Elementor\n       * sinon -> page d'erreur (shortcode)\n       * texte -> recherche fictive (onglet)\n   - Historique: bouton horloge, fermeture au clic dehors\n   - Home: revient au 1er onglet\n========================================================= *\/\n(function(){\n  if(window.__BERF_BROWSER123_INIT__) return;\n  window.__BERF_BROWSER123_INIT__ = true;\n\n  const scope = document.getElementById(\"berfBrowserTool\");\n  if(!scope) return;\n\n  const addressBar = scope.querySelector(\"#addressBar123\");\n  const tabContainer = scope.querySelector(\"#tabContainer123\");\n  const contentHost  = scope.querySelector(\"#content123\");\n  const addTabBtn     = scope.querySelector(\"#addTab123\");\n\n  const historyBtn   = scope.querySelector(\"#historyBtn123\");\n  const historyModal = scope.querySelector(\"#historyModal123\");\n  const historyClose = scope.querySelector(\"#historyClose123\");\n  const historyList  = scope.querySelector(\"#historyList123\");\n\n  const eggOverlay = scope.querySelector(\"#easterEggOverlay123\");\n  const eggBox     = scope.querySelector(\"#easterEggContainer123\");\n  const eggClose   = scope.querySelector(\"#closeEasterEgg123\");\n\n  \/\/ --- ROUTES (whitelist) ---\n  const CONFIG_TABS = Array.isArray(window.BERFDB && window.BERFDB.BROWSER_TABS) ? window.BERFDB.BROWSER_TABS : [];\n  const LOGIN_RULES = Array.isArray(window.BERFDB && window.BERFDB.BROWSER_LOGINS) ? window.BERFDB.BROWSER_LOGINS : [];\n  const AUTH_KEY = 'berf_browser_auth_v1';\n\n  function escapeBrowserHtml(value){\n    return String(value||'').replace(\/[&<>\"']\/g,char=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#039;'}[char]));\n  }\n\n  function loadBrowserAuth(){\n    try{ const parsed=JSON.parse(localStorage.getItem(AUTH_KEY)||'{}'); return parsed&&typeof parsed==='object'?parsed:{}; }catch(e){ return {}; }\n  }\n  function saveBrowserAuth(state){ try{ localStorage.setItem(AUTH_KEY,JSON.stringify(state||{})); }catch(e){} }\n  function hydrateFictitiousLogins(container){\n    if(!container) return;\n    container.querySelectorAll('[data-berf-browser-login]').forEach(host=>{\n      const id=String(host.getAttribute('data-berf-browser-login')||'').trim();\n      const rule=LOGIN_RULES.find(item=>String(item&&item.id||'')===id);\n      if(!rule){ host.innerHTML='<div class=\"berf-browser-login-error\">Connexion fictive non configur\u00e9e.<\/div>'; return; }\n      const auth=loadBrowserAuth();\n      if(auth[id] && rule.remember!==false){\n        host.innerHTML='<div class=\"berf-browser-login-ok\">Session reconnue. Redirection\u2026<\/div>';\n        window.setTimeout(()=>openUrlReplacingCurrent(rule.successUrl||''),250);\n        return;\n      }\n      host.innerHTML=''\n        +'<form class=\"berf-browser-login-form\" autocomplete=\"off\">'\n        +'<h2>'+escapeBrowserHtml(rule.label||'Connexion')+'<\/h2>'\n        +'<label>Identifiant<input type=\"text\" name=\"username\" autocomplete=\"off\"><\/label>'\n        +'<label>Mot de passe<input type=\"password\" name=\"password\" autocomplete=\"off\"><\/label>'\n        +'<div class=\"berf-browser-login-feedback\" role=\"alert\"><\/div>'\n        +'<button type=\"submit\">Se connecter<\/button>'\n        +'<\/form>';\n      const form=host.querySelector('form'), user=form.querySelector('[name=\"username\"]'), pass=form.querySelector('[name=\"password\"]'), feedback=form.querySelector('.berf-browser-login-feedback');\n      if(rule.prefillUsername!==false) user.value=String(rule.username||'');\n      form.addEventListener('submit',event=>{\n        event.preventDefault(); feedback.textContent='';\n        const ok=String(user.value||'')===String(rule.username||'') && String(pass.value||'')===String(rule.password||'');\n        if(!ok){ feedback.textContent=String(rule.errorMessage||'Identifiant ou mot de passe incorrect.'); pass.value=''; pass.focus(); return; }\n        if(rule.remember!==false){ const state=loadBrowserAuth(); state[id]=true; saveBrowserAuth(state); }\n        feedback.classList.add('is-success'); feedback.textContent='Connexion r\u00e9ussie. Redirection\u2026';\n        try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('browser_login_success',id,{ id, username:user.value, successUrl:rule.successUrl||'' }); }catch(e){}\n        window.setTimeout(()=>openUrlReplacingCurrent(rule.successUrl||''),350);\n      });\n    });\n  }\n  const ROUTES = {};\n  CONFIG_TABS.forEach(tab=>{\n    if(!tab) return;\n    const routeKey = String(tab.link || tab.title || '').trim().toLowerCase();\n    if(!routeKey) return;\n    \/\/ R\u00e9cup\u00e8re le HTML depuis la balise <template> pour \u00e9viter de casser le JSON inline\n    let html = (typeof tab.html === 'string') ? tab.html : '';\n    if(!html && tab.htmlRef){\n      const tpl = document.getElementById(tab.htmlRef);\n      if(tpl){\n        if(tpl.content){\n          const holder=document.createElement('div'); holder.appendChild(tpl.content.cloneNode(true)); html=holder.innerHTML;\n        }else{\n          html=tpl.innerHTML||'';\n        }\n      }\n    }\n    const route = { title: tab.title || routeKey, html: html, id: tab.id || '', link: tab.link || '' };\n    ROUTES[routeKey] = route;\n    const cleanKey = routeKey.replace(\/^https?:\\\/\\\/\/,'').replace(\/^www\\.\/,'').replace(\/\\\/$\/,'');\n    ROUTES[cleanKey] = route;\n    const domainKey = cleanKey.replace(\/\\\/.*$\/,'');\n    if(!ROUTES[domainKey]) ROUTES[domainKey] = route;\n  });\n  const ERROR_SHORTCODE = '<div style=\"padding:18px;color:rgba(255,255,255,.86);\"><b>Page introuvable<\/b><div style=\"margin-top:8px;opacity:.78;\">Aucun onglet configur\u00e9 ne correspond \u00e0 cette adresse.<\/div><\/div>';\n\n  \/\/ --- Recherche fictive (local) ---\n  function normalizeSearchText(value){\n    return String(value || '').normalize('NFD').replace(\/[\\u0300-\\u036f]\/g, '').toLowerCase().trim();\n  }\n  const SEARCH_RESULTS = (q) => {\n    const key = normalizeSearchText(q);\n    const out = [];\n    const rules = Array.isArray(window.BERFDB && window.BERFDB.BROWSER_SEARCH_RULES) ? window.BERFDB.BROWSER_SEARCH_RULES : [];\n    rules.forEach(rule=>{\n      const terms = Array.isArray(rule.terms) ? rule.terms : [];\n      if(terms.some(term=>normalizeSearchText(term) === key)) out.push({ title: rule.title || `Recherche: ${q}`, directHtml: rule.html || '' });\n    });\n    return out;\n  };\n\n  \/\/ --- State ---\n  \/\/ tabs de base (non supprimables pour \u00e9viter de casser)\n  const PINNED = new Set();\n  let tabStack = [];\n  let history  = [];\n\n  \/\/ --- Helpers ---\n  function sanitizeTitle(s){\n    return String(s || \"\").replace(\/[<>]\/g,\"\").trim().slice(0,70) || \"Nouvel onglet\";\n  }\n  function hostOnly(input){\n    const v = String(input||\"\").trim().toLowerCase();\n    return v.replace(\/^https?:\\\/\\\/\/,\"\").replace(\/^www\\.\/,\"\").replace(\/\\\/.*$\/,\"\");\n  }\n  function routeKeyFromInput(input){\n    return String(input||'').trim().toLowerCase().replace(\/^https?:\\\/\\\/\/,'').replace(\/^www\\.\/,'').replace(\/\\\/$\/,'');\n  }\n  function looksLikeUrl(input){\n    return \/^(https?:\\\/\\\/)?(www\\.)?[\\w.-]+\\.[a-z]{2,}([\\\/?#].*)?$\/i.test(String(input||\"\").trim());\n  }\n\n  function setActive(tabId){\n    scope.querySelectorAll(\".tab-content123\").forEach(el=>{\n      el.style.display = (el.id === tabId) ? \"block\" : \"none\";\n    });\n    scope.querySelectorAll(\".browser-tab123[data-tab]\").forEach(t=>{\n      t.classList.toggle(\"active123\", t.dataset.tab === tabId);\n    });\n    tabStack = tabStack.filter(x=>x!==tabId);\n    tabStack.push(tabId);\n  }\n\n  function openTab(tabId){\n    const page = document.getElementById(String(tabId || ''));\n    const tab  = scope.querySelector('.browser-tab123[data-tab=\"'+tabId+'\"]');\n    if(!page || !tab || !scope.contains(page)) return false;\n    setActive(tabId);\n    const route=configuredRoute(tabId);\n    if(route && addressBar) addressBar.value=route.link||'';\n    return true;\n  }\n\n  function createTab(tabId, title, htmlContent){\n    tabId=String(tabId||'').trim();\n    if(!tabId) tabId='tab-'+Date.now();\n    const existingPage=document.getElementById(tabId);\n    const existingTab=scope.querySelector('.browser-tab123[data-tab=\"'+tabId+'\"]');\n    if(existingPage&&existingTab&&scope.contains(existingPage)){ openTab(tabId); return existingPage; }\n    htmlContent=String(htmlContent||'');\n    if(!htmlContent.trim()){\n      htmlContent='<div class=\"berf-browser-empty-route\" style=\"padding:28px;background:#fff;color:#222;border-radius:8px\"><strong>Page configur\u00e9e sans contenu<\/strong><p style=\"margin:10px 0 0\">L\u2019onglet existe, mais aucun HTML ou shortcode enregistr\u00e9 ne lui est associ\u00e9.<\/p><\/div>';\n    }\n    \/\/ tab pill\n    const tab = document.createElement(\"div\");\n    tab.className = \"browser-tab123 berfBrowser__tab\";\n    tab.dataset.tab = tabId;\n    tab.setAttribute('role','button');\n    tab.setAttribute('tabindex','0');\n    tab.innerHTML = `${sanitizeTitle(title)}\n      <button class=\"close-tab123 berfBrowser__close\" type=\"button\" data-close-tab=\"${tabId}\" aria-label=\"Fermer\">\u00d7<\/button>`;\n\n    tab.addEventListener('click',event=>{ if(event.target.closest('[data-close-tab]')) return; openTab(tabId); });\n    tab.addEventListener('keydown',event=>{ if(event.key==='Enter'||event.key===' '){ event.preventDefault(); openTab(tabId); } });\n    tabContainer.insertBefore(tab, addTabBtn);\n\n    \/\/ page\n    const page = document.createElement(\"div\");\n    page.id = tabId;\n    page.className = \"tab-content123 berfBrowser__page\";\n    page.style.display = \"none\";\n    \/\/ Injecte le HTML en extrayant les styles pour les mettre dans <head>\n    (function injectWithStyles(container, html) {\n      const tmp = document.createElement('div');\n      tmp.innerHTML = html;\n      \/\/ D\u00e9place les <style> et <link rel=stylesheet> dans <head>\n      tmp.querySelectorAll('style, link[rel=\"stylesheet\"]').forEach(function(el) {\n        const id = el.id || ('berfdb-tab-style-' + Math.random().toString(36).slice(2));\n        if (!document.getElementById(id)) {\n          el.id = id;\n          document.head.appendChild(el.cloneNode(true));\n        }\n        el.remove();\n      });\n      container.innerHTML = tmp.innerHTML;\n    })(page, htmlContent);\n    hydrateFictitiousLogins(page);\n    page.querySelectorAll('a[href], [data-berf-browser-link]').forEach(link=>{\n      link.addEventListener('click', e=>{\n        const target = link.getAttribute('data-berf-browser-link') || link.getAttribute('href') || '';\n        if(!target || target === '#' || target.startsWith('#')) return;\n        e.preventDefault();\n        if(link.getAttribute('data-berf-browser-replace')==='1') openUrlReplacingCurrent(target);\n        else openUrlOrError(target);\n      });\n    });\n    contentHost.appendChild(page);\n\n    openTab(tabId);\n    return page;\n  }\n\n  function closeTab(tabId){\n    if(PINNED.has(tabId)) return; \/\/ \u00e9vite la casse\n\n    const tab  = scope.querySelector('.browser-tab123[data-tab=\"'+tabId+'\"]');\n    const page = scope.querySelector(\"#\"+tabId);\n    if(tab) tab.remove();\n    if(page) page.remove();\n\n    tabStack = tabStack.filter(x=>x!==tabId);\n    const next = tabStack[tabStack.length-1];\n    if(next) openTab(next);\n\n    try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('browser_close_tab', tabId, { tabId }); }catch(e){}\n  }\n\n  function pushHistory(entry){\n    history.push(entry);\n    if(history.length > 30) history = history.slice(-30);\n    renderHistory();\n  }\n\n  function renderHistory(){\n    if(!historyList) return;\n    historyList.innerHTML = \"\";\n    const recent = history.slice().reverse().slice(0, 14);\n    if(!recent.length){\n      historyList.innerHTML = \"<div style='opacity:.8;'>Aucun historique.<\/div>\";\n      return;\n    }\n    recent.forEach(h=>{\n      const a = document.createElement(\"a\");\n      a.href = \"#\";\n      a.textContent = (h.type === \"search\") ? `Recherche: ${h.label}` : h.label;\n      a.addEventListener(\"click\", (e)=>{\n        e.preventDefault();\n        if(h.tabId && scope.querySelector(\"#\"+h.tabId)) openTab(h.tabId);\n      });\n      historyList.appendChild(a);\n    });\n  }\n\n  function showHistory(){\n    historyModal.style.display = \"block\";\n    historyModal.setAttribute(\"aria-hidden\",\"false\");\n    renderHistory();\n  }\n  function hideHistory(){\n    historyModal.style.display = \"none\";\n    historyModal.setAttribute(\"aria-hidden\",\"true\");\n  }\n\n  function openTemplateTab(title, htmlContent, routeKey, routeId, routeLink){\n    const tabId = \"tpl\" + Date.now();\n    createTab(tabId, title, htmlContent || \"\");\n    pushHistory({ type:\"template\", label: title, tabId });\n    try{\n      if(window.BERF_EVENTS){\n        if(routeKey) window.BERF_EVENTS.trigger('browser_navigate', String(routeKey), { url: routeKey, title });\n        if(routeLink && String(routeLink) !== String(routeKey)) window.BERF_EVENTS.trigger('browser_navigate', String(routeLink), { url: routeLink, title, routeId });\n        if(routeId) window.BERF_EVENTS.trigger('browser_open_tab', String(routeId), { tabId: routeId, runtimeTabId: tabId, title });\n        window.BERF_EVENTS.trigger('browser_open_tab', tabId, { tabId, title });\n      }\n    }catch(e){}\n  }\n\n  function openUrlOrError(input){\n    const fullKey = routeKeyFromInput(input);\n    const host = hostOnly(input);\n    const route = ROUTES[fullKey] || ROUTES[host];\n    if(route){\n      \/\/ V\u00e9rifie si l'onglet est verrouill\u00e9\n      try{\n        const st = JSON.parse(localStorage.getItem('berf_events_state_v1') || '{}');\n        if(st.flags && st.flags['_browser_locked_' + route.id]){\n          openTemplateTab(\"Acc\u00e8s refus\u00e9\", '<div style=\"padding:18px;color:rgba(255,255,255,.86);\"><b>Acc\u00e8s refus\u00e9<\/b><div style=\"margin-top:8px;opacity:.78;\">Cette page est verrouill\u00e9e.<\/div><\/div>');\n          return;\n        }\n      }catch(e){}\n      openTemplateTab(route.title, route.html, fullKey, route.id, route.link);\n    } else {\n      openTemplateTab(host || \"Erreur\", ERROR_SHORTCODE);\n    }\n  }\n\n  function openUrlReplacingCurrent(input){\n    const active=scope.querySelector('.browser-tab123[data-tab].active123');\n    const previousId=active ? String(active.dataset.tab||'') : '';\n    openUrlOrError(input);\n    const next=scope.querySelector('.browser-tab123[data-tab].active123');\n    const nextId=next ? String(next.dataset.tab||'') : '';\n    if(previousId && previousId!==nextId) closeTab(previousId);\n  }\n\n  function openSearchTab(query){\n    const tabId = \"search\" + Date.now();\n    const q = sanitizeTitle(query);\n\n    const results = SEARCH_RESULTS(q);\n    if(results.length === 1 && Object.prototype.hasOwnProperty.call(results[0], 'directHtml')){\n      createTab(tabId, results[0].title, results[0].directHtml);\n      pushHistory({ type:\"search\", label:q, tabId });\n      return;\n    }\n    const container = document.createElement(\"div\");\n    container.innerHTML = `\n      <div style=\"font-weight:900; color: rgba(255,255,255,.92); margin: 6px 0 12px;\">R\u00e9sultats pour : \u201c${q}\u201d<\/div>\n      <div id=\"${tabId}_results\"><\/div>\n    `;\n    createTab(tabId, `Recherche: ${q}`, container.innerHTML);\n\n    const host = scope.querySelector(\"#\"+tabId+\"_results\");\n    if(host){\n      if(!results.length){\n        host.innerHTML = `<div style=\"opacity:.85;\">Aucun r\u00e9sultat trouv\u00e9.<\/div>`;\n      } else {\n        results.forEach(item=>{\n          const a = document.createElement(\"a\");\n          a.href = \"#\";\n          a.textContent = item.title;\n          a.style.display = \"block\";\n          a.style.padding = \"10px\";\n          a.style.borderRadius = \"14px\";\n          a.style.border = \"1px solid rgba(255,255,255,0.08)\";\n          a.style.background = \"rgba(255,255,255,0.05)\";\n          a.style.color = \"rgba(255,255,255,0.88)\";\n          a.style.textDecoration = \"none\";\n          a.style.marginBottom = \"8px\";\n          a.style.fontWeight = \"800\";\n          a.addEventListener(\"click\", (e)=>{ e.preventDefault(); item.action(); });\n          a.addEventListener(\"mouseenter\", ()=>{ a.style.borderColor = \"rgba(175,50,50,0.45)\"; a.style.background = \"rgba(175,50,50,0.16)\"; });\n          a.addEventListener(\"mouseleave\", ()=>{ a.style.borderColor = \"rgba(255,255,255,0.08)\"; a.style.background = \"rgba(255,255,255,0.05)\"; });\n          host.appendChild(a);\n        });\n      }\n    }\n\n    pushHistory({ type:\"search\", label:q, tabId });\n  }\n\n  \/\/ --- Easter egg ---\n  const eggSeq = ['right','right','left','right','left','left','left','right','left','right'];\n  let curSeq = [];\n  function checkEgg(dir){\n    curSeq.push(dir);\n    if(curSeq.length > eggSeq.length) curSeq.shift();\n    if(curSeq.join(',') === eggSeq.join(',')){\n      eggOverlay.style.display = \"block\";\n      eggBox.style.display = \"block\";\n      eggOverlay.setAttribute(\"aria-hidden\",\"false\");\n      eggBox.setAttribute(\"aria-hidden\",\"false\");\n    }\n  }\n  function closeEgg(){\n    eggOverlay.style.display = \"none\";\n    eggBox.style.display = \"none\";\n    eggOverlay.setAttribute(\"aria-hidden\",\"true\");\n    eggBox.setAttribute(\"aria-hidden\",\"true\");\n  }\n\n  \/\/ --- Events ---\n  tabContainer.addEventListener(\"click\", (e)=>{\n    const closeBtn = e.target.closest(\"[data-close-tab]\");\n    if(closeBtn){\n      e.stopPropagation();\n      closeTab(closeBtn.getAttribute(\"data-close-tab\"));\n      return;\n    }\n    const add = e.target.closest(\"#addTab123\");\n    if(add){\n      const tabId = \"new\" + Date.now();\n      createTab(tabId, \"Nouvel onglet\", `\n        <div style=\"text-align:center; padding: 22px 10px;\">\n          <div style=\"font-weight: 900; color: rgba(255,255,255,.92); margin-bottom: 8px;\">Nouvel onglet<\/div>\n          <div style=\"opacity:.8; margin-bottom: 14px;\">Tape une URL autoris\u00e9e ou une recherche.<\/div>\n          <div style=\"max-width: 520px; margin: 0 auto;\">\n            <input type=\"text\" class=\"berfBrowser__address\" placeholder=\"Ex: bdgchastel-myblog.com\"\n              onkeydown=\"if(event.key==='Enter'){ const a=document.getElementById('addressBar123'); a.value=this.value; a.dispatchEvent(new KeyboardEvent('keydown',{key:'Enter'})); }\">\n          <\/div>\n        <\/div>\n      `);\n      return;\n    }\n    const tab = e.target.closest(\".browser-tab123[data-tab]\");\n    if(tab) openTab(tab.dataset.tab);\n  });\n\n  addressBar.addEventListener(\"keydown\", (e)=>{\n    if(e.key !== \"Enter\") return;\n    const q = addressBar.value.trim();\n    if(!q) return;\n    if(looksLikeUrl(q)) openUrlOrError(q);\n    else openSearchTab(q);\n  });\n\n  scope.querySelectorAll(\"[data-nav]\").forEach(btn=>{\n    btn.addEventListener(\"click\", ()=>{\n      const nav = btn.getAttribute(\"data-nav\");\n      if(nav === \"back\"){ checkEgg(\"left\"); }\n      if(nav === \"forward\"){ checkEgg(\"right\"); }\n      if(nav === \"home\"){\n        const first = CONFIG_TABS.find(t => t.visibleAtStart !== false) || CONFIG_TABS[0];\n        if(first){\n          const existing = scope.querySelector('#' + first.id);\n          if(existing) openTab(first.id);\n          else openTemplateTab(first.title, first.html);\n        }\n      }\n    });\n  });\n\n  historyBtn.addEventListener(\"click\", (e)=>{ e.stopPropagation(); showHistory(); });\n  historyClose.addEventListener(\"click\", hideHistory);\n  document.addEventListener(\"click\", (e)=>{\n    if(historyModal.style.display === \"block\" && !historyModal.contains(e.target) && !historyBtn.contains(e.target)){\n      hideHistory();\n    }\n  });\n\n  eggClose.addEventListener(\"click\", closeEgg);\n  eggOverlay.addEventListener(\"click\", closeEgg);\n\n  function configuredRoute(target){\n    const wanted=String(target||'').trim().toLowerCase();\n    return Object.values(ROUTES).find(route=>[route.id,route.link,route.title].some(value=>String(value||'').trim().toLowerCase()===wanted)) || null;\n  }\n  function browserLockState(){\n    try{ const parsed=JSON.parse(localStorage.getItem('berf_events_state_v1')||'{}'); return parsed&&typeof parsed==='object'?parsed:{}; }catch(e){ return {}; }\n  }\n  function saveBrowserLockState(state){ try{ localStorage.setItem('berf_events_state_v1',JSON.stringify(state||{})); }catch(e){} }\n  function openConfiguredTab(target){\n    const route=configuredRoute(target); if(!route) return false;\n    const tabId=String(route.id||target||'').trim();\n    const state=browserLockState(); if(state.flags&&state.flags['_browser_locked_'+tabId]) return false;\n    const existing=scope.querySelector('#'+tabId); if(existing) openTab(tabId); else createTab(tabId,route.title,route.html||'');\n    const routeKey=String(route.link||route.title||'').trim().toLowerCase();\n    if(addressBar) addressBar.value=route.link||'';\n    pushHistory({type:'template',label:route.title,tabId});\n    try{ if(window.BERF_EVENTS){ if(routeKey) window.BERF_EVENTS.trigger('browser_navigate',routeKey,{url:routeKey,title:route.title}); window.BERF_EVENTS.trigger('browser_open_tab',tabId,{tabId,title:route.title}); } }catch(e){}\n    return true;\n  }\n  window.BERF_BROWSER={\n    openConfigured:openConfiguredTab,\n    unlock:function(target){ const route=configuredRoute(target),tabId=String(route&&route.id||target||'').trim(); const state=browserLockState(); if(!state.flags)state.flags={}; delete state.flags['_browser_locked_'+tabId]; saveBrowserLockState(state); return openConfiguredTab(tabId); },\n    lock:function(target){ const route=configuredRoute(target),tabId=String(route&&route.id||target||'').trim(); closeTab(tabId); const state=browserLockState(); if(!state.flags)state.flags={}; state.flags['_browser_locked_'+tabId]=true; saveBrowserLockState(state); return true; },\n    close:function(target){ const route=configuredRoute(target); closeTab(String(route&&route.id||target||'')); return true; }\n  };\n\n  \/\/ init \u2014 ouvre les onglets marqu\u00e9s open_at_start\n  let hasOpenAtStart = false;\n  CONFIG_TABS.forEach(tab => {\n    if(!tab || !tab.openAtStart) return;\n    const routeKey = String(tab.link || tab.title || '').trim().toLowerCase();\n    const route = ROUTES[routeKey];\n    if(!route) return;\n    const tabId = tab.id || ('tab-' + routeKey.replace(\/[^a-z0-9]\/g,'-'));\n    createTab(tabId, route.title, route.html);\n    hasOpenAtStart = true;\n  });\n  if(!hasOpenAtStart) openTab(\"forum123\");\n  renderHistory();\n})();\n\n\n\n\n\/* =========================================================\n   FIX : Elementor templates dans \u00e9l\u00e9ments cach\u00e9s (off-canvas)\n   Quand un outil est ouvert, Elementor n'initialise pas toujours\n   ses widgets si le contenu \u00e9tait display:none au chargement.\n   On d\u00e9clenche donc un \"refresh\" \u00e0 l'ouverture du navigateur et\n   \u00e0 chaque changement d'onglet.\n========================================================= *\/\n(function(){\n  const desk = document.getElementById(\"berfDesk\");\n  if(!desk) return;\n\n  function refreshElementor(container){\n    try{\n      \/\/ Elementor + jQuery (cas le plus fr\u00e9quent)\n      if(window.elementorFrontend && window.elementorFrontend.elementsHandler && window.jQuery){\n        window.elementorFrontend.elementsHandler.runReadyTrigger(window.jQuery(container));\n        return;\n      }\n      \/\/ Fallback : tenter init global (moins pr\u00e9cis mais utile)\n      if(window.elementorFrontend && typeof window.elementorFrontend.init === \"function\"){\n        window.elementorFrontend.init();\n      }\n    }catch(e){\n      console.warn(\"Elementor refresh error:\", e);\n    }\n  }\n\n  \/\/ 1) \u00c0 l'ouverture de l'off-canvas navigateur\n  const browserBtn = desk.querySelector('[data-open-oc=\"browser\"]');\n  const browserOC  = desk.querySelector('#berf-oc-browser');\n  if(browserBtn && browserOC){\n    browserBtn.addEventListener(\"click\", ()=>{\n      \/\/ attendre le DOM repaint + ouverture\n      requestAnimationFrame(()=>{\n        setTimeout(()=>{\n          const tool = browserOC.querySelector(\"#berfBrowserTool\");\n          if(tool) refreshElementor(tool);\n        }, 60);\n      });\n    });\n  }\n\n  \/\/ 2) \u00c0 chaque changement d'onglet du navigateur (delegation)\n  desk.addEventListener(\"click\", (e)=>{\n    const tab = e.target.closest && e.target.closest(\"#berfBrowserTool .browser-tab123[data-tab]\");\n    if(!tab) return;\n    const tool = desk.querySelector(\"#berfBrowserTool\");\n    if(tool) setTimeout(()=>refreshElementor(tool), 30);\n  });\n\n  \/\/ 3) Apr\u00e8s cr\u00e9ation d'un onglet (adresse bar \/ + \/ recherche), on refresh aussi\n  const address = desk.querySelector(\"#berfBrowserTool #addressBar123\");\n  if(address){\n    address.addEventListener(\"keydown\", (e)=>{\n      if(e.key === \"Enter\"){\n        const tool = desk.querySelector(\"#berfBrowserTool\");\n        if(tool) setTimeout(()=>refreshElementor(tool), 80);\n      }\n    });\n  }\n})();\n\n\n\n\/* =========================================================\nHARDENING : debug\/anti-overlay en front-end\n- Sur certains th\u00e8mes\/optimiseurs, un overlay peut rester au-dessus\n- On d\u00e9tecte l'\u00e9l\u00e9ment topmost au centre de la taskbar et on corrige\n========================================================= *\/\n(function(){\n  const desk = document.getElementById(\"berfDesk\");\n  if(!desk) return;\n\n  function fixOverlayAtPoint(){\n    const tb = desk.querySelector(\".berf-taskbar\");\n    if(!tb) return;\n\n    const r = tb.getBoundingClientRect();\n    const x = r.left + Math.min(60, r.width\/2);\n    const y = r.top + r.height\/2;\n\n    const el = document.elementFromPoint(x, y);\n    if(!el) return;\n\n    \/\/ Si l'\u00e9l\u00e9ment au-dessus n'est pas dans le desk -> overlay externe\n    if(!desk.contains(el)){\n      \/\/ on tente de neutraliser les overlays Elementor les plus courants\n      document.querySelectorAll(\".elementor-background-overlay, .dialog-widget, .elementor-lightbox\").forEach(node=>{\n        node.style.pointerEvents = \"none\";\n      });\n    }\n  }\n\n  \/\/ Au chargement + apr\u00e8s 1s (lazy effects) + au resize\n  window.addEventListener(\"load\", ()=>{\n    fixOverlayAtPoint();\n    setTimeout(fixOverlayAtPoint, 400);\n    setTimeout(fixOverlayAtPoint, 1200);\n  });\n  window.addEventListener(\"resize\", ()=> setTimeout(fixOverlayAtPoint, 150));\n})();\n\n\n\n\/* =========================================================\nTRIANGULATION77_LOGIC\n- Garde les r\u00e8gles\/contraintes du script original\n- IDs suffix\u00e9s 77 pour \u00e9viter conflits\n========================================================= *\/\n(function(){\n  const root = document.getElementById(\"berfTriangulation77\");\n  if(!root) return;\n\n  \/\/ Data (script original)\n  const citiesInFrance = [\n    { location: \"Paris\", latitude: 48.8566, longitude: 2.3522 },\n    { location: \"Lyon\", latitude: 45.7640, longitude: 4.8357 },\n    { location: \"Marseille\", latitude: 43.2965, longitude: 5.3698 },\n    { location: \"Bordeaux\", latitude: 44.8378, longitude: -0.5792 },\n    { location: \"Toulouse\", latitude: 43.6047, longitude: 1.4442 },\n    { location: \"Nice\", latitude: 43.7102, longitude: 7.2620 },\n    { location: \"Nantes\", latitude: 47.2184, longitude: -1.5536 },\n    { location: \"Strasbourg\", latitude: 48.5734, longitude: 7.7521 },\n    { location: \"Montpellier\", latitude: 43.6108, longitude: 3.8767 },\n    { location: \"Lille\", latitude: 50.6292, longitude: 3.0573 },\n\n    { location: \"Saint-Guilhem-le-D\u00e9sert (H\u00e9rault)\", latitude: 43.7367, longitude: 3.5550 },\n    { location: \"Rocamadour (Lot)\", latitude: 44.7967, longitude: 1.6275 },\n    { location: \"Gordes (Vaucluse)\", latitude: 43.9139, longitude: 5.2028 },\n    { location: \"Collonges-la-Rouge (Corr\u00e8ze)\", latitude: 45.0608, longitude: 1.6583 },\n    { location: \"\u00c8ze (Alpes-Maritimes)\", latitude: 43.7333, longitude: 7.3667 },\n    { location: \"Sancerre (Cher)\", latitude: 47.3314, longitude: 2.8369 },\n    { location: \"V\u00e9zelay (Yonne)\", latitude: 47.4667, longitude: 3.7400 },\n    { location: \"P\u00e9rouges (Ain)\", latitude: 45.8653, longitude: 5.1744 },\n    { location: \"Aubeterre-sur-Dronne (Charente)\", latitude: 45.2675, longitude: 0.1758 },\n    { location: \"La Roque-Gageac (Dordogne)\", latitude: 44.8333, longitude: 1.1833 },\n\n    { location: \"For\u00eat de Broc\u00e9liande (Ille-et-Vilaine)\", latitude: 48.0167, longitude: -2.1667 },\n    { location: \"For\u00eat de Fontainebleau (Seine-et-Marne)\", latitude: 48.4167, longitude: 2.7000 },\n    { location: \"For\u00eat des Landes de Gascogne (Landes)\", latitude: 44.2000, longitude: -0.7000 },\n    { location: \"For\u00eat d'Orient (Aube)\", latitude: 48.3500, longitude: 4.3833 },\n    { location: \"For\u00eat de Tron\u00e7ais (Allier)\", latitude: 46.6333, longitude: 2.7333 },\n\n    { location: \"Ch\u00e2teau de Brissac (Maine-et-Loire)\", latitude: 47.3667, longitude: -0.4500 },\n    { location: \"Ch\u00e2teau de Murol (Puy-de-D\u00f4me)\", latitude: 45.5594, longitude: 2.9492 },\n    { location: \"Ch\u00e2teau de Bonaguil (Lot-et-Garonne)\", latitude: 44.5500, longitude: 0.9333 },\n    { location: \"Ch\u00e2teau de Val (Corr\u00e8ze)\", latitude: 45.4203, longitude: 2.0331 },\n    { location: \"Ch\u00e2teau de Foug\u00e8res (Ille-et-Vilaine)\", latitude: 48.3517, longitude: -1.2025 },\n\n    { location: \"Alesia (C\u00f4te-d'Or)\", latitude: 47.5389, longitude: 4.5039 },\n    { location: \"Oradour-sur-Glane (Haute-Vienne)\", latitude: 45.9375, longitude: 1.0314 },\n    { location: \"Les Ar\u00e8nes de Lut\u00e8ce (Paris)\", latitude: 48.8456, longitude: 2.3533 },\n    { location: \"Le Mont Saint-Michel (Manche)\", latitude: 48.6361, longitude: -1.5114 },\n    { location: \"La Coupole (Pas-de-Calais)\", latitude: 50.7390, longitude: 2.2453 },\n    { location: \"Les Alignements de Carnac (Morbihan)\", latitude: 47.5850, longitude: -3.0783 },\n\n    { location: \"Ch\u00e2teau de Ripaille (Thonon-les-Bains)\", latitude: 46.3742, longitude: 6.4694 },\n    { location: \"Monts\u00e9gur (Ari\u00e8ge)\", latitude: 42.8725, longitude: 1.8358 }\n  ];\n\n  const agentsPhones = {\n    \"0742236587\": \"V\u00e9rril Belhair\",\n    \"0742341298\": \"Paul Dufort\",\n    \"0742457821\": \"Claire Gamerault\",\n    \"0742568932\": \"Madeleine Lemaitre\",\n    \"0742671243\": \"Catherine Dubois\",\n    \"0742783454\": \"Leila Ali\",\n    \"0742894565\": \"Elena Moreau\",\n    \"0742905676\": \"Isabelle Benoit\",\n    \"0742116787\": \"Sylvie Durand\",\n    \"0742227898\": \"Anjali Patel\",\n    \"0742338909\": \"Marie Leroy\",\n    \"0742449010\": \"Camille Martin\",\n    \"0742550121\": \"Louise Tremblay\",\n    \"0742661232\": \"Jean Ngono\",\n    \"0742772343\": \"Takeshi Kawasaki\",\n    \"0742883454\": \"Akira Hoshino\",\n    \"0742994565\": \"Michel Dubois\",\n    \"0742105676\": \"Amaury Delacroix\",\n    \"0742216787\": \"Thibault Morel\",\n    \"0742327898\": \"Henri Lefebvre\",\n    \"0742438909\": \"Claude Giraud\",\n    \"0742549010\": \"Nadir Boussif\",\n    \"0742650121\": \"Louis Smith\",\n    \"0742761232\": \"Jacques Fournier\",\n    \"0742872343\": \"Georges Lemoine\",\n    \"0742983454\": \"G\u00e9rard Martin\",\n    \"0742094565\": \"Talon Redfeather\",\n    \"0742105676\": \"Amaury Delacroix\",\n    \"0742116787\": \"William Peters\",\n    \"0742127898\": \"David Johnson\",\n    \"0742438909\": \"Alain Lambert\",\n    \"0742549010\": \"James Harrison\"\n  };\n\n  const SPECIFIC_PHONE = \"0742105676\";\n  const SPECIFIC_DATES = {\n    \"11\/02\/2023\": { latitude: 44.51803, longitude: 3.50115, location: \"Mende\" },\n    \"17\/04\/2023\": { latitude: 44.51703, longitude: 3.63889, location: \"Chadenet\" },\n    \"11\/06\/2023\": { latitude: 44.37082, longitude: 3.53373, location: \"Ispagnac\" },\n    \"16\/07\/2023\": { latitude: 44.37082, longitude: 3.53373, location: \"Ispagnac\" },\n    \"02\/09\/2023\": { latitude: 44.65958, longitude: 3.75682, location: \"Chaudeyrac\" },\n    \"16\/10\/2023\": { latitude: 44.71338, longitude: 3.78315, location: \"Rocles\" },\n    \"23\/10\/2023\": { latitude: 44.69068, longitude: 3.73313, location: \"Pierrefiche\" },\n    \"23\/11\/2023\": { latitude: 44.67033, longitude: 3.78809, location: \"Rocles\" },\n    \"28\/11\/2023\": { latitude: 44.67033, longitude: 3.78809, location: \"Rocles\" },\n    \"06\/12\/2023\": { latitude: 44.47951, longitude: 3.16928, location: \"St Germain du Teil\" },\n    \"08\/01\/2024\": { latitude: 44.52276, longitude: 3.27000, location: \"Bourgs-sur-Colagne\" },\n    \"04\/02\/2024\": { latitude: 44.34186, longitude: 3.22678, location: \"St Georges-de-L\u00e9v\u00e9jac\" }\n  };\n\n  \/\/ State\n  let currentCircle = null;\n  let osmMap = null;\n  let mapType = \"satellite\";\n  const triangulationHistory = [];\n  const agentLastLocation = {};\n\n  const MAX_SPEED_KMH = 60;\n  const SLEEP_END_HOUR = 7.5;\n\n  \/\/ DOM\n  const form = root.querySelector(\"#triForm77\");\n  const phoneEl = root.querySelector(\"#phoneInput77\");\n  const dateEl  = root.querySelector(\"#dateInput77\");\n  const startBtn = root.querySelector(\"#triStartBtn77\");\n\n  const resultBox = root.querySelector(\"#triResult77\");\n  const resultText = root.querySelector(\"#resultText77\");\n  const mapDiv = root.querySelector(\"#map77\");\n  const returnBtn = root.querySelector(\"#triReturnBtn77\");\n  const historyList = root.querySelector(\"#historyList77\");\n  const loadingBox = root.querySelector(\"#triLoading77\");\n  const loadingText = root.querySelector(\"#triLoadingText77\");\n  const loadingMeta = root.querySelector(\"#triLoadingMeta77\");\n  const loadingBar = root.querySelector(\"#triLoadingBar77\");\n\n  const mapViewSel = root.querySelector(\"#mapView77\");\n\n  function formatDate(date){\n    const day = String(date.getDate()).padStart(2,'0');\n    const month = String(date.getMonth()+1).padStart(2,'0');\n    const year = date.getFullYear();\n    return `${day}\/${month}\/${year}`;\n  }\n  function toRadians(deg){ return deg * (Math.PI\/180); }\n  function haversineDistance(lat1, lon1, lat2, lon2){\n    const R = 6371;\n    const dLat = toRadians(lat2-lat1);\n    const dLon = toRadians(lon2-lon1);\n    const a = Math.sin(dLat\/2)**2 + Math.cos(toRadians(lat1))*Math.cos(toRadians(lat2))*Math.sin(dLon\/2)**2;\n    return R * (2*Math.atan2(Math.sqrt(a), Math.sqrt(1-a)));\n  }\n\n  function simulateAgentMovement(phone, date){\n    let newLocation;\n    if(agentLastLocation[phone]){\n      const lastLocation = agentLastLocation[phone].location;\n      const lastDate = agentLastLocation[phone].date;\n      const timeDiffHours = (date - lastDate)\/(1000*60*60);\n      const maxPossibleDistance = MAX_SPEED_KMH * timeDiffHours;\n\n      let attempts = 0;\n      do{\n        newLocation = citiesInFrance[Math.floor(Math.random()*citiesInFrance.length)];\n        const distance = haversineDistance(lastLocation.latitude,lastLocation.longitude,newLocation.latitude,newLocation.longitude);\n        attempts++;\n        if(distance <= maxPossibleDistance) break;\n      }while(attempts < 100);\n\n      if(attempts >= 100){\n        newLocation = citiesInFrance[Math.floor(Math.random()*citiesInFrance.length)];\n      }\n    } else {\n      newLocation = citiesInFrance[Math.floor(Math.random()*citiesInFrance.length)];\n    }\n    agentLastLocation[phone] = { location: newLocation, date };\n    return newLocation;\n  }\n\n  function simulateDeparture(startLocation, date){\n    const departureTime = new Date(date);\n    departureTime.setHours(SLEEP_END_HOUR, 30, 0, 0);\n    const timeSinceDeparture = (date - departureTime)\/(1000*60*60);\n    const maxDistance = MAX_SPEED_KMH * timeSinceDeparture;\n\n    let newLocation, attempts = 0;\n    do{\n      newLocation = citiesInFrance[Math.floor(Math.random()*citiesInFrance.length)];\n      const distance = haversineDistance(startLocation.latitude,startLocation.longitude,newLocation.latitude,newLocation.longitude);\n      attempts++;\n      if(distance <= maxDistance) break;\n    }while(attempts < 100);\n\n    if(attempts >= 100){\n      newLocation = citiesInFrance[Math.floor(Math.random()*citiesInFrance.length)];\n    }\n    return newLocation;\n  }\n\n  function normalizeCoord(v){\n    if(typeof v === \"number\") return v;\n    const s = String(v == null ? '' : v).trim().replace(',', '.');\n    const n = parseFloat(s);\n    return Number.isFinite(n) ? n : 0;\n  }\n\n  function renderFallbackMap(latitude, longitude, label, precisionKm){\n    const lat = normalizeCoord(latitude);\n    const lon = normalizeCoord(longitude);\n    const radius = Number.isFinite(parseFloat(precisionKm)) ? parseFloat(precisionKm) : 1.2;\n    if(osmMap){ try{ osmMap.remove(); }catch(e){} osmMap = null; }\n    mapDiv.style.display = \"block\";\n    mapDiv.classList.add(\"tri77__map--fallback\");\n    mapDiv.innerHTML = `\n      <div class=\"tri77__fallbackMap\">\n        <div class=\"tri77__fallbackGrid\"><\/div>\n        <div class=\"tri77__fallbackScan\"><\/div>\n        <div class=\"tri77__fallbackPulse tri77__fallbackPulse--one\"><\/div>\n        <div class=\"tri77__fallbackPulse tri77__fallbackPulse--two\"><\/div>\n        <div class=\"tri77__fallbackPin\"><i class=\"fa-solid fa-location-dot\"><\/i><\/div>\n        <div class=\"tri77__fallbackReadout\">\n          <b>${label || 'Zone triangulee'}<\/b>\n          <span>Lat. ${lat.toFixed(5)} \/ Lon. ${lon.toFixed(5)}<\/span>\n          <span>Precision estimee : ${radius} km<\/span>\n          <em>Mode cartographique local<\/em>\n        <\/div>\n      <\/div>\n    `;\n  }\n\n  function ensureMapBase(latitude, longitude){\n    if(osmMap){ try{ osmMap.remove(); }catch(e){} osmMap = null; }\n    mapDiv.classList.remove(\"tri77__map--fallback\");\n    mapDiv.innerHTML = \"\";\n    if(!window.L || typeof L.map !== \"function\"){\n      renderFallbackMap(latitude, longitude, 'Carte externe indisponible', 1.2);\n      return null;\n    }\n    osmMap = L.map(mapDiv).setView([latitude, longitude], 8);\n\n    const tileLayerUrl = mapType === \"satellite\"\n      ? \"https:\/\/api.mapbox.com\/styles\/v1\/mapbox\/satellite-v9\/tiles\/{z}\/{x}\/{y}?access_token=pk.eyJ1IjoiaGVsdG9uOTc0IiwiYSI6ImNtMWFwbzh3eDF2cWYycXM4N2Q3NWU0eXUifQ.qlij4Anr2ntdqBAAjeDnJw\"\n      : \"https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png\";\n\n    const layer = L.tileLayer(tileLayerUrl, {\n      maxZoom: 22,\n      tileSize: 512,\n      zoomOffset: -1,\n      attribution: mapType === \"satellite\" ? \"\u00a9 Mapbox \u00a9 OpenStreetMap\" : \"\u00a9 OpenStreetMap\"\n    });\n    let tileErrors = 0;\n    layer.on(\"tileerror\", function(){\n      tileErrors += 1;\n      if(tileErrors === 3){\n        window.setTimeout(function(){\n          if(mapDiv && mapDiv.style.display !== \"none\"){\n            renderFallbackMap(latitude, longitude, 'Fond de carte externe indisponible', 1.2);\n          }\n        }, 450);\n      }\n    });\n    layer.addTo(osmMap);\n    window.setTimeout(function(){ try{ osmMap.invalidateSize(true); }catch(e){} }, 120);\n    return osmMap;\n  }\n\n\n  async function geocodePlace(place){\n    const q = String(place || '').trim();\n    if(!q) return null;\n    try{\n      const url = `https:\/\/nominatim.openstreetmap.org\/search?format=jsonv2&limit=1&q=${encodeURIComponent(q)}`;\n      const res = await fetch(url, { headers: { 'Accept': 'application\/json' } });\n      if(!res.ok) return null;\n      const data = await res.json();\n      if(!Array.isArray(data) || !data.length) return null;\n      const first = data[0];\n      const lat = parseFloat(first.lat);\n      const lon = parseFloat(first.lon);\n      if(!Number.isFinite(lat) || !Number.isFinite(lon)) return null;\n      return { latitude: lat, longitude: lon, location: q };\n    }catch(e){\n      return null;\n    }\n  }\n\n  async function resolveLocation(loc){\n    if(!loc) return null;\n    const lat = normalizeCoord(loc.latitude);\n    const lon = normalizeCoord(loc.longitude);\n    if(lat || lon){\n      return {\n        ...loc,\n        latitude: lat,\n        longitude: lon,\n        radius_km: Number.isFinite(parseFloat(String(loc.radius_km || '').replace(',', '.'))) ? parseFloat(String(loc.radius_km || '').replace(',', '.')) : 2\n      };\n    }\n    const geo = await geocodePlace(loc.location || '');\n    if(!geo) return null;\n    return {\n      ...loc,\n      latitude: geo.latitude,\n      longitude: geo.longitude,\n      radius_km: Number.isFinite(parseFloat(String(loc.radius_km || '').replace(',', '.'))) ? parseFloat(String(loc.radius_km || '').replace(',', '.')) : 2\n    };\n  }\n\n  async function resolveLocations(locations){\n    const out = [];\n    for(const loc of (Array.isArray(locations) ? locations : [])){\n      const resolved = await resolveLocation(loc);\n      if(resolved) out.push(resolved);\n    }\n    return out;\n  }\n\n  function showMapWithAnimation(lat, lon){\n    lat = normalizeCoord(lat);\n    lon = normalizeCoord(lon);\n    mapDiv.style.display = \"block\";\n    if(!ensureMapBase(lat, lon)){\n      renderFallbackMap(lat, lon, 'Localisation triangulee', 1.2);\n      return;\n    }\n\n    let radius = 5000;\n    const radiusStep = 1000;\n    const zoomLevelStep = 2;\n    const minRadius = 500;\n    const interval = 1000;\n\n    const circleInterval = setInterval(()=>{\n      if(!osmMap){\n        clearInterval(circleInterval);\n        return;\n      }\n      if(currentCircle){ try{ osmMap.removeLayer(currentCircle);}catch(e){} }\n      if(radius >= minRadius){\n        currentCircle = L.circle([lat, lon], { radius, color: \"#af3232\" }).addTo(osmMap);\n        radius -= radiusStep;\n        osmMap.setView([lat, lon], osmMap.getZoom() + zoomLevelStep);\n      } else {\n        clearInterval(circleInterval);\n        L.marker([lat, lon]).addTo(osmMap).bindPopup(\"Localisation triangul\u00e9e avec succ\u00e8s\").openPopup();\n      }\n    }, interval);\n  }\n\n  async function showMultipleLocationsAnimated(locations, phone, date, errorMsg){\n    hideTriangulationLoading();\n    resultText.innerHTML = `<h3>Erreur de triangulation :<\/h3><p class=\"prout\">${errorMsg || 'Plusieurs localisations possibles ont \u00e9t\u00e9 d\u00e9tect\u00e9es.'}<\/p>`;\n    mapDiv.style.display = \"block\";\n\n    const first = locations[0];\n    if(!ensureMapBase(normalizeCoord(first.latitude), normalizeCoord(first.longitude))){\n      renderFallbackMap(first.latitude, first.longitude, first.location || 'Position possible', first.radius_km || 1.2);\n      updateHistory(phone, date, errorMsg || 'Plusieurs localisations possibles');\n      return;\n    }\n\n    for(const loc of locations){\n      const lat = normalizeCoord(loc.latitude);\n      const lng = normalizeCoord(loc.longitude);\n      const radiusKm = Number.isFinite(parseFloat(String(loc.radius_km || '').replace(',', '.'))) ? parseFloat(String(loc.radius_km || '').replace(',', '.')) : 2;\n\n      osmMap.setView([lat, lng], 9);\n      let radius = Math.max(0.5, radiusKm) * 1800;\n      let loop = 0;\n\n      await new Promise(resolve=>{\n        const iv = setInterval(()=>{\n          if(!osmMap){\n            clearInterval(iv);\n            resolve();\n            return;\n          }\n          if(currentCircle){ try{ osmMap.removeLayer(currentCircle); }catch(e){} }\n          currentCircle = L.circle([lat, lng], {\n            radius,\n            color: \"#af3232\",\n            fillColor: \"#af3232\",\n            fillOpacity: 0.10,\n            weight: 2\n          }).addTo(osmMap);\n          radius = Math.max(radius * 0.62, Math.max(0.2, radiusKm) * 1000);\n          loop++;\n          if(loop >= 4){\n            clearInterval(iv);\n            L.circle([lat, lng], {\n              radius: Math.max(0.2, radiusKm) * 1000,\n              color: \"#af3232\",\n              fillColor: \"#af3232\",\n              fillOpacity: 0.12,\n              weight: 2\n            }).addTo(osmMap);\n            L.marker([lat, lng]).addTo(osmMap).bindPopup(loc.location || 'Position possible');\n            resolve();\n          }\n        }, 240);\n      });\n\n      await triDelay(180);\n    }\n\n    updateHistory(phone, date, errorMsg || 'Plusieurs localisations possibles');\n  }\n\n  function triDelay(ms){\n    return new Promise(resolve => setTimeout(resolve, ms));\n  }\n\n  async function playTriangulationLoading(){\n    if(!loadingBox || !loadingText || !resultText || !mapDiv || !returnBtn) return;\n    loadingBox.style.display = \"flex\";\n    resultText.style.display = \"none\";\n    mapDiv.style.display = \"none\";\n    returnBtn.style.display = \"none\";\n    if(loadingBar) loadingBar.style.width = \"8%\";\n    if(loadingMeta) loadingMeta.textContent = \"Signal brut : 12% \u00b7 Antennes verrouill\u00e9es : 0\/3\";\n\n    const steps = [\n      { text: \"Connexion aux antennes relais\u2026\", meta: \"Signal brut : 12% \u00b7 Antennes verrouill\u00e9es : 0\/3\", pct: 18, ms: 420 },\n      { text: \"Synchronisation des horodatages r\u00e9seau\u2026\", meta: \"Signal brut : 36% \u00b7 Antennes verrouill\u00e9es : 1\/3\", pct: 38, ms: 460 },\n      { text: \"Analyse du signal r\u00e9seau\u2026\", meta: \"Signal brut : 59% \u00b7 Antennes verrouill\u00e9es : 2\/3\", pct: 62, ms: 440 },\n      { text: \"Corr\u00e9lation temporelle des bornes\u2026\", meta: \"Signal brut : 81% \u00b7 Antennes verrouill\u00e9es : 3\/3\", pct: 84, ms: 420 },\n      { text: \"Calcul de la zone de recoupement\u2026\", meta: \"Pr\u00e9cision renforc\u00e9e \u00b7 Pr\u00e9visualisation cartographique\", pct: 100, ms: 520 }\n    ];\n\n    for(const step of steps){\n      loadingText.textContent = step.text;\n      if(loadingMeta) loadingMeta.textContent = step.meta;\n      if(loadingBar) loadingBar.style.width = step.pct + \"%\";\n      await triDelay(step.ms);\n    }\n  }\n\n  function hideTriangulationLoading(){\n    if(!loadingBox) return;\n    loadingBox.style.display = \"none\";\n    if(resultText) resultText.style.display = \"\";\n  }\n\n  function updateHistory(phone, date, message){\n    const item = document.createElement(\"div\");\n    item.className = \"history-item\";\n    item.innerHTML = `<p>T\u00e9l\u00e9phone : ${phone}<\/p><p>Date : ${date}<\/p><p>R\u00e9sultat : ${message}<\/p>`;\n    historyList.appendChild(item);\n    triangulationHistory.push({ phone, date, message });\n  }\n\n  function showLocation(location, agentName, phone, date, historyOverride){\n    hideTriangulationLoading();\n    resultText.innerHTML = `\n      <h3>R\u00e9sultats de la Triangulation :<\/h3>\n      <p class=\"prout\">Agent : ${agentName}<\/p>\n      <p class=\"prout\">Lieu : ${location.location}<\/p>\n      <p class=\"prout\">Coordonn\u00e9es GPS : Latitude ${location.latitude}, Longitude ${location.longitude}<\/p>\n    `;\n    updateHistory(phone, date, historyOverride || `Succ\u00e8s: ${location.location}`);\n    showMapWithAnimation(location.latitude, location.longitude);\n  }\n\n  async function showMultipleLocations(locations, phone, date, errorMsg){\n    await showMultipleLocationsAnimated(locations, phone, date, errorMsg);\n  }\n\n  function showRuleError(phone, date, errorMsg){\n    hideTriangulationLoading();\n    resultText.innerHTML = `<h3>Erreur de triangulation :<\/h3><p class=\"prout\">${errorMsg || 'Aucun signal exploitable.'}<\/p>`;\n    updateHistory(phone, date, errorMsg || 'Aucun signal exploitable');\n  }\n\n  function parseTriDate(v){\n    if(!v) return null;\n    const d = new Date(v);\n    return isNaN(d.getTime()) ? null : d;\n  }\n\n  function findCustomTriCase(phone, date){\n    const cases = Array.isArray(window.BERF_TRI_CASES) ? window.BERF_TRI_CASES : [];\n    const normalizedPhone = String(phone || '').replace(\/\\D+\/g,'');\n    const target = date instanceof Date ? date : new Date(date);\n    if(!normalizedPhone || isNaN(target.getTime())) return null;\n\n    for(const c of cases){\n      if(!c || String(c.phone || '').replace(\/\\D+\/g,'') !== normalizedPhone) continue;\n      const from = parseTriDate(c.from);\n      const to = parseTriDate(c.to);\n      let ok = false;\n      if(from && to){\n        ok = target >= from && target <= to;\n      }else if(from){\n        ok =\n          target.getFullYear() === from.getFullYear() &&\n          target.getMonth() === from.getMonth() &&\n          target.getDate() === from.getDate() &&\n          target.getHours() === from.getHours() &&\n          target.getMinutes() === from.getMinutes();\n      }\n      if(ok) return c;\n    }\n    return null;\n  }\n\n  function returnToForm(){\n    hideTriangulationLoading();\n    form.style.display = \"block\";\n    resultBox.style.display = \"none\";\n    if(osmMap){ try{ osmMap.remove(); }catch(e){} osmMap = null; }\n  }\n\n  async function startTriangulation(){\n    const phoneInput = (phoneEl.value || \"\").replace(\/\\s+\/g,'');\n    const dateInput = dateEl.value;\n\n    resultText.innerHTML = \"\";\n    resultBox.style.display = \"block\";\n    mapDiv.style.display = \"none\";\n    returnBtn.style.display = \"none\";\n    form.style.display = \"none\";\n    await playTriangulationLoading();\n\n    const date = new Date(dateInput);\n    if(!phoneInput || !dateInput || isNaN(date.getTime())){\n      hideTriangulationLoading();\n      resultText.innerHTML = `<p class=\"prout\">Veuillez renseigner un num\u00e9ro et une date\/heure.<\/p>`;\n      form.style.display = \"block\";\n      resultBox.style.display = \"block\";\n      returnBtn.style.display = \"block\";\n      return;\n    }\n\n    const customCase = findCustomTriCase(phoneInput, date);\n    if(customCase){\n      const agentName = customCase.agent_name || customCase.title || (agentsPhones[phoneInput] || phoneInput);\n      const locations = await resolveLocations(Array.isArray(customCase.locations) ? customCase.locations : []);\n\n      if(customCase.mode === 'error'){\n        showRuleError(phoneInput, dateInput, customCase.error_message || 'Aucun signal exploitable.');\n      } else if(customCase.mode === 'multiple' || locations.length > 1){\n        if(locations.length){\n          await showMultipleLocations(locations, phoneInput, dateInput, customCase.error_message || 'Plusieurs localisations possibles ont \u00e9t\u00e9 d\u00e9tect\u00e9es.');\n        } else {\n          showRuleError(phoneInput, dateInput, customCase.error_message || 'Impossible de g\u00e9ocoder les lieux d\u00e9finis.');\n        }\n      } else if(locations.length){\n        showLocation(locations[0], agentName, phoneInput, dateInput, customCase.history_message || '');\n      } else {\n        showRuleError(phoneInput, dateInput, customCase.error_message || 'Impossible de g\u00e9ocoder le lieu d\u00e9fini.');\n      }\n\n    } else if(phoneInput === SPECIFIC_PHONE){\n      const dateString = formatDate(date);\n      if(SPECIFIC_DATES[dateString]){\n        const arrivalTimeStart = new Date(date); arrivalTimeStart.setHours(19,30,0,0);\n        const arrivalTimeEnd   = new Date(date); arrivalTimeEnd.setHours(20,15,0,0);\n        const departureTime    = new Date(date); departureTime.setDate(departureTime.getDate()+1); departureTime.setHours(SLEEP_END_HOUR,30,0,0);\n\n        if(date >= arrivalTimeStart && date <= arrivalTimeEnd){\n          showLocation(SPECIFIC_DATES[dateString], \"Amaury Delacroix (Arriv\u00e9e)\", phoneInput, dateInput);\n        } else if(date < departureTime && date > arrivalTimeEnd){\n          showLocation(SPECIFIC_DATES[dateString], \"Amaury Delacroix (Nuit)\", phoneInput, dateInput);\n        } else if(date >= departureTime){\n          const depLoc = simulateDeparture(SPECIFIC_DATES[dateString], date);\n          showLocation(depLoc, \"Amaury Delacroix (D\u00e9part)\", phoneInput, dateInput);\n        } else {\n          const agentName = agentsPhones[phoneInput] || \"Amaury Delacroix\";\n          const loc = simulateAgentMovement(phoneInput, date);\n          showLocation(loc, agentName, phoneInput, dateInput);\n        }\n      } else {\n        const agentName = agentsPhones[phoneInput] || \"Amaury Delacroix\";\n        const loc = simulateAgentMovement(phoneInput, date);\n        showLocation(loc, agentName, phoneInput, dateInput);\n      }\n    } else if(phoneInput in agentsPhones){\n      const agentName = agentsPhones[phoneInput];\n      const loc = simulateAgentMovement(phoneInput, date);\n      showLocation(loc, agentName, phoneInput, dateInput);\n    } else {\n      resultText.innerHTML = `<p class=\"prout\">Num\u00e9ro non trouv\u00e9 dans la base de donn\u00e9es.<\/p>`;\n      updateHistory(phoneInput, dateInput, \"Num\u00e9ro non trouv\u00e9\");\n    }\n\n    returnBtn.style.display = \"block\";\n  }\n\n  function changeMapView(){\n    mapType = mapViewSel.value;\n    if(resultBox.style.display !== \"none\" && mapDiv.style.display !== \"none\" && osmMap){\n      \/\/ Recharger la carte au centre actuel\n      const center = osmMap.getCenter();\n      showMapWithAnimation(center.lat, center.lng);\n    }\n  }\n\n  \/\/ Bind UI\n  startBtn.addEventListener(\"click\", startTriangulation);\n  returnBtn.addEventListener(\"click\", returnToForm);\n  mapViewSel.addEventListener(\"change\", changeMapView);\n\n  \/\/ expose for debugging if needed\n  root.__tri77 = { startTriangulation, returnToForm, changeMapView };\n})();\n\n\n\/\/ =========================\n\/\/ ROUTE TOOL 23 (Leaflet + Mapbox geocoding)\n\/\/ - Conserve les fonctionnalit\u00e9s du code fourni\n\/\/ - Scop\u00e9, sans globals, sans CSS fixed\n\/\/ =========================\n(function(){\n  const ocId = \"route23\";\n  const oc = document.getElementById(\"berf-oc-route23\");\n  if(!oc) return;\n\n  const mapEl = document.getElementById(\"route23-map\");\n  const input = document.getElementById(\"route23-search\");\n  const btnAdd = document.getElementById(\"route23-add\");\n  const btnCenter = document.getElementById(\"route23-center\");\n  const listEl = document.getElementById(\"route23-list\");\n  const btnClear = document.getElementById(\"route23-clear\");\n  if(!mapEl || !input || !btnAdd || !listEl || !btnClear) return;\n\n  let map = null;\n  let markers = [];\n  let polylines = [];\n  let locations = [];\n\n  \/\/ Token Mapbox (si tu veux le centraliser: window.MAPBOX_ACCESS_TOKEN = '...')\n  const accessToken = (typeof window.MAPBOX_ACCESS_TOKEN === \"string\" && window.MAPBOX_ACCESS_TOKEN.trim())\n    ? window.MAPBOX_ACCESS_TOKEN.trim()\n    : \"pk.eyJ1IjoiaGVsdG9uOTc0IiwiYSI6ImNtMWFwbzh3eDF2cWYycXM4N2Q3NWU0eXUifQ.qlij4Anr2ntdqBAAjeDnJw\";\n\n  function clamp(n,min,max){ return Math.max(min, Math.min(max,n)); }\n\n  function fmtLatLng(latlng){\n    const lat = (Array.isArray(latlng) ? latlng[0] : latlng.lat);\n    const lng = (Array.isArray(latlng) ? latlng[1] : latlng.lng);\n    return `${lat.toFixed(5)}, ${lng.toFixed(5)}`;\n  }\n\n  function ensureMap(){\n    if(map) return map;\n    if(!window.L) {\n      alert(\"Leaflet n'est pas charg\u00e9.\");\n      return null;\n    }\n\n    map = L.map(mapEl, { zoomControl: true }).setView([48.8566, 2.3522], 5);\n    L.tileLayer('https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', { maxZoom: 18 }).addTo(map);\n\n    map.on('click', e => createMarker([e.latlng.lat, e.latlng.lng], 'Lieu sans nom'));\n\n    setTimeout(()=>{ try{ map.invalidateSize(true); }catch(_){} }, 120);\n    return map;\n  }\n\n  function updatePolylines(){\n    if(!map) return;\n    polylines.forEach(p => map.removeLayer(p));\n    polylines = [];\n\n    if (locations.length > 1) {\n      let coordinates = [];\n      let lastLatLng = null;\n\n      locations.forEach((location) => {\n        const cur = location.latLng;\n        if (lastLatLng && cur[0] === lastLatLng[0] && cur[1] === lastLatLng[1]) {\n          if (coordinates.length > 1) {\n            const polyline = L.polyline(coordinates, { color: '#af3232' }).addTo(map);\n            polylines.push(polyline);\n          }\n          coordinates = [];\n        } else {\n          coordinates.push(cur);\n        }\n        lastLatLng = cur;\n      });\n\n      if (coordinates.length > 1) {\n        const polyline = L.polyline(coordinates, { color: '#af3232' }).addTo(map);\n        polylines.push(polyline);\n      }\n    }\n  }\n\n  function renderList(){\n    if(!locations.length){\n      listEl.innerHTML = `<div class=\"route23-empty\">Aucune localisation. Ajoute un point \u00e0 gauche ou clique sur la carte.<\/div>`;\n      btnClear.style.display = 'none';\n      return;\n    }\n\n    listEl.innerHTML = locations.map((loc, idx)=>{\n      const meta = fmtLatLng(loc.latLng);\n      const safeName = String(loc.name || '').replace(\/[&<>\"']\/g, s=>({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",\"\\\"\":\"&quot;\",\"'\":\"&#039;\"}[s]));\n      return `\n        <div class=\"route23-item\" data-idx=\"${idx}\">\n          <div style=\"min-width:0; flex:1;\">\n            <div class=\"route23-itemName\">${safeName}<\/div>\n            <div class=\"route23-itemMeta\">${meta}<\/div>\n          <\/div>\n          <div class=\"route23-itemBtns\">\n            <button class=\"route23-miniBtn\" data-act=\"focus\" title=\"Aller au point\"><i class=\"fa-solid fa-location-crosshairs\"><\/i><\/button>\n            <button class=\"route23-miniBtn\" data-act=\"remove\" title=\"Supprimer\"><i class=\"fa-solid fa-xmark\"><\/i><\/button>\n          <\/div>\n        <\/div>\n      `;\n    }).join('');\n\n    btnClear.style.display = locations.length > 2 ? 'block' : 'none';\n  }\n\n  function addLocation(name, latLng){\n    locations.push({ name, latLng });\n    renderList();\n    updatePolylines();\n  }\n\n  function createMarker(latLng, name){\n    const m = L.marker(latLng).addTo(map).bindPopup(name);\n    markers.push(m);\n    addLocation(name, [latLng[0], latLng[1]]);\n    try{ m.openPopup(); }catch(_){}\n  }\n\n  function removeLocation(index){\n    index = clamp(index, 0, locations.length-1);\n    locations.splice(index, 1);\n    if(markers[index]){ try{ markers[index].remove(); }catch(_){} }\n    markers.splice(index, 1);\n    updatePolylines();\n    renderList();\n  }\n\n  function clearAllLocations(){\n    locations = [];\n    markers.forEach(m => { try{ m.remove(); }catch(_){} });\n    markers = [];\n    updatePolylines();\n    renderList();\n  }\n\n  async function geocodePlace(query){\n    const url = `https:\/\/api.mapbox.com\/geocoding\/v5\/mapbox.places\/${encodeURIComponent(query)}.json?access_token=${accessToken}`;\n    const res = await fetch(url);\n    const data = await res.json();\n    if (data.features && data.features.length > 0) {\n      const f = data.features[0];\n      const latLng = [f.center[1], f.center[0]];\n      return { latLng, name: f.place_name };\n    }\n    return null;\n  }\n\n  async function addLocationFromInput(){\n    if(!map) ensureMap();\n    const query = input.value.trim();\n    if(!query || !map) return;\n\n    const gpsRegex = \/^(-?\\d+(?:\\.\\d+)?),\\s*(-?\\d+(?:\\.\\d+)?)$\/;\n    if (gpsRegex.test(query)) {\n      const matches = query.match(gpsRegex);\n      const latLng = [parseFloat(matches[1]), parseFloat(matches[2])];\n      createMarker(latLng, `Lieu GPS: ${query}`);\n      input.value = '';\n      map.setView(latLng, Math.max(map.getZoom(), 12));\n      return;\n    }\n\n    try{\n      const result = await geocodePlace(query);\n      if(!result){ alert('Localisation non trouv\u00e9e.'); return; }\n      createMarker(result.latLng, result.name);\n      input.value = '';\n      map.setView(result.latLng, Math.max(map.getZoom(), 12));\n    }catch(err){\n      console.warn(err);\n      alert(\"Erreur de recherche. V\u00e9rifie ta connexion.\");\n    }\n  }\n\n  \/\/ List interactions\n  listEl.addEventListener('click', (e)=>{\n    const card = e.target.closest('.route23-item');\n    if(!card) return;\n    const idx = parseInt(card.getAttribute('data-idx'), 10);\n    const actBtn = e.target.closest('[data-act]');\n    if(!actBtn) return;\n    const act = actBtn.getAttribute('data-act');\n    if(act === 'remove'){\n      removeLocation(idx);\n    } else if(act === 'focus'){\n      if(!map) ensureMap();\n      const loc = locations[idx];\n      if(!loc || !map) return;\n      map.setView(loc.latLng, Math.max(map.getZoom(), 14));\n      if(markers[idx]){ try{ markers[idx].openPopup(); }catch(_){} }\n    }\n  });\n\n  btnAdd.addEventListener('click', addLocationFromInput);\n  input.addEventListener('keydown', (e)=>{ if(e.key === 'Enter') addLocationFromInput(); });\n  btnClear.addEventListener('click', clearAllLocations);\n  if(btnCenter){\n    btnCenter.addEventListener('click', ()=>{\n      if(!map) ensureMap();\n      if(!map) return;\n      if(locations.length){\n        const last = locations[locations.length-1];\n        map.setView(last.latLng, Math.max(map.getZoom(), 12));\n      }else{\n        map.setView([48.8566, 2.3522], 5);\n      }\n    });\n  }\n\n  \/\/ When opening the OC, ensure map is initialized + resized\n  const openBtn = document.querySelector(`.berf-taskbar-app[data-open-oc=\"${ocId}\"]`);\n  if(openBtn){\n    openBtn.addEventListener('click', ()=>{\n      setTimeout(()=>{\n        ensureMap();\n        if(map){ try{ map.invalidateSize(true); }catch(_){} }\n        renderList();\n      }, 140);\n    });\n  }\n\n  \/\/ First paint\n  renderList();\n})();\n\n<\/script>\n<script>\nwindow.addEventListener(\"DOMContentLoaded\", function(){\n  const desk = document.getElementById(\"berfDesk\");\n  const root = document.getElementById(\"imgtool991-root\");\n  if(!desk || !root) return;\n\n  const canvas = document.getElementById('imgtool991-canvas');\n  const ctx = canvas.getContext('2d');\n\n  const uploadInput = document.getElementById('imgtool991-upload-input');\n  const uploadButton = document.getElementById('imgtool991-upload-button');\n  const canvasContainer = document.getElementById('imgtool991-canvas-container');\n\n  const metaButton = document.getElementById('imgtool991-meta');\n  const reloadButton = document.getElementById('imgtool991-reload');\n  const resetButton = document.getElementById('imgtool991-reset');\n  const notice = document.getElementById('imgtool991-notice');\n  const closeNotice = document.getElementById('imgtool991-close-notice');\n\n  const srcCanvas = document.createElement('canvas');\n  const srcCtx = srcCanvas.getContext('2d', { willReadFrequently: true });\n\n  let img = new Image();\n  let hasImageLoaded = false;\n  let currentFile808 = null;\n\n  let zoomLevel = 1;\n  let offsetX = 0, offsetY = 0;\n  let isDragging = false;\n  let lastX = 0, lastY = 0;\n\n  let contrastLevel808 = 0;\n  let brightnessLevel808 = 0;\n  let inverted808 = false;\n  let originalImageData808 = null;\n  let compareEnabled808 = false;\n  let comparePosition808 = 50;\n  let annotationMode808 = false;\n  let annotations808 = [];\n\n  function clamp808(v){ return v < 0 ? 0 : (v > 255 ? 255 : v); }\n\n  function redrawFromSource808(){\n    if (!hasImageLoaded) return;\n    ctx.clearRect(0,0,canvas.width,canvas.height);\n    ctx.save();\n    ctx.setTransform(zoomLevel, 0, 0, zoomLevel, offsetX, offsetY);\n    ctx.drawImage(srcCanvas, 0, 0);\n    if(compareEnabled808 && originalImageData808){\n      const originalCanvas = document.createElement('canvas');\n      originalCanvas.width=srcCanvas.width; originalCanvas.height=srcCanvas.height;\n      originalCanvas.getContext('2d').putImageData(originalImageData808,0,0);\n      const cut=srcCanvas.width*(comparePosition808\/100);\n      ctx.save(); ctx.beginPath(); ctx.rect(0,0,cut,srcCanvas.height); ctx.clip(); ctx.drawImage(originalCanvas,0,0); ctx.restore();\n      ctx.strokeStyle='#ffffff'; ctx.lineWidth=Math.max(2,3\/zoomLevel); ctx.beginPath(); ctx.moveTo(cut,0); ctx.lineTo(cut,srcCanvas.height); ctx.stroke();\n    }\n    annotations808.forEach((mark,index)=>{\n      ctx.beginPath(); ctx.fillStyle='#af3232'; ctx.strokeStyle='#fff'; ctx.lineWidth=Math.max(2,2\/zoomLevel); ctx.arc(mark.x,mark.y,Math.max(10,16\/zoomLevel),0,Math.PI*2); ctx.fill(); ctx.stroke();\n      ctx.fillStyle='#fff'; ctx.font=`bold ${Math.max(12,15\/zoomLevel)}px Arial`; ctx.textAlign='center'; ctx.textBaseline='middle'; ctx.fillText(String(index+1),mark.x,mark.y);\n    });\n    ctx.restore();\n    const zoomValue=document.getElementById('imgtool991-zoom-value'); if(zoomValue) zoomValue.textContent=Math.round(zoomLevel*100)+' %';\n  }\n\n  function rebuildProcessed808(){\n    if(!hasImageLoaded || !originalImageData808) return;\n    const imageData=new ImageData(new Uint8ClampedArray(originalImageData808.data),originalImageData808.width,originalImageData808.height);\n    const data=imageData.data, L=Math.max(-100,Math.min(100,contrastLevel808));\n    const factor=(259*(L+255))\/(255*(259-L));\n    const light=brightnessLevel808*2.55;\n    for(let i=0;i<data.length;i+=4){\n      let r=clamp808(factor*(data[i]-128)+128+light), g=clamp808(factor*(data[i+1]-128)+128+light), b=clamp808(factor*(data[i+2]-128)+128+light);\n      if(inverted808){r=255-r;g=255-g;b=255-b;}\n      if(currentColorFilter808==='r'){g=0;b=0;} else if(currentColorFilter808==='g'){r=0;b=0;} else if(currentColorFilter808==='b'){r=0;g=0;}\n      data[i]=r;data[i+1]=g;data[i+2]=b;\n    }\n    srcCtx.putImageData(imageData,0,0); baseSourceImageData808=imageData; setActiveColorBtn808(); redrawFromSource808();\n  }\n\n  function imageTarget808(){ return currentFile808 && currentFile808.name ? currentFile808.name : 'image'; }\n  function triggerImageEvent808(type,payload){ try{if(window.BERF_EVENTS)window.BERF_EVENTS.trigger(type,imageTarget808(),Object.assign({fileName:imageTarget808()},payload||{}));}catch(e){} }\n  function annotationStore808(){\n    try{const data=JSON.parse(localStorage.getItem('berf_img_annotations_v1')||'{}');return data&&typeof data==='object'?data:{};}catch(e){return {};}\n  }\n  function saveAnnotations808(){try{const data=annotationStore808();data[imageTarget808()]=annotations808;localStorage.setItem('berf_img_annotations_v1',JSON.stringify(data));}catch(e){}}\n  function loadAnnotations808(){try{const data=annotationStore808();annotations808=Array.isArray(data[imageTarget808()])?data[imageTarget808()]:[];}catch(e){annotations808=[];}}\n\n  function applyContrastForensicToSource808(level){\n    if (!hasImageLoaded) return;\n    const imageData = srcCtx.getImageData(0, 0, srcCanvas.width, srcCanvas.height);\n    const data = imageData.data;\n\n    const L = Math.max(-100, Math.min(100, level));\n    const factor = (259 * (L + 255)) \/ (255 * (259 - L));\n\n    for (let i = 0; i < data.length; i += 4) {\n      data[i]     = clamp808(factor * (data[i]     - 128) + 128);\n      data[i + 1] = clamp808(factor * (data[i + 1] - 128) + 128);\n      data[i + 2] = clamp808(factor * (data[i + 2] - 128) + 128);\n    }\n    srcCtx.putImageData(imageData, 0, 0);\n    redrawFromSource808();\n  }\n\n  function invertSource808(){\n    if (!hasImageLoaded) return;\n    const imageData = srcCtx.getImageData(0, 0, srcCanvas.width, srcCanvas.height);\n    const data = imageData.data;\n    for (let i = 0; i < data.length; i += 4) {\n      data[i] = 255 - data[i];\n      data[i+1] = 255 - data[i+1];\n      data[i+2] = 255 - data[i+2];\n    }\n    srcCtx.putImageData(imageData, 0, 0);\n    redrawFromSource808();\n  }\n\n  let currentColorFilter808 = 'none';\n  let baseSourceImageData808 = null;\n  function snapshotBaseSource808(){ baseSourceImageData808 = srcCtx.getImageData(0, 0, srcCanvas.width, srcCanvas.height); }\n\n  function setActiveColorBtn808(){\n    ['imgtool991-r','imgtool991-g','imgtool991-b','imgtool991-rgb-off'].forEach(id=>{\n      const el = document.getElementById(id); if(el) el.classList.remove('active');\n    });\n    if (currentColorFilter808 === 'r') document.getElementById('imgtool991-r').classList.add('active');\n    else if (currentColorFilter808 === 'g') document.getElementById('imgtool991-g').classList.add('active');\n    else if (currentColorFilter808 === 'b') document.getElementById('imgtool991-b').classList.add('active');\n    else document.getElementById('imgtool991-rgb-off').classList.add('active');\n  }\n\n  function applyColorFilterToSource808(){\n    if (!hasImageLoaded || !baseSourceImageData808) return;\n\n    srcCtx.putImageData(baseSourceImageData808, 0, 0);\n\n    if (currentColorFilter808 === 'none') {\n      redrawFromSource808();\n      setActiveColorBtn808();\n      return;\n    }\n\n    const imageData = srcCtx.getImageData(0, 0, srcCanvas.width, srcCanvas.height);\n    const data = imageData.data;\n\n    for (let i = 0; i < data.length; i += 4) {\n      if (currentColorFilter808 === 'r') { data[i+1]=0; data[i+2]=0; }\n      if (currentColorFilter808 === 'g') { data[i]=0; data[i+2]=0; }\n      if (currentColorFilter808 === 'b') { data[i]=0; data[i+1]=0; }\n    }\n    srcCtx.putImageData(imageData, 0, 0);\n    redrawFromSource808();\n    setActiveColorBtn808();\n  }\n\n  const modeState123 = {\n    mode: 'normal',\n    grain: 0,\n    apply() {\n      let css = '';\n      if (this.mode === 'night') {\n        css = 'contrast(1.35) brightness(0.90) saturate(0.35)';\n        setOverlay123('night');\n        this.grain = Math.max(this.grain, 0.18);\n      } else if (this.mode === 'uv') {\n        css = 'contrast(1.70) brightness(1.05) saturate(0.20)';\n        setOverlay123('uv');\n        this.grain = Math.max(this.grain, 0.22);\n      } else if (this.mode === 'archive') {\n        css = 'contrast(1.05) brightness(1.02) saturate(0.60)';\n        setOverlay123('archive');\n        this.grain = Math.max(this.grain, 0.12);\n      } else {\n        css = '';\n        setOverlay123('normal');\n      }\n      canvas.style.filter = css;\n      document.getElementById('imgtool991-grainOverlay').style.opacity = String(this.grain);\n      setModeBtnActive123(this.mode);\n    }\n  };\n\n  function setOverlay123(mode) {\n    const o = document.getElementById('imgtool991-modeOverlay');\n    if (!o) return;\n\n    if (mode === 'night') {\n      o.style.opacity = '0.35';\n      o.style.mixBlendMode = 'screen';\n      o.style.background = 'radial-gradient(circle at 50% 40%, rgba(120,255,160,0.35), rgba(0,0,0,0.85) 70%)';\n    } else if (mode === 'uv') {\n      o.style.opacity = '0.42';\n      o.style.mixBlendMode = 'color-dodge';\n      o.style.background = 'radial-gradient(circle at 50% 45%, rgba(180,255,255,0.55), rgba(0,30,60,0.95) 70%)';\n    } else if (mode === 'archive') {\n      o.style.opacity = '0.35';\n      o.style.mixBlendMode = 'multiply';\n      o.style.background = 'radial-gradient(circle at 50% 40%, rgba(255,240,200,0.75), rgba(80,60,40,0.55) 80%)';\n    } else {\n      o.style.opacity = '0';\n      o.style.mixBlendMode = 'normal';\n      o.style.background = 'transparent';\n    }\n  }\n\n  function setModeBtnActive123(mode) {\n    const ids = ['imgtool991-mode-night','imgtool991-mode-uv','imgtool991-mode-archive','imgtool991-mode-normal'];\n    ids.forEach(id => document.getElementById(id).classList.remove('active'));\n    if (mode === 'night') document.getElementById('imgtool991-mode-night').classList.add('active');\n    else if (mode === 'uv') document.getElementById('imgtool991-mode-uv').classList.add('active');\n    else if (mode === 'archive') document.getElementById('imgtool991-mode-archive').classList.add('active');\n    else document.getElementById('imgtool991-mode-normal').classList.add('active');\n  }\n\n  function loadFileIntoPipeline808(file){\n    currentFile808 = file;\n    const reader = new FileReader();\n    reader.onload = (e) => { img.src = e.target.result; };\n    reader.readAsDataURL(file);\n\n    reloadButton.style.display = 'block';\n    uploadButton.style.display = 'none';\n  }\n\n  \/\/ \u2705 Load an image from URL (evidence -> image tool)\n  window.berfImgToolLoadFromUrl = async function(url){\n    if(!url) return;\n    try{\n      const res = await fetch(url, { mode: 'cors' });\n      if(!res.ok) throw new Error('HTTP ' + res.status);\n      const blob = await res.blob();\n      const filename = (url.split('\/').pop() || 'evidence-image').split('?')[0] || 'evidence-image';\n      const file = new File([blob], filename, { type: blob.type || 'image\/png' });\n      uploadInput.value = '';\n      loadFileIntoPipeline808(file);\n    }catch(err){\n      console.warn(err);\n      try{\n        img.crossOrigin = \"anonymous\";\n        img.src = url;\n      }catch(e2){\n        console.warn(e2);\n        alert(\"Impossible de charger cette image (CORS). Essayez de l'ouvrir puis de la t\u00e9l\u00e9charger localement.\");\n      }\n    }\n  };\n\n\n  \/\/ Upload fixes\n  uploadButton.addEventListener('click', (e) => e.stopPropagation());\n  canvasContainer.addEventListener('click', (e) => {\n    if (e.target === uploadButton || e.target === uploadInput) return;\n    if (!hasImageLoaded) uploadInput.click();\n  });\n  uploadInput.addEventListener('change', (event) => {\n    const file = event.target.files && event.target.files[0];\n    if (file) loadFileIntoPipeline808(file);\n  });\n\n  canvasContainer.addEventListener('dragover', (e) => e.preventDefault());\n  canvasContainer.addEventListener('drop', (e) => {\n    e.preventDefault();\n    const file = e.dataTransfer.files[0];\n    if (file && file.type && file.type.startsWith('image')) loadFileIntoPipeline808(file);\n  });\n\n  img.onload = () => {\n    hasImageLoaded = true;\n    canvas.style.display = 'block';\n\n    srcCanvas.width = img.width;\n    srcCanvas.height = img.height;\n    canvas.width = img.width;\n    canvas.height = img.height;\n\n    zoomLevel = 1; offsetX = 0; offsetY = 0;\n    contrastLevel808 = 0;\n    brightnessLevel808 = 0; inverted808 = false; compareEnabled808 = false; comparePosition808 = 50; annotationMode808 = false;\n    currentColorFilter808 = 'none';\n    setActiveColorBtn808();\n\n    srcCtx.setTransform(1,0,0,1,0,0);\n    srcCtx.clearRect(0,0,srcCanvas.width,srcCanvas.height);\n    srcCtx.drawImage(img, 0, 0);\n\n    originalImageData808=srcCtx.getImageData(0,0,srcCanvas.width,srcCanvas.height);\n    snapshotBaseSource808(); loadAnnotations808(); rebuildProcessed808();\n    const contrastInput=document.getElementById('imgtool991-contrast'); const brightnessInput=document.getElementById('imgtool991-brightness');\n    if(contrastInput) contrastInput.value='0'; if(brightnessInput) brightnessInput.value='0';\n    document.getElementById('imgtool991-contrast-value').textContent='0'; document.getElementById('imgtool991-brightness-value').textContent='0';\n    document.getElementById('imgtool991-compare-wrap').hidden=true; document.getElementById('imgtool991-compare').classList.remove('active'); document.getElementById('imgtool991-annotate').classList.remove('active');\n    modeState123.apply();\n    triggerImageEvent808('image_opened',{width:img.width,height:img.height});\n  };\n\n  \/\/ EXIF helpers\n  function formatDate808(d){\n    try{\n      if (!d) return null;\n      const dt = (d instanceof Date) ? d : new Date(d);\n      if (isNaN(dt.getTime())) return String(d);\n      return dt.toLocaleString();\n    }catch(e){ return String(d); }\n  }\n  function formatGps808(lat, lon){\n    if (typeof lat !== 'number' || typeof lon !== 'number') return null;\n    return `${lat.toFixed(6)}, ${lon.toFixed(6)}`;\n  }\n  async function getExif808(file){\n    if (!file || !window.exifr) return null;\n    try{\n      const exif = await exifr.parse(file, { gps:true, tiff:true, ifd0:true, exif:true });\n      return exif || null;\n    }catch(err){ return null; }\n  }\n\n  const metaModal = document.getElementById('imgtool991-modal');\n  const metaContent = document.getElementById('imgtool991-modal-content');\n  const metaClose = document.getElementById('imgtool991-modal-close');\n  const escMeta808 = value => String(value ?? '').replace(\/[&<>\\\"']\/g, char => ({'&':'&amp;','<':'&lt;','>':'&gt;','\\\"':'&quot;',\"'\":'&#039;'}[char]));\n  const metaRow808 = (label,value) => `<div class=\"kv\"><span>${escMeta808(label)}<\/span><b>${escMeta808(value)}<\/b><\/div>`;\n\n  metaButton.addEventListener('click', async () => {\n    if (!hasImageLoaded) { alert(\"Veuillez charger une image d'abord.\"); return; }\n\n    const file = currentFile808 || (uploadInput.files && uploadInput.files[0]) || null;\n    const fileSize = file ? (file.size \/ 1024).toFixed(2) : 'Inconnu';\n    const fileType = file ? (file.type || 'Inconnu') : 'Inconnu';\n    const fileName = file ? (file.name || 'Inconnu') : 'Inconnu';\n\n    metaContent.innerHTML = `<div class=\"imgtool991-extract\"><span class=\"imgtool991-extract-spinner\"><\/span><b>Extraction des m\u00e9tadonn\u00e9es\u2026<\/b><small>Lecture de la structure EXIF du fichier<\/small><i><\/i><\/div>`;\n    \n    \/\/ \u2705 FIX : en frontend Elementor, certains conteneurs cr\u00e9ent un \"stacking context\" (transform\/overflow)\n    \/\/ qui peut faire passer la modale derri\u00e8re. On d\u00e9place donc la modale en fin de <body> + z-index max.\n    (function ensureImgtoolModalOnTop(){\n      const modal = document.getElementById('imgtool991-modal');\n      if (!modal) return;\n      if (modal.parentElement !== document.body) {\n        document.body.appendChild(modal);\n      }\n      modal.style.zIndex = '2147483647';\n      modal.style.position = 'fixed';\n      modal.style.inset = '0';\n    })();\n\n    metaModal.classList.add('show');\n\n    const [exif] = await Promise.all([getExif808(file), new Promise(resolve=>setTimeout(resolve,900))]);\n    triggerImageEvent808('image_exif_viewed', {});\n    if (!exif){\n      metaContent.innerHTML = `<div class=\"imgtool991-meta-grid\"><section><h4>Fichier analys\u00e9<\/h4>${metaRow808('Nom',fileName)}${metaRow808('Type',fileType)}${metaRow808('Poids',fileSize+' Ko')}${metaRow808('Dimensions',img.width+' \u00d7 '+img.height+' px')}<\/section><section><h4>Donn\u00e9es EXIF<\/h4><div class=\"kv\"><span>R\u00e9sultat<\/span><b>Aucune donn\u00e9e d\u00e9tect\u00e9e<\/b><\/div><\/section><\/div>`;\n      return;\n    }\n\n    const make = exif.Make || exif.make;\n    const model = exif.Model || exif.model;\n    const lens = exif.LensModel || exif.Lens || exif.lensModel;\n    const software = exif.Software || exif.software;\n    const date = formatDate808(exif.DateTimeOriginal || exif.CreateDate || exif.ModifyDate);\n    const exposure = exif.ExposureTime ? `${exif.ExposureTime}s` : null;\n    const fnumber = exif.FNumber ? `f\/${exif.FNumber}` : null;\n    const iso = exif.ISO || exif.ISOSpeedRatings;\n    const focal = exif.FocalLength ? `${exif.FocalLength}mm` : null;\n    const flash = (exif.Flash !== undefined) ? String(exif.Flash) : null;\n    const orientation = exif.Orientation || null;\n    const gps = formatGps808(exif.latitude, exif.longitude);\n\n    const technical = [];\n    if (date) technical.push(metaRow808('Prise de vue',date));\n    if (make || model) technical.push(metaRow808('Appareil',`${(make||'').trim()} ${(model||'').trim()}`.trim()));\n    if (lens) technical.push(metaRow808('Objectif',lens));\n    if (fnumber) technical.push(metaRow808('Ouverture',fnumber));\n    if (exposure) technical.push(metaRow808('Vitesse',exposure));\n    if (iso) technical.push(metaRow808('Sensibilit\u00e9','ISO '+iso));\n    if (focal) technical.push(metaRow808('Focale',focal));\n    if (flash) technical.push(metaRow808('Flash',flash));\n    if (orientation) technical.push(metaRow808('Orientation',orientation));\n    if (software) technical.push(metaRow808('Logiciel',software));\n    const gpsHtml = gps ? `<section class=\"imgtool991-meta-gps\"><h4>G\u00e9olocalisation<\/h4>${metaRow808('Coordonn\u00e9es',gps)}<button type=\"button\" id=\"imgtool991-copy-gps\">Copier les coordonn\u00e9es<\/button><\/section>` : '';\n    metaContent.innerHTML = `<div class=\"imgtool991-meta-grid\"><section><h4>Fichier analys\u00e9<\/h4>${metaRow808('Nom',fileName)}${metaRow808('Type',fileType)}${metaRow808('Poids',fileSize+' Ko')}${metaRow808('Dimensions',img.width+' \u00d7 '+img.height+' px')}<\/section><section><h4>Donn\u00e9es techniques<\/h4>${technical.length?technical.join(''):'<div class=\"kv\"><span>R\u00e9sultat<\/span><b>Champs non standards<\/b><\/div>'}<\/section>${gpsHtml}<\/div>`;\n    const copyGps = document.getElementById('imgtool991-copy-gps');\n    if (copyGps) copyGps.addEventListener('click', async ()=>{\n      try{await navigator.clipboard.writeText(gps);}catch(e){const ta=document.createElement('textarea');ta.value=gps;document.body.appendChild(ta);ta.select();document.execCommand('copy');ta.remove();}\n      copyGps.textContent='Coordonn\u00e9es copi\u00e9es';\n      triggerImageEvent808('image_gps_copied',{gps,latitude:exif.latitude,longitude:exif.longitude});\n      setTimeout(()=>{copyGps.textContent='Copier les coordonn\u00e9es';},1600);\n    });\n  });\n\n  metaClose.addEventListener('click', ()=> metaModal.classList.remove('show'));\n  metaModal.addEventListener('click', (e)=>{ if(e.target === metaModal) metaModal.classList.remove('show'); });\n\n  \/\/ Controls\n  const contrastInput808=document.getElementById('imgtool991-contrast');\n  const brightnessInput808=document.getElementById('imgtool991-brightness');\n  const contrastValue808=document.getElementById('imgtool991-contrast-value');\n  const brightnessValue808=document.getElementById('imgtool991-brightness-value');\n  const invertButton808=document.getElementById('imgtool991-invert');\n  const compareButton808=document.getElementById('imgtool991-compare');\n  const compareWrap808=document.getElementById('imgtool991-compare-wrap');\n  const compareInput808=document.getElementById('imgtool991-compare-position');\n  const annotateButton808=document.getElementById('imgtool991-annotate');\n  const canvasPoint808=e=>{const r=canvas.getBoundingClientRect(),sx=canvas.width\/r.width,sy=canvas.height\/r.height;return{x:(e.clientX-r.left)*sx,y:(e.clientY-r.top)*sy};};\n  const setZoom808=(value,anchor)=>{const old=zoomLevel;zoomLevel=Math.max(.25,Math.min(8,value));if(anchor){const ix=(anchor.x-offsetX)\/old,iy=(anchor.y-offsetY)\/old;offsetX=anchor.x-ix*zoomLevel;offsetY=anchor.y-iy*zoomLevel;}redrawFromSource808();};\n\n  contrastInput808.addEventListener('input',()=>{contrastLevel808=Number(contrastInput808.value);contrastValue808.textContent=contrastLevel808;rebuildProcessed808();});\n  brightnessInput808.addEventListener('input',()=>{brightnessLevel808=Number(brightnessInput808.value);brightnessValue808.textContent=brightnessLevel808;rebuildProcessed808();});\n  invertButton808.addEventListener('click',()=>{if(!hasImageLoaded)return;inverted808=!inverted808;invertButton808.classList.toggle('active',inverted808);rebuildProcessed808();});\n  document.getElementById('imgtool991-zoom-in').addEventListener('click',()=>{if(hasImageLoaded)setZoom808(zoomLevel*1.25,{x:canvas.width\/2,y:canvas.height\/2});});\n  document.getElementById('imgtool991-zoom-out').addEventListener('click',()=>{if(hasImageLoaded)setZoom808(zoomLevel\/1.25,{x:canvas.width\/2,y:canvas.height\/2});});\n  document.getElementById('imgtool991-fit').addEventListener('click',()=>{if(!hasImageLoaded)return;zoomLevel=1;offsetX=0;offsetY=0;redrawFromSource808();});\n  canvas.addEventListener('wheel',e=>{if(!hasImageLoaded)return;e.preventDefault();setZoom808(zoomLevel*(e.deltaY<0?1.12:.89),canvasPoint808(e));},{passive:false});\n\n  canvas.addEventListener('mousedown', (e) => { if (!hasImageLoaded) return; const p=canvasPoint808(e); if(annotationMode808){const mark={x:(p.x-offsetX)\/zoomLevel,y:(p.y-offsetY)\/zoomLevel,createdAt:new Date().toISOString()};if(mark.x>=0&&mark.y>=0&&mark.x<=srcCanvas.width&&mark.y<=srcCanvas.height){annotations808.push(mark);saveAnnotations808();redrawFromSource808();triggerImageEvent808('image_annotation_created',{annotation:mark,count:annotations808.length});}return;} isDragging = true; lastX = p.x; lastY = p.y; canvas.classList.add('panning'); });\n  canvas.addEventListener('mousemove', (e) => {\n    if (!hasImageLoaded || !isDragging) return;\n    const p=canvasPoint808(e); const dx = p.x - lastX; const dy = p.y - lastY;\n    offsetX += dx; offsetY += dy;\n    lastX = p.x; lastY = p.y;\n    redrawFromSource808();\n  });\n  ['mouseup','mouseleave'].forEach(ev=> canvas.addEventListener(ev, ()=>{ isDragging = false; canvas.classList.remove('panning'); }));\n\n  compareButton808.addEventListener('click',()=>{if(!hasImageLoaded)return;compareEnabled808=!compareEnabled808;compareButton808.classList.toggle('active',compareEnabled808);compareWrap808.hidden=!compareEnabled808;redrawFromSource808();});\n  compareInput808.addEventListener('input',()=>{comparePosition808=Number(compareInput808.value);redrawFromSource808();});\n  annotateButton808.addEventListener('click',()=>{if(!hasImageLoaded)return;annotationMode808=!annotationMode808;annotateButton808.classList.toggle('active',annotationMode808);canvas.classList.toggle('annotating',annotationMode808);});\n  document.getElementById('imgtool991-annotation-undo').addEventListener('click',()=>{if(!annotations808.length)return;annotations808.pop();saveAnnotations808();redrawFromSource808();});\n  document.getElementById('imgtool991-annotation-clear').addEventListener('click',()=>{if(!annotations808.length)return;annotations808=[];saveAnnotations808();redrawFromSource808();});\n\n  const setColor808=filter=>{if(!hasImageLoaded)return;currentColorFilter808=currentColorFilter808===filter?'none':filter;rebuildProcessed808();};\n  document.getElementById('imgtool991-r').addEventListener('click',()=>setColor808('r'));\n  document.getElementById('imgtool991-g').addEventListener('click',()=>setColor808('g'));\n  document.getElementById('imgtool991-b').addEventListener('click',()=>setColor808('b'));\n  document.getElementById('imgtool991-rgb-off').addEventListener('click',()=>{currentColorFilter808='none';rebuildProcessed808();});\n\n  resetButton.addEventListener('click', () => {\n    if (!hasImageLoaded) return;\n    zoomLevel = 1; offsetX = 0; offsetY = 0;\n\n    contrastLevel808 = 0;\n    brightnessLevel808 = 0;\n    inverted808 = false;\n    currentColorFilter808 = 'none';\n    compareEnabled808 = false;\n    comparePosition808 = 50;\n    contrastInput808.value=0;brightnessInput808.value=0;contrastValue808.textContent='0';brightnessValue808.textContent='0';compareInput808.value=50;compareWrap808.hidden=true;\n    invertButton808.classList.remove('active');compareButton808.classList.remove('active');\n    notice.style.display = 'none';\n\n    modeState123.mode = 'normal';\n    modeState123.grain = 0;\n    modeState123.apply();\n\n    rebuildProcessed808();\n  });\n\n  reloadButton.addEventListener('click', ()=>{ currentFile808 = null; uploadInput.value = ''; uploadInput.click(); });\n  closeNotice.addEventListener('click', ()=>{ notice.style.display = 'none'; });\n\n  document.getElementById('imgtool991-mode-night').addEventListener('click', () => { modeState123.mode = (modeState123.mode === 'night' ? 'normal' : 'night'); modeState123.apply(); });\n  document.getElementById('imgtool991-mode-uv').addEventListener('click', () => { modeState123.mode = (modeState123.mode === 'uv' ? 'normal' : 'uv'); modeState123.apply(); });\n  document.getElementById('imgtool991-mode-archive').addEventListener('click', () => { modeState123.mode = (modeState123.mode === 'archive' ? 'normal' : 'archive'); modeState123.apply(); });\n  document.getElementById('imgtool991-mode-normal').addEventListener('click', () => { modeState123.mode = 'normal'; modeState123.grain = 0; modeState123.apply(); });\n  \/\/ --- Expose bridge for other tools (Evidence DB -> ImgTool) ---\n  window.BERF_IMGTOOL_IMPORT_FILE = function(file){\n    try{ loadFileIntoPipeline808(file); }catch(e){ console.warn('IMGTOOL_IMPORT_FILE failed', e); }\n  };\n  window.BERF_IMGTOOL_IMPORT_URL = async function(url, name){\n    try{\n      const res = await fetch(url, { cache: 'no-store' });\n      const blob = await res.blob();\n      const fname = name || 'evidence.jpg';\n      const file = new File([blob], fname, { type: blob.type || 'image\/jpeg' });\n      loadFileIntoPipeline808(file);\n    }catch(e){\n      console.warn('IMGTOOL_IMPORT_URL failed', e);\n      throw e;\n    }\n  };\n\n});\n<\/script>\n<script>\n(function(){\n  const ROOT_ID = 'audiotool772-root';\n  let inited = false;\n\n  function loadScriptOnce(src){\n    return new Promise((resolve,reject)=>{\n      const existing = document.querySelector('script[data-src=\"'+src+'\"]');\n      if (existing){\n        if (existing.dataset.loaded === '1') return resolve();\n        existing.addEventListener('load', ()=>resolve());\n        existing.addEventListener('error', ()=>reject(new Error('load failed')));\n        return;\n      }\n      const s = document.createElement('script');\n      s.src = src;\n      s.async = true;\n      s.dataset.src = src;\n      s.addEventListener('load', ()=>{ s.dataset.loaded='1'; resolve(); });\n      s.addEventListener('error', ()=>reject(new Error('load failed: '+src)));\n      document.head.appendChild(s);\n    });\n  }\n\n  function ensureLibs(){\n    const tasks = [];\n    if (!window.WaveSurfer) tasks.push(loadScriptOnce('https:\/\/unpkg.com\/wavesurfer.js'));\n    if (!window.Tone) tasks.push(loadScriptOnce('https:\/\/unpkg.com\/tone'));\n    return Promise.all(tasks);\n  }\n\n  function $(id){ return document.getElementById(id); }\n  function fmtTime(s){ if(!isFinite(s)||s<0)s=0; const m=Math.floor(s\/60), r=Math.floor(s%60); return String(m).padStart(2,'0')+':'+String(r).padStart(2,'0'); }\n  function clamp(v,a,b){ return Math.max(a, Math.min(b, v)); }\n\n  async function init(){\n    if (inited) return;\n    if (!$(ROOT_ID)) return;\n    await ensureLibs();\n\n    const wavesurfer = WaveSurfer.create({\n      container:'#audiotool772-wave',\n      waveColor:'#af3232',\n      progressColor:'#ff6b6b',\n      backend:'WebAudio',\n      height:160,\n      interact:true,\n      normalize:true\n    });\n\n    const output = new Tone.Gain(1).toDestination();\n    const pitchShift = new Tone.PitchShift({ pitch:0, windowSize:0.1, delayTime:0 }).connect(output);\n    const filter = new Tone.Filter({ frequency:1000, type:'lowpass', rolloff:-12, Q:1 });\n    const reverb = new Tone.Reverb({ decay:2.2, preDelay:0.01, wet: 0.0 });\n    const delay = new Tone.FeedbackDelay({ delayTime:0.25, feedback:0.35, wet: 0.0 });\n    const eq = new Tone.EQ3({ low:0, mid:0, high:0, lowFrequency:200, highFrequency:3500 });\n\n    const player = new Tone.Player({ autostart:false, loop:false });\n    player.chain(pitchShift, filter, reverb, delay, eq, output);\n\n    let isPlaying=false, audioDuration=0, playheadSec=0, startedAt=0, currentUrl=null, rafId=null;\n\n    const playBtn=$('audiotool772-play'), resetBtn=$('audiotool772-reset'), filePill=$('audiotool772-file'), timePill=$('audiotool772-time'), upload=$('audiotool772-upload');\n\n    function updateTime(){ timePill.textContent = `${fmtTime(playheadSec)} \/ ${fmtTime(audioDuration)}`; }\n    function computePos(){ const elapsed=(Tone.now()-startedAt)*player.playbackRate; return player.reverse ? clamp(playheadSec - elapsed, 0, audioDuration) : clamp(playheadSec + elapsed, 0, audioDuration); }\n\n    function stop(keep){\n      if (!audioDuration){ player.stop(); return; }\n      if (isPlaying){\n        const pos = computePos();\n        player.stop();\n        isPlaying=false;\n        playBtn.innerHTML='<i class=\"fa-solid fa-play\"><\/i> Play';\n        if(rafId) cancelAnimationFrame(rafId); rafId=null;\n        if(keep) playheadSec=pos;\n        updateTime();\n      } else { player.stop(); updateTime(); }\n    }\n\n    function loop(){\n      if(!isPlaying) return;\n      const pos=computePos();\n      const dur=audioDuration || wavesurfer.getDuration() || 0;\n      if(dur>0) wavesurfer.seekTo(pos\/dur);\n      timePill.textContent = `${fmtTime(pos)} \/ ${fmtTime(dur)}`;\n      if((!player.reverse && pos>=dur) || (player.reverse && pos<=0)){ stop(true); return; }\n      rafId=requestAnimationFrame(loop);\n    }\n\n    function start(){\n      if(!audioDuration || !player.buffer || !player.buffer.loaded) return;\n      playheadSec = clamp(playheadSec, 0, audioDuration);\n      startedAt = Tone.now();\n      player.stop();\n      player.start(undefined, playheadSec);\n      isPlaying=true;\n      playBtn.innerHTML='<i class=\"fa-solid fa-pause\"><\/i> Pause';\n      if(rafId) cancelAnimationFrame(rafId);\n      rafId=requestAnimationFrame(loop);\n    }\n\n    function seek(sec){\n      if(!audioDuration) return;\n      const next=clamp(sec, 0, audioDuration);\n      const was=isPlaying;\n      stop(true);\n      playheadSec=next;\n      if(audioDuration>0) wavesurfer.seekTo(playheadSec\/audioDuration);\n      updateTime();\n      if(was) start();\n    }\n\n    wavesurfer.on('seek', (p)=>{ if(!audioDuration) return; seek(p*audioDuration); });\n\n    upload.addEventListener('change', async (e)=>{\n      const file=e.target.files && e.target.files[0];\n      if(!file) return;\n      stop(false);\n      if(currentUrl) URL.revokeObjectURL(currentUrl);\n      currentUrl=URL.createObjectURL(file);\n      filePill.textContent = file.name || 'Fichier audio';\n      playBtn.disabled=true; resetBtn.disabled=true;\n      wavesurfer.load(currentUrl);\n      try{\n        await player.load(currentUrl);\n        audioDuration = player.buffer.duration || wavesurfer.getDuration() || 0;\n        playheadSec = player.reverse ? audioDuration : 0;\n        playBtn.disabled=false; resetBtn.disabled=false;\n        if(audioDuration>0) wavesurfer.seekTo(player.reverse ? 1 : 0);\n        updateTime();\n      }catch(err){\n        console.error(err);\n        alert('Impossible de charger ce fichier audio. Essayez un autre format (wav\/mp3\/m4a\/ogg).');\n        playBtn.disabled=true; resetBtn.disabled=true;\n      }\n    });\n\n    playBtn.addEventListener('click', async ()=>{\n      if(!player.buffer || !player.buffer.loaded) return;\n      await Tone.start();\n      if(isPlaying) stop(true); else start();\n    });\n\n    \/\/ Sliders bindings\n    const pitch=$('audiotool772-pitch'), pitchV=$('audiotool772-pitch-v');\n    pitch.addEventListener('input', ()=>{ const v=parseInt(pitch.value,10); pitchShift.pitch=v; pitchV.textContent=String(v); });\n\n    const filt=$('audiotool772-filter'), filtV=$('audiotool772-filter-v');\n    filt.addEventListener('input', ()=>{ const v=parseInt(filt.value,10); filter.frequency.value=v; filtV.textContent=String(v); });\n\n    const rev=$('audiotool772-reverb'), revV=$('audiotool772-reverb-v');\n    rev.addEventListener('input', ()=>{ const v=parseFloat(rev.value); reverb.wet.value=v; revV.textContent=v.toFixed(1); });\n\n    const del=$('audiotool772-delay'), delV=$('audiotool772-delay-v');\n    del.addEventListener('input', ()=>{ const v=parseFloat(del.value); delay.wet.value=v; delV.textContent=v.toFixed(1); });\n\n    const eql=$('audiotool772-eq-low'), eqlV=$('audiotool772-eq-low-v');\n    eql.addEventListener('input', ()=>{ const v=parseInt(eql.value,10); eq.low.value=v; eqlV.textContent=String(v); });\n\n    const eqm=$('audiotool772-eq-mid'), eqmV=$('audiotool772-eq-mid-v');\n    eqm.addEventListener('input', ()=>{ const v=parseInt(eqm.value,10); eq.mid.value=v; eqmV.textContent=String(v); });\n\n    const eqh=$('audiotool772-eq-high'), eqhV=$('audiotool772-eq-high-v');\n    eqh.addEventListener('input', ()=>{ const v=parseInt(eqh.value,10); eq.high.value=v; eqhV.textContent=String(v); });\n\n    const sp=$('audiotool772-speed'), spV=$('audiotool772-speed-v');\n    sp.addEventListener('input', ()=>{ const v=parseFloat(sp.value); const was=isPlaying; if(was) stop(true); player.playbackRate=v; spV.textContent=v.toFixed(1); if(was) start(); });\n\n    const revToggle=$('audiotool772-reverse');\n    revToggle.addEventListener('change', ()=>{ \n      if(!audioDuration){ player.reverse = revToggle.checked; return; }\n      const was=isPlaying; if(was) stop(true);\n      playheadSec = clamp(audioDuration - playheadSec, 0, audioDuration);\n      player.reverse = revToggle.checked;\n      wavesurfer.seekTo(audioDuration ? (playheadSec\/audioDuration) : 0);\n      updateTime();\n      if(was) start();\n    });\n\n    resetBtn.addEventListener('click', ()=>{\n      stop(false);\n      pitchShift.pitch=0; filter.frequency.value=1000; reverb.wet.value=0.0; delay.wet.value=0.0;\n      eq.low.value=0; eq.mid.value=0; eq.high.value=0;\n      player.playbackRate=1.0; player.reverse=false;\n\n      pitch.value=0; filt.value=1000; rev.value=0.5; del.value=0.5;\n      eql.value=0; eqm.value=0; eqh.value=0; sp.value=1.0; revToggle.checked=false;\n\n      pitchV.textContent='0'; filtV.textContent='1000'; revV.textContent='0.5'; delV.textContent='0.5';\n      eqlV.textContent='0'; eqmV.textContent='0'; eqhV.textContent='0'; spV.textContent='1.0';\n\n      playheadSec=0;\n      if(audioDuration>0) wavesurfer.seekTo(0);\n      playBtn.innerHTML='<i class=\"fa-solid fa-play\"><\/i> Play';\n      updateTime();\n    });\n\n    updateTime();\n\n    \/\/ --- Expose bridge for other tools (Evidence DB -> AudioTool) ---\n    async function importAudioFileIntoTool(file){\n      if(!file) return;\n      await init();\n      try{\n        stop(false);\n        if(currentUrl) URL.revokeObjectURL(currentUrl);\n      }catch(_e){}\n      currentUrl = URL.createObjectURL(file);\n      filePill.textContent = file.name || 'Fichier audio';\n      playBtn.disabled = true;\n      resetBtn.disabled = true;\n      wavesurfer.load(currentUrl);\n      try{\n        await player.load(currentUrl);\n        audioDuration = player.buffer.duration || wavesurfer.getDuration() || 0;\n        playheadSec = player.reverse ? audioDuration : 0;\n        playBtn.disabled = false;\n        resetBtn.disabled = false;\n        if(audioDuration > 0) wavesurfer.seekTo(player.reverse ? 1 : 0);\n        updateTime();\n      }catch(err){\n        console.error(err);\n        alert('Impossible de charger ce fichier audio. Essayez un autre format (wav\/mp3\/m4a\/ogg).');\n        playBtn.disabled = true;\n        resetBtn.disabled = true;\n      }\n    }\n\n    window.BERF_AUDIOTOOL_IMPORT_FILE = function(file){\n      return importAudioFileIntoTool(file);\n    };\n\n    window.BERF_AUDIOTOOL_IMPORT_URL = async function(url, name){\n      const res = await fetch(url, { cache: 'no-store' });\n      const blob = await res.blob();\n      const fname = name || 'evidence.mp3';\n      const file = new File([blob], fname, { type: blob.type || 'audio\/mpeg' });\n      return importAudioFileIntoTool(file);\n    };\n\n    inited = true;\n\n    document.addEventListener('click', (ev)=>{\n      const close = ev.target && ev.target.closest && ev.target.closest('#berf-oc-audiotool [data-close]');\n      if (close && isPlaying) stop(true);\n    });\n  }\n\n  window.addEventListener('DOMContentLoaded', ()=>{ init(); });\n})();\n\n\/* =========================================================\n   Evidence Tool (evidtool992) - keeps original features\n   ========================================================= *\/\n(function(){\n  const root = document.getElementById('evidtool992-root');\n  if(!root) return;\n\n  \/\/ Screens\n  const screens = {\n    home: document.getElementById('evidtool992-home'),\n    detail: document.getElementById('evidtool992-detail'),\n    edit: document.getElementById('evidtool992-editScreen'),\n    subs: document.getElementById('evidtool992-subsScreen'),\n    notif: document.getElementById('evidtool992-notifScreen'),\n    recents: document.getElementById('evidtool992-recentsScreen'),\n  };\n  function showScreen(key){\n    Object.values(screens).forEach(s=> s && s.classList.remove('is-active'));\n    if(screens[key]) screens[key].classList.add('is-active');\n  }\n\n  \/\/ UI elements\n  const input = document.getElementById('evidtool992-input');\n  const btnAnalyze = document.getElementById('evidtool992-analyze');\n  const btnSubs = document.getElementById('evidtool992-subs');\n  const btnRecents = document.getElementById('evidtool992-recents');\n  const btnBell = document.getElementById('evidtool992-bell');\nconst btnCloseTool = document.getElementById('evidtool992-close');\nif(btnCloseTool){\n    btnCloseTool.addEventListener('click', (e)=>{\n      e.preventDefault(); e.stopPropagation();\n      const oc = document.getElementById('berf-oc-evidencetool');\n      if(oc && typeof closeOC==='function') closeOC(oc);\n    });\n  }\n  const badge = document.getElementById('evidtool992-badge');\n\n  const btnBack = document.getElementById('evidtool992-back');\n  const title = document.getElementById('evidtool992-title');\n  const desc = document.getElementById('evidtool992-desc');\n  const btnEdit = document.getElementById('evidtool992-edit');\n  const btnSubscribe = document.getElementById('evidtool992-subscribe');\n  const btnCopy = document.getElementById('evidtool992-copy');\n\n  const img = document.getElementById('evidtool992-img');\n  const vid = document.getElementById('evidtool992-vid');\n  const aud = document.getElementById('evidtool992-aud');\n  const mediaLabel = document.getElementById('evidtool992-medialabel');\n\n  const editBack = document.getElementById('evidtool992-editBack');\n  const textarea = document.getElementById('evidtool992-textarea');\n  const btnSave = document.getElementById('evidtool992-save');\n\n  const subsBack = document.getElementById('evidtool992-subsBack');\n  const subsList = document.getElementById('evidtool992-subsList');\n\n  const notifBack = document.getElementById('evidtool992-notifBack');\n  const notifList = document.getElementById('evidtool992-notifList');\n\n  const recentsBack = document.getElementById('evidtool992-recentsBack');\n  const recentsList = document.getElementById('evidtool992-recentsList');\n\n  \/\/ Viewer modal\n  const viewer = document.getElementById('evidtool992-viewer');\n  const viewerClose = document.getElementById('evidtool992-viewerClose');\n  const viewerImg = document.getElementById('evidtool992-viewerImg');\n  const viewerVid = document.getElementById('evidtool992-viewerVid');\n  const viewerAud = document.getElementById('evidtool992-viewerAud');\n  const viewerAnalyzeBtn = document.getElementById('evidtool992-analyzeViewerBtn');\n\n  const AGENT = \"Theta004\";\n\n  \/\/ Database (keeps existing keys\/structure)\n  const defaultDb = (function(){\n    try{\n      const boot = window.BERFDB && window.BERFDB.BOOT;\n      if(boot && boot.data && boot.data.indices && Array.isArray(boot.data.indices.seed)){\n        const out = {};\n        boot.data.indices.seed.forEach(it=>{\n          if(!it || !it.id) return;\n          out[String(it.id)] = {\n            analysis: it.analysis || '',\n            mediaType: it.mediaType || '',\n            mediaSrc: it.mediaSrc || '',\n            subscribers: Array.isArray(it.subscribers) ? it.subscribers : []\n          };\n        });\n        return out;\n      }\n    }catch(e){}\n    return {};\n  })();\n\n  const db = (function(){\n    try{\n      const raw = localStorage.getItem(\"database\");\n      if(raw){\n        const parsed = JSON.parse(raw);\n        if(parsed && typeof parsed === \"object\") return parsed;\n      }\n    }catch(e){}\n    localStorage.setItem(\"database\", JSON.stringify(defaultDb));\n    return defaultDb;\n  })();\n\n  let notifications = (function(){\n    try{\n      const raw = localStorage.getItem(\"notifications\");\n      if(raw){\n        const parsed = JSON.parse(raw);\n        if(Array.isArray(parsed)) return parsed;\n      }\n    }catch(e){}\n    localStorage.setItem(\"notifications\", JSON.stringify([]));\n    return [];\n  })();\n\n  function saveDb(){ localStorage.setItem(\"database\", JSON.stringify(db)); }\n  function saveNotif(){ localStorage.setItem(\"notifications\", JSON.stringify(notifications)); }\n\n  window.BERF_EVID_ADD_ENTRY = function(id, entry){\n    if(!id || !entry) return;\n    const key = String(id || '').trim();\n    db[key] = entry;\n    saveDb();\n    renderSubs();\n  };\n\n  window.BERF_EVID_PUSH_NOTIFICATION = function(n){\n    if(!n || !n.id) return;\n    notifications.push({ id: n.id, message: n.message || 'Nouvelle mise \u00e0 jour disponible' });\n    saveNotif();\n    updateBadge();\n    renderNotifs();\n  };\n\n  window.BERF_EVID_OPEN = function(id){\n    const key = resolveIndexKey(id);\n    if(!key || !db[key]) return false;\n    try{ if(typeof openOC === 'function') openOC('evidencetool'); }catch(e){}\n    showDetail(key);\n    return true;\n  };\n\n  window.BERF_EVID_SUBSCRIBE = function(id){\n    const key = resolveIndexKey(id);\n    if(!key || !db[key]) return;\n    const subs = Array.isArray(db[key].subscribers) ? db[key].subscribers : [];\n    if(!subs.includes(AGENT)){\n      subs.push(AGENT);\n      db[key].subscribers = subs;\n      saveDb();\n      renderSubs();\n      if(currentId === key) refreshSubscribeBtn();\n    }\n  };\n\n  function updateBadge(){\n    const n = notifications.length;\n    badge.textContent = String(n);\n    badge.style.display = n > 0 ? \"inline-block\" : \"none\";\n\n    const evidWidget = document.querySelector('.evid-widget');\n    const evidBadge = document.querySelector('.evid-badge');\n    if(evidWidget) evidWidget.setAttribute('data-unread', String(n));\n    if(evidBadge){\n      evidBadge.textContent = String(n);\n      evidBadge.style.display = n > 0 ? 'flex' : 'none';\n    }\n\n    const evidTaskbarWidget = document.querySelector('.evid-taskbar-widget');\n    const evidTaskbarBadge = document.querySelector('.evid-taskbar-badge');\n    if(evidTaskbarWidget) evidTaskbarWidget.setAttribute('data-unread', String(n));\n    if(evidTaskbarBadge){\n      evidTaskbarBadge.textContent = String(n);\n      evidTaskbarBadge.style.display = n > 0 ? 'flex' : 'none';\n    }\n  }\n\n  function setMediaNone(){\n    img.style.display = \"none\"; vid.style.display = \"none\"; aud.style.display = \"none\";\n    img.removeAttribute(\"src\"); vid.removeAttribute(\"src\"); aud.removeAttribute(\"src\");\n    mediaLabel.textContent = \"Aucun m\u00e9dia\";\n  }\n\n  function openViewer(type, src){\n    viewerImg.style.display = \"none\";\n    viewerVid.style.display = \"none\";\n    viewerAud.style.display = \"none\";\n    viewerImg.classList.remove('is-zoomed');\n\n    if(type === \"image\"){\n      viewerImg.src = src;\n      viewerImg.style.display = \"block\";\n    }else if(type === \"video\"){\n      viewerVid.src = src;\n      viewerVid.style.display = \"block\";\n      viewerVid.play?.().catch(()=>{});\n    }else if(type === \"audio\"){\n      viewerAud.src = src;\n      viewerAud.style.display = \"block\";\n      viewerAud.play?.().catch(()=>{});\n    }\n    if(viewerAnalyzeBtn){\n      viewerAnalyzeBtn.style.display = type === 'image' ? 'inline-flex' : 'none';\n    }\n    viewer.classList.add(\"is-open\");\n    viewer.setAttribute(\"aria-hidden\",\"false\");\n  }\n\n  function closeViewer(){\n    viewer.classList.remove(\"is-open\");\n    viewer.setAttribute(\"aria-hidden\",\"true\");\n    try{ viewerVid.pause(); }catch(e){}\n    try{ viewerAud.pause(); }catch(e){}\n  }\n\n  viewerClose.addEventListener(\"click\", closeViewer);\n  viewer.addEventListener(\"click\", (e)=>{ if(e.target === viewer) closeViewer(); });\n  viewerImg.addEventListener(\"click\", ()=> viewerImg.classList.toggle(\"is-zoomed\"));\n\n  if(viewerAnalyzeBtn){\n    viewerAnalyzeBtn.addEventListener('click', async ()=>{\n      if(viewerImg.style.display === 'none' || !viewerImg.src) return;\n      try{\n        closeViewer();\n        await window.BERF_ANALYZE_IMAGE_FROM_URL?.(viewerImg.src, 'evidence-image');\n      }catch(e){ console.warn(e); }\n    });\n  }\n\n  \/\/ zoom css via inline style to avoid global collision\n  const zoomStyle = document.createElement('style');\n  zoomStyle.textContent = \"#evidtool992-viewerImg.is-zoomed{transform:scale(2);cursor:zoom-out;} #evidtool992-viewerImg{cursor:zoom-in; transition: transform .25s ease;}\";\n  document.head.appendChild(zoomStyle);\n\n  \/\/ Recents\n  function getRecents(){\n    try{\n      const raw = localStorage.getItem(\"evidtool992_recents\");\n      const parsed = JSON.parse(raw || \"[]\");\n      return Array.isArray(parsed) ? parsed : [];\n    }catch(e){ return []; }\n  }\n  function pushRecent(id){\n    const list = getRecents().filter(x=>x!==id);\n    list.unshift(id);\n    const trimmed = list.slice(0, 12);\n    localStorage.setItem(\"evidtool992_recents\", JSON.stringify(trimmed));\n  }\n\n  let currentId = null;\n\n  function normalizeIndexId(value){\n    return String(value || '')\n      .normalize('NFD')\n      .replace(\/[\\u0300-\\u036f]\/g, '')\n      .replace(\/[^a-zA-Z0-9]\/g, '')\n      .toUpperCase()\n      .trim();\n  }\n\n  function resolveIndexKey(value){\n    const wanted = normalizeIndexId(value);\n    if(!wanted) return '';\n    if(db[wanted]) return wanted;\n\n    const keys = Object.keys(db || {});\n    for(const key of keys){\n      if(normalizeIndexId(key) === wanted) return key;\n    }\n    return '';\n  }\n\n  function refreshSubscribeBtn(){\n    if(!currentId || !db[currentId]) return;\n    const subscribed = (db[currentId].subscribers || []).includes(AGENT);\n    btnSubscribe.innerHTML = subscribed ? '<i class=\"fa-solid fa-bell-slash\"><\/i> Se d\u00e9sabonner' : '<i class=\"fa-solid fa-bell\"><\/i> S\\'abonner';\n    btnSubscribe.classList.toggle('evidtool992-btn-primary', !subscribed);\n    btnSubscribe.classList.toggle('evidtool992-btn-ghost', subscribed);\n  }\n\n  \n  \/\/ --- Bridge: envoyer une image vers l'outil Analyse d'image ---\n  async function sendEvidenceImageToImgTool(ev){\n    try{\n      if(!ev || ev.mediaType !== 'image' || !ev.mediaSrc) return;\n\n      \/\/ Fermer explicitement la base d'indices\n      try{\n        const evidOC = document.getElementById('berf-oc-evidencetool');\n        if(evidOC){\n          const closeBtn = evidOC.querySelector('.berf-oc__close[data-close], #evidtool992-close[data-close]');\n          if(closeBtn){ try{ closeBtn.click(); }catch(_e){} }\n          if (typeof closeOC === 'function') { try{ closeOC(evidOC); }catch(_e){} }\n          evidOC.removeAttribute('data-open');\n          evidOC.setAttribute('aria-hidden', 'true');\n        }\n      }catch(_e){}\n\n      \/\/ Laisser le temps \u00e0 la fermeture visuelle puis ouvrir l'outil cible\n      await new Promise(r=>setTimeout(r, 80));\n\n      try{\n        if (typeof openOC === 'function') openOC('imgtool');\n        const imgOC = document.getElementById('berf-oc-imgtool');\n        if(imgOC){\n          imgOC.setAttribute('data-open', 'true');\n          imgOC.setAttribute('aria-hidden', 'false');\n        }\n      }catch(_e){}\n\n      \/\/ Petit d\u00e9lai pour laisser la transition se faire + init de l'outil\n      await new Promise(r=>setTimeout(r, 180));\n\n      if (!window.BERF_IMGTOOL_IMPORT_URL && !window.BERF_IMGTOOL_IMPORT_FILE){\n        console.warn('Imgtool bridge not ready yet.');\n      }\n\n      const url = ev.mediaSrc;\n      const ext = (url.split('.').pop() || 'jpg').split('?')[0].toLowerCase();\n      const safeExt = \/^(jpg|jpeg|png|webp|gif|bmp|svg)$\/.test(ext) ? ext : 'jpg';\n      const name = (ev.id ? (ev.id + '.' + safeExt) : ('evidence.' + safeExt));\n\n      if (window.BERF_IMGTOOL_IMPORT_URL){\n        await window.BERF_IMGTOOL_IMPORT_URL(url, name);\n        return;\n      }\n\n      \/\/ Fallback: fetch -> File -> import_file\n      const res = await fetch(url, { cache: 'no-store' });\n      const blob = await res.blob();\n      const file = new File([blob], name, { type: blob.type || 'image\/jpeg' });\n      if (window.BERF_IMGTOOL_IMPORT_FILE){\n        window.BERF_IMGTOOL_IMPORT_FILE(file);\n        return;\n      }\n\n      alert(\"L'outil d'analyse d'image n'est pas pr\u00eat pour l'import.\");\n    }catch(err){\n      console.warn('sendEvidenceImageToImgTool failed:', err);\n      alert(\"Impossible d'envoyer l'image vers l'outil d'analyse (CORS ou format).\");\n    }\n  }\n\n  async function sendEvidenceAudioToAudioTool(ev){\n    try{\n      if(!ev || !(ev.mediaType === 'audio' || ev.mediaType === 'mp3') || !ev.mediaSrc) return;\n\n      try{\n        const evidOC = document.getElementById('berf-oc-evidencetool');\n        if(evidOC){\n          const closeBtn = evidOC.querySelector('.berf-oc__close[data-close], #evidtool992-close[data-close]');\n          if(closeBtn){ try{ closeBtn.click(); }catch(_e){} }\n          if (typeof closeOC === 'function') { try{ closeOC(evidOC); }catch(_e){} }\n          evidOC.removeAttribute('data-open');\n          evidOC.setAttribute('aria-hidden', 'true');\n        }\n      }catch(_e){}\n\n      await new Promise(r=>setTimeout(r, 80));\n\n      try{\n        if (typeof openOC === 'function') openOC('audiotool');\n        const audioOC = document.getElementById('berf-oc-audiotool');\n        if(audioOC){\n          audioOC.setAttribute('data-open', 'true');\n          audioOC.setAttribute('aria-hidden', 'false');\n        }\n      }catch(_e){}\n\n      await new Promise(r=>setTimeout(r, 180));\n\n      const url = ev.mediaSrc;\n      const ext = (url.split('.').pop() || 'mp3').split('?')[0].toLowerCase();\n      const safeExt = \/^(mp3|wav|ogg|m4a|aac|flac|webm)$\/.test(ext) ? ext : 'mp3';\n      const name = (ev.id ? (ev.id + '.' + safeExt) : ('evidence.' + safeExt));\n\n      if (window.BERF_AUDIOTOOL_IMPORT_URL){\n        await window.BERF_AUDIOTOOL_IMPORT_URL(url, name);\n        return;\n      }\n\n      const res = await fetch(url, { cache: 'no-store' });\n      const blob = await res.blob();\n      const file = new File([blob], name, { type: blob.type || 'audio\/mpeg' });\n\n      if (window.BERF_AUDIOTOOL_IMPORT_FILE){\n        window.BERF_AUDIOTOOL_IMPORT_FILE(file);\n        return;\n      }\n\n      alert(\"L'outil d'analyse audio n'est pas pr\u00eat pour l'import.\");\n    }catch(err){\n      console.warn('sendEvidenceAudioToAudioTool failed:', err);\n      alert(\"Impossible d'envoyer l'audio vers l'outil d'analyse.\");\n    }\n  }\n\nfunction showDetail(id){\n    const key = resolveIndexKey(id) || id;\n    const ev = db[key];\n    if(!ev){ alert(\"Indice introuvable.\"); return; }\n\n    currentId = key;\n    try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('open_index', key, { id: key, item: ev }); }catch(e){}\n    \n    \/\/ Show contextual analysis button for image\/audio evidences\n    (function(){\n      const btn = document.getElementById('evidtool992-sendToImg');\n      if(!btn) return;\n      if (ev.mediaType === 'image' && ev.mediaSrc){\n        btn.style.display = 'inline-flex';\n        btn.innerHTML = '<i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser l\\'image';\n        btn.dataset.src = ev.mediaSrc;\n        btn.dataset.eid = key;\n        btn.onclick = () => { try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('analyze_image', key, { id: key, item: ev }); }catch(e){} return sendEvidenceImageToImgTool(ev); };\n      } else if ((ev.mediaType === 'audio' || ev.mediaType === 'mp3') && ev.mediaSrc){\n        btn.style.display = 'inline-flex';\n        btn.innerHTML = '<i class=\"fa-solid fa-wave-square\"><\/i> Analyser l\\'audio';\n        btn.dataset.src = ev.mediaSrc;\n        btn.dataset.eid = key;\n        btn.onclick = () => { try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('analyze_audio', key, { id: key, item: ev }); }catch(e){} return sendEvidenceAudioToAudioTool(ev); };\n      } else {\n        btn.style.display = 'none';\n        btn.dataset.src = '';\n        btn.dataset.eid = '';\n        btn.onclick = null;\n      }\n    })();\npushRecent(key);\n\n    title.textContent = `Indice ${key}`;\n    desc.textContent = ev.analysis || \"\";\n\n    setMediaNone();\n    if(ev.mediaType === \"image\"){\n      img.src = ev.mediaSrc;\n      img.style.display = \"block\";\n      mediaLabel.textContent = \"Image\";\n      img.onclick = ()=> openViewer(\"image\", ev.mediaSrc);\n    }else if(ev.mediaType === \"video\"){\n      vid.src = ev.mediaSrc;\n      vid.style.display = \"block\";\n      mediaLabel.textContent = \"Vid\u00e9o\";\n      vid.onclick = ()=> openViewer(\"video\", ev.mediaSrc);\n    }else if(ev.mediaType === \"audio\"){\n      aud.src = ev.mediaSrc;\n      aud.style.display = \"block\";\n      mediaLabel.textContent = \"Audio\";\n      aud.onclick = ()=> openViewer(\"audio\", ev.mediaSrc);\n    }else{\n      mediaLabel.textContent = \"M\u00e9dia non renseign\u00e9\";\n    }\n\n    refreshSubscribeBtn();\n    showScreen(\"detail\");\n  }\n\n  function renderSubs(){\n    subsList.innerHTML = \"\";\n    const ids = Object.keys(db).filter(id => (db[id].subscribers || []).includes(AGENT)).sort();\n    if(!ids.length){\n      subsList.innerHTML = '<div class=\"evidtool992-item\" style=\"cursor:default;\"><div>Aucun abonnement<\/div><small>Abonne-toi depuis la fiche d\\'un indice<\/small><\/div>';\n      return;\n    }\n    ids.forEach(id=>{\n      const el = document.createElement(\"div\");\n      el.className = \"evidtool992-item\";\n      el.innerHTML = `<div><b>Indice ${id}<\/b><div style=\"font-size:12px;opacity:.7;margin-top:2px;\">${(db[id].analysis||'').slice(0,70)}${(db[id].analysis||'').length>70?'\u2026':''}<\/div><\/div><i class=\"fa-solid fa-chevron-right\" style=\"opacity:.7;\"><\/i>`;\n      el.addEventListener(\"click\", ()=> showDetail(id));\n      subsList.appendChild(el);\n    });\n  }\n\n  function renderNotifs(){\n    notifList.innerHTML = \"\";\n    if(!notifications.length){\n      notifList.innerHTML = '<div class=\"evidtool992-item\" style=\"cursor:default;\"><div>Aucune notification<\/div><small>Tout est \u00e0 jour<\/small><\/div>';\n      return;\n    }\n    notifications.forEach((n, idx)=>{\n      const el = document.createElement(\"div\");\n      el.className = \"evidtool992-item\";\n      el.innerHTML = `<div><b>Indice ${n.id}<\/b><div style=\"font-size:12px;opacity:.75;margin-top:2px;\">${n.message}<\/div><\/div><i class=\"fa-solid fa-eye\" style=\"opacity:.7;\"><\/i>`;\n      el.addEventListener(\"click\", ()=>{\n        \/\/ remove notif when opened (keeps original behavior)\n        notifications.splice(idx, 1);\n        saveNotif();\n        updateBadge();\n        renderNotifs();\n        const key = resolveIndexKey(n.id);\n      if(key && db[key]) showDetail(key);\n      else alert(\"Indice introuvable.\");\n      });\n      notifList.appendChild(el);\n    });\n  }\n\n  function renderRecents(){\n    recentsList.innerHTML = \"\";\n    const ids = getRecents();\n    if(!ids.length){\n      recentsList.innerHTML = '<div class=\"evidtool992-item\" style=\"cursor:default;\"><div>Aucun r\u00e9cent<\/div><small>Analyse un indice pour commencer<\/small><\/div>';\n      return;\n    }\n    ids.forEach(id=>{\n      const el = document.createElement(\"div\");\n      el.className = \"evidtool992-item\";\n      const key = resolveIndexKey(id) || id;\n      el.innerHTML = `<div><b>Indice ${key}<\/b><div style=\"font-size:12px;opacity:.7;margin-top:2px;\">${db[key]?.mediaType ? ('M\u00e9dia: '+db[key].mediaType) : 'Non pr\u00e9sent dans la base'}<\/div><\/div><i class=\"fa-solid fa-chevron-right\" style=\"opacity:.7;\"><\/i>`;\n      el.addEventListener(\"click\", ()=> db[key] ? showDetail(key) : alert(\"Indice introuvable.\"));\n      recentsList.appendChild(el);\n    });\n  }\n\n  function addNotification(id, message){\n    notifications.push({ id, message });\n    saveNotif();\n    updateBadge();\n  }\n\n  \/\/ Actions\n  btnAnalyze.addEventListener(\"click\", ()=>{\n    const raw = (input.value || \"\").trim();\n    if(!raw) return;\n    const key = resolveIndexKey(raw);\n    if(key && db[key]) showDetail(key);\n    else alert(\"Indice introuvable.\");\n  });\n  input.addEventListener(\"keydown\", (e)=>{\n    if(e.key === \"Enter\"){ e.preventDefault(); btnAnalyze.click(); }\n  });\n\n  btnSubs.addEventListener(\"click\", ()=>{ renderSubs(); showScreen(\"subs\"); });\n  btnBell.addEventListener(\"click\", ()=>{ renderNotifs(); showScreen(\"notif\"); });\n  btnRecents.addEventListener(\"click\", ()=>{ renderRecents(); showScreen(\"recents\"); });\n\n  subsBack.addEventListener(\"click\", ()=> showScreen(\"home\"));\n  notifBack.addEventListener(\"click\", ()=> showScreen(\"home\"));\n  recentsBack.addEventListener(\"click\", ()=> showScreen(\"home\"));\n\n  btnBack.addEventListener(\"click\", ()=> showScreen(\"home\"));\n\n  btnEdit.addEventListener(\"click\", ()=>{\n    textarea.value = desc.textContent || \"\";\n    showScreen(\"edit\");\n  });\n  editBack.addEventListener(\"click\", ()=> showScreen(\"detail\"));\n\n  btnSave.addEventListener(\"click\", ()=>{\n    if(!currentId || !db[currentId]) return;\n    db[currentId].analysis = textarea.value || \"\";\n    saveDb();\n    showDetail(currentId);\n    addNotification(currentId, \"analyse modifi\u00e9e par l'agent Theta004\");\n  });\n\n  btnSubscribe.addEventListener(\"click\", ()=>{\n    if(!currentId || !db[currentId]) return;\n    const subs = db[currentId].subscribers || (db[currentId].subscribers = []);\n    const isSub = subs.includes(AGENT);\n    if(isSub){\n      db[currentId].subscribers = subs.filter(s=>s!==AGENT);\n      saveDb();\n      refreshSubscribeBtn();\n      alert(`Vous \u00eates d\u00e9sabonn\u00e9 de l'indice ${currentId}`);\n    }else{\n      subs.push(AGENT);\n      saveDb();\n      refreshSubscribeBtn();\n      alert(`Vous \u00eates maintenant abonn\u00e9 \u00e0 l'indice ${currentId}`);\n    }\n  });\n\n  btnCopy.addEventListener(\"click\", async ()=>{\n    if(!currentId) return;\n    try{\n      await navigator.clipboard.writeText(currentId);\n      btnCopy.style.transform = \"scale(0.96)\";\n      setTimeout(()=>{ btnCopy.style.transform=\"\"; }, 120);\n    }catch(e){\n      \/\/ fallback\n      const t = document.createElement(\"textarea\");\n      t.value = currentId; document.body.appendChild(t);\n      t.select(); document.execCommand(\"copy\");\n      document.body.removeChild(t);\n    }\n  });\n\n  \/\/ Init\n  updateBadge();\n  showScreen(\"home\");\n})();\n\n<\/script>\n<script>\n\/* ============================================================\n   POST-IT 23 \u2014 sticky notes on desktop (no window)\n   - toggle via taskbar icon [data-postit-toggle]\n   - drag via header (no jQuery)\n   - persistent in localStorage: postit23_notes_v1\n   ============================================================ *\/\n(function(){\n  function qs(sel, root){ return (root||document).querySelector(sel); }\n  function qsa(sel, root){ return Array.from((root||document).querySelectorAll(sel)); }\n\n  const LSK = \"postit23_notes_v1\";\n  const DEFAULT_NOTE = \"Le loup hurle \u00e0 la nuit = LORALU\";\n\n  function loadNotes(){\n    try{\n      const raw = localStorage.getItem(LSK);\n      const arr = raw ? JSON.parse(raw) : [];\n      return Array.isArray(arr) ? arr : [];\n    }catch(e){ return []; }\n  }\n  function saveNotes(arr){\n    try{ localStorage.setItem(LSK, JSON.stringify(arr||[])); }catch(e){}\n  }\n  function uid(){\n    return \"n\" + Math.random().toString(16).slice(2) + Date.now().toString(16);\n  }\n  function clamp(v, a, b){ return Math.max(a, Math.min(b, v)); }\n\n  function init(){\n    if(window.__BERF_POSTIT23_INIT__) return;\n    window.__BERF_POSTIT23_INIT__ = true;\n\n    const desk = document.getElementById(\"berfDesk\");\n    const layer = document.getElementById(\"postit23-container\");\n    const toggleBtn = qs(\"#ouvrirpostit\") || qs('[data-postit-toggle=\"postit23\"]');\n    if(!desk || !layer) return;\n    \/\/ If toggle button not found, still initialize notes (can be opened programmatically)\n    if(!toggleBtn){\n      console.warn(\"[POSTIT23] Toggle not found (#ouvrirpostit or [data-postit-toggle]).\");\n    }\n\n    \/\/ Make sure layer is attached to desk (not inside another tool)\n    if(layer.parentElement !== desk){\n      desk.appendChild(layer);\n    }\n\n    \/\/ Ensure visible toggle works even if inline styles were changed elsewhere\n    layer.style.display = \"block\";\n    layer.setAttribute(\"aria-hidden\", \"true\");\n    layer.dataset.visible = \"false\";\n\n    \/\/ Render existing notes\n    let notes = loadNotes();\n\n    function persistFromDOM(){\n      const next = qsa(\".postit23-note\", layer).map(el => {\n        const id = el.dataset.id;\n        const ta = qs(\"textarea\", el);\n        const rect = el.getBoundingClientRect();\n        const deskRect = desk.getBoundingClientRect();\n        return {\n          id,\n          text: (ta && ta.value) ? ta.value : \"\",\n          x: Math.round(rect.left - deskRect.left),\n          y: Math.round(rect.top - deskRect.top),\n          z: Number(el.style.zIndex||1)\n        };\n      });\n      notes = next;\n      saveNotes(notes);\n    }\n\n    let zTop = 10;\n    function bringToFront(noteEl){\n      zTop += 1;\n      noteEl.style.zIndex = String(zTop);\n    }\n\n    function createNote(data){\n      const n = data || { id: uid(), text: \"\", x: 80, y: 80, z: 1 };\n      const el = document.createElement(\"div\");\n      el.className = \"postit23-note\";\n      el.dataset.id = n.id;\n      el.style.left = (n.x ?? 80) + \"px\";\n      el.style.top  = (n.y ?? 80) + \"px\";\n      el.style.zIndex = String(n.z ?? 1);\n\n      el.innerHTML = `\n        <div class=\"postit23-head\">\n          <div class=\"postit23-title\">NOTE<\/div>\n          <div class=\"postit23-actions\">\n            <button class=\"postit23-btn postit23-btn-add\" title=\"Nouveau\">+<\/button>\n            <button class=\"postit23-btn postit23-btn-close\" title=\"Fermer\">\u00d7<\/button>\n          <\/div>\n        <\/div>\n        <textarea class=\"postit23-text\" spellcheck=\"false\" placeholder=\"\u00c9crivez vos notes ici...\"><\/textarea>\n        <div class=\"postit23-foot\">\n          <button class=\"postit23-save\">Sauvegarder<\/button>\n          \n        <\/div>\n      `;\n\n      const ta = qs(\".postit23-text\", el);\n      ta.value = n.text || \"\";\n\n      \/\/ Add\n      qs(\".postit23-btn-add\", el).addEventListener(\"click\", (e)=>{\n        e.stopPropagation();\n        const deskRect = desk.getBoundingClientRect();\n        const baseX = clamp((n.x ?? 80) + 26, 10, Math.max(10, deskRect.width - 240));\n        const baseY = clamp((n.y ?? 80) + 26, 10, Math.max(10, deskRect.height - 260));\n        const nn = { id: uid(), text: \"\", x: baseX, y: baseY, z: zTop+1 };\n        const child = createNote(nn);\n        layer.appendChild(child);\n        bringToFront(child);\n        notes.push(nn);\n        saveNotes(notes);\n      });\n\n      \/\/ Close (remove note)\n      qs(\".postit23-btn-close\", el).addEventListener(\"click\", (e)=>{\n        e.stopPropagation();\n        const id = el.dataset.id;\n        el.remove();\n        notes = notes.filter(x => x.id !== id);\n        saveNotes(notes);\n        \/\/ If no notes left, keep layer hidden flag reset (so next open recreates default)\n        if(qsa(\".postit23-note\", layer).length === 0){\n          \/\/ nothing else\n        }\n      });\n\n      \/\/ Save button\n      qs(\".postit23-save\", el).addEventListener(\"click\", (e)=>{\n        e.stopPropagation();\n        persistFromDOM();\n        \/\/ tiny visual feedback\n        const btn = e.currentTarget;\n        btn.classList.add(\"saved\");\n        setTimeout(()=>btn.classList.remove(\"saved\"), 700);\n      });\n\n      \/\/ Bring to front on focus\/click\n      el.addEventListener(\"pointerdown\", ()=> bringToFront(el));\n\n      \/\/ Drag on header\n      const head = qs(\".postit23-head\", el);\n      let drag = null;\n      head.addEventListener(\"pointerdown\", (e)=>{\n        \/\/ IMPORTANT: don't start drag when clicking the + \/ \u00d7 buttons\n        if(e.target && e.target.closest && e.target.closest(\"button\")){\n          return;\n        }\n        \/\/ Allow text selection\/caret in textarea etc.\n        if(e.target && e.target.closest && e.target.closest(\"textarea\")){\n          return;\n        }\n        e.preventDefault();\n        bringToFront(el);\n        const deskRect = desk.getBoundingClientRect();\n        const startX = e.clientX;\n        const startY = e.clientY;\n        const rect = el.getBoundingClientRect();\n        const offsetX = rect.left - deskRect.left;\n        const offsetY = rect.top - deskRect.top;\n        drag = { startX, startY, offsetX, offsetY, deskRect };\n        try{ head.setPointerCapture(e.pointerId); }catch(_){}\n      });\n      head.addEventListener(\"pointermove\", (e)=>{\n        if(!drag) return;\n        const dx = e.clientX - drag.startX;\n        const dy = e.clientY - drag.startY;\n        const x = clamp(drag.offsetX + dx, 6, Math.max(6, drag.deskRect.width - 230));\n        const y = clamp(drag.offsetY + dy, 6, Math.max(6, drag.deskRect.height - 260));\n        el.style.left = x + \"px\";\n        el.style.top = y + \"px\";\n      });\n      head.addEventListener(\"pointerup\", (e)=>{\n        if(!drag) return;\n        drag = null;\n        persistFromDOM();\n      });\n      head.addEventListener(\"pointercancel\", ()=>{\n        if(!drag) return;\n        drag = null;\n        persistFromDOM();\n      });\n\n      \/\/ Autosave on blur (lightweight)\n      ta.addEventListener(\"blur\", ()=> persistFromDOM());\n\n      return el;\n    }\n\n    function renderAll(){\n      layer.innerHTML = \"\";\n      notes = loadNotes();\n      notes.forEach(n => layer.appendChild(createNote(n)));\n      \/\/ update zTop\n      const maxZ = notes.reduce((m,n)=>Math.max(m, Number(n.z||1)), 10);\n      zTop = maxZ;\n    }\n\n    function ensureDefaultIfEmpty(){\n      notes = loadNotes();\n      if(!notes.length){\n        const deskRect = desk.getBoundingClientRect();\n        const n = { id: uid(), text: DEFAULT_NOTE, x: Math.round(deskRect.width*0.12), y: Math.round(deskRect.height*0.14), z: 20 };\n        notes = [n];\n        saveNotes(notes);\n      }\n    }\n\n    function setVisible(v){\n      layer.dataset.visible = v ? \"true\" : \"false\";\n      layer.setAttribute(\"aria-hidden\", v ? \"false\" : \"true\");\n      layer.style.pointerEvents = v ? \"auto\" : \"none\";\n      \/\/ Notes remain but interaction disabled when hidden\n      qsa(\".postit23-note\", layer).forEach(n => n.style.display = v ? \"block\" : \"none\");\n      if(toggleBtn) toggleBtn.classList.toggle(\"active\", !!v);\n    }\n\n    \/\/ Initial render (keep hidden by default)\n    ensureDefaultIfEmpty();\n    renderAll();\n    setVisible(false);\n\n    \/\/ Toggle click\n    if(toggleBtn) toggleBtn.addEventListener(\"click\", (e)=>{\n      e.preventDefault();\n      e.stopPropagation();\n      const isVisible = layer.dataset.visible === \"true\";\n      if(!isVisible){\n        ensureDefaultIfEmpty();\n        renderAll();\n      }\n      setVisible(!isVisible);\n    });\n\n    \/\/ Esc hides notes (doesn't destroy)\n    document.addEventListener(\"keydown\", (e)=>{\n      if(e.key === \"Escape\" && layer.dataset.visible === \"true\"){\n        setVisible(false);\n      }\n    });\n  }\n\n  window.addEventListener(\"DOMContentLoaded\", init);\n})();\n\n\n\n\/* =========================================================\n   TOOL : CALCULATRICE S\u00c9CURIS\u00c9E\n   ========================================================= *\/\n(function(){\n  const root = document.getElementById('berfCalcTool');\n  if(!root) return;\n\n  const secrets = Array.isArray(window.BERFDB && window.BERFDB.CALCULATOR_SECRETS) ? window.BERFDB.CALCULATOR_SECRETS.slice() : [];\n  const KEY = 'berf_calculator_state_v1';\n  const display = document.getElementById('berfCalcDisplay');\n  const status = document.getElementById('berfCalcStatus');\n\n  function loadState(){\n    try{ const raw = localStorage.getItem(KEY); const parsed = raw ? JSON.parse(raw) : null; if(parsed && typeof parsed === 'object') return parsed; }catch(e){}\n    return { solved:{} };\n  }\n  function saveState(state){ localStorage.setItem(KEY, JSON.stringify(state || { solved:{} })); }\n  function normalizeExpression(value){ return String(value || '').replace(\/\\s+\/g,'').replace(\/\u00d7\/g,'*').replace(\/\u00f7\/g,'\/'); }\n  function safeEval(expr){\n    const clean = normalizeExpression(expr);\n    if(!clean || \/[^0-9+\\-*\/().]\/.test(clean)) throw new Error('invalid');\n    const out = Function('\"use strict\"; return (' + clean + ');')();\n    if(typeof out !== 'number' || !isFinite(out)) throw new Error('invalid');\n    return out;\n  }\n  function setStatus(message, kind){\n    status.textContent = message || '';\n    status.classList.remove('is-error','is-success');\n    if(kind) status.classList.add(kind);\n  }\n  function append(val){ display.value += val; }\n  function clearDisplay(){ display.value = ''; setStatus(''); }\n  function backspace(){ display.value = display.value.slice(0,-1); }\n  function findSecret(rawInput){\n    const normalized = normalizeExpression(rawInput);\n    const state = loadState();\n\n    function evalOrNull(value){\n      try{ return safeEval(value); }catch(e){ return null; }\n    }\n    function slugify(value){\n      return String(value || '')\n        .toLowerCase()\n        .normalize('NFD').replace(\/[\\u0300-\\u036f]\/g,'')\n        .replace(\/[^a-z0-9]+\/g,'')\n        .trim();\n    }\n\n    for(const secret of secrets){\n      if(!secret) continue;\n      const id = String(secret.id || '');\n      const alreadySolved = !!(state.solved && state.solved[id]);\n      const mode = String(secret.mode || 'expression');\n      const expr = String(secret.expression || '');\n      const exprNormalized = normalizeExpression(expr);\n\n      if(mode === 'result'){\n        try{\n          const got = safeEval(rawInput);\n          const expected = Number(String(expr).replace(',','.'));\n          if(isFinite(expected) && Math.abs(got - expected) < 1e-9){\n            return Object.assign({}, secret, { __alreadySolved: alreadySolved });\n          }\n        }catch(e){}\n      } else {\n        if(normalized && normalized === exprNormalized){\n          return Object.assign({}, secret, { __alreadySolved: alreadySolved });\n        }\n\n        const gotEval = evalOrNull(rawInput);\n        const expectedEval = evalOrNull(expr);\n        if(gotEval !== null && expectedEval !== null && Math.abs(gotEval - expectedEval) < 1e-9){\n          return Object.assign({}, secret, { __alreadySolved: alreadySolved });\n        }\n\n        if(slugify(rawInput) && slugify(rawInput) === slugify(expr)){\n          return Object.assign({}, secret, { __alreadySolved: alreadySolved });\n        }\n      }\n    }\n    return null;\n  }\n  function resolveFolderTarget(target){\n    const raw = String(target || '').trim();\n    if(!raw) return null;\n\n    const foldersSource = Array.isArray(window.BERFDB && window.BERFDB.FILES_ALL) ? window.BERFDB.FILES_ALL : [];\n    const lowered = raw.toLowerCase();\n\n    function slugify(value){\n      return String(value || '')\n        .toLowerCase()\n        .normalize('NFD').replace(\/[\\u0300-\\u036f]\/g,'')\n        .replace(\/[^a-z0-9]+\/g,'')\n        .trim();\n    }\n\n    const exact = foldersSource.find(f => {\n      const id = String((f && f.id) || '').trim().toLowerCase();\n      const name = String((f && (f.name || f.label)) || '').trim().toLowerCase();\n      return id === lowered || name === lowered;\n    });\n    if(exact) return exact;\n\n    const targetSlug = slugify(raw);\n    const soft = foldersSource.find(f => {\n      const id = slugify((f && f.id) || '');\n      const name = slugify((f && (f.name || f.label)) || '');\n      return id === targetSlug || name === targetSlug || name.includes(targetSlug) || targetSlug.includes(name);\n    });\n    return soft || null;\n  }\n  function performSecret(secret){\n    if(!secret) return false;\n    const alreadySolved = !!secret.__alreadySolved;\n    const secretId = String(secret.id || '');\n    const action = String(secret.action_type || 'none');\n    const target = String(secret.action_target || '');\n\n    if(!alreadySolved){\n      const state = loadState();\n      if(!state.solved || typeof state.solved !== 'object') state.solved = {};\n      state.solved[secretId] = true;\n      saveState(state);\n      try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('calc_secret_solved', secretId, { secret, target }); }catch(e){}\n      if(action === 'trigger_event'){\n        try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('calc_secret_solved', target || secretId, { secret, target }); }catch(e){}\n      } else if(action === 'set_flag'){\n        try{ if(window.BERF_EVENTS) window.BERF_EVENTS.setFlag(target, true); }catch(e){}\n      }\n    }\n\n    function closeCalculatorUI(){\n      try{\n        const calcOc = document.getElementById('berf-oc-calculator');\n        if(!calcOc) return true;\n        const btn = calcOc.querySelector('[data-close]');\n        if(btn){ btn.click(); return true; }\n        calcOc.removeAttribute('data-open');\n        calcOc.setAttribute('aria-hidden','true');\n        return true;\n      }catch(e){ console.warn(e); }\n      return false;\n    }\n\n    function openFileManagerUI(){\n      try{\n        const launchers = Array.from(document.querySelectorAll('[data-open-oc=\"filemanager\"]'));\n        if(launchers.length){\n          launchers[0].click();\n          return true;\n        }\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.open){\n          return !!window.BERF_FILE_MANAGER.open();\n        }\n      }catch(e){ console.warn(e); }\n      return false;\n    }\n\n    function openFolderRobust(folderTarget){\n      try{\n        if(window.BERF_FILE_MANAGER && window.BERF_FILE_MANAGER.openFolder){\n          if(window.BERF_FILE_MANAGER.openFolder(folderTarget, { unlock:true })) return true;\n        }\n      }catch(e){ console.warn(e); }\n\n      try{\n        const folderList = document.getElementById('berfFileManagerFolders');\n        if(folderList){\n          const folder = resolveFolderTarget(folderTarget);\n          const wanted = (folder && (folder.id || folder.name || folder.label))\n            ? String(folder.id || folder.name || folder.label).trim().toLowerCase()\n            : String(folderTarget || '').trim().toLowerCase();\n          const buttons = Array.from(folderList.querySelectorAll('.berf-filemanager__folderbtn,[data-folder-id],[data-folder-name]'));\n          const btn = buttons.find(el => {\n            const txt = String(el.textContent || '').trim().toLowerCase();\n            const fid = String(el.getAttribute('data-folder-id') || '').trim().toLowerCase();\n            const fname = String(el.getAttribute('data-folder-name') || '').trim().toLowerCase();\n            return wanted && (fid === wanted || fname === wanted || txt === wanted || txt.includes(wanted) || wanted.includes(txt));\n          });\n          if(btn){ btn.click(); return true; }\n        }\n      }catch(e){ console.warn(e); }\n      return false;\n    }\n\n    if(action === 'open_file_manager'){\n      closeCalculatorUI();\n      window.setTimeout(function(){\n        openFileManagerUI();\n      }, 30);\n    } else if(action === 'open_file_folder'){\n      closeCalculatorUI();\n      window.setTimeout(function(){\n        openFileManagerUI();\n        let attempts = 0;\n        const timer = window.setInterval(function(){\n          attempts += 1;\n          if(openFolderRobust(target) || attempts >= 20){\n            window.clearInterval(timer);\n          }\n        }, 120);\n      }, 60);\n    } else if(action === 'open_calculator'){\n      window.setTimeout(function(){\n        try{\n          const launchers = Array.from(document.querySelectorAll('[data-open-oc=\"calculator\"]'));\n          if(launchers.length) launchers[0].click();\n        }catch(e){ console.warn(e); }\n      }, 40);\n    }\n\n    setStatus(secret.success_message || '', 'is-success');\n    return true;\n  }\n  function submit(){\n    const raw = String(display.value || '');\n    const secret = findSecret(raw);\n    if(secret){\n      performSecret(secret);\n      return;\n    }\n    try{\n      display.value = String(safeEval(raw));\n      setStatus('', '');\n    }catch(e){\n      setStatus((secrets.find(s => !(loadState().solved||{})[String(s.id||'')]) || {}).fail_message || 'Calcul invalide.', 'is-error');\n      display.value = 'Erreur';\n    }\n  }\n\n  root.querySelectorAll('[data-calc-key]').forEach(btn=> btn.addEventListener('click', ()=> append(btn.getAttribute('data-calc-key') || '')));\n  root.querySelectorAll('[data-calc-action]').forEach(btn=> btn.addEventListener('click', ()=>{\n    const action = btn.getAttribute('data-calc-action');\n    if(action === 'clear') clearDisplay();\n    else if(action === 'backspace') backspace();\n    else if(action === 'equals') submit();\n  }));\n  display.addEventListener('keydown', (e)=>{\n    if(e.key === 'Enter'){ e.preventDefault(); submit(); }\n    if(e.key === 'Escape'){ e.preventDefault(); clearDisplay(); }\n  });\n\n  window.BERF_CALCULATOR = {\n    open: function(){ try{ if(typeof openOC === 'function') openOC('calculator'); }catch(e){} },\n    run: submit,\n    clear: clearDisplay,\n    setValue: function(value){ display.value = String(value || ''); }\n  };\n})();\n\n\n\/* =========================================================\n   TOOL : FILE MANAGER (clean rebuild)\n   ========================================================= *\/\n(function(){\n  const root = document.getElementById('berfFileManagerTool');\n  if(!root) return;\n\n  const allFolders = Array.isArray(window.BERFDB && window.BERFDB.FILES_ALL) ? window.BERFDB.FILES_ALL.slice() : [];\n  const COLLECTED_FOLDER_ID = '__berf_collected__';\n  const collectedFolder = { id:COLLECTED_FOLDER_ID, name:'\u00c9l\u00e9ments collect\u00e9s', parent_id:'', visible_at_start:true, locked:false, files:[], virtual:true };\n  allFolders.push(collectedFolder);\n  \/\/ v2 intentionally invalidates legacy unlocks. In v1, a folder opened by an\n  \/\/ event could be persisted as unlocked even when the admin marked it locked.\n  const KEY = 'berf_file_manager_state_v2';\n\n  const ui = {\n    folderList: document.getElementById('berfFileManagerFolders'),\n    stage: document.getElementById('berfFileManagerStage'),\n    crumbs: document.getElementById('berfFileManagerCrumbs'),\n    back: document.getElementById('berfFileManagerBack'),\n    lockBtn: document.getElementById('berfFileManagerLockBtn'),\n    viewer: document.getElementById('berfFileViewer'),\n    viewerTitle: document.getElementById('berfFileViewerTitle'),\n    viewerBody: document.getElementById('berfFileViewerBody'),\n    viewerAnalyze: document.getElementById('berfFileViewerAnalyze'),\n    viewerCollect: document.getElementById('berfFileViewerCollect'),\n    lockModal: document.getElementById('berfFileLockModal'),\n    lockTitle: document.getElementById('berfFileLockTitle'),\n    lockText: document.getElementById('berfFileLockText'),\n    lockError: document.getElementById('berfFileLockError'),\n    unlockWrap: document.getElementById('berfFileUnlockWrap'),\n    unlockPassword: document.getElementById('berfFileUnlockPassword'),\n    createWrap: document.getElementById('berfFileCreateWrap'),\n    createPassword: document.getElementById('berfFileCreatePassword'),\n    createPasswordConfirm: document.getElementById('berfFileCreatePasswordConfirm'),\n    lockSubmit: document.getElementById('berfFileLockSubmit'),\n    lockRemove: document.getElementById('berfFileLockRemove')\n  };\n\n  \/\/ La visionneuse doit rester accessible depuis tous les outils (registre,\n  \/\/ suspects, mails), m\u00eame lorsque l'explorateur de fichiers est ferm\u00e9.\n  const deskRoot = document.getElementById('berfDesk');\n  if(ui.viewer && deskRoot && ui.viewer.parentElement !== deskRoot){\n    deskRoot.appendChild(ui.viewer);\n  }\n\n  let currentFolderId = '';\n  let viewerFile = null;\n  let lockContext = null;\n\n  function loadState(){\n    try{\n      const raw = localStorage.getItem(KEY);\n      const parsed = raw ? JSON.parse(raw) : null;\n      if(parsed && typeof parsed === 'object') return normalizeState(parsed);\n    }catch(e){}\n    return normalizeState({});\n  }\n  function normalizeState(state){\n    const s = state && typeof state === 'object' ? state : {};\n    if(!Array.isArray(s.backendUnlocked)) s.backendUnlocked = [];\n    if(!s.backendUnlockTokens || typeof s.backendUnlockTokens !== 'object') s.backendUnlockTokens = {};\n    if(!Array.isArray(s.revealed)) s.revealed = [];\n    if(!s.playerLocks || typeof s.playerLocks !== 'object') s.playerLocks = {};\n    if(!Array.isArray(s.collectedFiles)) s.collectedFiles = [];\n    return s;\n  }\n  function saveState(state){\n    localStorage.setItem(KEY, JSON.stringify(normalizeState(state)));\n  }\n  function mutateState(mutator){\n    const state = loadState();\n    mutator(state);\n    saveState(state);\n    return state;\n  }\n\n  function slugifyFolderValue(value){\n    return String(value || '')\n      .toLowerCase()\n      .normalize('NFD').replace(\/[\u0300-\u036f]\/g,'')\n      .replace(\/[^a-z0-9]+\/g,'')\n      .trim();\n  }\n  function resolveFolderRef(folderRef){\n    const raw = String(folderRef || '').trim();\n    if(!raw) return null;\n    const lowered = raw.toLowerCase();\n    let found = allFolders.find(f => String(f && f.id || '').trim().toLowerCase() === lowered);\n    if(found) return found;\n    found = allFolders.find(f => String(f && (f.name || f.label) || '').trim().toLowerCase() === lowered);\n    if(found) return found;\n    const wanted = slugifyFolderValue(raw);\n    found = allFolders.find(f => slugifyFolderValue(f && (f.id || '')) === wanted || slugifyFolderValue(f && (f.name || f.label || '')) === wanted);\n    if(found) return found;\n    found = allFolders.find(f => {\n      const name = slugifyFolderValue(f && (f.name || f.label || ''));\n      return !!name && (name.includes(wanted) || wanted.includes(name));\n    });\n    return found || null;\n  }\n  function getFolder(folderId){\n    return resolveFolderRef(folderId);\n  }\n  function backendUnlockToken(folder){\n    if(!folder) return '';\n    return [String(folder.id || ''), folder.locked ? '1' : '0', String(folder.password || '')].join('|');\n  }\n  function reconcileBackendUnlocks(){\n    const state = loadState();\n    const valid = [];\n    const tokens = {};\n    state.backendUnlocked.forEach(folderId=>{\n      const folder = getFolder(folderId);\n      const id = String(folder && folder.id || '');\n      if(!folder || !folder.locked || !id) return;\n      const expected = backendUnlockToken(folder);\n      if(String(state.backendUnlockTokens[id] || '') !== expected) return;\n      valid.push(id);\n      tokens[id] = expected;\n    });\n    state.backendUnlocked = valid;\n    state.backendUnlockTokens = tokens;\n    saveState(state);\n  }\n  function fileType(file){\n    const rawType = String(file && (file.type || file.mime || file.mime_type) || '').toLowerCase();\n    const rawName = String(file && (file.url || file.name || file.label) || '').toLowerCase();\n    const ext = (rawName.split('.').pop() || '').split('?')[0].split('#')[0].toLowerCase();\n    if(rawType === 'mp3' || rawType.indexOf('audio') !== -1 || ['mp3','wav','ogg','m4a','aac','flac','webm'].includes(ext)) return 'audio';\n    if(rawType === 'pdf' || rawType.indexOf('pdf') !== -1 || ext === 'pdf') return 'pdf';\n    if(rawType === 'text' || rawType.indexOf('text') !== -1 || ['txt','md'].includes(ext) || (file && file.content)) return 'text';\n    if(rawType.indexOf('image') !== -1 || ['jpg','jpeg','png','gif','webp','bmp','svg'].includes(ext)) return 'image';\n    if(rawType.indexOf('video') !== -1 || ['mp4','mov','avi','mkv','webm'].includes(ext)) return 'video';\n    return rawType || 'file';\n  }\n  function fileKey(file){\n    return String((file && (file.id || file.attachment_id || file.url || file.label || file.name)) || '');\n  }\n  function cloneFileRef(file, sourceFolderId){\n    if(!file) return null;\n    return { id:file.id || file.attachment_id || fileKey(file), attachment_id:file.attachment_id || file.id || '', label:file.label || file.name || 'Fichier', name:file.name || file.label || 'Fichier', url:file.url || '', type:file.type || file.mime || file.mime_type || fileType(file), mime:file.mime || file.mime_type || '', content:file.content || '', sourceFolderId:String(sourceFolderId || file.sourceFolderId || '') };\n  }\n  function syncCollectedFolder(){ collectedFolder.files = loadState().collectedFiles.map(item=>cloneFileRef(item,item.sourceFolderId)).filter(Boolean); }\n  function isCollected(file){ const key=fileKey(file); return loadState().collectedFiles.some(item=>fileKey(item)===key); }\n  function collectFile(file, sourceFolderId){\n    const ref=cloneFileRef(file,sourceFolderId); if(!ref)return false;\n    let added=false; mutateState(state=>{if(!state.collectedFiles.some(item=>fileKey(item)===fileKey(ref))){state.collectedFiles.push(ref);added=true;}}); syncCollectedFolder();\n    if(added){renderFolderList();try{if(window.BERF_EVENTS)window.BERF_EVENTS.trigger('file_collected',fileKey(ref),{file:ref,sourceFolderId:String(sourceFolderId||'')});}catch(e){}}\n    return added;\n  }\n  function playerLockFor(folderId){\n    const state = loadState();\n    return state.playerLocks && state.playerLocks[String(folderId || '')] ? state.playerLocks[String(folderId || '')] : null;\n  }\n  function folderOwnVisible(folder){\n    if(!folder) return false;\n    if(folder.visible_at_start !== false) return true;\n    const state = loadState();\n    return state.revealed.includes(String(folder.id || ''));\n  }\n  function folderIsVisible(folder, visited){\n    if(!folder || !folderOwnVisible(folder)) return false;\n    const parentId = String(folder.parent_id || '').trim();\n    if(!parentId) return true;\n    const seen = visited instanceof Set ? visited : new Set();\n    const id = String(folder.id || '');\n    if(seen.has(id)) return false;\n    seen.add(id);\n    const parent = getFolder(parentId);\n    return !!parent && folderIsVisible(parent, seen);\n  }\n  function folderBackendLocked(folder){\n    if(!folder || !folder.locked) return false;\n    const state = loadState();\n    return !state.backendUnlocked.includes(String(folder.id || ''));\n  }\n  function folderLockMode(folder){\n    if(!folder) return 'none';\n    if(playerLockFor(folder.id)) return 'player';\n    if(folderBackendLocked(folder)) return 'backend';\n    return 'none';\n  }\n  function visibleFolders(){\n    return allFolders.filter(folderIsVisible);\n  }\n  function childFolders(parentId){\n    const wanted = String(parentId || '');\n    return visibleFolders().filter(folder => String(folder.parent_id || '') === wanted);\n  }\n  function folderPath(folder){\n    const path = [], seen = new Set();\n    let cursor = folder;\n    while(cursor){\n      const id = String(cursor.id || '');\n      if(!id || seen.has(id)) break;\n      seen.add(id);\n      path.unshift(cursor);\n      const parentId = String(cursor.parent_id || '');\n      cursor = parentId ? getFolder(parentId) : null;\n    }\n    return path;\n  }\n\n  function escapeHtml(value){\n    return String(value || '').replace(\/[&<>\"']\/g, function(ch){\n      return ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;', \"'\":'&#039;'})[ch];\n    });\n  }\n  function iconFor(type){\n    switch(String(type || '').toLowerCase()){\n      case 'image': return 'fa-file-image';\n      case 'video': return 'fa-file-video';\n      case 'audio':\n      case 'mp3': return 'fa-file-audio';\n      case 'pdf': return 'fa-file-pdf';\n      case 'text': return 'fa-file-lines';\n      default: return 'fa-file';\n    }\n  }\n  function fileMetaLabel(file){\n    const type = fileType(file);\n    if(type === 'image') return 'Image';\n    if(type === 'video') return 'Vid\u00e9o';\n    if(type === 'audio') return 'Audio';\n    if(type === 'pdf') return 'PDF';\n    if(type === 'text') return 'Document';\n    return 'Fichier';\n  }\n\n  function setLockError(message){\n    ui.lockError.textContent = message || '';\n    ui.lockError.style.display = message ? 'block' : 'none';\n  }\n  function closeLockModal(){\n    lockContext = null;\n    ui.lockModal.removeAttribute('data-open');\n    ui.lockModal.setAttribute('aria-hidden','true');\n    setLockError('');\n    ui.unlockPassword.value = '';\n    ui.createPassword.value = '';\n    ui.createPasswordConfirm.value = '';\n  }\n  function openLockModal(context){\n    lockContext = context || null;\n    setLockError('');\n    ui.unlockPassword.value = '';\n    ui.createPassword.value = '';\n    ui.createPasswordConfirm.value = '';\n    ui.lockRemove.style.display = 'none';\n    ui.unlockWrap.style.display = 'none';\n    ui.createWrap.style.display = 'none';\n\n    if(context.mode === 'unlock-backend'){\n      ui.lockTitle.textContent = 'Dossier verrouill\u00e9';\n      ui.lockText.textContent = 'Ce dossier et prot\u00e9g\u00e9 par un mot de passe';\n      ui.unlockWrap.style.display = 'block';\n      ui.lockSubmit.textContent = 'D\u00e9verrouiller';\n    } else if(context.mode === 'unlock-player'){\n      ui.lockTitle.textContent = 'Dossier verrouill\u00e9';\n      ui.lockText.textContent = 'Ce dossier est prot\u00e9g\u00e9 par un mot de passe.';\n      ui.unlockWrap.style.display = 'block';\n      ui.lockSubmit.textContent = 'Ouvrir';\n    } else {\n      const hasPlayerLock = !!playerLockFor(context.folderId);\n      ui.lockTitle.textContent = hasPlayerLock ? 'Modifier le mot de passe' : 'Verrouiller le dossier';\n      ui.lockText.textContent = hasPlayerLock\n        ? 'Modifie le mot de passe de ce dossier ou retire le verrou.'\n        : 'Cr\u00e9e un mot de passe pour verrouiller ce dossier.';\n      ui.createWrap.style.display = 'block';\n      ui.lockSubmit.textContent = hasPlayerLock ? 'Mettre \u00e0 jour' : 'Cr\u00e9er le verrou';\n      ui.lockRemove.style.display = hasPlayerLock ? 'inline-flex' : 'none';\n    }\n\n    ui.lockModal.setAttribute('data-open','true');\n    ui.lockModal.setAttribute('aria-hidden','false');\n    window.setTimeout(()=>{\n      const targetInput = ui.unlockWrap.style.display !== 'none' ? ui.unlockPassword : ui.createPassword;\n      if(targetInput) targetInput.focus();\n    }, 30);\n  }\n\n  function closeViewer(){\n    viewerFile = null;\n    ui.viewer.removeAttribute('data-open');\n    ui.viewer.setAttribute('aria-hidden','true');\n    ui.viewerAnalyze.style.display = 'none';\n    ui.viewerAnalyze.onclick = null;\n    ui.viewerCollect.style.display = 'none';\n    ui.viewerCollect.onclick = null;\n    ui.viewerBody.innerHTML = '';\n  }\n\n  async function analyzeAudioFromUrl(url, name){\n    try{\n      if(!url) return false;\n\n      try{\n        closeViewer();\n        const fm = document.getElementById('berf-oc-filemanager');\n        if(fm){\n          if(typeof closeOC === 'function') { try{ closeOC(fm); }catch(_e){} }\n          fm.removeAttribute('data-open');\n          fm.setAttribute('aria-hidden','true');\n        }\n      }catch(_e){}\n\n      await new Promise(r=>setTimeout(r, 80));\n\n      try{\n        if(typeof openOC === 'function') openOC('audiotool');\n        const audioOC = document.getElementById('berf-oc-audiotool');\n        if(audioOC){\n          audioOC.setAttribute('data-open','true');\n          audioOC.setAttribute('aria-hidden','false');\n        }\n      }catch(_e){}\n\n      await new Promise(r=>setTimeout(r, 180));\n\n      if(window.BERF_AUDIOTOOL_IMPORT_URL){\n        await window.BERF_AUDIOTOOL_IMPORT_URL(url, name || 'file-audio');\n        return true;\n      }\n      return false;\n    }catch(err){\n      console.warn('analyzeAudioFromUrl failed', err);\n      return false;\n    }\n  }\n  window.BERF_ANALYZE_AUDIO_FROM_URL = analyzeAudioFromUrl;\n\n  function openFileViewer(file){\n    if(!file) return;\n    viewerFile = file;\n    ui.viewerTitle.textContent = file.label || file.name || 'Fichier';\n    ui.viewerBody.innerHTML = '';\n    ui.viewerAnalyze.style.display = 'none';\n    ui.viewerAnalyze.onclick = null;\n    ui.viewerCollect.style.display = 'inline-flex';\n    ui.viewerCollect.disabled = isCollected(file);\n    ui.viewerCollect.innerHTML = isCollected(file) ? '<i class=\"fa-solid fa-check\"><\/i> D\u00e9j\u00e0 collect\u00e9' : '<i class=\"fa-solid fa-download\"><\/i> Ajouter aux \u00e9l\u00e9ments collect\u00e9s';\n    ui.viewerCollect.onclick = function(){\n      const added=collectFile(file,currentFolderId);\n      ui.viewerCollect.disabled=true;\n      ui.viewerCollect.innerHTML='<i class=\"fa-solid fa-check\"><\/i> Ajout\u00e9 aux \u00e9l\u00e9ments collect\u00e9s';\n      if(added && String(currentFolderId)===COLLECTED_FOLDER_ID) renderFolder(COLLECTED_FOLDER_ID);\n    };\n\n    const type = fileType(file);\n    const url = file.url || '';\n\n    let node = null;\n    if(type === 'image'){\n      node = document.createElement('img');\n      node.src = url;\n      ui.viewerAnalyze.style.display = 'inline-flex';\n      ui.viewerAnalyze.innerHTML = '<i class=\"fa-solid fa-wand-magic-sparkles\"><\/i> Analyser l\\'image';\n      ui.viewerAnalyze.onclick = async function(){\n        closeViewer();\n        try{\n          const fm = document.getElementById('berf-oc-filemanager');\n          if(fm){\n            if(typeof closeOC === 'function') { try{ closeOC(fm); }catch(_e){} }\n            fm.removeAttribute('data-open');\n            fm.setAttribute('aria-hidden','true');\n          }\n        }catch(e){}\n        await (window.BERF_ANALYZE_IMAGE_FROM_URL ? window.BERF_ANALYZE_IMAGE_FROM_URL(url, file.label || file.name || 'fichier-image') : Promise.resolve(false));\n      };\n    } else if(type === 'video'){\n      node = document.createElement('video');\n      node.src = url;\n      node.controls = true;\n      node.playsInline = true;\n    } else if(type === 'audio'){\n      node = document.createElement('audio');\n      node.src = url;\n      node.controls = true;\n      node.autoplay = true;\n      ui.viewerAnalyze.style.display = 'inline-flex';\n      ui.viewerAnalyze.innerHTML = '<i class=\"fa-solid fa-wave-square\"><\/i> Analyser l\\'audio';\n      ui.viewerAnalyze.onclick = async function(){\n        await analyzeAudioFromUrl(url, file.label || file.name || 'fichier-audio');\n      };\n    } else if(type === 'pdf'){\n      node = document.createElement('iframe');\n      node.src = url;\n      node.setAttribute('title', file.label || file.name || 'PDF');\n    } else if(type === 'text'){\n      const article = document.createElement('article');\n      article.className = 'berf-filemanager__textdoc';\n      const content = String(file.content || '');\n      article.innerHTML = '<pre>' + escapeHtml(content) + '<\/pre>';\n      node = article;\n    } else {\n      const wrap = document.createElement('div');\n      wrap.className = 'berf-filemanager__empty';\n      wrap.innerHTML = '<i class=\"fa-solid fa-file\"><\/i><strong>Visionneuse non disponible<\/strong><span>Ce fichier peut \u00eatre ouvert dans un nouvel onglet.<\/span>';\n      const openBtn = document.createElement('button');\n      openBtn.type = 'button';\n      openBtn.className = 'berf-filemanager__primary';\n      openBtn.innerHTML = '<i class=\"fa-solid fa-arrow-up-right-from-square\"><\/i> Ouvrir le fichier';\n      openBtn.addEventListener('click', ()=> window.open(url, '_blank'));\n      wrap.appendChild(openBtn);\n      node = wrap;\n    }\n\n    if(node) ui.viewerBody.appendChild(node);\n    ui.viewer.setAttribute('data-open','true');\n    ui.viewer.setAttribute('aria-hidden','false');\n  }\n\n  function renderHome(){\n    currentFolderId = '';\n    ui.back.style.display = 'none';\n    ui.lockBtn.style.display = 'none';\n    ui.crumbs.textContent = 'S\u00e9lectionne un dossier';\n    const folders = childFolders('');\n\n    if(!folders.length){\n      ui.stage.innerHTML = '<div class=\"berf-filemanager__empty\"><i class=\"fa-solid fa-folder-open\"><\/i><strong>Aucun dossier disponible<\/strong><\/div>';\n      renderFolderList();\n      return;\n    }\n\n    ui.stage.innerHTML = '<div class=\"berf-filemanager__empty\"><i class=\"fa-solid fa-folder-tree\"><\/i><strong>'+ folders.length +' dossier(s) disponible(s)<\/strong><span>S\u00e9lectionne un dossier pour afficher son contenu.<\/span><\/div>';\n    renderFolderList();\n  }\n\n  function renderFolderList(){\n    const folders = childFolders('');\n    ui.folderList.innerHTML = '';\n    if(!folders.length){\n      ui.folderList.innerHTML = '<div class=\"berf-filemanager__empty\"><i class=\"fa-solid fa-folder-open\"><\/i><strong>Vide<\/strong><span>Aucun dossier.<\/span><\/div>';\n      return;\n    }\n\n    folders.forEach(folder=>{\n      const mode = folderLockMode(folder);\n      const count = Array.isArray(folder.files) ? folder.files.length : 0;\n      const subCount = childFolders(folder.id).length;\n      const btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = 'berf-filemanager__folderbtn' + (String(folder.id||'') === String(currentFolderId||'') ? ' is-active' : '');\n      btn.innerHTML = ''\n        + '<span class=\"berf-filemanager__foldermain\">'\n        +   '<i class=\"fa-solid '+ (mode === 'none' ? 'fa-folder-open' : 'fa-folder-lock') +'\"><\/i>'\n        +   '<span class=\"berf-filemanager__foldername\">'+ escapeHtml(folder.name || 'Dossier') +'<\/span>'\n        + '<\/span>'\n        + '<span class=\"berf-filemanager__foldermeta\">'+ (mode === 'none' ? count + ' fichier(s)' + (subCount ? ' \u00b7 '+subCount+' dossier(s)' : '') : 'Verrouill\u00e9') +'<\/span>';\n      btn.addEventListener('click', ()=> requestOpenFolder(String(folder.id || '')));\n      ui.folderList.appendChild(btn);\n    });\n  }\n\n  function renderFolder(folderId){\n    syncCollectedFolder();\n    const folder = getFolder(folderId);\n    if(!folder || !folderIsVisible(folder)){\n      renderHome();\n      return;\n    }\n    currentFolderId = String(folderId || '');\n    renderFolderList();\n\n    ui.back.style.display = 'inline-flex';\n    ui.lockBtn.style.display = folder.virtual ? 'none' : 'inline-flex';\n    ui.lockBtn.innerHTML = playerLockFor(folder.id)\n      ? '<i class=\"fa-solid fa-lock\"><\/i> Modifier le mot de passe'\n      : '<i class=\"fa-solid fa-lock\"><\/i> Verrouiller ce dossier';\n    ui.crumbs.textContent = folderPath(folder).map(item=>item.name || 'Dossier').join(' \/ ');\n\n    const files = Array.isArray(folder.files) ? folder.files : [];\n    const children = childFolders(folder.id);\n    if(!files.length && !children.length){\n      ui.stage.innerHTML = ''\n        + '<div class=\"berf-filemanager__folderhead\"><div><h3>'+ escapeHtml(folder.name || 'Dossier') +'<\/h3><p>Ce dossier est vide.<\/p><\/div><\/div>'\n        + '<div class=\"berf-filemanager__empty\"><i class=\"fa-solid fa-folder-open\"><\/i><strong>Aucun fichier<\/strong><\/div>';\n      return;\n    }\n\n    const head = ''\n      + '<div class=\"berf-filemanager__folderhead\">'\n      +   '<div><h3>'+ escapeHtml(folder.name || 'Dossier') +'<\/h3><p>'+ children.length +' sous-dossier(s) \u00b7 '+ files.length +' fichier(s)<\/p><\/div>'\n      + '<\/div>';\n\n    const folderCards = children.map(child => {\n      const mode=folderLockMode(child);\n      return ''\n        + '<button type=\"button\" class=\"berf-filemanager__card berf-filemanager__card--folder\" data-folder-id=\"'+ escapeHtml(String(child.id||'')) +'\">'\n        +   '<i class=\"fa-solid '+ (mode === 'none' ? 'fa-folder' : 'fa-folder-lock') +'\"><\/i>'\n        +   '<span class=\"berf-filemanager__cardtitle\" title=\"'+ escapeHtml(child.name || 'Dossier') +'\">'+ escapeHtml(child.name || 'Dossier') +'<\/span>'\n        +   '<span class=\"berf-filemanager__cardmeta\">'+ (mode === 'none' ? 'Dossier' : 'Verrouill\u00e9') +'<\/span>'\n        + '<\/button>';\n    }).join('');\n\n    const cards = files.map(file => {\n      const normalizedType = fileType(file);\n      return ''\n        + '<button type=\"button\" class=\"berf-filemanager__card\" data-file-key=\"'+ escapeHtml(fileKey(file)) +'\">'\n        +   '<i class=\"fa-solid '+ iconFor(normalizedType) +'\"><\/i>'\n        +   '<span class=\"berf-filemanager__cardtitle\" title=\"'+ escapeHtml(file.label || file.name || 'Fichier') +'\">'+ escapeHtml(file.label || file.name || 'Fichier') +'<\/span>'\n        +   '<span class=\"berf-filemanager__cardmeta\">'+ escapeHtml(fileMetaLabel(file)) +'<\/span>'\n        + '<\/button>';\n    }).join('');\n\n    ui.stage.innerHTML = head + '<div class=\"berf-filemanager__grid\">'+ folderCards + cards +'<\/div>';\n\n    ui.stage.querySelectorAll('[data-folder-id]').forEach(btn=>{\n      btn.addEventListener('click', ()=>requestOpenFolder(btn.getAttribute('data-folder-id') || ''));\n    });\n\n    ui.stage.querySelectorAll('[data-file-key]').forEach(btn=>{\n      btn.addEventListener('click', ()=>{\n        const file = files.find(item => fileKey(item) === btn.getAttribute('data-file-key'));\n        if(!file) return;\n        try{\n          if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('open_file_item', fileKey(file), { folderId: folder.id, folder, file });\n        }catch(e){}\n        openFileViewer(file);\n      });\n    });\n\n    try{\n      if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('open_file_folder', String(folder.id || ''), { folder });\n    }catch(e){}\n  }\n\n  function requestOpenFolder(folderId){\n    const folder = getFolder(folderId);\n    if(!folder || !folderIsVisible(folder)) return;\n    const mode = folderLockMode(folder);\n    if(mode === 'backend'){\n      openLockModal({ mode:'unlock-backend', folderId:String(folder.id || '') });\n      return;\n    }\n    if(mode === 'player'){\n      openLockModal({ mode:'unlock-player', folderId:String(folder.id || '') });\n      return;\n    }\n    renderFolder(folderId);\n  }\n\n  function submitLockModal(){\n    if(!lockContext) return;\n    const folder = getFolder(lockContext.folderId);\n    if(!folder) return;\n\n    if(lockContext.mode === 'unlock-backend'){\n      const pwd = String(ui.unlockPassword.value || '');\n      if(pwd !== String(folder.password || '')){\n        setLockError(folder.error_message || 'Mot de passe incorrect.');\n        return;\n      }\n      mutateState(state=>{\n        const id = String(folder.id || '');\n        if(!state.backendUnlocked.includes(id)) state.backendUnlocked.push(id);\n        state.backendUnlockTokens[id] = backendUnlockToken(folder);\n        if(!state.revealed.includes(id)) state.revealed.push(id);\n      });\n      closeLockModal();\n      try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('unlock_file_folder', String(folder.id || ''), { folder, source:'backend' }); }catch(e){}\n      renderFolder(folder.id);\n      return;\n    }\n\n    if(lockContext.mode === 'unlock-player'){\n      const lock = playerLockFor(folder.id);\n      const pwd = String(ui.unlockPassword.value || '');\n      if(!lock || pwd !== String(lock.password || '')){\n        setLockError('Mot de passe incorrect.');\n        return;\n      }\n      closeLockModal();\n      try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('unlock_file_folder', String(folder.id || ''), { folder, source:'player' }); }catch(e){}\n      renderFolder(folder.id);\n      return;\n    }\n\n    const pwd = String(ui.createPassword.value || '');\n    const confirm = String(ui.createPasswordConfirm.value || '');\n    if(!pwd || pwd.length < 2){\n      setLockError('Choisis un mot de passe valide.');\n      return;\n    }\n    if(pwd !== confirm){\n      setLockError('Les mots de passe ne correspondent pas.');\n      return;\n    }\n    mutateState(state=>{\n      state.playerLocks[String(folder.id || '')] = { password: pwd };\n      if(!state.revealed.includes(String(folder.id || ''))) state.revealed.push(String(folder.id || ''));\n    });\n    closeLockModal();\n    try{ if(window.BERF_EVENTS) window.BERF_EVENTS.trigger('player_lock_file_folder', String(folder.id || ''), { folder }); }catch(e){}\n    renderFolder(folder.id);\n  }\n\n  ui.back.addEventListener('click', function(){\n    const current=getFolder(currentFolderId);\n    const parentId=String(current && current.parent_id || '');\n    if(parentId) requestOpenFolder(parentId);\n    else renderHome();\n  });\n  ui.lockBtn.addEventListener('click', function(){\n    if(!currentFolderId) return;\n    openLockModal({ mode:'create-player', folderId:String(currentFolderId) });\n  });\n  ui.lockSubmit.addEventListener('click', submitLockModal);\n  ui.lockRemove.addEventListener('click', function(){\n    if(!lockContext || !lockContext.folderId) return;\n    mutateState(state=>{\n      delete state.playerLocks[String(lockContext.folderId || '')];\n    });\n    const folder = getFolder(lockContext.folderId);\n    closeLockModal();\n    if(folder) renderFolder(folder.id);\n  });\n  ui.unlockPassword.addEventListener('keydown', function(e){ if(e.key === 'Enter') submitLockModal(); });\n  ui.createPassword.addEventListener('keydown', function(e){ if(e.key === 'Enter') submitLockModal(); });\n  ui.createPasswordConfirm.addEventListener('keydown', function(e){ if(e.key === 'Enter') submitLockModal(); });\n\n  document.querySelectorAll('[data-filelock-close]').forEach(btn=> btn.addEventListener('click', closeLockModal));\n  document.querySelectorAll('[data-fileviewer-close]').forEach(btn=> btn.addEventListener('click', closeViewer));\n\n  window.BERF_FILE_MANAGER = {\n    open: function(){\n      try{ if(typeof openOC === 'function') openOC('filemanager'); }catch(e){}\n      return true;\n    },\n    revealFolder: function(folderId){\n      const folder = getFolder(folderId);\n      if(!folder) return false;\n      mutateState(state=>{\n        const id = String(folder.id || '');\n        if(!state.revealed.includes(id)) state.revealed.push(id);\n      });\n      if(currentFolderId) renderFolder(currentFolderId); else renderHome();\n      return true;\n    },\n    openFolder: function(folderId, opts){\n      const folder = getFolder(folderId);\n      if(!folder) return false;\n      const options = opts && typeof opts === 'object' ? opts : {};\n      mutateState(state=>{\n        const id = String(folder.id || '');\n        if((options.reveal !== false) && !state.revealed.includes(id)) state.revealed.push(id);\n        if(options.unlock){\n          if(!state.backendUnlocked.includes(id)) state.backendUnlocked.push(id);\n          state.backendUnlockTokens[id] = backendUnlockToken(folder);\n        }\n      });\n      try{ if(typeof openOC === 'function') openOC('filemanager'); }catch(e){}\n      if(!options.unlock && folderLockMode(folder) !== 'none'){\n        requestOpenFolder(folder.id);\n        return true;\n      }\n      currentFolderId = String(folder.id || '');\n      renderFolder(folder.id);\n      return true;\n    },\n    unlockFolder: function(folderId){\n      const folder = getFolder(folderId);\n      if(!folder) return false;\n      mutateState(state=>{\n        const id = String(folder.id || '');\n        if(!state.revealed.includes(id)) state.revealed.push(id);\n        if(!state.backendUnlocked.includes(id)) state.backendUnlocked.push(id);\n        state.backendUnlockTokens[id] = backendUnlockToken(folder);\n      });\n      if(String(currentFolderId || '') === String(folder.id || '')) renderFolder(folder.id);\n      else renderFolderList();\n      if(!document.getElementById('berf-oc-filemanager').hasAttribute('data-open')) renderHome();\n      return true;\n    },\n    lockFolder: function(folderId){\n      const folder = getFolder(folderId);\n      if(!folder) return false;\n      mutateState(state=>{\n        const id = String(folder.id || '');\n        state.backendUnlocked = state.backendUnlocked.filter(x => String(x) !== id);\n        delete state.backendUnlockTokens[id];\n        if(!state.revealed.includes(id)) state.revealed.push(id);\n      });\n      if(String(currentFolderId || '') === String(folder.id || '')) renderHome();\n      else renderFolderList();\n      return true;\n    },\n    refresh: function(){\n      if(currentFolderId) renderFolder(currentFolderId);\n      else renderHome();\n    },\n    collectFile: function(file, sourceFolderId){ return collectFile(file, sourceFolderId); },\n    isCollected: function(file){ return isCollected(file); },\n    openFile: function(file){ if(!file)return false; openFileViewer(file); return true; },\n    listAccessibleFolders: function(){\n      syncCollectedFolder();\n      return visibleFolders().filter(folder=>folderPath(folder).every(item=>folderLockMode(item)==='none')).map(folder=>({\n        id:String(folder.id||''), name:folder.name||'Dossier', parent_id:String(folder.parent_id||''), virtual:!!folder.virtual,\n        files:(Array.isArray(folder.files)?folder.files:[]).map(file=>cloneFileRef(file,folder.id)).filter(Boolean)\n      }));\n    }\n  };\n\n  reconcileBackendUnlocks();\n  syncCollectedFolder();\n  renderHome();\n})();\n<\/script>\n<style>\n#berfMissionRegistry{--rr:#af3232;min-height:680px;background:#101316;color:#eee9df;padding:24px;font-family:Arial,sans-serif}\n#berfDesk>.berf-fileviewer{position:fixed!important;inset:0!important;z-index:2147483644!important}\n.berf-registry-tabs{display:flex;gap:8px;border-bottom:1px solid #373b3e;margin-bottom:26px}.berf-registry-tabs button{border:0;background:transparent;color:#aaa;padding:12px 18px;font-weight:700;cursor:pointer;border-bottom:3px solid transparent}.berf-registry-tabs button.is-active{color:#fff;border-color:var(--rr)}\n.berf-registry-panel{display:none}.berf-registry-panel.is-active{display:block}.berf-registry-heading h2{margin:0 0 5px;font-size:32px;text-transform:uppercase}.berf-registry-heading p{margin:0;color:#aaa}\n.berf-registry-search{display:grid;grid-template-columns:1fr auto;gap:14px;align-items:end;margin:28px 0}.berf-registry-search label{display:flex;flex-direction:column;gap:8px;color:#ddd}.berf-registry-search input{min-height:48px;background:#1b1f22;color:#fff;border:1px solid #52575b;border-radius:4px;padding:0 16px;font:16px monospace}.berf-registry-search button,.berf-registry-record button{min-height:48px;border:0;border-radius:4px;background:var(--rr);color:#fff;padding:0 24px;font-weight:800;text-transform:uppercase;cursor:pointer}\n.berf-registry-empty{border:1px solid #3c4145;min-height:260px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;color:#92989c}.berf-registry-empty i{font-size:38px;color:var(--rr)}.berf-registry-empty strong{font-size:19px;color:#ddd}\n.berf-registry-record{border:1px solid #4a4f53;border-left:3px solid var(--rr);padding:24px;background:#15191c}.berf-registry-record__head{display:flex;justify-content:space-between;gap:20px;align-items:flex-start}.berf-registry-record__ref{font:700 27px monospace}.berf-registry-badge{background:var(--rr);padding:6px 12px;border-radius:3px;font-weight:800}.berf-registry-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 28px;margin-top:20px}.berf-registry-field{padding:12px 0;border-bottom:1px dashed #3d4245}.berf-registry-field span{display:block;color:#92989c;font-size:12px;text-transform:uppercase;margin-bottom:5px}.berf-registry-log{margin-top:22px;border-top:1px solid #373b3e;padding-top:18px}.berf-registry-log h3{font-size:15px;text-transform:uppercase}.berf-registry-log ol{list-style:none;padding:0}.berf-registry-log li{display:flex;gap:18px;padding:9px 0;border-bottom:1px dotted #363a3d}.berf-registry-log time{min-width:125px;color:#d65b55;font-weight:700}.berf-registry-format{border-color:#7c302c}.berf-registry-format strong{color:#ee8b84}\n.berf-registry-record>[data-registry-pdf]{margin-top:22px}\n#berfMissionRegistry [data-registry-panel=\"agents\"] #berfTrombiTool{padding:0;background:transparent}\n@media(max-width:760px){.berf-registry-search,.berf-registry-grid{grid-template-columns:1fr}.berf-registry-record__head{flex-direction:column}}\n<\/style>\n<script>\n(function(){\n  const root=document.getElementById('berfMissionRegistry'); if(!root)return;\n  const tabs=[...root.querySelectorAll('[data-registry-tab]')];\n  tabs.forEach(btn=>btn.addEventListener('click',()=>{const name=btn.dataset.registryTab;tabs.forEach(x=>x.classList.toggle('is-active',x===btn));root.querySelectorAll('[data-registry-panel]').forEach(p=>p.classList.toggle('is-active',p.dataset.registryPanel===name));}));\n  const input=root.querySelector('#berfRegistrySearch'),button=root.querySelector('#berfRegistrySearchBtn'),result=root.querySelector('#berfRegistryResult');\n  const registry=window.BERFDB&&window.BERFDB.BOOT&&window.BERFDB.BOOT.data&&window.BERFDB.BOOT.data.mission_registry||{};\n  const orders=Array.isArray(registry.orders)?registry.orders:[];\n  const esc=s=>String(s==null?'':s).replace(\/[&<>\"']\/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#039;'}[c]));\n  const labels={active:'ACTIF',pending:'EN ATTENTE',closed:'CL\u00d4TUR\u00c9',cancelled:'ANNUL\u00c9',suspended:'SUSPENDU'};\n  let selectedOrder=null;\n  function formatDate(value,withTime){const s=String(value||'').trim();const m=s.match(\/^(\\d{4})-(\\d{2})-(\\d{2})(?:[T ](\\d{2}):(\\d{2}))?\/);if(!m)return s||'\u2014';return m[3]+'\/'+m[2]+'\/'+m[1]+(withTime&&m[4]?' \u00e0 '+m[4]+' h '+m[5]:'');}\n  function search(){\n    const raw=String(input.value||'').trim(),q=raw.toLowerCase();\n    if(!q){result.innerHTML='<div class=\"berf-registry-empty\"><i class=\"fa-solid fa-magnifying-glass\"><\/i><strong>R\u00e9f\u00e9rence requise<\/strong><span>Saisissez une r\u00e9f\u00e9rence, un agent ou un mot de l\u2019objet.<\/span><\/div>';return;}\n    const found=orders.find(o=>String(o.reference||'').trim().toLowerCase()===q);\n    if(!found){const format=\/^[a-z]{3}-\\d{2}-\\d{2}-\\d{3}$\/i.test(raw);result.innerHTML='<div class=\"berf-registry-empty '+(format?'berf-registry-format':'')+'\"><i class=\"fa-solid fa-triangle-exclamation\"><\/i><strong>'+(format?'Format de r\u00e9f\u00e9rence non reconnu':'Aucun ordre trouv\u00e9')+'<\/strong><span>'+(format?'Les r\u00e9f\u00e9rences BERF utilisent des s\u00e9parateurs normalis\u00e9s. V\u00e9rifiez la r\u00e9f\u00e9rence saisie.':'Aucun ordre ne correspond \u00e0 cette recherche.')+'<\/span><\/div>';return;}\n    selectedOrder=found;\n    const agents=Array.isArray(found.agents)?found.agents.join(' \u00b7 '):found.agents||'Aucun';\n    const log=Array.isArray(found.log)&&found.log.length?'<div class=\"berf-registry-log\"><h3>Journal de l\u2019ordre<\/h3><ol>'+found.log.map(x=>'<li><time>'+esc(formatDate(x.date,false))+'<\/time><span>'+esc(x.label)+'<\/span><\/li>').join('')+'<\/ol><\/div>':'';\n    const pdf=found.document_url?'<button type=\"button\" data-registry-pdf><i class=\"fa-solid fa-file-pdf\"><\/i> Consulter l\u2019ordre de mission<\/button>':'';\n    result.innerHTML='<article class=\"berf-registry-record\"><header class=\"berf-registry-record__head\"><div><div class=\"berf-registry-record__ref\">'+esc(found.reference)+'<\/div><h3>'+esc(found.object||'Objet non renseign\u00e9')+'<\/h3><\/div><span class=\"berf-registry-badge\">'+esc(labels[found.status]||found.status)+'<\/span><\/header><div class=\"berf-registry-grid\"><div class=\"berf-registry-field\"><span>Destination<\/span><b>'+esc(found.destination||'\u2014')+'<\/b><\/div><div class=\"berf-registry-field\"><span>Agents affect\u00e9s<\/span><b>'+esc(agents)+'<\/b><\/div><div class=\"berf-registry-field\"><span>P\u00e9riode<\/span><b>'+esc(formatDate(found.start_date,false)+' \u2014 '+formatDate(found.end_date,false))+'<\/b><\/div><div class=\"berf-registry-field\"><span>Validation<\/span><b>'+esc(found.validator||'\u2014')+'<\/b><\/div><div class=\"berf-registry-field\"><span>Cl\u00f4ture<\/span><b>'+esc(formatDate(found.closed_at,true))+'<\/b><\/div><div class=\"berf-registry-field\"><span>\u00c9tat op\u00e9rationnel<\/span><b>'+(found.status==='active'?'Mission autoris\u00e9e':'Aucune ouverture d\u2019enqu\u00eate autoris\u00e9e')+'<\/b><\/div><\/div>'+log+pdf+'<\/article>';\n  }\n  button.addEventListener('click',search);input.addEventListener('keydown',e=>{if(e.key==='Enter')search();});result.addEventListener('click',e=>{const btn=e.target.closest('[data-registry-pdf]');if(!btn||!selectedOrder||!selectedOrder.document_url)return;const file={attachment_id:selectedOrder.document_id||0,id:'om-'+String(selectedOrder.reference||''),name:selectedOrder.document_name||('Ordre de mission '+selectedOrder.reference+'.pdf'),label:selectedOrder.document_name||('Ordre de mission '+selectedOrder.reference),type:'pdf',mime:'application\/pdf',url:selectedOrder.document_url};if(window.BERF_FILE_MANAGER&&window.BERF_FILE_MANAGER.openFile)window.BERF_FILE_MANAGER.openFile(file);else window.open(selectedOrder.document_url,'_blank','noopener');});\n})();\n<\/script>\n<\/link>\n\n    <script>\n      (function(){\n        const boot = window.BERFDB && window.BERFDB.BOOT;\n        if(!boot) return;\n        const data = boot.data || {};\n        const tri = data.triangulation || {};\n        const postits = data.postits || {};\n\n        \/\/ Tri rules + DB\n        try{\n          const ul = document.querySelector('#berfTriangulation77 .tri77__hint ul');\n          if(ul && Array.isArray((tri.notes && tri.notes.length) ? tri.notes : tri.rules)){\n            ul.innerHTML = '';\n            ((tri.notes && tri.notes.length) ? tri.notes : tri.rules).forEach(r=>{ const li=document.createElement('li'); li.innerHTML=String(r); ul.appendChild(li); });\n          }\n          window.BERF_TRI_DB = tri.numbers || {};\n          window.BERF_TRI_CASES = Array.isArray(tri.cases) ? tri.cases : [];\n          window.BERF_TRI_NOTES = Array.isArray(tri.notes) ? tri.notes : (Array.isArray(tri.rules) ? tri.rules : []);\n        }catch(e){ console.warn(e); }\n\n        \/\/ Seed post-its ONLY if player hasn't already created\/moved notes for this scenario\n        try{\n          const key = 'postit23_notes_v1';\n          const current = localStorage.getItem(key);\n          if(!current || current === '[]' || current === '{}' ){\n            localStorage.setItem(key, JSON.stringify((postits.seed||[]).map(p=>({\n              id:p.id, text:p.text, x:p.x, y:p.y, color:p.color||'#ffef7a'\n            }))));\n          }\n        }catch(e){ console.warn(e); }\n\n\n        \/\/ Dynamic file explorer from backend\n        try{\n          const filesRoot = document.getElementById('berfFilesTool');\n          const viewer = document.getElementById('media-viewer264');\n          const viewerContent = document.getElementById('media-content479');\n          const viewerClose = viewer ? viewer.querySelector('.close-btn193') : null;\n          const downloadBtn = document.getElementById('download-btn');\n          const passModal = document.getElementById('password-modal307');\n          const passInput = document.getElementById('password-input132');\n          const passValidate = passModal ? passModal.querySelector('[data-validate-password]') : null;\n          const passClose = passModal ? passModal.querySelector('.close-modal-btn') : null;\n\n          const filesSeed = (data.files && Array.isArray(data.files.seed)) ? data.files.seed : [];\n          const filesFront = [{\"id\":\"FD_BDG\",\"name\":\"La Bete du Gevaudan\",\"parent_id\":\"\",\"locked\":true,\"visible_at_start\":true,\"password\":\"CHASTEL\",\"error_message\":\"Mot de passe incorrect. Amaury aurait choisi un nom de famille.\",\"files\":[{\"id\":\"journal-sonore-notes-retranscrites\",\"name\":\"Journal sonore - notes retranscrites.txt\",\"label\":\"Journal sonore - notes retranscrites\",\"type\":\"text\",\"url\":\"\",\"content\":\"AUDIO 1 - Message a Verril\\n\\nHmmm... salut Verril. C'est moi, Amaury. J'ai decouvert des trucs etranges au sein de l'agence. Si je ne rappelle pas, commence par F713.\\n\\nAUDIO 2 - Etude de Paul\\n\\nLes Meneurs de loups. Des hommes qui auraient ete capables de commander les loups. Si Jean Chastel n'avait pas tue la Bete parce qu'il etait son complice ? Et s'il l'avait tuee parce qu'il avait compris qui la tenait en laisse ?\\n\\nAUDIO 3 - F713\\n\\nDecision de justice, 1803. Georges Melonie, condamne pour sorcellerie apres l'attaque d'un village. Trois loups enormes auraient obei a sa voix.\\n\\nAUDIO 4 - Disparition de F713\\n\\nF713 a disparu. Pas archive. Pas deplace. Supprime. Quelqu'un a vu ce que je consultais.\\n\\nAUDIO 5 - Empreinte de Mirandol\\n\\nUne seule empreinte. Enorme. Une habitante dit avoir vu un animal marcher sur deux pattes.\\n\\nAUDIO 6 - Meneurs de loups\\n\\nLes archives parlent aussi d'immortalite. Si Melonie etait un Meneur de loups, sa condamnation en 1803 n'est peut-etre pas la fin de son histoire.\"},{\"id\":\"etude-paul-meneurs-de-loups\",\"name\":\"Etude Paul - Meneurs de loups.txt\",\"label\":\"Etude Paul - Meneurs de loups\",\"type\":\"text\",\"url\":\"\",\"content\":\"Extrait : les Meneurs de loups seraient capables de commander des loups par la voix. Plusieurs recits du Gevaudan evoquent une Bete se comportant moins comme un animal sauvage que comme une arme dirigee.\"}]},{\"id\":\"FD_IDENTITE\",\"name\":\"Identite Amaury\",\"parent_id\":\"\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"arbre-genealogique-chastel\",\"name\":\"Arbre genealogique Chastel.txt\",\"label\":\"Arbre genealogique Chastel\",\"type\":\"text\",\"url\":\"\",\"content\":\"Amaury Delacroix apparait dans une branche descendante de la famille Chastel. Le nom Delacroix correspond au nom maternel utilise dans les dossiers du BERF.\"},{\"id\":\"incendie-de-marvejols-1993\",\"name\":\"Incendie de Marvejols - 1993.txt\",\"label\":\"Incendie de Marvejols - 1993\",\"type\":\"text\",\"url\":\"\",\"content\":\"Article local : la maison familiale Chastel a ete detruite par un incendie classe accident domestique. La famille a quitte la Lozere peu apres.\"}]},{\"id\":\"FD_CERCLE\",\"name\":\"Cercle des Douze\",\"parent_id\":\"\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"lettre-du-cercle-decryptee\",\"name\":\"Lettre du Cercle - decryptee.txt\",\"label\":\"Lettre du Cercle - decryptee\",\"type\":\"text\",\"url\":\"\",\"content\":\"Amaury,\\n\\nTu as passe ta vie a fuir un nom que nous n'avons jamais oublie.\\n\\nChastel.\\n\\nTon ancetre nous a trahis. Il a detruit ce qui devait ouvrir la voie et a offert au peuple un heros de circonstance.\\n\\nTu as trouve Melonie. Tu as trouve F713. Tu as trouve assez pour devenir dangereux.\\n\\nMais pas assez pour comprendre ou tu mettais les pieds.\\n\\nLe Cercle ne s'ouvre pas aux curieux.\\nIl se referme sur eux.\"}]},{\"id\":\"FD_FINAL\",\"name\":\"Fichier cache Amaury\",\"parent_id\":\"\",\"locked\":false,\"visible_at_start\":false,\"password\":\"\",\"error_message\":\"\",\"files\":[{\"id\":\"video-cachee-transcription\",\"name\":\"Video cachee - transcription.txt\",\"label\":\"Video cachee - transcription\",\"type\":\"text\",\"url\":\"\",\"content\":\"TRANSCRIPTION VIDEO CACHEE\\n\\nL'image tremble. Amaury est assis contre un mur de pierre. Son visage est pale, couvert de terre sechee. Un bandage sale lui recouvre l'oeil gauche.\\n\\nAmaury :\\nIls ont cru que je voulais prouver l'innocence de ma famille. Au debut, c'etait vrai.\\n\\nMaintenant, je veux autre chose.\\n\\nIls ont voulu m'enterrer avec leurs secrets.\\n\\nAlors je vais ouvrir les tombes.\"}]}] || [];\n          if(filesRoot){\n            filesRoot.innerHTML = `\n              <div id=\"file-explorer573\">\n                <div class=\"files-toolbar883\">\n                  <button class=\"files-navbtn883\" id=\"back-btn526\" type=\"button\" title=\"Retour\"><i class=\"fa-solid fa-arrow-left\"><\/i><\/button>\n                  <div class=\"files-toolbar-spacer883\"><\/div>\n                  <button class=\"files-lockbtn883\" id=\"files-lock-btn883\" style=\"display:none;\" type=\"button\">\n                    <i class=\"fa-solid fa-lock\"><\/i><span class=\"files-locktxt883\">Dossier verrouill\u00e9<\/span>\n                  <\/button>\n                <\/div>\n                <div id=\"folders-container928\"><\/div>\n                <div id=\"dynamic-folder-stage\"><\/div>\n              <\/div>\n              <div id=\"media-viewer264\" aria-hidden=\"true\">\n                <button type=\"button\" class=\"close-btn193\" aria-label=\"Fermer\">\u2715<\/button>\n                <div id=\"media-content479\"><button id=\"download-btn\" type=\"button\">T\u00e9l\u00e9charger<\/button><\/div>\n              <\/div>\n              <div id=\"password-modal307\" aria-hidden=\"true\">\n                <div class=\"modal-content874\">\n                  <button type=\"button\" class=\"close-modal-btn\" aria-label=\"Fermer\">\u2715<\/button>\n                  <p>Entrez le mot de passe :<\/p>\n                  <input id=\"password-input132\" type=\"password\" placeholder=\"Mot de passe\"\/>\n                  <button type=\"button\" data-validate-password>Valider<\/button>\n                <\/div>\n              <\/div>`;\n          }\n\n          const scopeF = document.getElementById('berfFilesTool');\n          if(!scopeF) return;\n          const foldersContainer = scopeF.querySelector('#folders-container928');\n          const stage = scopeF.querySelector('#dynamic-folder-stage');\n          const backBtn = scopeF.querySelector('#back-btn526');\n          const lockBtn = scopeF.querySelector('#files-lock-btn883');\n          const viewer2 = scopeF.querySelector('#media-viewer264');\n          const viewerContent2 = scopeF.querySelector('#media-content479');\n          const viewerClose2 = scopeF.querySelector('.close-btn193');\n          const downloadBtn2 = scopeF.querySelector('#download-btn');\n          const passModal2 = scopeF.querySelector('#password-modal307');\n          const passInput2 = scopeF.querySelector('#password-input132');\n          const passValidate2 = scopeF.querySelector('[data-validate-password]');\n          const passClose2 = scopeF.querySelector('.close-modal-btn');\n\n          let pendingFolder = null;\n          let currentFolder = null;\n\n          function iconFor(type){\n            switch(type){\n              case 'image': return 'fa-file-image';\n              case 'video': return 'fa-file-video';\n              case 'audio':\n              case 'mp3': return 'fa-file-audio';\n              case 'pdf': return 'fa-file-pdf';\n              default: return 'fa-file';\n            }\n          }\n\n          function closeViewer(){\n            if(viewer2){ viewer2.style.display='none'; viewer2.setAttribute('aria-hidden','true'); }\n            if(viewerContent2) viewerContent2.innerHTML = '<button id=\"download-btn\" type=\"button\">T\u00e9l\u00e9charger<\/button>';\n          }\n\n          function openMedia(file){\n            if(!viewer2 || !viewerContent2) return;\n            const url = file.url || '';\n            viewerContent2.innerHTML = '<button id=\"download-btn\" type=\"button\">T\u00e9l\u00e9charger<\/button>';\n            const btn = viewerContent2.querySelector('#download-btn');\n            if(btn) btn.onclick = ()=>{ if(url) window.open(url, '_blank'); };\n\n            let el = null;\n            if(file.type === 'image'){ el=document.createElement('img'); el.src=url; }\n            else if(file.type === 'video'){ el=document.createElement('video'); el.src=url; el.controls=true; }\n            else if(file.type === 'audio' || file.type === 'mp3'){ el=document.createElement('audio'); el.src=url; el.controls=true; }\n            else if(file.type === 'pdf'){ el=document.createElement('iframe'); el.src=url; }\n            if(el) viewerContent2.appendChild(el);\n            viewer2.style.display='flex'; viewer2.setAttribute('aria-hidden','false');\n          }\n\n          function renderFolder(folder){\n            currentFolder = folder;\n            foldersContainer.style.display='none';\n            stage.innerHTML='';\n            const content = document.createElement('div');\n            content.className='folder-content412';\n            content.style.display='flex';\n            content.style.flexWrap='wrap';\n            content.style.gap='14px';\n            (folder.files||[]).forEach(file=>{\n              const item = document.createElement('div');\n              item.className='file-thumb895';\n              item.innerHTML = `<i class=\"fa-solid ${iconFor(file.type)}\"><\/i><span>${file.label || file.name || 'Fichier'}<\/span>`;\n              item.addEventListener('click', ()=> openMedia(file));\n              content.appendChild(item);\n            });\n            stage.appendChild(content);\n            backBtn.style.display='inline-flex';\n            lockBtn.style.display = folder.locked ? 'inline-flex' : 'none';\n          }\n\n          function renderFolders(){\n            foldersContainer.innerHTML='';\n            stage.innerHTML='';\n            foldersContainer.style.display='grid';\n            foldersContainer.style.gridTemplateColumns='repeat(auto-fill,minmax(160px,1fr))';\n            foldersContainer.style.gap='14px';\n            (filesFront||[]).forEach(folder=>{\n              const item=document.createElement('div');\n              item.className='folder751';\n              item.innerHTML=`<i class=\"fa-solid fa-folder${folder.locked ? '-closed' : ''}\"><\/i><span>${folder.name || 'Dossier'}<\/span>`;\n              item.addEventListener('click', ()=>{\n                if(folder.locked){\n                  pendingFolder=folder;\n                  passInput2.value='';\n                  passModal2.style.display='flex';\n                  passModal2.setAttribute('aria-hidden','false');\n                } else {\n                  renderFolder(folder);\n                }\n              });\n              foldersContainer.appendChild(item);\n            });\n            backBtn.style.display='none';\n            lockBtn.style.display='none';\n            currentFolder = null;\n          }\n\n          backBtn && backBtn.addEventListener('click', renderFolders);\n          viewerClose2 && viewerClose2.addEventListener('click', closeViewer);\n          viewer2 && viewer2.addEventListener('click', (e)=>{ if(e.target===viewer2) closeViewer(); });\n          passClose2 && passClose2.addEventListener('click', ()=>{ passModal2.style.display='none'; passModal2.setAttribute('aria-hidden','true'); pendingFolder=null; });\n          passModal2 && passModal2.addEventListener('click', (e)=>{ if(e.target===passModal2){ passModal2.style.display='none'; passModal2.setAttribute('aria-hidden','true'); pendingFolder=null; }});\n          passValidate2 && passValidate2.addEventListener('click', ()=>{\n            if(!pendingFolder) return;\n            if((passInput2.value || '') === (pendingFolder.password || '')){\n              passModal2.style.display='none'; passModal2.setAttribute('aria-hidden','true');\n              renderFolder(pendingFolder);\n              pendingFolder = null;\n            } else {\n              alert(pendingFolder.error_message || 'Mot de passe incorrect.');\n            }\n          });\n          passInput2 && passInput2.addEventListener('keydown', (e)=>{ if(e.key==='Enter' && passValidate2) passValidate2.click(); });\n\n          renderFolders();\n        }catch(e){ console.warn(e); }\n\n        \/\/ Seed agenda ONLY if player has no scenario-specific appointments yet\n        try{\n          const agendaSeed = [{\"id\":\"AG_PAUL\",\"title\":\"Appel Paul - etude Gevaudan\",\"date\":\"2026-05-10T14:00\",\"note\":\"Paul signale un passage sur les Meneurs de loups.\",\"visible_at_start\":true},{\"id\":\"AG_MIRANDOL\",\"title\":\"Analyse empreinte\",\"date\":\"2026-05-11T18:30\",\"note\":\"Mirandol. Releve photo + mesures envoyees a Elena.\",\"visible_at_start\":true},{\"id\":\"AG_F713\",\"title\":\"Consultation archives F713\",\"date\":\"2026-05-12T09:00\",\"note\":\"Decision de justice de 1803. Georges Melonie.\",\"visible_at_start\":true}] || [];\n          const key = 'berf_agenda_appointments_v1';\n          const current = localStorage.getItem(key);\n          if((!current || current === '[]' || current === '{}') && Array.isArray(agendaSeed)){\n            localStorage.setItem(key, JSON.stringify(agendaSeed.map(a=>({\n              title: a.title || '',\n              date: a.date || '',\n              note: a.note || '',\n              id: a.id || ''\n            }))));\n          }\n        }catch(e){ console.warn(e); }\n\n        \/\/ Drone tool init\n        try{\n          const cfg = (window.BERFDB && window.BERFDB.DRONE) ? window.BERFDB.DRONE : null;\n          const root = document.getElementById('berfDroneTool');\n          const berfDroneJsLog = (label, payload)=>{\n            try{\n              console.log('[BERF DRONE DEBUG]', label, payload);\n              if(window.BERFDB && window.BERFDB.DRONE_DEBUG_ENDPOINT){\n                const body = new URLSearchParams();\n                body.append('action', 'berfdb_drone_debug');\n                body.append('nonce', window.BERFDB.DRONE_DEBUG_NONCE || '');\n                body.append('label', String(label || ''));\n                body.append('payload', JSON.stringify(payload || {}));\n                fetch(window.BERFDB.DRONE_DEBUG_ENDPOINT, {\n                  method: 'POST',\n                  headers: {'Content-Type': 'application\/x-www-form-urlencoded; charset=UTF-8'},\n                  body: body.toString(),\n                  credentials: 'same-origin'\n                }).catch(()=>{});\n              }\n            }catch(_e){}\n          };\n          berfDroneJsLog('init_check', {rootExists: !!root, hasCfg: !!cfg, alreadyBound: !!(root && root.dataset.droneBound === '1')});\n          if(root && cfg && root.dataset.droneBound !== '1'){\n            root.dataset.droneBound = '1';\n            const codeInput = root.querySelector('[data-drone-code]');\n            const unlockBtn = root.querySelector('[data-drone-unlock]');\n            const statusEl = root.querySelector('[data-drone-status]');\n            const feed = root.querySelector('[data-drone-feed]');\n            const noteEl = root.querySelector('[data-drone-notes]');\n            const badge = root.querySelector('[data-drone-badge]');\n            const titleEl = root.querySelector('[data-drone-title]');\n            const ts = root.querySelector('[data-drone-ts]');\n            const hud = root.querySelector('[data-drone-hud]');\n            const closeMedia = ()=>{ if(feed) feed.innerHTML=''; };\n            const setMessage = (html)=>{ if(feed) feed.innerHTML = html; };\n            const setStatus = (s)=>{\n              const map = {offline:'Hors ligne', unstable:'Signal instable', online:'Connect\u00e9'};\n              const safeState = map[s] ? s : 'offline';\n              if(statusEl) statusEl.textContent = map[safeState];\n              if(badge){ badge.setAttribute('data-state', safeState); badge.textContent = map[safeState]; }\n            };\n            const tick = ()=>{ if(ts && cfg.showTimestamp){ ts.textContent = new Date().toLocaleString('fr-FR'); } };\n            tick();\n            setInterval(tick, 1000);\n            if(titleEl) titleEl.textContent = cfg.title || 'Module drone';\n            if(noteEl) noteEl.textContent = cfg.notes || 'Aucun briefing renseign\u00e9 pour ce module.';\n            if(hud) hud.style.display = cfg.showHud ? 'flex' : 'none';\n            if(ts) ts.style.display = cfg.showTimestamp ? '' : 'none';\n            setStatus(cfg.status || 'offline');\n            berfDroneJsLog('init_bound', {cfg: cfg});\n\n            const getSimulatedMedia = ()=>{\n              if(cfg.simulatedMedia && cfg.simulatedMedia.url) return cfg.simulatedMedia;\n              if(cfg.simulatedMediaUrl){\n                return {\n                  url: cfg.simulatedMediaUrl,\n                  name: cfg.simulatedMediaType === 'video' ? 'Vid\u00e9o simul\u00e9e' : 'Image simul\u00e9e',\n                  type: cfg.simulatedMediaType || 'image'\n                };\n              }\n              return null;\n            };\n\n            const renderFeed = ()=>{\n              berfDroneJsLog('renderFeed_start', {sourceMode: cfg.sourceMode, liveStreamType: cfg.liveStreamType, liveStreamUrl: cfg.liveStreamUrl, simulatedMediaType: cfg.simulatedMediaType, simulatedMediaUrl: cfg.simulatedMediaUrl, simulatedMedia: cfg.simulatedMedia});\n              closeMedia();\n              if(!feed) return;\n              if(cfg.sourceMode === 'live'){\n                const url = String(cfg.liveStreamUrl || '').trim();\n                if(!url){ berfDroneJsLog('renderFeed_live_missing_url', cfg); setMessage('<div class=\"berf-drone-empty\">Aucun flux r\u00e9el configur\u00e9.<\/div>'); setStatus('offline'); return; }\n                if(cfg.liveStreamType === 'iframe'){\n                  const iframe = document.createElement('iframe');\n                  iframe.src = url;\n                  iframe.allow = 'autoplay; fullscreen';\n                  iframe.setAttribute('allowfullscreen','allowfullscreen');\n                  feed.appendChild(iframe);\n                }else{\n                  const video = document.createElement('video');\n                  video.controls = true;\n                  video.autoplay = !!cfg.autoplay;\n                  video.loop = !!cfg.loop;\n                  video.muted = !!cfg.autoplay;\n                  video.playsInline = true;\n                  video.src = url;\n                  video.addEventListener('error', ()=>{\n                    setMessage(\"<div class='berf-drone-empty'>Impossible de lire ce flux. V\u00e9rifie l\u2019URL ou le format.<\/div>\");\n                    setStatus('offline');\n                  });\n                  feed.appendChild(video);\n                  const playPromise = video.play && video.play();\n                  if(playPromise && typeof playPromise.catch === 'function') playPromise.catch(()=>{});\n                }\n                berfDroneJsLog('renderFeed_live_success', {url: url, type: cfg.liveStreamType});\n                setStatus('online');\n                return;\n              }\n\n              const media = getSimulatedMedia();\n              if(!media || !media.url){\n                berfDroneJsLog('renderFeed_simulated_missing_media', {media: media, cfg: cfg});\n                setMessage('<div class=\"berf-drone-empty\">Aucun m\u00e9dia simul\u00e9 configur\u00e9.<\/div>');\n                setStatus('offline');\n                return;\n              }\n\n              if((cfg.simulatedMediaType === 'video') || media.type === 'video'){\n                const video = document.createElement('video');\n                video.src = media.url;\n                video.controls = true;\n                video.autoplay = !!cfg.autoplay;\n                video.loop = !!cfg.loop;\n                video.muted = !!cfg.autoplay;\n                video.playsInline = true;\n                video.addEventListener('error', ()=>{\n                  setMessage('<div class=\"berf-drone-empty\">Impossible de lire cette vid\u00e9o simul\u00e9e.<\/div>');\n                  setStatus('offline');\n                });\n                feed.appendChild(video);\n                const playPromise = video.play && video.play();\n                if(playPromise && typeof playPromise.catch === 'function') playPromise.catch(()=>{});\n              }else{\n                const img = document.createElement('img');\n                img.src = media.url;\n                img.alt = media.name || 'Flux simul\u00e9';\n                img.addEventListener('error', ()=>{\n                  setMessage('<div class=\"berf-drone-empty\">Impossible de charger cette image simul\u00e9e.<\/div>');\n                  setStatus('offline');\n                });\n                feed.appendChild(img);\n              }\n              berfDroneJsLog('renderFeed_simulated_success', {media: media, finalStatus: (cfg.status === 'offline' ? 'online' : (cfg.status || 'online'))});\n              setStatus(cfg.status === 'offline' ? 'online' : (cfg.status || 'online'));\n            };\n\n            const unlock = ()=>{\n              berfDroneJsLog('unlock_clicked', {entered: String((codeInput && codeInput.value) || ''), expectedConfigured: !!String(cfg.accessCode || '').trim()});\n              const expected = String(cfg.accessCode || '').trim();\n              const entered = String((codeInput && codeInput.value) || '').trim();\n              const normalize = (v)=> String(v || '').trim().toUpperCase();\n              if(normalize(expected) && normalize(entered) !== normalize(expected)){\n                berfDroneJsLog('unlock_invalid_code', {entered: entered, expected: expected});\n                setStatus('offline');\n                setMessage(\"<div class='berf-drone-empty'>Code d\u2019acc\u00e8s invalide.<\/div>\");\n                return;\n              }\n              setStatus('unstable');\n              setMessage('<div class=\"berf-drone-empty\">Connexion au flux en cours\u2026<\/div>');\n              berfDroneJsLog('unlock_valid_code', {entered: entered, expected: expected});\n              window.setTimeout(renderFeed, 180);\n            };\n\n            if(unlockBtn){\n              unlockBtn.addEventListener('click', unlock);\n              berfDroneJsLog('bind_click_ok', {hasButton: true});\n            }\n            if(codeInput){\n              berfDroneJsLog('bind_input_ok', {hasInput: true});\n              codeInput.addEventListener('keydown', (e)=>{\n                if(e.key === 'Enter'){\n                  e.preventDefault();\n                  unlock();\n                }\n              });\n            }\n          }\n        }catch(e){ console.warn('BERF drone init error', e); try{ if(typeof berfDroneJsLog==='function'){ berfDroneJsLog('init_exception', {message: e && e.message ? e.message : String(e), stack: e && e.stack ? e.stack : ''}); } }catch(_e){} }\n      })();\n    <\/script>\n  <\/div>\n  \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-141","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/pages\/141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/comments?post=141"}],"version-history":[{"count":1,"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/pages\/141\/revisions"}],"predecessor-version":[{"id":143,"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/pages\/141\/revisions\/143"}],"wp:attachment":[{"href":"https:\/\/berf.lultime-frisson.com\/index.php\/wp-json\/wp\/v2\/media?parent=141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}