#!/usr/bin/env python3
"""REACH Compliance Presentatie — Phoenix Metals B.V. — v1.0"""

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

# ── Kleuren ──
DARK_BLUE = RGBColor(0x00, 0x33, 0x66)
ORANGE = RGBColor(0xFF, 0x66, 0x00)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
LIGHT_GRAY = RGBColor(0xF2, 0xF2, 0xF2)
MED_GRAY = RGBColor(0xCC, 0xCC, 0xCC)
BLACK = RGBColor(0x33, 0x33, 0x33)
ACCENT_BLUE = RGBColor(0x00, 0x56, 0x99)
RED = RGBColor(0xCC, 0x00, 0x00)
GREEN = RGBColor(0x00, 0x88, 0x44)
YELLOW = RGBColor(0xCC, 0xAA, 0x00)

SLIDE_W = Inches(13.333)
SLIDE_H = Inches(7.5)

prs = Presentation()
prs.slide_width = SLIDE_W
prs.slide_height = SLIDE_H

BLANK_LAYOUT = prs.slide_layouts[6]  # blank

def add_bg(slide, color=DARK_BLUE):
    bg = slide.background
    fill = bg.fill
    fill.solid()
    fill.fore_color.rgb = color

def add_shape_bg(slide, left, top, width, height, color):
    s = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
    s.fill.solid()
    s.fill.fore_color.rgb = color
    s.line.fill.background()
    return s

def add_textbox(slide, left, top, width, height, text, font_size=14, color=WHITE, bold=False, alignment=PP_ALIGN.LEFT, font_name="Calibri"):
    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 = Pt(font_size)
    p.font.color.rgb = color
    p.font.bold = bold
    p.font.name = font_name
    p.alignment = alignment
    return txBox

def add_footer(slide, num):
    add_shape_bg(slide, Inches(0), SLIDE_H - Inches(0.45), SLIDE_W, Inches(0.45), RGBColor(0x00, 0x22, 0x44))
    add_textbox(slide, Inches(0.5), SLIDE_H - Inches(0.42), Inches(8), Inches(0.4),
                "Phoenix Metals B.V. — REACH Compliance", 9, RGBColor(0x99, 0xAA, 0xBB))
    add_textbox(slide, SLIDE_W - Inches(1.5), SLIDE_H - Inches(0.42), Inches(1.2), Inches(0.4),
                f"Slide {num}", 9, RGBColor(0x99, 0xAA, 0xBB), alignment=PP_ALIGN.RIGHT)

def add_title_bar(slide, title, subtitle=None):
    add_shape_bg(slide, Inches(0), Inches(0), SLIDE_W, Inches(1.2), DARK_BLUE)
    # Orange accent line
    add_shape_bg(slide, Inches(0), Inches(1.2), SLIDE_W, Inches(0.06), ORANGE)
    add_textbox(slide, Inches(0.7), Inches(0.15), Inches(11), Inches(0.7), title, 28, WHITE, True)
    if subtitle:
        add_textbox(slide, Inches(0.7), Inches(0.75), Inches(11), Inches(0.4), subtitle, 13, RGBColor(0xBB, 0xCC, 0xDD))

def add_content_text(slide, left, top, width, height, lines, font_size=14, color=WHITE, spacing=Pt(6)):
    txBox = slide.shapes.add_textbox(left, top, width, height)
    tf = txBox.text_frame
    tf.word_wrap = True
    for i, line in enumerate(lines):
        if i == 0:
            p = tf.paragraphs[0]
        else:
            p = tf.add_paragraph()
        p.text = line
        p.font.size = Pt(font_size)
        p.font.color.rgb = color
        p.font.name = "Calibri"
        p.space_after = spacing
    return txBox

def add_table(slide, left, top, width, height, headers, rows, header_color=DARK_BLUE, alt_row=True):
    n_rows = len(rows) + 1
    n_cols = len(headers)
    table_shape = slide.shapes.add_table(n_rows, n_cols, left, top, width, height)
    table = table_shape.table
    
    # Header
    for j, h in enumerate(headers):
        cell = table.cell(0, j)
        cell.text = h
        for p in cell.text_frame.paragraphs:
            p.font.size = Pt(11)
            p.font.bold = True
            p.font.color.rgb = WHITE
            p.font.name = "Calibri"
            p.alignment = PP_ALIGN.LEFT
        cell.fill.solid()
        cell.fill.fore_color.rgb = header_color
        cell.vertical_anchor = MSO_ANCHOR.MIDDLE
    
    # Rows
    for i, row in enumerate(rows):
        for j, val in enumerate(row):
            cell = table.cell(i + 1, j)
            cell.text = str(val)
            for p in cell.text_frame.paragraphs:
                p.font.size = Pt(10)
                p.font.color.rgb = BLACK
                p.font.name = "Calibri"
            if alt_row and i % 2 == 1:
                cell.fill.solid()
                cell.fill.fore_color.rgb = RGBColor(0xE8, 0xEE, 0xF4)
            else:
                cell.fill.solid()
                cell.fill.fore_color.rgb = WHITE
            cell.vertical_anchor = MSO_ANCHOR.MIDDLE
    
    return table

