#!/usr/bin/env python3
"""REACH Presentatie v2.0 — JvG Consultancy"""

from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
import os, json

# Paths
BASE = "/root/projects/jg/2026-consult-REACH-kennisdossier"
LOGO = "/root/projects/jg/assets/branding/jvg-logo-white-large.png"
GHS_DIR = f"{BASE}/research/assets"
OUT = f"{BASE}/deliverables/pptx/REACH_Presentatie_v2.0.pptx"

# Load scanner data
with open(f"{BASE}/research/reach_scanner_data.json") as f:
    data = json.load(f)

# Colors
PRIMARY = RGBColor(0x00, 0x33, 0x66)
SECONDARY = RGBColor(0x37, 0x41, 0x51)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK = RGBColor(0x1F, 0x29, 0x37)
CARD_BG = RGBColor(0xF8, 0xF9, 0xFA)
BORDER = RGBColor(0xE5, 0xE7, 0xEB)
ACCENT_BLUE = RGBColor(0x3B, 0x82, 0xF6)
WARNING = RGBColor(0xF5, 0x9E, 0x0B)

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)

SLIDE_W = prs.slide_width
SLIDE_H = prs.slide_height

def add_logo(slide, top=Inches(0.2), left=Inches(0.3)):
    if os.path.exists(LOGO):
        slide.shapes.add_picture(LOGO, left, top, height=Inches(0.6))

def add_slide_number(slide, num, total=27):
    txBox = slide.shapes.add_textbox(Inches(12.5), Inches(7.0), Inches(0.7), Inches(0.3))
    tf = txBox.text_frame
    p = tf.paragraphs[0]
    p.text = f"{num}/{total}"
    p.font.size = Pt(10)
    p.font.color.rgb = SECONDARY
    p.alignment = PP_ALIGN.RIGHT

def add_footer_bar(slide):
    shape = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, Inches(7.15), SLIDE_W, Inches(0.35))
    shape.fill.solid()
    shape.fill.fore_color.rgb = PRIMARY
    shape.line.fill.background()

def add_title_text(slide, text, left=Inches(0.6), top=Inches(0.8), width=Inches(12), height=Inches(0.8), size=Pt(32), color=PRIMARY, bold=True, alignment=PP_ALIGN.LEFT):
    txBox = slide.shapes.add_textbox(left, top, width, height)
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = text
    p.font.size = size
    p.font.color.rgb = color
    p.font.bold = bold
    p.font.name = "Segoe UI"
    p.alignment = alignment
    return tf

def add_body_text(slide, text, left=Inches(0.6), top=Inches(1.8), width=Inches(12), height=Inches(4.5), size=Pt(16), color=DARK, alignment=PP_ALIGN.LEFT):
    txBox = slide.shapes.add_textbox(left, top, width, height)
    tf = txBox.text_frame
    tf.word_wrap = True
    for i, line in enumerate(text.split('\n')):
        if i == 0:
            p = tf.paragraphs[0]
        else:
            p = tf.add_paragraph()
        p.text = line
        p.font.size = size
        p.font.color.rgb = color
        p.font.name = "Calibri"
        p.space_after = Pt(6)
    return tf

def add_card(slide, left, top, width, height, text_lines, title=None):
    # Background
    shape = slide.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height)
    shape.fill.solid()
    shape.fill.fore_color.rgb = CARD_BG
    shape.line.color.rgb = BORDER
    shape.line.width = Pt(1)
    tf = shape.text_frame
    tf.word_wrap = True
    tf.margin_left = Inches(0.15)
    tf.margin_right = Inches(0.15)
    tf.margin_top = Inches(0.1)
    if title:
        p = tf.paragraphs[0]
        p.text = title
        p.font.size = Pt(14)
        p.font.bold = True
        p.font.color.rgb = PRIMARY
        p.font.name = "Segoe UI"
        p.space_after = Pt(4)
    for line in text_lines:
        p = tf.add_paragraph()
        p.text = line
        p.font.size = Pt(12)
        p.font.color.rgb = DARK
        p.font.name = "Calibri"
        p.space_after = Pt(2)

def make_content_slide(title_text, num):
    slide = prs.slides.add_slide(prs.slide_layouts[6])  # blank
    add_footer_bar(slide)
    add_logo(slide)
    add_title_text(slide, title_text)
    add_slide_number(slide, num)
    return slide

