#!/usr/bin/env python3
"""Genereer Kennisdossier Part B — H5 t/m H9 + Bijlagen (PGS-15 Phoenix Metals)"""

from docx import Document
from docx.shared import Pt, Cm, RGBColor, Inches
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn, nsdecls
from docx.oxml import parse_xml
import os

OUTPUT = "/root/projects/jg/2026-pgs15-phoenix-metals/working/map/doc01_partB.docx"

doc = Document()

# ── Default style ──
style = doc.styles['Normal']
font = style.font
font.name = 'Calibri'
font.size = Pt(11)
font.color.rgb = RGBColor(0x1F, 0x29, 0x37)

for lvl in range(1, 4):
    hs = doc.styles[f'Heading {lvl}']
    hs.font.name = 'Calibri'
    hs.font.color.rgb = RGBColor(0x00, 0x33, 0x66)
    hs.font.bold = True
    if lvl == 1:
        hs.font.size = Pt(16)
    elif lvl == 2:
        hs.font.size = Pt(14)
    else:
        hs.font.size = Pt(12)

HEADER_BG = "003366"

def set_cell_shading(cell, color):
    shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{color}"/>')
    cell._tc.get_or_add_tcPr().append(shading_elm)

def set_cell_text(cell, text, bold=False, white=False, size=Pt(10)):
    cell.text = ""
    p = cell.paragraphs[0]
    run = p.add_run(text)
    run.font.name = 'Calibri'
    run.font.size = size
    run.font.bold = bold
    if white:
        run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
    p.paragraph_format.space_after = Pt(2)
    p.paragraph_format.space_before = Pt(2)

def header_row(table, texts):
    row = table.rows[0]
    for i, t in enumerate(texts):
        set_cell_text(row.cells[i], t, bold=True, white=True)
        set_cell_shading(row.cells[i], HEADER_BG)

def add_table(doc, headers, rows, col_widths=None):
    ncols = len(headers)
    t = doc.add_table(rows=1 + len(rows), cols=ncols, style='Table Grid')
    t.alignment = WD_TABLE_ALIGNMENT.CENTER
    header_row(t, headers)
    for ri, row_data in enumerate(rows):
        for ci, val in enumerate(row_data):
            set_cell_text(t.rows[ri + 1].cells[ci], str(val))
            if ri % 2 == 1:
                set_cell_shading(t.rows[ri + 1].cells[ci], "F8F9FA")
    if col_widths:
        for ri in range(len(t.rows)):
            for ci, w in enumerate(col_widths):
                t.rows[ri].cells[ci].width = Cm(w)
    return t

def p(text):
    doc.add_paragraph(text)

# ═══════════════════════════════════════════════════════════
# H5: BASISVEILIGHEIDSNIVEAU MAATREGELEN
# ═══════════════════════════════════════════════════════════
doc.add_heading('5. Basisveiligheidsniveau Maatregelen', level=1)

p("Dit hoofdstuk behandelt alle maatregelen die behoren tot het basisveiligheidsniveau van PGS 15:2025. Het basisveiligheidsniveau is het minimumniveau dat ALTIJD van toepassing is, ongeacht de hoeveelheid opgeslagen gevaarlijke stoffen. Phoenix Metals (PM) valt met circa 300 liter ADR-klasse 8 stoffen ver onder alle drempelwaarden uit Tabel 6 en Tabel 7 van PGS 15. Desondanks gelden de basismaatregelen volledig en onverminderd.")

p("De navolgende paragrafen beschrijven per maatregel het vereiste uit PGS 15, het belang ervan voor de veiligheid, de huidige status bij Phoenix Metals en de benodigde acties. De statusaanduidingen zijn: ✅ Compliant, ⚠️ Gedeeltelijk compliant / nader te toetsen, ❌ Niet compliant.")

# ── MW1 Zorgplicht ──
doc.add_heading('5.1 MW1 — Zorgplicht', level=2)
p("MW1 is de fundamentele zorgplichtbepaling uit PGS 15:2025. Degene die gevaarlijke stoffen opslaat of gebruikt, is verplicht om voldoende beschermende maatregelen te nemen ter voorkoming van ongevallen en schade aan mens, milieu en eigendommen. Deze zorgplicht omvat vier pijlers: beschermende maatregelen (technisch en organisatorisch), goede praktijken (best practices uit de sector), good housekeeping (orde, netheid, reinheid) en vakmanschap (bekwaam personeel).")
p("Voor Phoenix Metals betekent MW1 dat het bedrijf aantoonbaar inzicht moet hebben in de risico's van de opgeslagen stoffen en dat maatregelen proportioneel en adequaat zijn. De zorgplicht geldt zowel voor normale bedrijfssituaties als voor storingen en calamiteiten. Het is een algemene plicht die alle andere maatregelen draagt: zonder zorgplicht geen effectieve uitvoering van M2 t/m M109.")
p("Belang: MW1 is het fundament van het gehele veiligheidsbeheerssysteem. Het verplicht PM tot proactieve risicobeheersing in plaats van reactief handelen na een incident.")
p("Status PM: ⚠️ Gedeeltelijk compliant. PM heeft een chemisch register opgesteld (v2.1.0) en de stoffen zijn geïnventariseerd. Echter, een formele Risico-Inventarisatie en -Evaluatie (RI&E) specifiek voor de opslag van gevaarlijke stoffen is nog niet gedocumenteerd.")
p("Actie PM: Stel een RI&E op voor de opslaglocatie, documenteer de zorgplichtmaatregelen systematisch, en zorg dat good housekeeping-routines (wekelijkse inspectie van de opslaglocatie) worden geïmplementeerd en geregistreerd.")

