(function attachPyroRuntime(root) {
  'use strict';

  const svgNS = 'http://www.w3.org/2000/svg';
  const byId = (id, owner = root.document) => owner?.getElementById(id) || null;
  const createSvg = (name, attrs = {}, owner = root.document) => {
    if (!owner?.createElementNS) throw new Error('SVG-Dokument ist nicht verfügbar');
    const node = owner.createElementNS(svgNS, name);
    Object.entries(attrs).forEach(([key, value]) => {
      if (value !== undefined && value !== null) node.setAttribute(key, String(value));
    });
    return node;
  };
  const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
  const uid = (prefix = 'id') => `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
  // JSON-basierte Kopien sind für Projektdaten ausreichend, müssen aber auch
  // optionale, nicht vorhandene Felder sicher durchreichen. Andernfalls kann
  // bereits das Bearbeiten eines normalen Textes an `deepClone(undefined)`
  // abbrechen, bevor die eigentliche Eigenschaft übernommen wird.
  const deepClone = (value) => value === undefined ? undefined : JSON.parse(JSON.stringify(value));
  const num = (value, fallback = 0) => Number.isFinite(Number(value)) ? Number(value) : fallback;
  const round = (value, digits = 2) => Number(num(value).toFixed(digits));
  const normalizeDocumentTitle = (value, fallback = 'Unbenannt') => String(value ?? '').replace(/\s+/g, ' ').trim().slice(0, 80) || fallback;

  const api = Object.freeze({ svgNS, byId, createSvg, clamp, uid, deepClone, num, round, normalizeDocumentTitle });
  root.PyroRuntime = api;
  if (typeof module === 'object' && module?.exports) module.exports = api;
})(typeof globalThis !== 'undefined' ? globalThis : window);
