msds-tds/scripts/generate-sds-en-v2.py
2026-07-08 13:12:20 +00:00

273 lines
12 KiB
Python

#!/usr/bin/env python3
"""Generate English SDS for Ethyl Acetate — fixed header/footer, full width."""
import os, base64
from weasyprint import HTML
PRIMARY = "#004C98"
SECONDARY = "#2B2E33"
MUTED = "#5B6670"
ACCENT = "#0071B8"
HIGHLIGHT = "#F2F6FA"
BORDER = "#D9E1E8"
WHITE = "#FFFFFF"
WARNING_AMBER = "#C77700"
def img_b64(path):
with open(path, 'rb') as f:
return f"data:image/png;base64,{base64.b64encode(f.read()).decode()}"
logo_b64 = img_b64('/home/bachko/msds-tds/assets/logo-synthesia.png')
iso_b64 = img_b64('/home/bachko/msds-tds/assets/iso-seal-tuv-rheinland.png')
html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
@page {{
size: A4;
margin: 2.5cm 1.8cm 2.2cm 1.8cm;
}}
body {{
font-family: Calibri, Carlito, Arial, sans-serif;
font-size: 10pt;
color: {SECONDARY};
line-height: 1.2;
margin: 0;
padding: 0;
}}
/* ═══ FIXED HEADER — full width ═══ */
.fixed-header {{
position: fixed;
top: 0; left: 0; right: 0;
height: 2cm;
padding: 0.3cm 1.8cm 0 1.8cm;
background: {WHITE};
z-index: 100;
}}
.fixed-header .hdr-table {{
width: 100%;
border-collapse: collapse;
table-layout: auto;
}}
.fixed-header .hdr-logo {{
width: 140px;
text-align: left;
vertical-align: middle;
}}
.fixed-header .hdr-logo img {{ height: 1.0cm; }}
.fixed-header .hdr-iso {{
width: 140px;
text-align: right;
vertical-align: middle;
}}
.fixed-header .hdr-iso img {{ height: 1.0cm; }}
.fixed-header .hdr-title {{
vertical-align: middle;
text-align: right;
}}
.fixed-header .hdr-title .title-main {{ font-size: 9pt; font-weight: bold; color: {PRIMARY}; }}
.fixed-header .hdr-title .title-sub {{ font-size: 7.5pt; color: {SECONDARY}; }}
.fixed-header .hdr-title .title-ref {{ font-size: 6.5pt; color: {MUTED}; }}
.fixed-header .hdr-rule {{
border: none;
border-top: 1pt solid {PRIMARY};
margin: 2px 0 0 0;
}}
/* ═══ FIXED FOOTER — full width ═══ */
.fixed-footer {{
position: fixed;
bottom: 0; left: 0; right: 0;
height: 1.6cm;
padding: 0.15cm 1.8cm 0 1.8cm;
background: {WHITE};
z-index: 100;
}}
.fixed-footer .ftr-rule {{
border: none;
border-top: 0.5pt solid {BORDER};
width: 100%;
}}
.fixed-footer .ftr-contact {{
font-size: 6.5pt; color: {MUTED}; text-align: center; margin: 1px 0;
}}
.fixed-footer .ftr-cert {{
font-size: 6pt; color: {MUTED}; text-align: center; font-style: italic; margin: 1px 0;
}}
/* ═══ CONTENT ═══ */
.doc-title {{
font-size: 16pt; font-weight: bold; color: {PRIMARY};
border-bottom: 2pt solid {PRIMARY}; padding-bottom: 3px; margin: 0 0 8pt 0;
}}
h2.section {{
font-size: 12pt; font-weight: bold; color: {SECONDARY};
border-left: 4pt solid {ACCENT}; padding-left: 6px; margin: 8pt 0 4pt 0;
}}
h3.subsection {{ font-size: 10.5pt; font-weight: bold; color: {SECONDARY}; margin: 6pt 0 3pt 0; }}
p {{ margin: 3px 0; }}
table.data {{ width: 100%; border-collapse: collapse; margin: 4px 0; font-size: 9pt; }}
table.data th {{ background-color: {PRIMARY}; color: {WHITE}; font-weight: bold; padding: 3pt 5pt; text-align: left; border: 0.5pt solid {BORDER}; font-size: 9pt; }}
table.data td {{ padding: 3pt 5pt; border: 0.5pt solid {BORDER}; }}
table.data tr:nth-child(even) td {{ background-color: {HIGHLIGHT}; }}
table.data tr:nth-child(odd) td {{ background-color: {WHITE}; }}
table.data td:first-child {{ font-weight: bold; color: {SECONDARY}; }}
table.layout {{ width: 100%; border-collapse: collapse; margin: 2px 0; }}
table.layout td {{ border: none; padding: 1px 5px 1px 0; vertical-align: top; }}
table.layout td:first-child {{ width: 30%; font-weight: bold; }}
.alert-warning {{ color: {WARNING_AMBER}; font-weight: bold; }}
.meta-line {{ font-size: 7.5pt; color: {MUTED}; text-align: right; border-bottom: 1px solid {BORDER}; padding-bottom: 3px; margin-bottom: 6px; }}
/* Pagination counter */
.pnum::before {{ content: counter(page); }}
</style>
</head>
<body>
<!-- ═══ FIXED HEADER ═══ -->
<div class="fixed-header">
<table class="hdr-table">
<tr>
<td class="hdr-logo"><img src="{logo_b64}" alt="Synthesia"></td>
<td class="hdr-title">
<div class="title-main">SAFETY DATA SHEET</div>
<div class="title-sub">Ethyl acetate</div>
<div class="title-ref">SDS-ETHYL-ACETATE-REV1 · 06/07/2026</div>
</td>
<td class="hdr-iso"><img src="{iso_b64}" alt="TÜV Rheinland"></td>
</tr>
</table>
<hr class="hdr-rule">
</div>
<!-- ═══ FIXED FOOTER ═══ -->
<div class="fixed-footer">
<hr class="ftr-rule">
<div class="ftr-contact">Synthesia Ltd. · VAT BG121306542 · Todor Radunchev 9, Krivina 1588, Bulgaria · +359 2 974 4968 · office@synthesia.bg</div>
<div class="ftr-cert">Certified ISO 9001:2015 · ISO 14001:2015 · ISO 45001:2018 — TÜV Rheinland, ID 9105074744</div>
<div class="ftr-contact">Page <span class="pnum"></span></div>
</div>
<!-- ═══ DOCUMENT CONTENT ═══ -->
<h1 class="doc-title">SAFETY DATA SHEET<br><span style="font-size:11pt;color:{SECONDARY};">Ethyl acetate</span></h1>
<p class="meta-line">According to Regulation (EU) 2020/878 (REACH Annex II) · CLP Regulation (EC) 1272/2008 as amended by EU 2024/2865</p>
<h2 class="section">SECTION 1: Identification of the substance/mixture and of the company/undertaking</h2>
<h3 class="subsection">1.1 Product identifier</h3>
<table class="data">
<tr><th>Property</th><th>Value</th></tr>
<tr><td>Product form</td><td>Substance</td></tr>
<tr><td>Chemical name</td><td>Ethyl acetate</td></tr>
<tr><td>EC Index-No.</td><td>607-022-00-5</td></tr>
<tr><td>EC-No.</td><td>205-500-4</td></tr>
<tr><td>CAS-No.</td><td>141-78-6</td></tr>
<tr><td>REACH registration No.</td><td>01-2119475103-46-XXXX</td></tr>
<tr><td>Molecular formula</td><td>C₄H₈O₂</td></tr>
</table>
<h3 class="subsection">1.2 Relevant identified uses of the substance or mixture and uses advised against</h3>
<table class="layout">
<tr><td>Use of the substance/mixture</td><td>Industrial use</td></tr>
<tr><td>Restrictions on use</td><td>No data available</td></tr>
</table>
<h3 class="subsection">1.3 Details of the supplier of the safety data sheet</h3>
<table class="data">
<tr><th>Field</th><th>Details</th></tr>
<tr><td>Company</td><td>Synthesia Ltd.</td></tr>
<tr><td>Address</td><td>Todor Radunchev 9, Krivina 1588, Bulgaria</td></tr>
<tr><td>VAT</td><td>BG121306542</td></tr>
<tr><td>Phone</td><td>+359 2 974 4968</td></tr>
<tr><td>Email</td><td>office@synthesia.bg</td></tr>
</table>
<h3 class="subsection">1.4 Emergency telephone number</h3>
<table class="layout">
<tr><td>Emergency number</td><td>112</td></tr>
</table>
<h2 class="section">SECTION 2: Hazards identification</h2>
<h3 class="subsection">2.1 Classification of the substance or mixture</h3>
<p><b>Classification according to Regulation (EC) No. 1272/2008 [CLP] as amended by EU 2024/2865:</b></p>
<table class="data">
<tr><th>Hazard class</th><th>Category</th><th>Hazard statement</th></tr>
<tr><td>Flammable liquids</td><td>Category 2</td><td>H225 — Highly flammable liquid and vapour</td></tr>
<tr><td>Serious eye damage/eye irritation</td><td>Category 2</td><td>H319 — Causes serious eye irritation</td></tr>
<tr><td>Specific target organ toxicity — Single exposure</td><td>Category 3 (Narcosis)</td><td>H336 — May cause drowsiness or dizziness</td></tr>
</table>
<p>Full text of H-statements: see Section 16.</p>
<h3 class="subsection">2.2 Label elements</h3>
<table class="data">
<tr><th>Element</th><th>Details</th></tr>
<tr><td>Hazard pictograms</td><td>GHS02 (Flame) · GHS07 (Exclamation mark)</td></tr>
<tr><td>Signal word</td><td><span class="alert-warning">Danger</span></td></tr>
<tr><td>Hazard statements</td><td>H225 — Highly flammable liquid and vapour.<br>H319 — Causes serious eye irritation.<br>H336 — May cause drowsiness or dizziness.</td></tr>
<tr><td>Precautionary statements</td><td>P210 — Keep away from heat, hot surfaces, sparks, open flames and other ignition sources. No smoking.<br>P280 — Wear protective gloves/protective clothing/eye protection/face protection.<br>P304+P340 — IF INHALED: Remove person to fresh air and keep comfortable for breathing.<br>P305+P351+P338 — IF IN EYES: Rinse cautiously with water for several minutes. Remove contact lenses, if present and easy to do. Continue rinsing.<br>P337+P313 — If eye irritation persists: Get medical advice/attention.<br>P403+P233 — Store in a well-ventilated place. Keep container tightly closed.</td></tr>
<tr><td>EUH-statements</td><td>EUH066 — Repeated exposure may cause skin dryness or cracking.</td></tr>
</table>
<h3 class="subsection">2.3 Other hazards</h3>
<p>This substance does not contain components considered to be persistent, bioaccumulative and toxic (PBT), very persistent and very bioaccumulative (vPvB), persistent, mobile and toxic (PMT), or very persistent and very mobile (vPvM) at levels of 0.1% or higher, in accordance with the criteria of CLP Regulation as amended by EU 2024/2865 and REACH Annex XIII.</p>
<p>This substance is not classified as an endocrine disruptor (ED) according to the criteria of CLP Regulation as amended by EU 2024/2865, Commission Delegated Regulation (EU) 2017/2100, or Commission Regulation (EU) 2018/605.</p>
<p>Vapours may form explosive mixture with air.</p>
<h2 class="section">SECTION 3: Composition/information on ingredients</h2>
<h3 class="subsection">3.1 Substances</h3>
<table class="data">
<tr><th>Component</th><th>CAS-No.</th><th>EC-No.</th><th>Index-No.</th><th>Classification</th><th>Concentration</th></tr>
<tr><td>Ethyl acetate</td><td>141-78-6</td><td>205-500-4</td><td>607-022-00-5</td><td>Flam. Liq. 2; Eye Irrit. 2; STOT SE 3; H225, H319, H336</td><td>&gt; 99.8%</td></tr>
</table>
<p>Molecular weight: 88.11 g/mol &nbsp;|&nbsp; Formula: C₄H₈O₂</p>
<h3 class="subsection">3.2 Mixtures</h3>
<p>Not applicable.</p>
<h2 class="section">SECTION 4: First aid measures</h2>
<h3 class="subsection">4.1 Description of first aid measures</h3>
<table class="data">
<tr><th>Route</th><th>Measures</th></tr>
<tr><td>General</td><td>Call a poison centre or a doctor if you feel unwell.</td></tr>
<tr><td>After inhalation</td><td>Remove person to fresh air and keep comfortable for breathing. If experiencing respiratory symptoms: Call a poison centre or a doctor.</td></tr>
<tr><td>After skin contact</td><td>Rinse skin with water/shower. Take off immediately all contaminated clothing.</td></tr>
<tr><td>After eye contact</td><td>Rinse cautiously with water for several minutes. Remove contact lenses, if present and easy to do. Continue rinsing. If eye irritation persists: Get medical advice/attention.</td></tr>
<tr><td>After ingestion</td><td>Rinse mouth. Do not induce vomiting. Call a poison centre or a doctor if you feel unwell.</td></tr>
</table>
<h3 class="subsection">4.2 Most important symptoms and effects, both acute and delayed</h3>
<table class="data">
<tr><th>Symptoms/effects</th><th>Description</th></tr>
<tr><td>General</td><td>May cause drowsiness or dizziness.</td></tr>
<tr><td>Skin contact</td><td>Repeated exposure may cause skin dryness or cracking.</td></tr>
<tr><td>Eye contact</td><td>Eye irritation.</td></tr>
</table>
<h3 class="subsection">4.3 Indication of any immediate medical attention and special treatment needed</h3>
<p>Treat symptomatically.</p>
<!-- Sections 5-16 omitted for brevity — same as before -->
<!-- Generate with full content -->
<p>...</p>
<br>
<p style="font-size: 8pt; color: {MUTED}; border-top: 1pt solid {BORDER}; padding-top: 5pt;">
<b>Disclaimer of Liability:</b> The information in this SDS was obtained from sources which we believe are reliable. However, the information is provided without any warranty, express or implied, regarding its correctness.
</p>
</body>
</html>"""
print("Script ready — need to add full content sections 5-16")