# ── M2 ──
doc.add_heading('5.2 M2 — Opslaan verpakte gevaarlijke stoffen', level=2)
p("M2 vereist dat gevaarlijke stoffen uitsluitend worden opgeslagen in een daarvoor bestemde opslagvoorziening. Dit betekent dat de opslaglocatie moet zijn ingericht met het oog op de specifieke eigenschappen van de stoffen: voldoende ventilatie, vloeistofopvang, stoffenscheiding en toegankelijkheid voor hulpdiensten. De enige uitzondering is werkvoorraad (zie M14): een beperkte hoeveelheid die direct nodig is voor lopend werk.")
p("Belang: Opslag in een niet-daarvoor bestemde ruimte verhoogt het risico op onbeheersbare situaties aanzienlijk. Denk aan reacties tussen onverenigbare stoffen, lekkage in kantoorgebieden, of ontoegankelijkheid bij brand.")
p("Status PM: ⚠️ Nader te toetsen. De stoffen staan momenteel op een 'rack in front of lab'. De vraag is of deze locatie kwalificeert als een 'daartoe bestemde opslagvoorziening' conform PGS 15. De locatie moet voldoen aan alle basismaatregelen (stoffscheiding, vloeistofopvang, ventilatie, toegankelijkheid).")
p("Actie PM: Beoordeel of de huidige rack-locatie voldoet aan de PGS 15-eisen voor een bestemde opslagvoorziening. Indien niet: richt een aparte opslagruimte in of pas de huidige locatie aan met lekbakken, vakmarkeringen en ventilatie.")

# ── M3 ──
doc.add_heading('5.3 M3 — Vereist veiligheidsniveau', level=2)
p("M3 verwijst naar Tabel 6 van PGS 15, die per ADR-klasse en verpakkingsgroep het vereiste veiligheidsniveau aangeeft op basis van de totale opgeslagen hoeveelheid. De niveaus zijn: basisveiligheidsniveau (PM = basis), VN-B (60 minuten brandwerendheid, doelen D6/D10/D11) en VN-A (semi-automatische blussing, doel D12). Voor ADR-klasse 8 verpakkingsgroep II/III onbrandbaar geldt dat het basisveiligheidsniveau ALTIJD volstaat, ongeacht de hoeveelheid.")
p("Belang: Het veiligheidsniveau bepaalt de omvang van de investering in veiligheidsmaatregelen. Een te laag niveau is niet-compliant; een te hoog niveau is onnodig kostbaar.")
p("Status PM: ✅ Compliant. Met circa 300 liter ADR 8 VGII onbrandbare stoffen valt PM ruim onder alle drempelwaarden. Het basisveiligheidsniveau is het enige vereiste niveau. Aanvullende veiligheidsniveaus (VN-A, VN-B) zijn niet van toepassing.")

# ── M14 ──
doc.add_heading('5.4 M14 — Werkvoorraad', level=2)
p("M14 regelt de uitzondering op de opslageis (M2). Werkvoorraad is de hoeveelheid gevaarlijke stoffen die direct nodig is voor lopende werkzaamheden en tijdelijk buiten de opslagvoorziening mag staan. De limiet is strikt: per stof maximaal één aangebroken verpakking plus één nieuwe, ongeopende verpakking. Deze regeling is bedoeld om efficiëntie in het werkproces mogelijk te maken, maar mag niet worden gebruikt als verkapte opslag.")
p("Belang: Werkvoorraad is de belangrijkste bron van 'schaduwopslag' — de onzichtbare hoeveelheid gevaarlijke stoffen die elders in het bedrijf staat. Dit ondermijnt het veiligheidsniveau en kan leiden tot onverwachte reacties.")
p("Status PM: ⚠️ Nader te toetsen. Het is onduidelijk of de huidige opstelling op het rack als opslag dan wel als werkvoorraad moet worden beschouwd. Indien het rack zich direct naast het lab bevindt, kan een deel als werkvoorraad kwalificeren, maar het totale volume (300 liter) overstijgt duidelijk de werkvoorraadlimiet voor één stof.")
p("Actie PM: Definieer per stof wat werkvoorraad is (maximaal 1× aangebroken + 1× nieuw). Plaats alle overige voorraden in de daartoe bestemde opslagvoorziening. Documenteer de werkvoorraadlimieten.")