# ===================== SLIDE 1: TITLE =====================
slide = prs.slides.add_slide(prs.slide_layouts[6])
# Full primary background
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SLIDE_W, SLIDE_H)
bg.fill.solid()
bg.fill.fore_color.rgb = PRIMARY
bg.line.fill.background()
if os.path.exists(LOGO):
    slide.shapes.add_picture(LOGO, Inches(1.0), Inches(1.5), height=Inches(1.2))
add_title_text(slide, "REACH Compliance", Inches(1.0), Inches(3.0), Inches(11), Inches(1.0), Pt(48), WHITE, True, PP_ALIGN.LEFT)
add_title_text(slide, "Kennisdossier & Strategisch Advies", Inches(1.0), Inches(4.0), Inches(11), Inches(0.7), Pt(28), RGBColor(0xBB,0xCC,0xDD), False, PP_ALIGN.LEFT)
add_body_text(slide, "JvG Consultancy | Versie 2.0 | April 2026", Inches(1.0), Inches(5.0), Inches(11), Inches(0.5), Pt(16), RGBColor(0x99,0xAA,0xBB))
add_slide_number(slide, 1)

# ===================== SLIDE 2: AGENDA =====================
s = make_content_slide("Agenda", 2)
agenda = [
    "1. Wat is REACH? -- Toepassingsgebied & scope",
    "2. REACH Verordening -- Key Articles",
    "3. Wie valt onder REACH? -- Rollen & verplichtingen",
    "4. Registratieplicht -- Tonnagebanden & Annex-eisen",
    "5. Kosten & doorlooptijden per tonnageband",
    "6. CLP Pictogrammen -- GHS classificatie",
    "7. SVHC, Autorisatie & Restrictie",
    "8. SDS & eSDS -- Veiligheidsinformatiebladen",
    "9. Phoenix Metals -- Scenarios per fase",
    "10. Chemicaliënregister & Vervoerswetgeving",
    "11. TierVerify -- Bronverificatie",
]
add_body_text(s, '\n'.join(agenda), size=Pt(16))

# ===================== SLIDE 3: WAT IS REACH =====================
s = make_content_slide("Wat is REACH?", 3)
add_body_text(s, 
    "Registration, Evaluation, Authorisation and Restriction of Chemicals\n\n"
    "REACH is de EU-verordening (EG) Nr. 1907/2006 die de registratie, evaluatie,\n"
    "autorisatie en restrictie van chemische stoffen regelt.\n\n"
    "Het beginsel 'No Data, No Market' betekent dat een stof niet op de EU-markt\n"
    "mag worden gebracht zonder geldige REACH-registratie.\n\n"
    "Scope: Alle chemische stoffen die in de EU worden gefabriceerd, geimporteerd\n"
    "of op de markt gebracht, in hoeveelheden van 1 ton/jaar of meer per bedrijf. [1]",
    size=Pt(16))

# ===================== SLIDE 4: KEY ARTICLES =====================
s = make_content_slide("REACH Verordening -- Key Articles", 4)
articles = [
    ("Art. 5-6", "Algemene registratieplicht voor fabrikanten en importeurs"),
    ("Art. 8", "Enige Importeur (Only Representative) buiten de EU"),
    ("Art. 12(1)", "Annex VII: registratie bij >= 1 ton/jaar [1]"),
    ("Art. 12(2)", "Annex VIII: registratie bij >= 10 ton/jaar [1]"),
    ("Art. 12(3)", "Annex IX: registratie bij >= 100 ton/jaar [1]"),
    ("Art. 12(4)", "Annex X: registratie bij >= 1.000 ton/jaar [1]"),
    ("Art. 14(1)", "Chemical Safety Report verplicht bij >= 10 ton/jaar [1]"),
    ("Art. 31", "SDS-verplichting bij gevaarlijke stoffen"),
    ("Art. 33", "SVHC-informatieverplichting aan afnemers"),
    ("Art. 37-38", "Verplichtingen downstream gebruikers"),
    ("Art. 55-60", "Autorisatie voor zeer zorgwekkende stoffen (SVHC)"),
    ("Art. 67-73", "Restricties op stoffen en mengsels"),
]
for i, (art, desc) in enumerate(articles):
    y = Inches(1.6) + Inches(i * 0.44)
    txBox = s.shapes.add_textbox(Inches(0.6), y, Inches(3), Inches(0.4))
    p = txBox.text_frame.paragraphs[0]
    p.text = art
    p.font.size = Pt(14)
    p.font.bold = True
    p.font.color.rgb = PRIMARY
    p.font.name = "Calibri"
    txBox2 = s.shapes.add_textbox(Inches(3.5), y, Inches(9), Inches(0.4))
    p2 = txBox2.text_frame.paragraphs[0]
    p2.text = desc
    p2.font.size = Pt(14)
    p2.font.color.rgb = DARK
    p2.font.name = "Calibri"