def content_slide(title, subtitle=None, slide_num=0, bg=WHITE):
    slide = prs.slides.add_slide(BLANK_LAYOUT)
    add_bg(slide, bg)
    add_title_bar(slide, title, subtitle)
    add_footer(slide, slide_num)
    return slide

# ══════════════════════════════════════════════════════════
# SLIDE 1 — Titelslide
# ══════════════════════════════════════════════════════════
s = prs.slides.add_slide(BLANK_LAYOUT)
add_bg(s, DARK_BLUE)
add_shape_bg(s, Inches(0), Inches(2.8), SLIDE_W, Inches(0.06), ORANGE)
add_textbox(s, Inches(1), Inches(1.5), Inches(11), Inches(1.2),
            "REACH Compliance", 44, WHITE, True)
add_textbox(s, Inches(1), Inches(2.1), Inches(11), Inches(0.7),
            "Phoenix Metals B.V. — Vanadiumextractie uit SARU ash", 22, RGBColor(0xBB, 0xCC, 0xDD))
add_textbox(s, Inches(1), Inches(3.3), Inches(11), Inches(0.5),
            "26 april 2026", 16, RGBColor(0x88, 0x99, 0xAA))
add_textbox(s, Inches(1), Inches(3.9), Inches(11), Inches(0.5),
            "⚠ VERTROUWELIJK — Alleen voor intern gebruik", 14, ORANGE, True)
add_footer(s, 1)

# ══════════════════════════════════════════════════════════
# SLIDE 2 — Agenda
# ══════════════════════════════════════════════════════════
s = content_slide("Agenda", slide_num=2, bg=WHITE)
agenda = [
    ("REACH Basis", "3–6"),
    ("Registratie & Informatie", "7–8"),
    ("CLP & Etikettering", "9–10"),
    ("SDS & Downstream Users", "11–12"),
    ("Evaluatie, SVHC, Autorisatie, Restricties", "13–16"),
    ("Gegevensdeling & Stofidentificatie", "17–18"),
    ("Phoenix Metals Casus", "19–26"),
    ("Compliance & Actieplan", "27–29"),
    ("Vragen & Discussie", "30"),
]
for i, (item, slides) in enumerate(agenda):
    y = Inches(1.6) + Inches(i * 0.52)
    add_textbox(s, Inches(0.8), y, Inches(8), Inches(0.45),
                f"▶  {item}", 15, DARK_BLUE)
    add_textbox(s, Inches(10), y, Inches(2), Inches(0.45),
                f"Slides {slides}", 13, RGBColor(0x66, 0x66, 0x66), alignment=PP_ALIGN.RIGHT)