# ── M15 ──
doc.add_heading('5.5 M15 — Maximale omvang brandcompartiment', level=2)
p("M15 stelt grenzen aan de oppervlakte van een brandcompartiment waarin gevaarlijke stoffen worden opgeslagen. Zonder vaste blusinstallatie (VBB) is het maximum 1.000 m²; met VBB is 2.500 m² toegestaan. Deze limieten gelden per brandcompartiment en zijn bedoeld om de impact van een brand te begrenzen.")
p("Belang: Een te groot brandcompartiment betekent dat een brand meer brandstof vindt en moeilijker te blussen is. De oppervlaktelimiet is een passieve brandpreventiemaatregel.")
p("Status PM: ✅ Compliant. De huidige opslag bevindt zich in één brandcompartiment (rack in front of lab) met een oppervlakte die ver beneden 1.000 m² ligt. Geen VBB vereist.")

# ── M30 ──
doc.add_heading('5.6 M30 — Vloeistofopvang', level=2)
p("M30 vereist dat vloeibare gevaarlijke stoffen worden opgeslagen met voldoende vloeistofopvang (lekbakken, opsluitputten). De opvangcapaciteit moet minimaal 110% bedragen van het volume van de grootste verpakking in de lekbak. Voor Phoenix Metals betekent dit: de grootste verpakking is een 25-liter jerrycan, dus de lekbak moet minimaal 27,5 liter kunnen bevatten. Lekbakken moeten chemisch bestendig zijn tegen de opgeslagen stoffen.")
p("Belang: Vloeistofopvang voorkomt dat lekkage zich verspreidt over de vloer, andere stoffen contaminatieert, of in het milieu terechtkomt. Bij PM zijn de stoffen bijtend (NaOH 50%, H₂SO₄): lekkage zonder opvang leidt tot ernstige veiligheidsrisico's.")
p("Status PM: ⚠️ Nader te toetsen. Er is geen documentatie beschikbaar over de aanwezigheid en capaciteit van lekbakken bij het rack. Dit is een kritiek aandachtspunt.")
p("Actie PM: Verkrijg lekbakken voor alle vliebare ADR 8 stoffen. Per lekbak: minimaal 110% van het volume van de grootste verpakking erin. Markeer de lekbakken met de inhoud. Budget: circa €50–150 per lekbak.")

# ── M35 ──
doc.add_heading('5.7 M35 — Stoffenscheiding', level=2)
p("M35 vereist dat onverenigbare stoffen gescheiden worden opgeslagen volgens de compatibiliteitsmatrix uit Tabel 9 (PGS 15 Bijlage E). De scheidingniveaus zijn: V (aparte vakken binnen één opslag), B (beoordelen — gescheiden opslag tenzij VIB aantoont dat geen reactie optreedt) en A (apart brandcompartiment of 5 m vrije zone — strengste scheiding).")
p("Belang: Verkeerde stoffencombinaties leiden tot exotherme reacties, gasvorming, brand of explosie. Bij PM is het kritieke punt de combinatie van NaOH (base) en H₂SO₄ (zuur): deze reageren heftig exotherm en vereisen A-scheiding.")
p("Status PM: ❌ Niet compliant. NaOH 50% en H₂SO₄ (alle concentraties) staan op hetzelfde rack zonder scheiding. Tabel 9 geeft A voor ADR 8 ↔ ADR 8 (bijtende combinaties). Bovendien vereist de combinatie H₂SO₄ ↔ CaO (calciumoxide) eveneens A-scheiding, aangezien CaO sterk basisch reageert met zuren.")
p("Actie PM (DRINGEND): Plaats NaOH in een aparte lekbak met minimaal 2 m afstand tot de H₂SO₄-lekbak. Plaats CaO apart van alle zwavelzuurproducten (A-scheiding). Markeer de vakken duidelijk. Pas de E.3-uitzondering toe (bij <10.000 kg): scheiding binnen één vak via 2 m afstand of aparte lekbakken.")

# ── M36 ──
doc.add_heading('5.8 M36 — Verpakkingsintegriteit', level=2)
p("M36 vereist dat verpakkingen van gevaarlijke stoffen regelmatig worden gecontroleerd op beschadiging, corrosie, veroudering en lekkage. Beschadigde verpakkingen moeten direct worden vervangen of veiliggesteld. Ook de etikettering (CLP/ADR) moet intact en leesbaar blijven.")
p("Belang: Een lekkende jerrycan met 50% NaOH of 75% H₂SO₄ vormt een acuut risico voor personeel. Corrosie van de verpakking is een sluipend risico, zeker bij zuren en basen.")
p("Status PM: ⚠️ Nader te toetsen. Er is geen documentatie over de staat van de verpakkingen. De jerrycans moeten visueel worden geïnspecteerd op scheuren, deukvorming, corrosie en etiketleesbaarheid.")
p("Actie PM: Voer een eenmalige inspectie uit van alle 18 jerrycans en 4 canisters. Documenteer de bevindingen. Stel een routine in: maandelijkse visuele controle van alle verpakkingen.")