# ===================== SLIDE 5: WIE VALT ONDER REACH =====================
s = make_content_slide("Wie valt onder REACH?", 5)
roles_data = data["roles"]
role_configs = [
    ("fabrikant", "Fabrikant"),
    ("importeur", "Importeur"),
    ("downstream_gebruiker", "Downstream Gebruiker"),
    ("distributeur", "Distributeur"),
    ("enkel_importeur", "Enige Importeur (OR)"),
]
for i, (key, title) in enumerate(role_configs):
    col = i % 3
    row = i // 3
    left = Inches(0.6) + Inches(col * 4.2)
    top = Inches(1.6) + Inches(row * 2.8)
    r = roles_data[key]
    add_card(s, left, top, Inches(3.8), Inches(2.5),
             [f"{r['label']}", f"{r['artikel']}", ""] + r["verplichtingen"][:3],
             title=title)

# ===================== SLIDE 6: REGISTRATIEPLICHT =====================
s = make_content_slide("Registratieplicht -- Overzicht", 6)
add_body_text(s,
    "Elke stof die in de EU wordt gefabriceerd of geimporteerd in een hoeveelheid\n"
    "van 1 ton/jaar of meer moet worden geregistreerd bij ECHA. [1]\n\n"
    "Registratie geschiedt via REACH-IT, het online portaal van ECHA.\n\n"
    "De omvang van het registratiedossier is afhankelijk van de tonnageband:\n"
    "hoe hoger de tonnage, hoe meer testdata en documentatie vereist is.\n\n"
    "Bij elke tonnageband gelden de CLP-verplichtingen (classificatie & etikettering)\n"
    "en bij gevaarlijke stoffen is een SDS verplicht. [2]\n\n"
    "Deadlines: Nieuwe stoffen moeten uiterlijk 30 dagen vóór eerste invoer worden\n"
    "geregistreerd (Art. 7(1) fase-in). Bestaande stoffen volgen de REACH fasering.",
    size=Pt(16))

# ===================== SLIDE 7: TONNAGEBAND TABEL =====================
s = make_content_slide("Tonnagebanden -- Overzicht", 7)
bands = [("<1", data["tonnage_bands"]["<1"]),
         ("1-10", data["tonnage_bands"]["1-10"]),
         ("10-100", data["tonnage_bands"]["10-100"]),
         ("100-1000", data["tonnage_bands"]["100-1000"]),
         (">1000", data["tonnage_bands"][">1000"])]
# Table
rows, cols = 6, 6
tbl = s.shapes.add_table(rows, cols, Inches(0.4), Inches(1.5), Inches(12.5), Inches(4.8)).table
tbl.columns[0].width = Inches(2.0)
tbl.columns[1].width = Inches(1.5)
tbl.columns[2].width = Inches(2.5)
tbl.columns[3].width = Inches(2.5)
tbl.columns[4].width = Inches(2.0)
tbl.columns[5].width = Inches(2.0)
headers = ["Tonnageband", "Registratie", "Annex", "CSR", "Kosten", "Doorlooptijd"]
for j, h in enumerate(headers):
    cell = tbl.cell(0, j)
    cell.text = h
    for p in cell.text_frame.paragraphs:
        p.font.size = Pt(13)
        p.font.bold = True
        p.font.color.rgb = WHITE
        p.font.name = "Segoe UI"
    cell.fill.solid()
    cell.fill.fore_color.rgb = PRIMARY
for i, (key, band) in enumerate(bands):
    vals = [band["label"], "Ja" if band["registratie"] else "Nee", band["annex"],
            "Ja" if band["csr"] else "Nee", band["kosten"], band["doorlooptijd"]]
    for j, v in enumerate(vals):
        cell = tbl.cell(i+1, j)
        cell.text = v
        for p in cell.text_frame.paragraphs:
            p.font.size = Pt(12)
            p.font.color.rgb = DARK
            p.font.name = "Calibri"
        if i % 2 == 0:
            cell.fill.solid()
            cell.fill.fore_color.rgb = CARD_BG

