| <!DOCTYPE html> |
| <html lang="fr"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <title>Portail Réglementation UE – Complet & Responsive</title> |
| <style> |
| :root{ |
| --bg-main: #f8fafc; |
| --bg-panel: #ffffff; |
| --bg-side: #f1f5f9; |
| --text-primary: #0f172a; |
| --text-secondary: #475569; |
| --text-light: #64748b; |
| --line: #e2e8f0; |
| --accent-blue: #2563eb; |
| --accent-blue-light: #eff6ff; |
| --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; |
| } |
| *, *::before, *::after { box-sizing: border-box; } |
| |
| html { scroll-behavior: smooth; } |
| body{ |
| margin:0; |
| font-family: var(--font-sans); |
| background: var(--bg-main); |
| color: var(--text-primary); |
| display: grid; |
| grid-template-columns: 340px 1fr; |
| height: 100vh; |
| overflow: hidden; |
| } |
| |
| |
| aside{ |
| background: var(--bg-side); |
| border-right: 1px solid var(--line); |
| display: flex; |
| flex-direction: column; |
| height: 100vh; |
| transition: transform 0.3s ease-in-out; |
| flex-shrink: 0; |
| } |
| .aside-header { padding: 16px 20px; } |
| .brand { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 16px; } |
| .brand h1 { font-size: 22px; margin: 0; } |
| .search { position: relative; margin-bottom: 16px; } |
| .search input, #theme-filter { |
| all: unset; box-sizing: border-box; |
| width: 100%; |
| background: var(--bg-panel); |
| border: 1px solid var(--line); |
| border-radius: 8px; |
| padding: 10px 12px; |
| font-size: 14px; |
| -webkit-appearance: none; |
| -moz-appearance: none; |
| appearance: none; |
| } |
| #theme-filter { |
| background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20d%3D%22M5%208l5%205%205-5H5z%22%20fill%3D%22%2364748b%22/%3E%3C/svg%3E'); |
| background-repeat: no-repeat; |
| background-position: right 8px center; |
| background-size: 1.2em; |
| padding-right: 2.5em; |
| cursor: pointer; |
| } |
| .search input { padding-left: 36px; } |
| .search-icon { position: absolute; top: 11px; left: 12px; color: var(--text-light); } |
| label { font-size: 13px; font-weight: 600; color: var(--text-secondary); display: block; margin-bottom: 6px; } |
| |
| .menu-container { |
| flex: 1; |
| overflow-y: auto; |
| padding: 0 12px 20px 20px; |
| } |
| nav { display: flex; flex-direction: column; gap: 6px; } |
| .item { |
| display: block; |
| padding: 12px 14px; |
| border-radius: 8px; |
| cursor: pointer; |
| border: 1px solid transparent; |
| transition: background-color 0.2s ease, border-color 0.2s ease; |
| } |
| .item:hover { background: #e9eef5; } |
| .item.active { |
| background: var(--bg-panel); |
| border-color: var(--line); |
| box-shadow: 0 1px 2px rgba(0,0,0,0.05); |
| } |
| .item-header { display:flex; justify-content: space-between; align-items: flex-start; gap: 8px; } |
| .item h4 { margin: 0; font-size: 15px; line-height: 1.5; color: var(--text-primary); } |
| .item code { font-size: 11px; color: var(--text-secondary); background: #e0e7ee; padding: 2px 5px; border-radius: 4px; flex-shrink: 0;} |
| .item .badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; } |
| .badge { font-size: 10px; font-weight: 500; padding: 4px 8px; border-radius: 6px; background: #e0e7ee; } |
| .aside-footer { padding: 16px 20px; border-top: 1px solid var(--line); font-size: 12px; color: var(--text-light); } |
| |
| |
| main { |
| display: flex; |
| flex-direction: column; |
| height: 100vh; |
| } |
| .main-header { |
| padding: 12px 24px; |
| background: var(--bg-panel); |
| border-bottom: 1px solid var(--line); |
| flex-shrink: 0; |
| display: flex; |
| align-items: center; |
| gap: 16px; |
| } |
| .main-header h2 { margin: 0; font-size: 24px; line-height: 1.2; } |
| .main-header .meta { display: flex; flex-wrap: wrap; gap: 12px; color: var(--text-light); font-size: 13px; margin-top: 4px; } |
| |
| .content-nav { |
| position: sticky; top: 0; |
| background: rgba(255, 255, 255, 0.85); |
| backdrop-filter: blur(8px); |
| -webkit-backdrop-filter: blur(8px); |
| border-bottom: 1px solid var(--line); |
| padding: 0 24px; |
| z-index: 10; |
| flex-shrink: 0; |
| } |
| .content-nav-links { display: flex; gap: 4px; } |
| .content-nav a { |
| color: var(--text-secondary); |
| text-decoration: none; |
| padding: 14px 12px; |
| font-size: 14px; |
| font-weight: 600; |
| border-bottom: 2px solid transparent; |
| transition: color 0.2s ease, border-color 0.2s ease; |
| cursor: pointer; |
| } |
| .content-nav a:hover { color: var(--text-primary); } |
| .content-nav a.active { |
| color: var(--accent-blue); |
| border-bottom-color: var(--accent-blue); |
| } |
| |
| .content-wrapper { |
| flex: 1; |
| overflow-y: auto; |
| padding: 32px; |
| } |
| .content-section { |
| padding-top: 16px; |
| margin-bottom: 32px; |
| } |
| .content-section > h3 { |
| font-size: 22px; |
| color: var(--text-primary); |
| margin: 0 0 20px 0; |
| display: flex; align-items: center; gap: 10px; |
| padding-bottom: 10px; |
| border-bottom: 1px solid var(--line); |
| } |
| .card { |
| background: var(--bg-panel); |
| border: 1px solid var(--line); |
| border-radius: 12px; |
| padding: 24px; |
| margin-bottom: 16px; |
| box-shadow: 0 1px 2px rgba(15, 23, 42, 0.03); |
| } |
| .card h4 { margin: 0 0 12px; font-size: 18px; } |
| .card ul { margin: 0; padding-left: 20px; font-size: 16px; line-height: 1.7; } |
| .card li { margin-bottom: 10px; } |
| .btn-link { |
| display: inline-flex; align-items: center; gap: 8px; text-decoration: none; color: var(--accent-blue); |
| background: var(--accent-blue-light); border: 1px solid var(--accent-blue-light); |
| padding: 10px 14px; border-radius: 8px; font-size: 14px; font-weight: 600; |
| } |
| .links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; } |
| |
| |
| #menu-toggle, #menu-close { |
| display: none; |
| background: none; border: none; font-size: 20px; color: var(--text-secondary); cursor: pointer; padding: 4px; |
| } |
| #overlay { |
| display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 99; |
| } |
| |
| |
| @media (max-width: 1024px) { |
| body { grid-template-columns: 1fr; } |
| aside { |
| position: fixed; |
| top: 0; left: 0; z-index: 100; |
| transform: translateX(-100%); |
| width: 320px; |
| box-shadow: 0 0 40px rgba(0,0,0,0.1); |
| } |
| aside.open { transform: translateX(0); } |
| #menu-toggle, #menu-close { display: inline-block; } |
| .content-wrapper { padding: 24px 16px; } |
| .main-header h2 { font-size: 20px; } |
| .content-section > h3 { font-size: 20px; } |
| .card { padding: 16px; } |
| .card h4 { font-size: 16px; } |
| .card ul { font-size: 15px; } |
| } |
| </style> |
| </head> |
| <body> |
| <div id="overlay"></div> |
|
|
| |
| <aside id="sidebar"> |
| <div class="aside-header"> |
| <div class="brand"> |
| <h1>Réglementation UE</h1> |
| <button id="menu-close" aria-label="Fermer le menu">×</button> |
| </div> |
| <div class="search"> |
| <svg class="search-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path fill-rule="evenodd" d="M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z" clip-rule="evenodd"/></svg> |
| <input id="q" placeholder="Rechercher un texte..." aria-label="Rechercher"/> |
| </div> |
| <div> |
| <label for="theme-filter">Filtrer par thème</label> |
| <select id="theme-filter"></select> |
| </div> |
| </div> |
| |
| <div class="menu-container"> |
| <nav id="menu" aria-label="Liste des textes"></nav> |
| </div> |
|
|
| <div class="aside-footer"> |
| Outil de consultation. Source : EUR-Lex. |
| </div> |
| </aside> |
|
|
| |
| <main> |
| <div class="main-header" role="banner"> |
| <button id="menu-toggle" aria-label="Ouvrir le menu"> |
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 12H21M3 6H21M3 18H21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> |
| </button> |
| <div> |
| <h2 id="title">Sélectionnez un texte pour commencer</h2> |
| <div class="meta" id="meta"></div> |
| </div> |
| </div> |
|
|
| <div class="content-nav"> |
| <div class="content-nav-links" id="content-nav-links"> |
| <a data-target="s-resume" class="active">Résumé & Portée</a> |
| <a data-target="s-exigences">Exigences & Audit</a> |
| <a data-target="s-refs">Références</a> |
| </div> |
| </div> |
|
|
| <div class="content-wrapper" id="content-wrapper"> |
| |
| </div> |
| </main> |
| |
| <script> |
| /** =================== Données (Exhaustives, inspirées de votre fichier) =================== **/ |
| const DATA = [ |
| /* ---- Cadre + Hygiène + Contrôles ---- */ |
| { |
| id:"178/2002", |
| titre:"Règlement (CE) n° 178/2002 – Principes généraux (Food Law)", |
| celex:"02002R0178", |
| categorie:["Cadre général","Traçabilité","Rappel/Retrait"], |
| statut:"V", |
| maj:"2022-07-01", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02002R0178-20220701"}], |
| resume:[ |
| "Analyse des risques, précaution, transparence; responsabilité première des exploitants.", |
| "Obligation de traçabilité ‘un pas en arrière/avant’ et de retrait/rappel si risque.", |
| "EFSA & RASFF pour l’évaluation/alerte rapide." |
| ], |
| exigences:[ |
| "Procédure documentée de gestion d’incident: détection, évaluation, retrait/rappel, notification autorités.", |
| "Traçabilité amont/aval opérationnelle (<4h pour fournir les infos pendant contrôle)." |
| ], |
| audit:[ |
| "Tester un scénario de retrait/rappel (exercice) avec délais et preuves.", |
| "Échantillon traçabilité: lot amont puis aval; mesure du temps d’obtention." |
| ], |
| maj_points:[ "Harmonisé avec 2017/625 pour les contrôles officiels." ] |
| }, |
| { |
| id:"852/2004", |
| titre:"Règlement (CE) n° 852/2004 – Hygiène des denrées", |
| celex:"02004R0852", |
| categorie:["Hygiène","PRP","HACCP"], |
| statut:"V", |
| maj:"2021-03-24", |
| liens:[ |
| {label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02004R0852-20210324"}, |
| {label:"Communication 2022/C 355/01 (HACCP)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:52022XC0916(01)"} |
| ], |
| resume:[ |
| "PRP/BPH obligatoires: locaux, équipements, hygiène du personnel, eau, nettoyage, nuisibles, déchets, etc.", |
| "Procédures HACCP proportionnées aux risques; flexibilité possible selon activités." |
| ], |
| exigences:[ |
| "Validation des mesures de maîtrise (température, temps, nettoyabilité, allergènes).", |
| "Programme de prérequis documenté (plans, fréquences, vérifications)." |
| ], |
| audit:[ |
| "Revue des PRP, tendances (analyses environnementales, efficacité nettoyage).", |
| "Preuves de validation HACCP & revalidation suite à changements." |
| ], |
| maj_points:[ "Guidances 2016/2022 sur flexibilité et mise en œuvre pratique." ] |
| }, |
| { |
| id:"2017/625", |
| titre:"Règlement (UE) 2017/625 – Contrôles officiels", |
| celex:"02017R0625", |
| categorie:["Contrôles officiels","Fraude","Import"], |
| statut:"V", |
| maj:"2022-01-28", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02017R0625-20220128"}], |
| resume:[ |
| "Cadre intégré pour les contrôles officiels; approche basée sur les risques et lutte anti‑fraude.", |
| "Règles d’import en PCF; transparence des résultats agrégés." |
| ], |
| exigences:[ |
| "Disponibilité des documents/accès; coopération avec l’autorité compétente.", |
| "Respect des exigences d’import (documents, certificats)." |
| ], |
| audit:[ "Vérifier préparation dossier contrôle et conformité PCF pour importateurs." ], |
| maj_points:[ "Complété par 2019/624 (viandes, bivalves)." ] |
| }, |
| { |
| id:"2073/2005", |
| titre:"Règlement (CE) n° 2073/2005 – Critères microbiologiques", |
| celex:"02005R2073", |
| categorie:["Microbiologie","Vérification","HACCP"], |
| statut:"V", |
| maj:"2020-03-08", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02005R2073-20200308"}], |
| resume:[ |
| "Critères de sécurité vs d’hygiène des procédés; plans d’échantillonnage (n, c, m, M).", |
| "Gestion: retrait/rappel pour critères de sécurité; corrections process pour hygiène." |
| ], |
| exigences:[ |
| "Listeria monocytogenes dans PAM: < 100 ufc/g pendant DLC si croissance contrôlée; 0 ufc/25 g avant sortie si croissance possible.", |
| "Plan d’échantillonnage défini (n, c, m, M) et méthodes normalisées (ISO)." |
| ], |
| audit:[ |
| "Vérifier matrices/critères applicables; tendances; revalidation si dérive.", |
| "Challenge-tests/études de croissance si nécessaire pour PAM." |
| ], |
| maj_points:[ "Suivre mises à jour annexes et avis EFSA." ] |
| }, |
| { |
| id:"2023/915", |
| titre:"Règlement (UE) 2023/915 – Contaminants (refonte)", |
| celex:"32023R0915", |
| categorie:["Contaminants","ALARA"], |
| statut:"V", |
| maj:"2023-05-05", |
| liens:[{label:"EUR‑Lex (texte)", url:"https://eur-lex.europa.eu/legal-content/fr/TXT/?uri=CELEX:32023R0915"}], |
| resume:[ |
| "Refonte des teneurs maximales (mycotoxines, métaux lourds, dioxines/PCB, PAH, HCAs…).", |
| "Principe ALARA; 1881/2006 abrogé." |
| ], |
| exigences:[ |
| "Plans de contrôle ciblés; méthodes conformes aux règlements d’échantillonnage (ex. 333/2007).", |
| "Gestion stricte des non‑conformités (blocage/retrait; pas de décontamination chimique)." |
| ], |
| audit:[ |
| "Vérifier matrice de risques contaminants + fréquences/LOQ.", |
| "Preuves de conformité laboratoire (accréditation ISO 17025)." |
| ], |
| maj_points:[ "Entrée en application 25/05/2023; mises à jour ciblées possibles." ] |
| }, |
| { |
| id:"333/2007", |
| titre:"Règlement (CE) n° 333/2007 – Échantillonnage/méthodes contaminants", |
| celex:"02007R0333", |
| categorie:["Méthodes","Contaminants"], |
| statut:"V", |
| maj:"2023-01-01", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02007R0333-20230101"}], |
| resume:[ |
| "Plans de prélèvement officiels et critères de performance analytiques (r, RSD, LOQ, MU)." |
| ], |
| exigences:[ |
| "Respect des schémas d’échantillonnage par lot/taille; homogénéisation; conservation.", |
| "Validation méthode (trueness, precision, recovery) et incertitude mesurée." |
| ], |
| audit:[ "Vérifier SOP d’échantillonnage et rapports d’aptitude (PT)." ], |
| maj_points:[ ] |
| }, |
| { |
| id:"1935/2004", |
| titre:"Règlement (CE) n° 1935/2004 – Matériaux au contact (FCM)", |
| celex:"02004R1935", |
| categorie:["FCM","Traçabilité","Déclaration de conformité"], |
| statut:"V", |
| maj:"2021-03-27", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02004R1935-20210327"}], |
| resume:[ |
| "Principe d’inertie; pas de transfert compromettant la sécurité, la composition ou l’odeur/goût.", |
| "Déclaration de conformité (DoC), traçabilité FCM, identification ‘verre & fourchette’." |
| ], |
| exigences:[ |
| "Dossier technique (DoC, migrations globale/spécifique, NIAS le cas échéant).", |
| "BPF obligatoires (2023/2006) couvrant toute la fabrication." |
| ], |
| audit:[ |
| "Vérifier DoC + rapports d’essais; contrôle fournisseurs/matériaux.", |
| "Validation nettoyage et usage prévu." |
| ], |
| maj_points:[ "Interactions avec 10/2011 (plastiques) et 2022/1616 (recyclés)." ] |
| }, |
| { |
| id:"10/2011", |
| titre:"Règlement (UE) n° 10/2011 – Plastiques FCM", |
| celex:"02011R0010", |
| categorie:["FCM","Plastiques"], |
| statut:"V", |
| maj:"2023-08-01", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02011R0010-20230801"}], |
| resume:[ |
| "Listes d’Union des substances autorisées (monomères, additifs) + SML/OML.", |
| "Règles d’essai/migration et scénarios de contact/temps/température." |
| ], |
| exigences:[ |
| "Conformité formulation vs Union list; SML/OML respectées; évaluation NIAS.", |
| "DoC détaillée avec simulations/essais et conditions d’usage." |
| ], |
| audit:[ "Contrôle fournisseurs, traçabilité formulations, essais tiers." ], |
| maj_points:[ "Mises à jour régulières des annexes (vérifier la dernière version)." ] |
| }, |
| { |
| id:"2022/1616", |
| titre:"Règlement (UE) 2022/1616 – Plastiques recyclés FCM", |
| celex:"02022R1616", |
| categorie:["FCM","Plastiques","Recyclage"], |
| statut:"V", |
| maj:"2022-09-20", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02022R1616-20220920"}], |
| resume:[ |
| "Autorisation des procédés de recyclage; maîtrise contamination; traçabilité chaîne.", |
| "Challenge-tests pour démontrer la décontamination." |
| ], |
| exigences:[ |
| "Utiliser seulement des procédés autorisés; documentation/contrôles spécifiques.", |
| "Contrat de qualité amont/aval; traçabilité des intrants." |
| ], |
| audit:[ "Vérifier statut d’autorisation du procédé; preuves opérationnelles." ], |
| maj_points:[ "Remplace 282/2008; période de transition." ] |
| }, |
| { |
| id:"2023/2006", |
| titre:"Règlement (CE) n° 2023/2006 – BPF FCM", |
| celex:"02006R2023", |
| categorie:["FCM","BPF"], |
| statut:"V", |
| maj:"2008-04-17", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006R2023-20080417"}], |
| resume:[ "BPF obligatoires pour la fabrication des FCM; système qualité documenté." ], |
| exigences:[ "Procédures, enregistrements, maîtrise des changements, traçabilité lot." ], |
| audit:[ "Vérifier conformité du système qualité BPF et preuves de formation." ], |
| maj_points:[ ] |
| }, |
| { |
| id:"450/2009", |
| titre:"Règlement (CE) n° 450/2009 – Matériaux actifs/intelligents", |
| celex:"02009R0450", |
| categorie:["FCM","Actifs/Intelligents"], |
| statut:"V", |
| maj:"2019-12-09", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02009R0450-20191209"}], |
| resume:[ |
| "Cadre spécifique pour matériaux/objets actifs et intelligents (MOAI) au contact.", |
| "Substances libérées/adsorbées: conformité substances autorisées et OML/SML." |
| ], |
| exigences:[ |
| "Étiquetage spécifique (‘actif/intelligent’), information sur fonction; pas de mise en danger du consommateur.", |
| "Substances actives/intelligentes sur liste autorisée; migration sous contrôle." |
| ], |
| audit:[ |
| "Vérifier autorisation substances actives; scénarios d’usage; conformité migration." |
| ], |
| maj_points:[ "Coordination avec 1935/2004 et mesures spécifiques (ex. 10/2011 si plastique)." ] |
| }, |
| { |
| id:"1829/2003", |
| titre:"Règlement (CE) n° 1829/2003 – Denrées & aliments pour animaux génétiquement modifiés", |
| celex:"02003R1829", |
| categorie:["OGM","Autorisation","Étiquetage"], |
| statut:"V", |
| maj:"2019-07-26", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02003R1829-20190726"}], |
| resume:[ |
| "Procédure d’autorisation centralisée des OGM/produits OGM pour l’alimentation humaine/animale.", |
| "Exigences d’étiquetage des denrées contenant/consistant en OGM ou produites à partir d’OGM." |
| ], |
| exigences:[ |
| "Pas de mise sur le marché sans autorisation; conditions d’utilisation et suivi post‑market si requis.", |
| "Étiquetage obligatoire; exemptions possibles si présence fortuite/techniquement inévitable ≤ 0,9 %." |
| ], |
| audit:[ |
| "Vérifier statut d’autorisation des ingrédients/produits; preuves fournisseurs.", |
| "Contrôler l’étiquetage et la maîtrise des contaminations croisées." |
| ], |
| maj_points:[ ] |
| }, |
| { |
| id:"1830/2003", |
| titre:"Règlement (CE) n° 1830/2003 – Traçabilité & étiquetage OGM", |
| celex:"02003R1830", |
| categorie:["OGM","Traçabilité","Étiquetage"], |
| statut:"V", |
| maj:"2014-04-09", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02003R1830-20140409"}], |
| resume:[ |
| "Traçabilité des OGM et des denrées produites à partir d’OGM tout au long de la chaîne.", |
| "Obligations d’identification (codes uniques), documents à transmettre opérateur→opérateur." |
| ], |
| exigences:[ |
| "Transmission des informations obligatoires à chaque étape; conservation ≥ 5 ans.", |
| "Seuil d’étiquetage 0,9 % pour présence fortuite/techniquement inévitable." |
| ], |
| audit:[ "Vérifier flux d’information OGM (réceptions, ventes) et archivage 5 ans." ], |
| maj_points:[ ] |
| }, |
| { |
| id:"1169/2011", |
| titre:"Règlement (UE) n° 1169/2011 – Information consommateurs (INCO)", |
| celex:"02011R1169", |
| categorie:["Étiquetage","Allergènes","Nutrition"], |
| statut:"V", |
| maj:"2018-01-01", |
| liens:[ |
| {label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02011R1169-20180101"}, |
| {label:"2018/775 – ingrédient primaire", url:"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02018R0775-20190609"} |
| ], |
| resume:[ |
| "Mentions obligatoires (dénomination, ingrédients, allergènes, QUID, DLC/DDM, lot, nutrition…), lisibilité, origine dans certains cas.", |
| "Règles spécifiques sur l’ingrédient primaire (cohérence origine)." |
| ], |
| exigences:[ |
| "Taille de police ≥ 1,2 mm (x‑height); mise en évidence des allergènes dans la liste des ingrédients.", |
| "Origine obligatoire pour certaines viandes; cohérence ‘ingrédient primaire’." |
| ], |
| audit:[ |
| "Circuit de validation/archivage maquettes; revue médias digitaux (e‑commerce)." |
| ], |
| maj_points:[ "Guidance Commission 2020/C 32/01 sur l’ingrédient primaire." ] |
| }, |
| { |
| id:"1333/2008", |
| titre:"Règlement (CE) n° 1333/2008 – Additifs alimentaires", |
| celex:"02008R1333", |
| categorie:["Additifs","Étiquetage"], |
| statut:"V", |
| maj:"2023-07-20", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02008R1333-20230720"}], |
| resume:[ |
| "Listes de l’Union; conditions d’utilisation par catégories d’aliments; exigences d’étiquetage." |
| ], |
| exigences:[ |
| "Vérifier matrices autorisées et doses max; pureté via 231/2012 (spécifications)." |
| ], |
| audit:[ "Dossiers techniques additifs; attestations fournisseurs; revues formulations." ], |
| maj_points:[ "Mises à jour régulières des annexes." ] |
| }, |
| { |
| id:"1334/2008", |
| titre:"Règlement (CE) n° 1334/2008 – Arômes", |
| celex:"02008R1334", |
| categorie:["Arômes","Étiquetage"], |
| statut:"V", |
| maj:"2023-03-21", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02008R1334-20230321"}], |
| resume:[ |
| "Emploi d’arômes/ingrédients aromatisants; listes de substances autorisées." |
| ], |
| exigences:[ "Conformité des arômes; étiquetage ‘arôme(s)’; restrictions spécifiques." ], |
| audit:[ "Spécifications fournisseurs; dosage/usage; mentions d’étiquetage." ], |
| maj_points:[ "Coordination avec 2065/2003 (arômes de fumée)." ] |
| }, |
| { |
| id:"1924/2006", |
| titre:"Règlement (CE) n° 1924/2006 – Allégations nutritionnelles et de santé", |
| celex:"02006R1924", |
| categorie:["Allégations","Marketing"], |
| statut:"V", |
| maj:"2014-12-13", |
| liens:[ |
| {label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02006R1924-20141213"}, |
| {label:"R (UE) 432/2012 – liste des allégations santé", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02012R0432-20210517"} |
| ], |
| resume:[ |
| "Cadre des allégations; autorisation/allégations santé listées; conditions d’emploi strictes." |
| ], |
| exigences:[ "Preuves de conformité nutritionnelle; libellés exacts; pas de tromperie." ], |
| audit:[ "Revue supports (étiquette, web, PLV) vs listes autorisées." ], |
| maj_points:[ "Mises à jour des listes (432/2012)." ] |
| }, |
| { |
| id:"396/2005", |
| titre:"Règlement (CE) n° 396/2005 – LMR pesticides", |
| celex:"02005R0396", |
| categorie:["Résidus","Pesticides"], |
| statut:"V", |
| maj:"2023-06-22", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:02005R0396-20230622"}], |
| resume:[ |
| "LMR harmonisées; surveillance officielle; responsabilité exploitants." |
| ], |
| exigences:[ |
| "Plan de contrôle pesticides; sélection matières actives cibles; seuils LMR par produit." |
| ], |
| audit:[ "Contrats fournisseurs; COA; actions en cas de dépassement LMR." ], |
| maj_points:[ "Mises à jour fréquentes des LMR (consulter la version récente)." ] |
| }, |
| { |
| id:"589/2008", |
| titre:"Règlement (CE) n° 589/2008 – Normes de commercialisation œufs", |
| celex:"02008R0589", |
| categorie:["Marketing","Œufs"], |
| statut:"V", |
| maj:"2017-11-25", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02008R0589-20171125"}], |
| resume:[ |
| "Marquage des œufs, catégories de qualité/poids, dates, traçabilité." |
| ], |
| exigences:[ "Calibrage/qualité; informations au consommateur; marquage producteur." ], |
| audit:[ "Vérifier conformité marquage/étiquetage et registres." ], |
| maj_points:[ ] |
| }, |
| { |
| id:"1379/2013", |
| titre:"Règlement (UE) n° 1379/2013 – Produits de la pêche/aquaculture (OCM)", |
| celex:"02013R1379", |
| categorie:["Marketing","Pêche"], |
| statut:"V", |
| maj:"2020-04-25", |
| liens:[{label:"EUR‑Lex (consolidé)", url:"https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:02013R1379-20200425"}], |
| resume:[ "Informations à fournir: espèce, zone de capture/production, méthode, etc." ], |
| exigences:[ "Étiquetage détaillé; traçabilité espèces/zone/méthode." ], |
| audit:[ "Vérifier cohérence espèces/FAO zone; documents fournisseurs." ], |
| maj_points:[ ] |
| } |
| ]; |
| |
| /** =================== UI & Logic (Responsive) =================== **/ |
| const sidebar = document.getElementById('sidebar'); |
| const menu = document.getElementById('menu'); |
| const themeFilter = document.getElementById('theme-filter'); |
| const q = document.getElementById('q'); |
| const title = document.getElementById('title'); |
| const meta = document.getElementById('meta'); |
| const contentWrapper = document.getElementById('content-wrapper'); |
| const contentNavLinks = document.getElementById('content-nav-links'); |
| const menuToggle = document.getElementById('menu-toggle'); |
| const menuClose = document.getElementById('menu-close'); |
| const overlay = document.getElementById('overlay'); |
| |
| const ICONS = { |
| resume: `<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor"><path d="M2.5 3.5a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-11Zm0 5a.5.5 0 0 1 0-1h11a.5.5 0 0 1 0 1h-11ZM2 11.5a.5.5 0 0 0 .5.5h6a.5.5 0 0 0 0-1h-6a.5.5 0 0 0-.5.5Z"/></svg>`, |
| exigences: `<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor"><path d="M3.5 2A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 12.5 2h-9ZM9.03 8.32a.75.75 0 0 1-1.06 1.06L6.22 7.62a.75.75 0 0 1 0-1.06L7.97 4.81a.75.75 0 0 1 1.06 1.06L8.06 7l.97 1.32Z"/></svg>`, |
| refs: `<svg width="18" height="18" viewBox="0 0 16 16" fill="currentColor"><path fill-rule="evenodd" d="M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z" clip-rule="evenodd"/></svg>` |
| }; |
| |
| const TAGS = Array.from(new Set(DATA.flatMap(d => d.categorie))).sort(); |
| |
| let current = null; |
| let activeItemId = null; |
| |
| function formatDate(iso) { if (!iso) return ""; const d = new Date(iso); return d.toLocaleDateString('fr-FR'); } |
| |
| function renderThemeDropdown() { |
| themeFilter.innerHTML = '<option value="">Tous les thèmes</option>'; |
| TAGS.forEach(tag => { |
| const option = document.createElement('option'); |
| option.value = tag; |
| option.textContent = tag; |
| themeFilter.appendChild(option); |
| }); |
| } |
| |
| function match(text, query) { |
| return text.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase() |
| .includes(query.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase()); |
| } |
| |
| function renderMenu() { |
| const query = q.value.trim(); |
| const activeTheme = themeFilter.value; |
| menu.innerHTML = ""; |
| const list = DATA.filter(d => { |
| const byTheme = activeTheme ? d.categorie.includes(activeTheme) : true; |
| if (!byTheme) return false; |
| const byQuery = query ? match(d.id + " " + d.titre + " " + d.categorie.join(" "), query) : true; |
| return byQuery; |
| }); |
| |
| list.forEach(d => { |
| const item = document.createElement('a'); |
| item.className = 'item' + (d.id === activeItemId ? ' active' : ''); |
| item.onclick = () => select(d.id); |
| item.innerHTML = ` |
| <div class="item-header"> |
| <h4>${d.titre}</h4> |
| <code>${d.id}</code> |
| </div> |
| <div class="badges"> |
| ${d.categorie.slice(0, 3).map(c => `<span class="badge">${c}</span>`).join('')} |
| </div> |
| `; |
| menu.appendChild(item); |
| }); |
| } |
| |
| function select(id) { |
| activeItemId = id; |
| current = DATA.find(d => d.id === id); |
| if (!current) return; |
| |
| title.textContent = current.titre; |
| meta.innerHTML = ` |
| <span><b>Statut:</b> ${current.statut || 'V'}</span> |
| ${current.maj ? `<span><b>MAJ:</b> ${formatDate(current.maj)}</span>` : ''} |
| `; |
| |
| renderContent(); |
| renderMenu(); |
| contentWrapper.scrollTo({ top: 0, behavior: 'auto' }); |
| |
| // Close menu on selection if on mobile |
| if (window.innerWidth <= 1024) { |
| sidebar.classList.remove('open'); |
| overlay.style.display = 'none'; |
| } |
| } |
| |
| function renderList(items) { |
| if (!items || !items.length) return '<p style="color:var(--text-light)"><em>— Non renseigné —</em></p>'; |
| return '<ul>' + items.map(li => `<li>${li.replace(/'/g, '’')}</li>`).join('') + '</ul>'; |
| } |
| |
| function renderContent() { |
| if (!current) { |
| contentWrapper.innerHTML = `<div class="card"><p>Sélectionnez un texte dans la liste de gauche pour afficher ses détails.</p></div>`; |
| return; |
| } |
| |
| contentWrapper.innerHTML = ` |
| <section id="s-resume" class="content-section"> |
| <h3>${ICONS.resume} Résumé & Portée</h3> |
| <div class="card"><h4>Résumé exécutif</h4>${renderList(current.resume)}</div> |
| <div class="card"><h4>Champ & Objectifs</h4>${renderList(current.scope || ["Champ d'application tel que défini dans le texte."])}</div> |
| <div class="card"><h4>Points Essentiels</h4>${renderList(current.key || ["Points de vigilance principaux."])}</div> |
| </section> |
| |
| <section id="s-exigences" class="content-section"> |
| <h3>${ICONS.exigences} Exigences & Audit</h3> |
| <div class="card"><h4>Exigences Clés</h4>${renderList(current.exigences)}</div> |
| <div class="card"><h4>Points d'Audit (type GFSI)</h4>${renderList(current.audit)}</div> |
| <div class="card"><h4>Valeurs / Aspects Techniques</h4>${renderList(current.limits || ["Consulter les annexes pour les valeurs limites (SML, LMR, etc.)."])}</div> |
| </section> |
| |
| <section id="s-refs" class="content-section"> |
| <h3>${ICONS.refs} Références & Mises à Jour</h3> |
| <div class="card"> |
| <h4>Points de Vigilance</h4>${renderList(current.maj_points)} |
| </div> |
| <div class="card"> |
| <h4>Liens Officiels</h4> |
| <div class="links">${(current.liens || []).map(l => `<a class="btn-link" target="_blank" rel="noopener" href="${l.url}">🔗 ${l.label}</a>`).join('')}</div> |
| </div> |
| </section> |
| `; |
| } |
| |
| function initNavigation() { |
| contentNavLinks.addEventListener('click', (e) => { |
| e.preventDefault(); |
| const targetLink = e.target.closest('a'); |
| if (!targetLink) return; |
| |
| contentNavLinks.querySelectorAll('a').forEach(link => link.classList.remove('active')); |
| targetLink.classList.add('active'); |
| |
| const targetId = targetLink.dataset.target; |
| const targetElement = document.getElementById(targetId); |
| if (targetElement) { |
| targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); |
| } |
| }); |
| } |
| |
| function initMobileMenu() { |
| menuToggle.onclick = () => { |
| sidebar.classList.add('open'); |
| overlay.style.display = 'block'; |
| }; |
| menuClose.onclick = () => { |
| sidebar.classList.remove('open'); |
| overlay.style.display = 'none'; |
| }; |
| overlay.onclick = () => { |
| sidebar.classList.remove('open'); |
| overlay.style.display = 'none'; |
| }; |
| } |
| |
| function init() { |
| q.onkeyup = renderMenu; |
| themeFilter.onchange = renderMenu; |
| renderThemeDropdown(); |
| renderMenu(); |
| if (DATA[0]) { |
| select(DATA[0].id); |
| } else { |
| renderContent(); |
| } |
| initNavigation(); |
| initMobileMenu(); |
| } |
| |
| init(); |
| |
| </script> |
| </body> |
| </html> |