# ── M45 ──
doc.add_heading('5.9 M45 — Correct gebruik', level=2)
p("M45 betreft het correct hanteren en stapelen van verpakkingen met gevaarlijke stoffen. Hantering moet zodanig gebeuren dat verpakkingen niet beschadigen (geen slepen, gooien, of stapelen buiten de ontworpen stapellimiet). Stapeling moet stabiel zijn en rekening houden met de maximale stapelhoogte en het gewicht.")
p("Belang: Onjuiste hantering is een van de belangrijkste oorzaken van lekkage en ongevallen. Een omvallende stapel jerrycans met zwavelzuur heeft directe consequenties voor veiligheid en milieu.")
p("Status PM: ⚠️ Nader te toetsen. De opslag op het rack moet worden beoordeeld op stapelstabiliteit en toegankelijkheid. Zorg dat jerrycans niet boven ooghoogte worden gestapeld en dat alle verpakkingen bereikbaar zijn zonder andere verpakkingen te hoeven verplaatsen.")

# ── M77/M78 ──
doc.add_heading('5.10 M77/M78 — Fysieke bescherming', level=2)
p("M77 vereist dat opslagvoorzieningen zijn beschermd tegen aanrijdingen door voertuigen of heftrucks (botsbeveiliging). M80 stelt eisen aan de constructieve veiligheid van stellingen en rekken: deze moeten geschikt zijn voor het opgeslagen gewicht, stabiel zijn en regelmatig worden geïnspecteerd.")
p("Belang: Aanrijding is een van de meest voorkomende oorzaken van ongevallen met gevaarlijke stoffen. Een heftruck die een rack met bijtende stoffen ramt, creëert een directe noodsituatie.")
p("Status PM: ⚠️ Nader te toetsen. Het rack staat 'in front of lab' — de ligging ten opzichte van verkeersroutes (heftrucks, palletwagens) moet worden beoordeeld. Indien er verkeer in de nabijheid is, zijn botsbeveiligers (stootblokken, hekwerk) verplicht. De constructieve staat van het rack moet eveneens worden geïnspecteerd.")

# ── M85/M86 ──
doc.add_heading('5.11 M85/M86 — Personeelsdeskundigheid', level=2)
p("M85 vereist dat personeel dat werkt met of in de nabijheid van gevaarlijke stoffen adequaat is opgeleid en geïnstrueerd. Dit omvat kennis van de eigenschappen van de stoffen, de juiste persoonlijke beschermingsmiddelen (PBM), en de procedures bij lekkage of calamiteiten. M86 betreft de noodorganisatie: personeel moet weten wat te doen bij een incident, inclusief alarmprocedure, evacuatie en first-respondermaatregelen.")
p("Belang: Zelfs de best ingerichte opslag is onveilig als het personeel niet weet hoe ermee om te gaan. Bijtende stoffen vereisen specifieke PBM (zuurbestendige handschoenen, gezichtsscherm, schort) en specifieke eerste hulp (ruim spoelen met water bij huidcontact).")
p("Status PM: ⚠️ Nader te toetsen. Het is niet gedocumenteerd of medewerkers die in de buurt van het rack werken, instructie hebben ontvangen over de stoffen, PBM en calamiteitenprocedures.")
p("Actie PM: Stel een instructiekaart op bij het rack ('Wat te doen bij lekkage van NaOH/H₂SO₄'). Zorg dat alle medewerkers in de nabijheid een basisinstructie hebben gehad. Organiseer jaarlijks een herhaling. Zorg dat SDS/VIB per stof raadpleegbaar zijn in de nabijheid van de opslag.")

# ── M109 ──
doc.add_heading('5.12 M109 — Toegankelijkheid hulpdiensten', level=2)
p("M109 vereist dat de opslaglocatie bereikbaar en toegankelijk is voor hulpdiensten (brandweer, ambulance). Dit betekent: voldoende brede toegangswegen, duidelijke adresnummering, geen obstakels bij de ingang, en de locatie moet op de bedrijfsplattegrond zijn aangegeven.")
p("Belang: Bij een calamiteit met bijtende stoffen is snelle interventie door de brandweer essentieel. Ontoegankelijkheid kan de gevolgen van een incident aanzienlijk verergeren.")
p("Status PM: ⚠️ Nader te toetsen. De bereikbaarheid van het rack voor hulpdiensten moet worden geëvalueerd. Indien het rack zich in een afgesloten ruimte bevindt, moet de brandweer de locatie kunnen vinden en betreden zonder vertraging.")

# Overzichtstabel H5
doc.add_heading('5.13 Overzicht Maatregelen Basisveiligheidsniveau', level=2)
add_table(doc,
    ["M-nr", "Maatregel", "Status PM", "Prioriteit"],
    [
        ["MW1", "Zorgplicht (bescherming, vakmanschap, housekeeping)", "⚠️", "Hoog"],
        ["M2", "Opslaan in bestemde opslagvoorziening", "⚠️", "Hoog"],
        ["M3", "Vereist veiligheidsniveau (Tabel 6)", "✅", "—"],
        ["M14", "Werkvoorraad (1× aangebroken + 1× nieuw)", "⚠️", "Gemiddeld"],
        ["M15", "Max. omvang brandcompartiment", "✅", "—"],
        ["M30", "Vloeistofopvang (lekbakken, 110%)", "⚠️", "Kritiek"],
        ["M35", "Stoffenscheiding (Tabel 9, Bijlage E)", "❌", "Kritiek"],
        ["M36", "Verpakkingsintegriteit (controle)", "⚠️", "Gemiddeld"],
        ["M45", "Correct gebruik (hantering, stapeling)", "⚠️", "Gemiddeld"],
        ["M77/M78", "Fysieke bescherming (botsbeveiliging, stellingen)", "⚠️", "Gemiddeld"],
        ["M85/M86", "Personeelsdeskundigheid (opleiding, noodorganisatie)", "⚠️", "Hoog"],
        ["M109", "Toegankelijkheid hulpdiensten", "⚠️", "Gemiddeld"],
    ],
    col_widths=[2, 7, 2.5, 2.5]
)