# ===================== SLIDES 8-11: ANNEX EISEN =====================
annex_slides = [
    (8, "Annex VII -- Eisen (>= 1 ton/jaar)", "1-10",
     ["REACH Art. 12(1): registratie bij >= 1 ton/jaar [1]",
      "Basis fysisch-chemische gegevens",
      "Basis toxicologische gegevens",
      "SDS verplicht bij gevaarlijke stoffen",
      "CLP-classificatie & etikettering",
      "Geen CSR vereist (tenzij CMR cat 1A/1B of PBT/vPvB) [1]",
      "", "Kosten: EUR 15.000 - EUR 50.000",
      "Doorlooptijd: 6-12 maanden"]),
    (9, "Annex VIII -- Eisen (>= 10 ton/jaar)", "10-100",
     ["REACH Art. 12(2): registratie bij >= 10 ton/jaar [1]",
      "REACH Art. 14(1): CSR VERPLICHT bij >= 10 ton/jaar [1]",
      "Uitgebreidere toxicologische data (Annex VII + VIII)",
      "Blootstellingsscenario's opstellen",
      "SDS met blootstellingsscenario's (eSDS)",
      "CLP-classificatie & etikettering",
      "", "Kosten: EUR 50.000 - EUR 150.000",
      "Doorlooptijd: 12-18 maanden"]),
    (10, "Annex IX -- Eisen (>= 100 ton/jaar)", "100-1000",
     ["REACH Art. 12(3): registratie bij >= 100 ton/jaar [1]",
      "Registratiedossier: Annex VII + VIII + IX",
      "Uitgebreid CSR met alle blootstellingsscenario's",
      "Extra toxicologische en ecotoxicologische testen",
      "Evaluatie door ECHA (compliance check) mogelijk",
      "SDS verplicht met volledige risicobeoordeling",
      "", "Kosten: EUR 150.000 - EUR 500.000",
      "Doorlooptijd: 18-36 maanden"]),
    (11, "Annex X -- Eisen (>= 1.000 ton/jaar)", ">1000",
     ["REACH Art. 12(4): registratie bij >= 1.000 ton/jaar [1]",
      "Volledig registratiedossier: Annex VII + VIII + IX + X",
      "Volledig CSR met alle gebruiksvoorwaarden",
      "Alle toxicologische en ecotoxicologische data",
      "Substance Evaluation mogelijk (CoRAP)",
      "SDS met alle relevante info",
      "", "Kosten: EUR 500.000 - EUR 2.000.000+",
      "Doorlooptijd: 24-48 maanden"]),
]
for num, title, band_key, lines in annex_slides:
    s = make_content_slide(title, num)
    band = data["tonnage_bands"][band_key]
    all_lines = lines + ["", "Vereiste documenten:"] + [f"  - {d}" for d in band["documenten"]]
    add_body_text(s, '\n'.join(all_lines), size=Pt(15))

# ===================== SLIDE 12: KOSTEN =====================
s = make_content_slide("Kosten overzicht", 12)
add_body_text(s,
    "De kosten van REACH-registratie zijn direct gekoppeld aan de tonnageband\n"
    "en de vereiste testdata. [1]\n\n"
    "Onderstaande kosten zijn gebaseerd op de REACH Scanner data:\n\n"
    "  < 1 ton/jaar:    Geen registratiekosten\n"
    "  1 - 10 ton/jaar:  EUR 15.000 - EUR 50.000\n"
    "  10 - 100 ton/jaar: EUR 50.000 - EUR 150.000\n"
    "  100 - 1.000 ton/jaar: EUR 150.000 - EUR 500.000\n"
    "  > 1.000 ton/jaar: EUR 500.000 - EUR 2.000.000+\n\n"
    "Deze kosten omvatten dossieropstelling, testprogramma's, SIEF-deelname,\n"
    "consultancy en ECHA-registratiekosten.\n\n"
    "Doorlooptijden variëren van 6 maanden (<1t) tot 48 maanden (>1000t). [1]",
    size=Pt(15))