# ══════════════════════════════════════════════════════════
# SLIDE 3 — Wat is REACH?
# ══════════════════════════════════════════════════════════
s = content_slide("Wat is REACH?", "Verordening (EG) 1907/2006", 3, WHITE)
add_content_text(s, Inches(0.8), Inches(1.6), Inches(11.5), Inches(4.5), [
    "● REgistration, Evaluation, Authorisation and restriction of CHemicals",
    "● Van kracht sinds 1 juni 2007 — verplichting gefaseerd tot 2018",
    "● Doel: bescherming menselijke gezondheid en milieu",
    "● Scope: alle chemische stoffen (individueel, in mengsels, in voorwerpen)",
    "● Verantwoordelijkheid bij producent/leverancier (verschuiving overheid → bedrijven)",
    "● Beheerd door ECHA (European Chemicals Agency, Helsinki)",
], 15, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 4 — REACH in één oogopslag
# ══════════════════════════════════════════════════════════
s = content_slide("REACH in één oogopslag", "Zes pijlers van de verordening", 4, WHITE)
items = [
    ("① Registratie", "≥1 ton/jaar →\nIUCLID dossier"),
    ("② Evaluatie", "Dossier- en\nstoffenbeoordeling"),
    ("③ Autorisatie", "SVHC → Bijlage XIV\nsunset dates"),
    ("④ Restrictie", "Bijlage XVII\ngebruiksbeperkingen"),
    ("⑤ CLP", "EG 1272/2008\nGHS-classificatie"),
    ("⑥ Informatieketen", "SDS, eSDS, DU\ncommunicatie"),
]
for i, (title, desc) in enumerate(items):
    col = i % 3
    row = i // 3
    x = Inches(0.7) + Inches(col * 4.1)
    y = Inches(1.7) + Inches(row * 2.6)
    box = add_shape_bg(s, x, y, Inches(3.7), Inches(2.2), DARK_BLUE)
    box.shadow.inherit = False
    add_textbox(s, x + Inches(0.2), y + Inches(0.2), Inches(3.3), Inches(0.5), title, 16, ORANGE, True)
    add_textbox(s, x + Inches(0.2), y + Inches(0.75), Inches(3.3), Inches(1.2), desc, 13, WHITE)

# ══════════════════════════════════════════════════════════
# SLIDE 5 — Wie valt onder REACH?
# ══════════════════════════════════════════════════════════
s = content_slide("Wie valt onder REACH?", "Art. 3 — Definities en actoren", 5, WHITE)
add_table(s, Inches(0.7), Inches(1.6), Inches(11.8), Inches(4), 
    ["Rol", "Definitie (Art. 3)", "Verplichting"],
    [
        ["Fabrikant", "In EU gevestigd, vervaardigt stof", "Registratie ≥1 ton/jaar"],
        ["Importeur", "In EU gevestigd, verantwoordelijk voor invoer", "Registratie ≥1 ton/jaar"],
        ["Downstream User", "Niet fabrikant/importeur, gebruikt stof", "Controleplicht Art. 37-39"],
        ["Enige Vertegenwoordiger (OR)", "EU-persoon aangewezen door niet-EU fabrikant", "Vervult importeur-verplichtingen"],
        ["Distributeur", "Levert stoffen, geen eigen gebruik", "SDS doorgeven, informatieplicht"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 6 — Registratieplicht
# ══════════════════════════════════════════════════════════
s = content_slide("Registratieplicht", "Art. 5-6, 12 — Drempelwaarden en tonnagebanden", 6, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(1), [
    "● Algemene plicht: ≥1 ton/jaar per fabrikant of importeur (Art. 6)",
    "● Stoffen in voorwerpen: >1 ton/jaar én bedoeld om vrij te komen (Art. 7)",
], 14, DARK_BLUE)
add_table(s, Inches(0.7), Inches(2.7), Inches(11.8), Inches(3),
    ["Tonnageband", "Bijlage", "CSR verplicht?", "Informatieniveau"],
    [
        ["1 – 10 ton/jaar", "Bijlage VII", "Nee", "Basis"],
        ["10 – 100 ton/jaar", "Bijlage VII + VIII", "Ja", "Uitgebreid"],
        ["100 – 1.000 ton/jaar", "Bijlage VII + VIII + IX", "Ja", "Gevorderd"],
        ["≥ 1.000 ton/jaar", "Bijlage VII–X", "Ja", "Volledig"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 7 — Informatie-eisen per tonnage
# ══════════════════════════════════════════════════════════
s = content_slide("Informatie-eisen per tonnage", "Bijlage VII-X — Overzicht standaardinformatie", 7, WHITE)
add_table(s, Inches(0.5), Inches(1.5), Inches(12.3), Inches(4.8),
    ["Eis", "Bijl. VII\n1-10t", "Bijl. VIII\n10-100t", "Bijl. IX\n100-1000t", "Bijl. X\n≥1000t"],
    [
        ["Fysisch-chemisch (smeltpunt, dichtheid, etc.)", "✓", "✓", "✓", "✓"],
        ["Acute toxiciteit (oraal/dermaal/inhalatie)", "✓", "✓", "✓", "✓"],
        ["Irritatie / corrosie (huid, ogen)", "✓", "✓", "✓", "✓"],
        ["Sensibilisatie (huid, luchtwegen)", "✓", "✓", "✓", "✓"],
        ["Herhaalde blootstelling (28-d / 90-d)", "○", "✓", "✓", "✓"],
        ["Genotoxiciteit (in vitro + in vivo)", "○", "✓", "✓", "✓"],
        ["Carcinogeniteit", "○", "○", "✓", "✓"],
        ["Reproductietoxiciteit", "○", "○", "✓", "✓"],
        ["Ecotoxiciteit (korter/langer)", "✓", "✓", "✓", "✓"],
        ["Afbraak / bioaccumulatie", "○", "✓", "✓", "✓"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 8 — Technisch Dossier
# ══════════════════════════════════════════════════════════
s = content_slide("Technisch Dossier", "Art. 10 — Inhoud registratiedossier", 8, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(5.5), Inches(5), [
    "Dossier bevat (Art. 10):",
    "1. Identiteit fabrikant/importeur",
    "2. Identiteit stof (CAS, EG, samenstelling)",
    "3. Informatie over vervaardiging en gebruik",
    "4. Indeling en etikettering",
    "5. Richtsnoeren veilig gebruik",
    "6-7. Onderzoekssamenvattingen",
    "8. Testvoorstellen",
    "9. Blootstellingsinformatie",
], 13, DARK_BLUE)
add_content_text(s, Inches(6.5), Inches(1.5), Inches(6), Inches(5), [
    "Tools & Systemen:",
    "● IUCLID — Dataformat voor indiening",
    "● REACH-IT — Elektronisch portaal ECHA",
    "● CSR (Art. 14) — Chemisch veiligheidsrapport",
    "   ▶ Deel A: Risicobeheersmaatregelen",
    "   ▶ Deel B: Gevaren- + blootstellingsbeoordeling",
    "● CSR verplicht bij ≥10 ton/jaar",
    "● Inquiry (Art. 26) — Check bestaande registraties",
    "● OSOR — Één stof, één registratie",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 9 — CLP Verordening
# ══════════════════════════════════════════════════════════
s = content_slide("CLP Verordening", "EG 1272/2008 — Classificatie, Labelling and Packaging", 9, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(4.5), [
    "● Gebaseerd op UN GHS (Global Harmonised System)",
    "● Alle stoffen/mengsels moeten ingedeeld worden vóór marktintroductie",
    "● Vult REACH aan voor gevarencommunicatie",
    "● Signaalwoorden: Danger (ernstig) > Warning (minder ernstig)",
    "● H-zinnen: fysisch (H200-299), gezondheid (H300-399), milieu (H400-499)",
    "● P-zinnen: preventie, reactie, opslag, verwijdering (P100-599)",
], 15, DARK_BLUE)
add_content_text(s, Inches(0.8), Inches(4.8), Inches(11.5), Inches(2), [
    "Voorrangsregels pictogrammen: GHS01 > GHS02/03; GHS06/GHS05 > GHS07; GHS08 > GHS07",
    "CLP-notificatie (PCN, Art. 40): C&L-inventaris binnen 1 maand na marktintroductie",
], 12, RGBColor(0x66, 0x66, 0x66))

# ══════════════════════════════════════════════════════════
# SLIDE 10 — Etikettering
# ══════════════════════════════════════════════════════════
s = content_slide("Etikettering", "Art. 17-25 CLP — Etiket-elementen", 10, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(3.5),
    ["Element", "Beschrijving", "Art."],
    [
        ["Leveranciergegevens", "Naam, adres, telefoonnummer", "Art. 17(a)"],
        ["Productidentificatie", "Naam stof/mengsel + CAS/EG", "Art. 18"],
        ["Gevarenpictogrammen", "Ruitvormig, zwart/wit/rood (9 GHS)", "Art. 19"],
        ["Signaalwoord", "Danger of Warning", "Art. 20"],
        ["H-zinnen", "Gevarenaanduidingen (H200-H499)", "Art. 21"],
        ["P-zinnen", "Voorzorgsmaatregelen (P100-P599)", "Art. 22"],
        ["UFI", "Unique Formula Identifier — 16 tekens alfanumeriek", "Art. 25.7"],
        ["Aanvullende info", "EUH-zinnen, specifieke vermeldingen", "Art. 25"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 11 — SDS & eSDS
# ══════════════════════════════════════════════════════════
s = content_slide("SDS & eSDS", "Art. 31 — Veiligheidsinformatieblad + uitgebreide SDS", 11, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(1.2), [
    "SDS verplicht indien: gevaarlijk (CLP), PBT/vPvB, SVHC-kandidaat — uiterlijk bij eerste levering (Art. 31)",
], 14, DARK_BLUE)
add_table(s, Inches(0.5), Inches(2.5), Inches(6), Inches(4.2),
    ["#", "Rubriek"],
    [[str(i), name] for i, name in enumerate([
        "Identificatie stof/mengsel + vennootschap",
        "Identificatie gevaren",
        "Samenstelling en bestanddelen",
        "Eerstehulpmaatregelen",
        "Brandbestrijdingsmaatregelen",
        "Maatregelen bij accidenteel vrijkomen",
        "Hantering en opslag",
        "Blootstellingsbeheersing / PBM",
        "Fysische en chemische eigenschappen",
        "Stabiliteit en reactiviteit",
        "Toxicologische informatie",
        "Ecologische informatie",
        "Verwijderingsinstructies",
        "Transportinformatie",
        "Regelgeving",
        "Overige informatie",
    ], 1)])
add_content_text(s, Inches(7), Inches(2.5), Inches(5.5), Inches(3.5), [
    "eSDS (uitgebreide SDS):",
    "● Verplicht bij ≥10 ton/jaar én gevaarlijk/PBT/vPvB",
    "● Bevat blootstellingsscenario's (ES)",
    "● Operationele omstandigheden (OC's)",
    "● Risicobeheersmaatregelen (RMM's)",
    "● DU moet instructies binnen 12 maanden toepassen",
    "● Bewaarplicht: 10 jaar (Art. 36)",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 12 — Downstream Users
# ══════════════════════════════════════════════════════════
s = content_slide("Downstream Users", "Art. 37-39 — Verplichtingen en controleplicht", 12, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(5.5), Inches(3), [
    "Kernverplichtingen DU:",
    "● Controleplicht: gebruik gedekt door SDS + ES",
    "● Informatieplicht: veilig gebruik doorgeven in keten",
    "● Documentatie: maatregelen en conclusies vastleggen",
], 14, DARK_BLUE)
add_content_text(s, Inches(7), Inches(1.5), Inches(5.5), Inches(3), [
    "Bij niet-dekking — 5 opties:",
    "a. Leverancier vragen gebruik op te nemen in CSR",
    "b. Eigen gebruiksomstandigheden aanpassen",
    "c. Stof elimineren/vervangen",
    "d. Andere leverancier zoeken",
    "e. Eigen DU CSR opstellen",
], 14, DARK_BLUE)
add_table(s, Inches(0.7), Inches(4.5), Inches(11.8), Inches(2.2),
    ["Activiteit", "Termijn"],
    [
        ["Melden gebruik (niet-geregistreerd)", "1 jaar voor registratiedeadline"],
        ["SDS maatregelen toepassen", "1 jaar na ontvangst"],
        ["DU CSR opstellen", "1 jaar na ontvangst SDS"],
        ["Melden aan ECHA (niet in ES)", "6 maanden na ontvangst SDS"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 13 — Evaluatie
# ══════════════════════════════════════════════════════════
s = content_slide("Evaluatie", "Art. 40-54 — Dossierbeoordeling en stoffenbeoordeling", 13, WHITE)
add_table(s, Inches(0.7), Inches(1.6), Inches(11.8), Inches(3.5),
    ["Type", "Art.", "Doel", "Termijn"],
    [
        ["Testvoorstellen", "Art. 40, 43", "Onnodige dierproeven voorkomen", "6-12 maanden"],
        ["Nalevingscontrole", "Art. 41", "Controleren verplichtingen", "Op prioriteit"],
        ["Stoffenbeoordeling", "Art. 44-48", "Risico gezondheid/milieu vaststellen", "Rolling"],
        ["Besluitvorming", "Art. 49-54", "Aanvullende informatie eisen", "Procedure afhankelijk"],
    ])
add_content_text(s, Inches(0.8), Inches(5.3), Inches(11.5), Inches(1.5), [
    "● Prioriteit nalevingscontrole: opt-out registraties",
    "● Beperking op dossieraanpassingen tijdens evaluatie (Art. 50)",
    "● Beroepsprocedures mogelijk (Art. 51-52)",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 14 — SVHC
# ══════════════════════════════════════════════════════════
s = content_slide("SVHC — Zorgwekkende stoffen", "Art. 57 — Criteria en kandidaatlijst", 14, WHITE)
add_table(s, Inches(0.7), Inches(1.6), Inches(11.8), Inches(3),
    ["Art.", "Gevarenklasse", "Referentie"],
    [
        ["57(a)", "Carcinogeniciteit Cat 1A/1B", "CLP Bijl. I §3.6"],
        ["57(b)", "Germ cell mutagenicity Cat 1A/1B", "CLP Bijl. I §3.5"],
        ["57(c)", "Reproductieve toxiciteit Cat 1A/1B", "CLP Bijl. I §3.7"],
        ["57(d)", "PBT — Persistent, Bioaccumulative, Toxic", "REACH Bijl. XIII"],
        ["57(e)", "vPvB — very Persistent, very Bioaccumulative", "REACH Bijl. XIII"],
        ["57(f)", "Equivalent Level of Concern (ELOC)", "Case-by-case"],
    ])
add_content_text(s, Inches(0.8), Inches(4.8), Inches(11.5), Inches(2), [
    "● Kandidaatlijst: ECHA publiceert SVHC-intenties (Art. 59) — Annex XV dossier",
    "● CMR (57a-c): volstaat met referentie CLP Bijlage VI",
    "● PBT/vPvB/ELOC (57d-f): volledige hazard assessment nodig",
    "● Publicatie op ECHA website → communicatieplicht Art. 33 bij >0,1% in voorwerp",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 15 — Autorisatie
# ══════════════════════════════════════════════════════════
s = content_slide("Autorisatie", "Art. 55-66 — Procedure en routes", 15, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(1.5), [
    "● Bijlage XIV: lijst stoffen onderworpen aan autorisatie",
    "● Sunset date: verbodsdatum — Latest application date ≥18 maanden vóór sunset date",
], 14, DARK_BLUE)
add_table(s, Inches(0.7), Inches(3.0), Inches(11.8), Inches(2),
    ["Route", "Criterium", "Beoordeling"],
    [
        ["Adequate Control", "Blootstelling < DNEL/PNEC", "RAC (4-10 maanden)"],
        ["Socio-Economic Benefits", "Voordelen > risico's, geen alternatieven", "RAC + SEAC → Commissie"],
    ])
add_content_text(s, Inches(0.8), Inches(5.2), Inches(11.5), Inches(1.5), [
    "● AoA (Analysis of Alternatives): veiliger, technisch/economisch haalbaar alternatief → substitutieplan",
    "● SEA (Socio-Economic Analysis): non-use scenario, kosten/baten vervanging",
    "● DU melding Art. 66: binnen 3 maanden na eerste levering",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 16 — Restricties
# ══════════════════════════════════════════════════════════
s = content_slide("Restricties", "Art. 67-73 — Bijlage XVII", 16, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(2), [
    "● Doel: beheersen onaanvaardbare risico's — niet gekoppeld aan registratie",
    "● Vormen: volledig verbod, concentratielimieten, gebruikbeperkingen",
    "● Fabrikanten, importeurs, DU's, distributeurs: allemaal verplicht",
    "● Bewaarplicht: 10 jaar na laatste levering",
], 14, DARK_BLUE)
add_table(s, Inches(0.7), Inches(3.8), Inches(11.8), Inches(2.2),
    ["Voorbeeld", "Restrictie"],
    [
        ["Asbest", "Volledig verbod"],
        ["Ftalaten (DEHP, e.a.)", "Concentratielimieten in speelgoed/kinderzorg"],
        ["Loodverbindingen", "Beperking in verf, sieraden"],
        ["PFAS (voorstel)", "Brede gebruikbeperking in voorbereiding"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 17 — Gegevensdeling
# ══════════════════════════════════════════════════════════
s = content_slide("Gegevensdeling", "OSOR, SIEF, Art. 26-27, LoA", 17, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(5), [
    "● OSOR (Art. 11): Één stof, één registratie — gezamenlijke indiening verplicht",
    "● Inquiry (Art. 26): Potentiële registrant vraagt ECHA of stof al geregistreerd",
    "● Art. 27: Verzoek om gegevens bij eerdere registrant → billijke, transparante kostenverdeling",
    "● LoA (Letter of Access): recht om te verwijzen naar onderzoek",
    "● SIEF's niet meer operationeel sinds 1 juni 2018",
    "● 12-jaar regel (Art. 25.3): na 12 jaar gratis gebruik door andere registranten",
    "● Uitv. Verordening (EU) 2016/9: transparantie kostenverdeling, terugbetalingsmechanisme",
], 14, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 18 — Stofidentificatie
# ══════════════════════════════════════════════════════════
s = content_slide("Stofidentificatie", "Mono/Multi/UVCB — CAS, EG-nummer, sameness", 18, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(2.5),
    ["Type", "Samenstelling", "Naamgeving"],
    [
        ["Mono-constituent", "≥80% hoofdbestanddeel", "Chemische naam hoofdbestanddeel"],
        ["Multi-constituent", "Meerdere ≥10% elk, <80%", "Reactiemengsel / blend naam"],
        ["UVCB", "Onbekend/variabel, complex", "Bron + procedé naamgeving"],
    ])
add_content_text(s, Inches(0.8), Inches(4.3), Inches(11.5), Inches(2.5), [
    "● EG-nummer: EINECS (2xx), ELINCS (4xx), NLP (5xx), Lijstnummer (6-9xx)",
    "● Sameness: 80%-regel mono-constituent; zuren/basen/zouten = verschillend",
    "● Hydraten vs watervrij: identiek | Vertakt vs lineair alkyl: verschillend",
    "● SIP (Stofidentiteitsprofiel): grenzen stofidentiteit in IUCLID (1.1 naam, 1.2 samenstelling)",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 19 — Phoenix Metals Profiel
# ══════════════════════════════════════════════════════════
s = content_slide("Phoenix Metals B.V.", "Bedrijfsprofiel — Vanadium uit secundaire grondstoffen", 19, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(4.5), [
    "● Missie: Vanadiumextractie uit SARU ash en staalslakken",
    "● Proces: Hydrometallurgisch → V₂O₅ + vanadium-elektrolyt",
    "● Locatie: PlantOne Rotterdam (demo + pilot)",
    "● Innovatie: Circulaire economie — afvalstromen upcyclen",
    "● REACH-relevantie: Nieuwe stofproductie uit afval → registratieplicht bij opschaling",
    "● PGS 15 van toepassing: ~405 kg ADR-klasse 8 (boven 250 kg ondergrens)",
], 15, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 20 — Proces
# ══════════════════════════════════════════════════════════
s = content_slide("Proces — Vanadiumextractie", "SARU ash → V₂O₅ — Hydrometallurgische route", 20, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(4.5), [
    "▶ Stap 1: SARU ash + staalslakken → logistiek aanvoer PlantOne",
    "▶ Stap 2: Zuur uitloging met H₂SO₄ (25-75%) — vanadium in oplossing",
    "▶ Stap 3: pH-correctie en zuivering (NaOH, Al₂(SO₄)₃, CaO, Mg(OH)₂)",
    "▶ Stap 4: Neerslag/kristallisatie → V₂O₅ (vanadium(V) oxide)",
    "▶ Stap 5: Reductie → vanadium-elektrolyt (UVCB mengsel)",
    "▶ Bijproducten: Fe₂O₃ (ijzeroxide), CaSO₄ (gips)",
], 15, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 21 — Grondstoffen tabel
# ══════════════════════════════════════════════════════════
s = content_slide("Stoffeninventarisatie — Grondstoffen", "Invoerstromen en REACH-status", 21, WHITE)
add_table(s, Inches(0.5), Inches(1.5), Inches(12.3), Inches(3.5),
    ["Stof", "CAS", "Volume", "REACH-status", "Verplichting"],
    [
        ["Zwavelzuur (25-75%)", "7664-93-9", "<5 ton", "Geregistreerd", "SDS aanvragen"],
        ["Natriumhydroxide (50%)", "1310-73-2", "<10 ton", "Geregistreerd", "SDS aanvragen"],
        ["Aluminiumsulfaat", "10043-01-3", "<2 ton", "Geregistreerd", "SDS aanvragen"],
        ["Calciumoxide", "1305-78-8", "<1 ton", "Geregistreerd", "SDS aanvragen"],
        ["Magnesiumhydroxide", "1309-42-8", "<1 ton", "Geregistreerd", "SDS aanvragen"],
        ["Calciumhydroxide", "1305-62-0", "<1 ton", "Geregistreerd", "SDS aanvragen"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 22 — Producten tabel
# ══════════════════════════════════════════════════════════
s = content_slide("Producten — Eindproducten", "Uitvoerstromen en REACH-regime", 22, WHITE)
add_table(s, Inches(0.3), Inches(1.5), Inches(12.7), Inches(4),
    ["Stof", "CAS", "Volume", "REACH-regime", "Verplichting"],
    [
        ["V₂O₅ (vanadium(V) oxide)", "1314-62-1", "<0.5 ton", "PPORD (Art. 9)", "Notificatie + SDS"],
        ["Vanadium-elektrolyt", "UVCB mengsel", "<0.2 ton", "PPORD (Art. 9)", "Notificatie + SDS + CLP"],
        ["Natriummetavanaadaat", "Geen apart CAS", "Sporen", "CMR-regime", "CMR-protocol"],
        ["Trinatriumorthowanaadaat", "Geen apart CAS", "Sporen", "CMR-regime", "CMR-protocol"],
        ["IJzeroxide Fe₂O₃", "1309-37-1", "<0.5 ton", "SR&D (Art. 3(23))", "Status bepalen"],
        ["Gips CaSO₄", "7778-18-9", "<1 ton", "SR&D (Art. 3(23))", "EoW beoordelen"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 23 — REACH-rechtspositie
# ══════════════════════════════════════════════════════════
s = content_slide("REACH-rechtspositie", "Drie opties voor Phoenix Metals", 23, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(3),
    ["Optie", "REACH-rol", "Waarschijnlijkheid", "Voorwaarde"],
    [
        ["A", "Fabrikant (Art. 3(8))", "Laag ⚠", "Stof is 'nieuwwaarde' creatie"],
        ["B", "Recovered substances (Art. 2(7)(d))", "Hoogst ✓", "Sameness check met geregistreerde stof"],
        ["C", "Downstream User", "Laag ⚠", "Stof reeds in mengsel geregistreerd"],
    ])
add_content_text(s, Inches(0.8), Inches(4.8), Inches(11.5), Inches(2), [
    "● Aanbeveling: Optie B (Recovered substances) — sterkste juridische basis",
    "● Vereist: sameness-toets met reeds geregistreerde V₂O₅",
    "● Let op: EoW-moment bepaalt wanneer REACH van toepassing wordt",
], 14, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 24 — SVHC Analyse
# ══════════════════════════════════════════════════════════
s = content_slide("SVHC Analyse — V₂O₅", "Art. 33, 59 — Vanadium(V) oxide als zorgwekkende stof", 24, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(2),
    ["Stof", "SVHC", "Classificatie", "Impact"],
    [
        ["V₂O₅", "Ja (sinds 2023)", "Reprotoxisch 1B (H361fd)", "Autorisatie bij >1 ton/jaar"],
        ["NiO (mogelijke verontreiniging)", "Nee", "Carc. 1A (H350i)", "CMR-protocol"],
    ])
add_content_text(s, Inches(0.8), Inches(4.0), Inches(11.5), Inches(3), [
    "● Art. 33: Informatieplicht bij >0,1% SVHC in artikel (niet van toepassing op stoffen/mengsels)",
    "● Art. 59: V₂O₅ op kandidaatlijst → kan naar Bijlage XIV (autorisatieplicht)",
    "● Huidig volume <0,5 ton/jaar → nog geen autorisatieplicht (drempel >1 ton/jaar)",
    "● Actie: Volume monitoren — bij overschrijding 1 ton/jaar → autorisatietraject starten",
], 14, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 25 — End-of-Waste
# ══════════════════════════════════════════════════════════
s = content_slide("End-of-Waste", "Kaderrichtlijn 2008/98/EG — REACH-trigger", 25, WHITE)
add_content_text(s, Inches(0.8), Inches(1.5), Inches(11.5), Inches(4.5), [
    "● Afvalstof → EoW-moment → product (REACH-toepasselijk)",
    "● EoW-criteria (Art. 6 Kaderrichtlijn):",
    "   1. Stof wordt algemeen voor specifiek doel gebruikt",
    "   2. Markt of vraag bestaat",
    "   3. Voldoet aan productnormen",
    "   4. Geen advers effecten op mens/milieu",
    "● SARU ash + staalslakken: afval → EoW → REACH van toepassing",
    "● EoW-moment = startpunt REACH-verplichtingen",
], 15, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 26 — Fasering
# ══════════════════════════════════════════════════════════
s = content_slide("Fasering — Demo → Pilot → FOAK", "Planning en acties per fase", 26, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(3),
    ["Fase", "Volume", "REACH-regime", "Actie"],
    [
        ["Demo", "≤60 kg", "PPORD/SR&D", "Notificatie ECHA"],
        ["Pilot (Q3'26–Q4'27)", "0,5–3 ton/jaar", "PPORD + monitoring", "Volume bewaken"],
        ["FOAK (>1 ton/jaar)", ">1 ton/jaar", "Volledige registratie", "CSR + SIEF + LoA"],
    ])
add_content_text(s, Inches(0.8), Inches(4.8), Inches(11.5), Inches(2), [
    "● Demo (2026): PPORD-notificatie bij ECHA, 5 jaar geldig",
    "● Pilot: Volume bewaken — bij overschrijding tonnageband → nieuwe verplichtingen",
    "● FOAK: Volledige REACH-registratie + Vanadium Consortium LoA",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 27 — Compliance Status
# ══════════════════════════════════════════════════════════
s = content_slide("Compliance Status", "Huidige status per domein", 27, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(4.5),
    ["Domein", "Status", "Opmerking"],
    [
        ["Stoffeninventarisatie", "✓ Groen", "Alle 12 stoffen geïnventariseerd"],
        ["SDS Grondstoffen", "⚠ Geel", "SDS'en aanvragen bij leveranciers"],
        ["PPORD Notificatie", "⚠ Geel", "Demo-notificatie ECHA voorbereiden"],
        ["CLP Classificatie", "✓ Groen", "V₂O₅ en mengsels ingedeeld"],
        ["REACH-rechtspositie", "✓ Groen", "Optie B (Recovered) bevestigd"],
        ["SVHC Monitoring", "✓ Groen", "V₂O₅ op kandidaatlijst, volume <1 ton"],
        ["EoW Beoordeling", "⚠ Geel", "Criteria moeten worden gedocumenteerd"],
        ["PGS 15 Opslag", "✗ Rood", ">250 kg ADR-klasse 8 — volledige naleving vereist"],
        ["DU Verplichtingen", "✓ Groen", "Controleplicht SD'en afgedekt"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 28 — Actieplan
# ══════════════════════════════════════════════════════════
s = content_slide("Actieplan — Top 10", "Geprioriteerde acties voor REACH compliance", 28, WHITE)
add_table(s, Inches(0.3), Inches(1.5), Inches(12.7), Inches(5),
    ["#", "Actie", "Prioriteit", "Deadline", "Eigenaar"],
    [
        ["1", "SDS'en alle grondstoffen aanvragen", "Hoog", "Q2 2026", "Inkoop"],
        ["2", "PPORD-notificatie ECHA indienen", "Hoog", "Q2 2026", "HSEQ"],
        ["3", "Sameness-toets V₂O₅ uitvoeren", "Hoog", "Q3 2026", "R&D"],
        ["4", "EoW-criteria documenteren", "Hoog", "Q3 2026", "HSEQ + R&D"],
        ["5", "PGS 15 naleving realiseren", "Hoog", "Q3 2026", "Facilities"],
        ["6", "Volume monitoring systeem inrichten", "Medium", "Q3 2026", "Operations"],
        ["7", "CLP-etiketten produkken (V₂O₅ + elektrolyt)", "Medium", "Q3 2026", "HSEQ"],
        ["8", "Vanadium Consortium benaderen (LoA)", "Medium", "Q4 2026", "HSEQ"],
        ["9", "DU CSR template voorbereiden", "Laag", "Q1 2027", "HSEQ"],
        ["10", "Budget FOAK-registratie reserveren", "Laag", "Q1 2027", "Management"],
    ])

# ══════════════════════════════════════════════════════════
# SLIDE 29 — Budgetraming
# ══════════════════════════════════════════════════════════
s = content_slide("Budgetraming", "Kosten per fase", 29, WHITE)
add_table(s, Inches(0.7), Inches(1.5), Inches(11.8), Inches(3),
    ["Fase", "Budget", "Scope"],
    [
        ["Demo (2026)", "~€ 5.000", "PPORD notificatie, SDS'en, basale compliance"],
        ["Pilot (Q3'26–Q4'27)", "€ 15.000–45.000", "Monitoring, EoW, PGS 15, CLP"],
        ["FOAK (>1 ton/jaar)", "€ 120.000–290.000", "Volledige registratie, CSR, SIEF"],
        ["Vanadium Consortium LoA", "€ 15.000–40.000", "Toegang gezamenlijke gegevens"],
    ])
add_content_text(s, Inches(0.8), Inches(5.0), Inches(11.5), Inches(1.5), [
    "● MKB-korting ECHA: van toepassing indien <250 medewerkers",
    "● LoA-kosten eenmalig; jaarlijkse SIEF-bijdrage variabel",
    "● Budget FOAK sterk afhankelijk van tonnageband en complexiteit CSR",
], 13, DARK_BLUE)

# ══════════════════════════════════════════════════════════
# SLIDE 30 — Vragen & Discussie
# ══════════════════════════════════════════════════════════
s = prs.slides.add_slide(BLANK_LAYOUT)
add_bg(s, DARK_BLUE)
add_shape_bg(s, Inches(0), Inches(3.0), SLIDE_W, Inches(0.06), ORANGE)
add_textbox(s, Inches(1), Inches(2.0), Inches(11), Inches(1),
            "Vragen & Discussie", 44, WHITE, True, PP_ALIGN.CENTER)
add_textbox(s, Inches(1), Inches(3.5), Inches(11), Inches(1),
            "Phoenix Metals B.V. — REACH Compliance\n26 april 2026", 18, RGBColor(0xBB, 0xCC, 0xDD), alignment=PP_ALIGN.CENTER)
add_textbox(s, Inches(1), Inches(5.0), Inches(11), Inches(0.5),
            "⚠ VERTROUWELIJK", 16, ORANGE, True, PP_ALIGN.CENTER)
add_footer(s, 30)

# ── Opslaan ──
output = "/root/projects/jg/2026-reach-phoenix-metals-v2/deliverables/pptx/REACH_Presentatie_Phoenix_Metals_v1.0.pptx"
prs.save(output)
print(f"✅ PPTX opgeslagen: {output}")
print(f"   Slides: {len(prs.slides)}")