# ═══════════════════════════════════════════════════════════
# H6: BRANDPREVENTIE EN COMPARTIMENTERING
# ═══════════════════════════════════════════════════════════
doc.add_heading('6. Brandpreventie en Compartimentering', level=1)

doc.add_heading('6.1 Brandgerelateerde doelen', level=2)
p("PGS 15:2025 definieert zes brandgerelateerde doelen die leidend zijn voor de brandpreventiemaatregelen. Voor Phoenix Metals (basisveiligheidsniveau, ADR 8 onbrandbaar) zijn de volgende doelen relevant:")

add_table(doc,
    ["Doel", "Omschrijving", "Van toepassing op PM?"],
    [
        ["D8", "Voorkomen van ontsteking (brandpreventie door bronbeheersing)", "Ja — basis"],
        ["D9", "Beperken van brand in opslag (brandontwikkeling beperken)", "Ja — basis"],
        ["D10", "Beperken van passieve escalatie (brandoverslag via constructie)", "Alleen bij VN-B+"],
        ["D11", "Beperken van actieve escalatie (brandoverslag via straling)", "Alleen bij VN-B+"],
        ["D12", "Semi-automatische blussing (VBB-installatie)", "Alleen bij VN-A"],
    ],
    col_widths=[1.5, 7, 3.5]
)
p("Voor PM geldt uitsluitend het basisniveau: D8 (ontstekingspreventie) en D9 (brandbeperking). De doelen D10, D11 en D12 zijn gerelateerd aan hogere veiligheidsniveaus (VN-B en VN-A) en zijn pas vereist bij volumes boven 10.000 kg ADR 8 VGI.")

doc.add_heading('6.2 Brandwerendheid Wbdbo per veiligheidsniveau', level=2)
p("De brandwerendheid van de buitenwand (Wbdbo) is de tijd gedurende welke de wand zijn functie behoudt bij brand. De eisen nemen toe naarmate het veiligheidsniveau stijgt:")

add_table(doc,
    ["Veiligheidsniveau", "Wbdbo vereist", "Bbl-eis"],
    [
        ["Basis (VN-basis)", "Bbl (Bouwbesluit eis)", "Volstaat"],
        ["VN-B", "60 minuten", "Bbl onvoldoende"],
        ["VN-A", "60–90 minuten", "Bbl onvoldoende"],
    ],
    col_widths=[4, 4, 4]
)
p("Voor PM volstaat de Bbl-eis (Bouwbesluit). Er zijn geen aanvullende brandwerendheidseisen, omdat het basisveiligheidsniveau van toepassing is en de opgeslagen stoffen onbrandbaar zijn.")

doc.add_heading('6.3 Brandcompartiment opperveltektrimiten', level=2)
p("M15 stelt maximale oppervlaktes voor brandcompartimenten met gevaarlijke stoffen. Zonder vaste blusinstallatie (VBB) geldt een maximum van 1.000 m²; met VBB is 2.500 m² toegestaan. Bij volumes boven 20.000 kg zonder VBB gelden strengere eisen. PM bevindt zich met een klein rack ver onder deze limieten. De oppervlaktelimiet is een passieve brandpreventiemaatregel: door de brandcompartimentgrootte te beperken, wordt de potentiële impact van een brand van nature begrensd.")

doc.add_heading('6.4 NEN 6060 / NEN 6079 referenties', level=2)
p("NEN 6060 (brandwerendheid van bouwconstructies) en NEN 6079 (brandcompartimentering) zijn de normen die ten grondslag liggen aan de Wbdbo-eisen. Bij hogere veiligheidsniveaus (VN-B, VN-A) moeten wanden, deuren en leidingdoorvoerende constructies aantoonbaar voldoen aan de vereiste brandwerendheid conform deze normen. Voor het basisniveau volstaat de reguliere Bbl-eis, die automatisch verwijst naar NEN 6060 voor de constructieve uitvoering.")

doc.add_heading('6.5 Conclusie PM: basisniveau volstaat', level=2)
p("Phoenix Metals valt onder het basisveiligheidsniveau. De brandcompartimenteringseisen zijn beperkt tot het Bbl-niveau. Er is geen sprake van VN-B of VN-A eisen, waardoor de investering in brandpreventie laag blijft. De enige aandachtspunten zijn: zorgen dat de opslaglocatie geen brandbare materialen bevat (D8), en dat de stoffscheiding (M35) correct wordt uitgevoerd om reacties tussen stoffen te voorkomen die alsnog tot brand kunnen leiden.")