# ===================== SLIDE 13: CLP PICTOGRAMMEN =====================
s = make_content_slide("CLP Pictogrammen -- GHS Classificatie", 13)
ghs_pics = [
    ("GHS01", "Ontploffing"),
    ("GHS02", "Brand"),
    ("GHS03", "Oxiderend"),
    ("GHS04", "Gecomprimeerd gas"),
    ("GHS05", "Corrosief"),
    ("GHS06", "Giftig"),
    ("GHS07", "Irriterend"),
    ("GHS08", "Gezondheidsschade"),
    ("GHS09", "Milieuschade"),
]
for i, (code, label) in enumerate(ghs_pics):
    col = i % 5
    row = i // 5
    left = Inches(0.6) + Inches(col * 2.5)
    top = Inches(1.6) + Inches(row * 2.8)
    img_path = f"{GHS_DIR}/{code}.png"
    if os.path.exists(img_path):
        s.shapes.add_picture(img_path, left + Inches(0.4), top, width=Inches(1.4))
    txBox = s.shapes.add_textbox(left, top + Inches(1.6), Inches(2.2), Inches(0.6))
    p = txBox.text_frame.paragraphs[0]
    p.text = f"{code}: {label}"
    p.font.size = Pt(11)
    p.font.color.rgb = DARK
    p.font.name = "Calibri"
    p.alignment = PP_ALIGN.CENTER

# ===================== SLIDE 14: SVHC =====================
s = make_content_slide("SVHC & Kandidaatlijst", 14)
add_body_text(s,
    "SVHC = Substances of Very High Concern (Zeer Zorgwekkende Stoffen)\n\n"
    "SVHC-stoffen worden door ECHA op de Kandidaatlijst geplaatst wanneer zij voldoen\n"
    "aan een of meer van de volgende criteria:\n\n"
    "  - Carcinogeen, mutageen of reprotoxisch (CMR, categorie 1A of 1B)\n"
    "  - Persistent, bioaccumulatief en toxisch (PBT)\n"
    "  - Zeer persistent en zeer bioaccumulatief (vPvB)\n"
    "  - Wetenschappelijk bewezen ernstige effecten op mens of milieu\n\n"
    "Verplichtingen bij SVHC (Art. 33 REACH):\n"
    "  - Leveranciers moeten afnemers informeren bij >= 0,1% gewichtspercentage\n"
    "  - Artikel-33 melding: consumenten hebben recht op informatie\n"
    "  - SCIP-melding aan ECHA voor afvalstoffen in producten\n\n"
    "Autorisatieplicht (Art. 55-60): SVHC-stoffen mogen alleen gebruikt worden\n"
    "na verlening van een autorisatie door de Europese Commissie. [1][5]",
    size=Pt(14))

# ===================== SLIDE 15: AUTORISATIE & RESTRICTIE =====================
s = make_content_slide("Autorisatie & Restrictie", 15)
add_body_text(s,
    "AUTORISATIE (Art. 55-60 REACH)\n\n"
    "Stoffen op de Autorisatielijst (Annex XIV) mogen niet langer op de markt\n"
    "blijven na een bepaalde 'sunset date' zonder geldige autorisatie.\n\n"
    "Proces:\n"
    "  1. SVHC-stof wordt voorgedragen voor Annex XIV\n"
    "  2. ECHA stelt zonodig een autorisatieplan op\n"
    "  3. Bedrijven dienen een aanvraag in bij ECHA\n"
    "  4. Commissie beslist over toekenning\n\n"
    "RESTRICTIE (Art. 67-73 REACH)\n\n"
    "Restricties zijn beperkingen op het vervaardigen, op de markt brengen of\n"
    "gebruiken van bepaalde stoffen. Zij gelden voor alle bedrijven in de EU.\n\n"
    "Restricties staan in Annex XVII van REACH en zijn bindend voor alle\n"
    "actoren in de toeleveringsketen. [1][6]",
    size=Pt(14))