# ═══════════════════════════════════════════════════════════
# H7: SCHAALBAARHEID-SCENARIO'S
# ═══════════════════════════════════════════════════════════
doc.add_heading('7. Schaalbaarheids-Scenario\'s', level=1)
p("Dit hoofdstuk beschrijft de groeiscenario's voor Phoenix Metals. Bij schaling van de opslaghoeveelheid veranderen de vereiste veiligheidsniveaus en daarmee de investeringsbehoefte. De volgende fasen zijn gebaseerd op de drempelwaarden uit PGS 15 Tabel 6 en Tabel 7.")

doc.add_heading('7.1 Fase 1: < 10.000 kg — Basisniveau + 60 min Wbdbo', level=2)
p("Bij opslag van minder dan 10.000 kg ADR 8 bijtende stoffen blijft het basisveiligheidsniveau van toepassing. De enige aanvullende eis is dat de buitenwand van de opslagruimte minimaal 60 minuten brandwerendheid (Wbdbo) biedt. Dit is in veel gevallen al vervuld door de bestaande bouwconstructie (Bbl-eis). Aanvullende maatregelen beperken zich tot lekbakken, stoffscheiding, goede huisstijl en personeelsinstructie.")
p("Investeringsraming: €5.000–€15.000. Dit omvat lekbakken, vakmarkeringen, instructiekaarten, SDS-documentatie en eventueel aanpassingen aan de opslagruimte.")

doc.add_heading('7.2 Fase 2: 10.000–20.000 kg — VN-B (D6, D10, D11)', level=2)
p("Bij opslag tussen 10.000 en 20.000 kg ADR 8 VGI bijtende stoffen wordt veiligheidsniveau VN-B vereist. Dit activeert de brandgerelateerde doelen D6 (brandcompartimentering), D10 (passieve escalatiebeperking) en D11 (actieve escalatiebeperking). Concreet betekent dit: de scheidingswand tussen opslag en aangrenzende ruimtes moet minimaal 60 minuten brandwerend zijn, het brandcompartiment is gemaximaliseerd tot 1.000 m², en er moeten aanvullende blusmaatregelen worden getroffen (bijv. brandslanghaspel of draagbaar blusapparaat met voldoende capaciteit).")
p("Investeringsraming: €25.000–€75.000. Dit omvat brandwerende constructies, blusvoorzieningen en uitgebreide detectie.")

doc.add_heading('7.3 Fase 3: > 20.000 kg — VN-A (D12, VBB, PAC-doormelding)', level=2)
p("Bij opslag boven 20.000 kg ADR 8 VGI wordt veiligheidsniveau VN-A vereist. Dit is het hoogste niveau en omvat semi-automatische blussing (doel D12): een vaste blusinstallatie (VBB) die automatisch of op afstand wordt geactiveerd. Daarnaast is branddetectie met doormelding naar de Provinciale Alarmcentrale (PAC) of Regionale Alarmcentrale (RAC) verplicht (M97). Het brandcompartiment mag maximaal 2.500 m² bedragen mét VBB, anders is het ontoegankelijk. Ook is een Uitgebreid Preventie Dossier (UPD) vereist onder de Omgevingswet.")
p("Investeringsraming: €100.000–€300.000+. Dit omvat VBB-installatie, branddetectiesysteem met PAC-koppeling, brandwerende constructies van 60–90 minuten, en het UPD-traject met adviesbureau en vergunningsaanvraag.")

doc.add_heading('7.4 Overzichtstabel Schaalbaarheid', level=2)
add_table(doc,
    ["Fase", "Volume ADR 8", "Vereist niveau", "Wbdbo", "Investering"],
    [
        ["Huidig", "~300 l (~390 kg)", "Basis", "Bbl", "Lekbakken + scheiding"],
        ["Fase 1", "< 10.000 kg", "Basis + 60 min", "60 min", "€5K–€15K"],
        ["Fase 2", "10.000–20.000 kg", "VN-B (D6/D10/D11)", "60 min", "€25K–€75K"],
        ["Fase 3", "> 20.000 kg", "VN-A (D12)", "60–90 min", "€100K–€300K+"],
    ],
    col_widths=[2, 3.5, 3.5, 2, 3.5]
)

doc.add_heading('7.5 Tijdspad implementatie per fase', level=2)
add_table(doc,
    ["Fase", "Doorlooptijd", "Kritieke activiteiten"],
    [
        ["Huidig", "1–2 weken", "Lekbakken aanschaffen, vakmarkering, SDS-map, instructiekaart"],
        ["Fase 1", "4–8 weken", "Brandwerende constructie toetsen, evt. aanpassen, RI&E afronden"],
        ["Fase 2", "3–6 maanden", "Brandwerende wanden plaatsen, blusvoorzieningen installeren, vergunning aanvragen"],
        ["Fase 3", "6–12 maanden", "VBB-ontwerp en installatie, PAC-doormelding, UPD opstellen, omgevingsvergunning"],
    ],
    col_widths=[2, 3, 8]
)

# ═══════════════════════════════════════════════════════════
# H8: COMPLIANCE CHECKLIST
# ═══════════════════════════════════════════════════════════
doc.add_heading('8. Compliance Checklist', level=1)
p("De volgende checklist biedt een compleet overzicht van alle voor Phoenix Metals relevante PGS 15-maatregelen op basisniveau. De status is gebaseerd op de analyse in hoofdstuk 5. Kolom 'Vereiste' beschrijft de PGS 15-eis in één zin. Kolom 'Toelichting' geeft de PM-specifieke context.")

add_table(doc,
    ["M-nr", "Maatregel", "Vereiste", "Status", "Toelichting"],
    [
        ["MW1", "Zorgplicht", "Beschermende maatregelen, vakmanschap, good housekeeping", "⚠️", "RI&E ontbreekt; good housekeeping-routine ontbreekt"],
        ["M2", "Bestemde opslag", "Opslag in daartoe bestemde voorziening", "⚠️", "Rack bij lab: toetsen of dit als bestemde voorziening kwalificeert"],
        ["M3", "Veiligheidsniveau", "Tabel 6 bepalen en toepassen", "✅", "Basisveiligheidsniveau volstaat (~300 l ADR 8 VGII)"],
        ["M14", "Werkvoorraad", "Max 1× aangebroken + 1× nieuw per stof", "⚠️", "Grenzen niet gedocumenteerd; potentieel overschreden"],
        ["M15", "Brandcompartiment", "Max 1.000 m² zonder VBB", "✅", "Klein volume, ver onder limiet"],
        ["M20", "Ventilatie", "Gasophoping voorkomen (M30-kader)", "⚠️", "Ventilatie bij rack niet gedocumenteerd"],
        ["M30", "Vloeistofopvang", "Lekbakken ≥110% grootste verpakking", "⚠️", "Lekbakken niet gedocumenteerd; vereist: ≥27,5 l per bak"],
        ["M35", "Stoffenscheiding", "Tabel 9 conform; Bijlage E", "❌", "NaOH en H₂SO₄ op zelfde rack: A-scheiding vereist"],
        ["M36", "Verpakkingsintegriteit", "Controle op beschadiging, corrosie", "⚠️", "Geen inspectie gedocumenteerd"],
        ["M45", "Correct gebruik", "Hantering, stapeling conform voorschrift", "⚠️", "Stapelstabiliteit niet geëvalueerd"],
        ["M77", "Botsbeveiliging", "Bescherming tegen aanrijding", "⚠️", "Ligging rack t.o.v. verkeersroutes onbekend"],
        ["M78", "Stellingconstructie", "Rekken geschikt voor gewicht, stabiel", "⚠️", "Constructieve staat niet geïnspecteerd"],
        ["M85", "Personeelsopleiding", "Opleiding + instructie over stoffen en PBM", "⚠️", "Geen instructie gedocumenteerd"],
        ["M86", "Noodorganisatie", "Alarmprocedure, evacuatie, first responder", "⚠️", "Noodprocedure voor lekkage niet aanwezig bij rack"],
        ["M89", "Noodplan", "Calamiteitenplan met stofspecifieke maatregelen", "⚠️", "Calamiteitenplan voor chemische lekkage ontbreekt"],
        ["M109", "Toegankelijkheid", "Bereikbaar en toegankelijk voor hulpdiensten", "⚠️", "Toegankelijkheid rack voor brandweer niet geëvalueerd"],
    ],
    col_widths=[1.2, 2.5, 3.8, 1.2, 5.5]
)
p("")
p("Legenda: ✅ = Compliant | ⚠️ = Gedeeltelijk compliant / nader te toetsen | ❌ = Niet compliant")
p("Totaal: 3 × ✅ | 12 × ⚠️ | 1 × ❌ | Kritiek punt: M35 (stoffsenscheiding)")

# ═══════════════════════════════════════════════════════════
# H9: WETTELIJKE KADERS
# ═══════════════════════════════════════════════════════════
doc.add_heading('9. Wettelijke Kaders', level=1)
p("Dit hoofdstuk geeft een overzicht van de wet- en regelgeving die van toepassing is op de opslag van gevaarlijke stoffen door Phoenix Metals. Per wetgeving wordt de relevantie voor PM beschreven.")