# ===================== SLIDE 16: SDS & eSDS =====================
s = make_content_slide("SDS & eSDS", 16)
add_body_text(s,
    "Veiligheidsinformatieblad (Safety Data Sheet) -- Art. 31 REACH\n\n"
    "Een SDS is verplicht bij:\n"
    "  - Gevaarlijke stoffen en mengsels (conform CLP)\n"
    "  - PBT- of vPvB-stoffen\n"
    "  - Stoffen op de SVHC-kandidaatlijst bij >= 0,1% gewichtspercentage\n\n"
    "De SDS bevat 16 secties conform REACH Art. 31 en CLP:\n"
    "  1. Identificatie | 2. Gevaarsidentificatie | 3. Samenstelling\n"
    "  4. Eerste hulp | 5. Brandbestrijding | 6. Maatregelen bij ongevallen\n"
    "  7. Hantering & opslag | 8. Blootstellingsgrenzen | 9. Fysische eigenschappen\n"
    "  10. Stabiliteit | 11. Toxicologie | 12. Ecotoxicologie\n"
    "  13. Afvoer | 14. Vervoersinformatie | 15. Wetgeving | 16. Overige info\n\n"
    "eSDS (Extended SDS):\n"
    "  - Bevat blootstellingsscenario's (Exposure Scenarios) -- verplicht bij >= 10 ton/jaar\n"
    "  - Beschrijft hoe de stof veilig gebruikt kan worden in de toepassing [1][7]",
    size=Pt(13))

# ===================== SLIDE 17: PHOENIX METALS INTRO =====================
s = make_content_slide("Phoenix Metals -- Intro", 17)
add_body_text(s,
    "Phoenix Metals verwerkt secundaire grondstoffen tot waardevolle metalen\n"
    "en verbindingen, waaronder vanadium-elektrolyten uit staalslakken. [3]\n\n"
    "Voor de REACH-compliance zijn de volgende scenario's gedefinieerd:\n\n"
    "  Scenario 1:  Pilot (< 1 ton/jaar) -- Geen REACH-registratie\n"
    "  Scenario 2:  Demonstrator (1 - 10 ton/jaar) -- Annex VII\n"
    "  Scenario 3a: Commercieel (10 - 100 ton/jaar) -- Annex VII + VIII\n"
    "  Scenario 3b: Commercieel (100 - 1.000 ton/jaar) -- Annex VII-IX\n"
    "  Scenario 3c: Commercieel (> 1.000 ton/jaar) -- Annex VII-X\n\n"
    "Elk scenario kent specifieke verplichtingen, kosten en doorlooptijden\n"
    "die in de volgende slides worden toegelicht. [1][3]",
    size=Pt(15))

# ===================== SLIDES 18-22: SCENARIOS =====================
scenario_slides = [
    (18, "Scenario 1: Pilot (< 1 ton/jaar)", "<1",
     ["Tonnageband: < 1 ton/jaar",
      "Registratie: Niet verplicht",
      "",
      "Vereisten:",
      "  - CLP-verplichtingen blijven gelden [2]",
      "  - Risico Inventarisatie & Evaluatie (RI&E) [9]",
      "  - SDS vrijwillig maar aanbevolen bij gevaarlijke stoffen",
      "",
      "Kosten: Geen registratiekosten",
      "Doorlooptijd: N.v.t.",
      "",
      "Advies: Vrijwillige SDS opstellen, RI&E up-to-date houden",
      "en vroegtijdig beginnen met data-acquisitie voor toekomstige registratie."]),
    (19, "Scenario 2: Demonstrator (1 - 10 ton/jaar)", "1-10",
     ["Tonnageband: 1 - 10 ton/jaar",
      "Registratie: VERPLICHT -- Annex VII (REACH Art. 12(1)) [1]",
      "",
      "Vereisten:",
      "  - Registratiedossier Annex VII (fysisch-chemisch + toxicologisch)",
      "  - SDS verplicht bij gevaarlijke stoffen",
      "  - CLP-classificatie & etikettering",
      "  - Geen CSR (tenzij CMR cat 1A/1B of PBT/vPvB)",
      "",
      "Kosten: EUR 15.000 - EUR 50.000",
      "Doorlooptijd: 6 - 12 maanden"]),
    (20, "Scenario 3a: Commercieel (10 - 100 ton/jaar)", "10-100",
     ["Tonnageband: 10 - 100 ton/jaar",
      "Registratie: VERPLICHT -- Annex VII + VIII (REACH Art. 12(2)) [1]",
      "CSR: VERPLICHT (REACH Art. 14(1)) [1]",
      "",
      "Vereisten:",
      "  - Registratiedossier Annex VII + VIII",
      "  - Chemical Safety Report (CSR)",
      "  - Blootstellingsscenario's",
      "  - eSDS met blootstellingsscenario's",
      "  - CLP-classificatie & etikettering",
      "",
      "Kosten: EUR 50.000 - EUR 150.000",
      "Doorlooptijd: 12 - 18 maanden"]),
    (21, "Scenario 3b: Commercieel (100 - 1.000 ton/jaar)", "100-1000",
     ["Tonnageband: 100 - 1.000 ton/jaar",
      "Registratie: VERPLICHT -- Annex VII + VIII + IX (REACH Art. 12(3)) [1]",
      "CSR: VERPLICHT",
      "",
      "Vereisten:",
      "  - Volledig registratiedossier Annex VII-IX",
      "  - Uitgebreid CSR met alle blootstellingsscenario's",
      "  - Extra toxicologische en ecotoxicologische testen",
      "  - ECHA compliance check mogelijk",
      "  - eSDS met volledige risicobeoordeling",
      "",
      "Kosten: EUR 150.000 - EUR 500.000",
      "Doorlooptijd: 18 - 36 maanden"]),
    (22, "Scenario 3c: Commercieel (> 1.000 ton/jaar)", ">1000",
     ["Tonnageband: > 1.000 ton/jaar",
      "Registratie: VERPLICHT -- Annex VII-X (REACH Art. 12(4)) [1]",
      "CSR: VERPLICHT",
      "",
      "Vereisten:",
      "  - Volledig registratiedossier Annex VII-X",
      "  - Compleet CSR met alle gebruiksvoorwaarden",
      "  - Alle toxicologische en ecotoxicologische data",
      "  - Substance Evaluation mogelijk (CoRAP)",
      "  - DU-meldingen",
      "",
      "Kosten: EUR 500.000 - EUR 2.000.000+",
      "Doorlooptijd: 24 - 48 maanden"]),
]
for num, title, band_key, lines in scenario_slides:
    s = make_content_slide(title, num)
    add_body_text(s, '\n'.join(lines), size=Pt(14))