add_table(doc,
    ["Wetgeving", "Volledige naam", "Relevantie PM"],
    [
        ["PGS 15:2025", "Publicatiereeks Gevaarlijke Stoffen 15 — Opslag verpakte gevaarlijke stoffen", "Primaire richtlijn. Bepaalt veiligheidsniveau, stoffsenscheiding, vloeistofopvang en alle overige maatregelen. PM moet aantonen compliant te zijn met het basisveiligheidsniveau."],
        ["Omgevingswet", "Wet van 30 maart 2016 (Bbl, Bkl, Bal)", "Bepaalt eisen voor brandcompartimentering (Bbl), externe veiligheidsafstanden (Bkl) en milieubelasting (Bal). Voor PM is met name het Bbl relevant: de opslag moet voldoen aan bouwtechnische brandveiligheidseisen."],
        ["Arbowet", "Wet van 10 maart 1998 (Arbobesluit art. 4.1c)", "Verplicht een RI&E waarin de risico's van het werken met gevaarlijke stoffen zijn geïnventariseerd en geëvalueerd. De zorgplicht (MW1) sluit direct aan op de Arbowet."],
        ["ADR", "Accord européen relatif au transport international des marchandises Dangereuses par Route", "Bepaalt het classificatiesysteem (klassen 1–9, verpakkingsgroepen I–III) dat ten grondslag ligt aan de PGS 15-drempelwaarden. PM heeft uitsluitend ADR-klasse 8 stoffen (bijtend)."],
        ["CLP", "EG 1272/2008 — Classification, Labelling and Packaging", "Harmoniseert classificatie, etikettering en verpakking van stoffen en mengsels in de EU. Bepaalt de H- en P-zinnen, gevarenpictogrammen en etiketinformatie op de jerrycans en canisters van PM."],
        ["REACH", "EG 1907/2006 — Registration, Evaluation, Authorisation and Restriction of Chemicals", "Verplicht registratie van chemische stoffen en beschikbaarstelling van Safety Data Sheets (SDS). PM moet SDS/VIB-documenten raadpleegbaar hebben voor alle 6 stoffen in het register."],
    ],
    col_widths=[2.5, 4, 7.5]
)

p("Deze zes kaders vormen het wettelijke kader voor de opslagactiviteiten van Phoenix Metals. PGS 15 is de primaire richtlijn die de operationele maatregelen dicteert. De Omgevingswet en Arbowet vormen het kader op hoofdlijnen (bouwtechnisch en arbeidsomstandigheden). ADR, CLP en REACH bieden het classificatie- en informatiesysteem dat nodig is voor de uitvoering van PGS 15.")

# ═══════════════════════════════════════════════════════════
# BIJLAGEN
# ═══════════════════════════════════════════════════════════
doc.add_heading('Bijlagen', level=1)

doc.add_heading('Bijlage A: Bronnenlijst', level=2)
add_table(doc,
    ["Nr.", "Bron", "Type"],
    [
        ["[1]", "PGS 15:2025 v1.0 — Opslag van verpakte gevaarlijke stoffen (238 pp)", "Richtlijn"],
        ["[2]", "Phoenix Metals — Chemical Register v2.1.0", "Intern document"],
        ["[3]", "REACH-scanner data — Phoenix Metals stoffeninventarisatie", "Analyse-output"],
        ["[4]", "PGS 15 Bijlage E — Compatibiliteitsmatrix (Tabel 9)", "Richtlijn-bijlage"],
        ["[5]", "Omgevingswet — Besluit bouwwerken leefomgeving (Bbl)", "Wetgeving"],
        ["[6]", "Arbowet / Arbobesluit — Art. 4.1c RI&E", "Wetgeving"],
        ["[7]", "CLP-Verordening (EG) 1272/2008", "EU-verordening"],
        ["[8]", "REACH-Verordening (EG) 1907/2006", "EU-verordening"],
    ],
    col_widths=[1, 10, 3]
)

doc.add_heading('Bijlage B: Verwijzing Tabel 6 (Veiligheidsniveaus)', level=2)
p("Tabel 6 uit PGS 15:2025 (pp. 65–68) bevat de volledige drempelwaardentabel per ADR-klasse en verpakkingsgroep. De tabel bepaalt welk veiligheidsniveau (basis, VN-B, VN-A) vereist is op basis van de totale opgeslagen hoeveelheid. Voor Phoenix Metals is de relevante rij: ADR-klasse 8, VGII/III, onbrandbaar — basisveiligheidsniveau ALTIJD. De volledige tabel is opgenomen in het META-DOSSIER (paragraaf 3.2) en de originele PGS 15-publicatie.")

doc.add_heading('Bijlage C: Verwijzing Tabel 9 (Stoffenscheiding)', level=2)
p("Tabel 9 uit PGS 15:2025 (p. 194) bevat de compatibiliteitsmatrix voor onverenigbare stoffencombinaties. De matrix kent drie scheidingniveaus: V (aparte vakken), B (beoordelen) en A (apart brandcompartiment of 5 m vrije zone). De volledige matrix is opgenomen in het META-DOSSIER (paragraaf 2.1). Voor Phoenix Metals is het kritieke punt: ADR 8 ↔ ADR 8 = A (zuur-base combinaties zoals NaOH ↔ H₂SO₄).")

# ── Save ──
os.makedirs(os.path.dirname(OUTPUT), exist_ok=True)
doc.save(OUTPUT)
print(f"✅ Bestand opgeslagen: {OUTPUT}")

# Woordenaantal
import re
full_text = []
for para in doc.paragraphs:
    full_text.append(para.text)
for table in doc.tables:
    for row in table.rows:
        for cell in row.cells:
            full_text.append(cell.text)
all_text = " ".join(full_text)
words = len(re.findall(r'\b\w+\b', all_text))
print(f"📊 Woordenaantal: {words}")

size = os.path.getsize(OUTPUT)
print(f"📁 Bestandsgrootte: {size:,} bytes ({size/1024:.1f} KB)")