# ===================== SLIDE 23: CHEMICALIENREGISTER =====================
s = make_content_slide("Chemicalienregister (CLP + ADR)", 23)
add_body_text(s,
    "Het chemicaliënregister is een verplichting uit de Arbowet en PGS 15:2025\n"
    "voor bedrijven die met gevaarlijke stoffen werken. [9][10]\n\n"
    "CLP -- Classificatie, Labelling and Packaging (EG Nr. 1272/2008):\n"
    "  - Classificatie van stoffen en mengsels volgens GHS-criteria\n"
    "  - Etikettering met GHS-pictogrammen en H/P-zinnen\n"
    "  - Verpaktingsvoorschriften [2]\n\n"
    "ADR -- European Agreement concerning the International Carriage\n"
    "of Dangerous Goods by Road:\n"
    "  - Vervoer van gevaarlijke stoffen over de weg\n"
    "  - Classificatie in 9 gevarenklassen (ADR-klassen)\n"
    "  - Eisen aan voertuigen, documentatie en opleiding chauffeurs\n\n"
    "PGS 15:2025 geeft richtlijnen voor de opslag van gevaarlijke stoffen\n"
    "en de maximale opslaghoeveelheden per categorie. [10]",
    size=Pt(14))

# ===================== SLIDE 24: CLP vs ADR vs ADN vs IMDG =====================
s = make_content_slide("CLP vs ADR vs ADN vs IMDG", 24)
# Table
rows2, cols2 = 5, 5
tbl2 = s.shapes.add_table(rows2, cols2, Inches(0.4), Inches(1.6), Inches(12.5), Inches(3.5)).table
headers2 = ["Regelgeving", "Scope", "Toepassing", "Classificatie", "Beheer"]
for j, h in enumerate(headers2):
    cell = tbl2.cell(0, j)
    cell.text = h
    for p in cell.text_frame.paragraphs:
        p.font.size = Pt(13)
        p.font.bold = True
        p.font.color.rgb = WHITE
        p.font.name = "Segoe UI"
    cell.fill.solid()
    cell.fill.fore_color.rgb = PRIMARY
compare_data = [
    ["CLP", "Etikettering & verpakking", "Alle stoffen op EU-markt", "GHS-pictogrammen, H/P-zinnen", "ECHA / nationale autoriteit"],
    ["ADR", "Vervoer over de weg", "Gevaarlijke stoffen per vrachtwagen", "ADR-gevarenklassen 1-9", "Nationale inspectie"],
    ["ADN", "Vervoer over binnenwateren", "Gevaarlijke stoffen per binnenschip", "ADR-klassen + maritieme aanvullingen", "Scheepvaartinspectie"],
    ["IMDG", "Vervoer over zee", "Gevaarlijke stoffen per zeeschip", "IMDG Code klassen", "Scheepvaartinspectie"],
]
for i, row_data in enumerate(compare_data):
    for j, v in enumerate(row_data):
        cell = tbl2.cell(i+1, j)
        cell.text = v
        for p in cell.text_frame.paragraphs:
            p.font.size = Pt(12)
            p.font.color.rgb = DARK
            p.font.name = "Calibri"
        if i % 2 == 0:
            cell.fill.solid()
            cell.fill.fore_color.rgb = CARD_BG

# ===================== SLIDE 25: TIERVERIFY =====================
s = make_content_slide("TierVerify -- Bronverificatie", 25)
add_body_text(s,
    "TierVerify Protocol -- Bronverificatie en controle [11]\n\n"
    "Alle feiten in deze presentatie zijn geverifieerd tegen de volgende bronnen:\n\n"
    "Tier 1 -- Interne bronnen (Phoenix Metals):\n"
    "  - REACH procedures en projectdata [3]\n"
    "  - Chemicaliën master data [4]\n\n"
    "Tier 2 -- Wetgeving en richtsnoeren:\n"
    "  - REACH Verordening (EG) Nr. 1907/2006 [1]\n"
    "  - CLP Verordening (EG) Nr. 1272/2008 [2]\n"
    "  - ECHA Registratie Richtsnoer [5]\n"
    "  - ECHA SDS Richtsnoer [7]\n"
    "  - ECHA SVHC Guidance [6]\n"
    "  - PGS 15:2025 Opslag Gevaarlijke Stoffen [10]\n\n"
    "Tier 3 -- Online bronnen (geraadpleegd april 2026):\n"
    "  - ECHA Stoffendatabase [11]\n"
    "  - ECHA SVHC Kandidaatlijst [12]\n"
    "  - PubChem Database [13]\n"
    "  - ECHA CLP Pictogrammen [14]",
    size=Pt(14))

# ===================== SLIDE 26: BRONVERWIJZINGEN =====================
s = make_content_slide("Bronverwijzingen", 26)
refs = [
    "[1]  REACH Verordening (EG) Nr. 1907/2006",
    "[2]  CLP Verordening (EG) Nr. 1272/2008",
    "[3]  Phoenix Metals -- REACH procedures & projectdata",
    "[4]  Phoenix Metals -- Chemicaliën master data",
    "[5]  ECHA -- REACH Registratie Richtsnoer",
    "[6]  ECHA -- SVHC Guidance",
    "[7]  ECHA -- Veiligheidsinformatiebladen Richtsnoer",
    "[8]  ECHA -- Chemical Safety Guide SME",
    "[9]  Arbowet & Arbobesluit -- Risico Inventarisatie & Evaluatie",
    "[10] PGS 15:2025 -- Opslag Gevaarlijke Stoffen",
    "[11] ECHA Stoffendatabase -- echa.europa.eu (geraadpleegd apr 2026)",
    "[12] ECHA SVHC Kandidaatlijst -- echa.europa.eu (geraadpleegd apr 2026)",
    "[13] PubChem Database -- pubchem.ncbi.nlm.nih.gov",
    "[14] ECHA CLP Pictogrammen -- echa.europa.eu",
]
add_body_text(s, '\n'.join(refs), size=Pt(13))

# ===================== SLIDE 27: VRAAGEN =====================
slide = prs.slides.add_slide(prs.slide_layouts[6])
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SLIDE_W, SLIDE_H)
bg.fill.solid()
bg.fill.fore_color.rgb = PRIMARY
bg.line.fill.background()
if os.path.exists(LOGO):
    slide.shapes.add_picture(LOGO, Inches(5.6), Inches(1.5), height=Inches(1.2))
add_title_text(slide, "Vragen?", Inches(1.0), Inches(3.5), Inches(11), Inches(1.0), Pt(48), WHITE, True, PP_ALIGN.CENTER)
add_body_text(slide, "JvG Consultancy | REACH Compliance Advies", Inches(1.0), Inches(4.8), Inches(11), Inches(0.5), Pt(18), RGBColor(0xBB,0xCC,0xBB), alignment=PP_ALIGN.CENTER)
add_slide_number(slide, 27)

# Save
os.makedirs(os.path.dirname(OUT), exist_ok=True)
prs.save(OUT)
print(f"SAVED: {OUT}")
print(f"Slides: {len(prs.slides)}")
