// CSP-safe event delegation (replaces inline on* handlers)
(function() {
  var H = {
      'data-onclick': 'click',
      'data-onsubmit': 'submit',
      'data-onchange': 'change',
      'data-oninput': 'input',
      'data-onkeyup': 'keyup',
      'data-onkeydown': 'keydown',
      'data-onkeypress': 'keypress',
      'data-onfocus': 'focusin',
      'data-onblur': 'focusout',
  };
  function _resolveFn(path, el) {
       var parts = path.split('.');
       var obj = el;
       for (var i = 0; i < parts.length; i++) {
           if (obj && typeof obj[parts[i]] === 'function') obj = obj[parts[i]];
           else {
               obj = window[path];
               if (typeof obj === 'function') return obj;
               return null;
           }
       }
       return obj || window[path];
   }
  function _parseCall(code) {
      var s = code.trim();
      if (s.startsWith('return ')) s = s.slice(7).trim();
      var m = s.match(/^([\w.$]+)\((.*)\)$/);
      if (m) return { fn: m[1], argsStr: m[2] };
      if (/^[\w.$]+$/.test(s)) return { fn: s, argsStr: '' };
      return null;
  }
  function _splitArgs(str) {
      if (!str.trim()) return [];
      var args = [], current = '', depth = 0, inStr = false, strChar = '';
      for (var i = 0; i < str.length; i++) {
          var c = str[i];
          if (inStr) { if (c === strChar) inStr = false; current += c; continue; }
          if (c === '"' || c === "'") { inStr = true; strChar = c; current += c; continue; }
          if (c === '(' || c === '[' || c === '{') depth++;
          if (c === ')' || c === ']' || c === '}') depth--;
          if (c === ',' && depth === 0) { args.push(current.trim()); current = ''; continue; }
          current += c;
      }
      if (current.trim()) args.push(current.trim());
      return args;
  }
  function _invoke(code, el, e) {
      var parsed = _parseCall(code);
      if (!parsed) return undefined;
      var fn = _resolveFn(parsed.fn, el);
      if (!fn) { console.warn('CSP delegate: unknown function', parsed.fn); return undefined; }
      var args = _splitArgs(parsed.argsStr);
      args = args.map(function(a) {
          // Strip surrounding quotes from string literals
          if ((a.startsWith("'") && a.endsWith("'")) || (a.startsWith('"') && a.endsWith('"'))) {
              return a.slice(1, -1);
          }
          if (a === 'this') return el;
          if (a === 'event' || a === 'e') return e;
          if (a === 'this.value') return el.value;
          if (a === 'this.form') return el.form;
          if (a === 'this.checked') return el.checked;
          return a;
      });
      return fn.apply(window, args);
  }
  for (var attr in H) {
      (function(a, ev) {
          document.addEventListener(ev, function(e) {
              var el = e.target.closest('[' + a + ']');
              if (!el) return;
              var code = el.getAttribute(a);
              if (!code) return;
              var result = _invoke(code, el, e);
              if (result === false) {
                  e.preventDefault();
                  e.stopPropagation();
              }
          }, ev === 'focusin' || ev === 'focusout');
      })(attr, H[attr]);
  }
  ['error', 'load'].forEach(function(ev) {
      document.addEventListener(ev, function(e) {
          var code = e.target.getAttribute('data-' + ev);
          if (!code) return;
          _invoke(code, e.target, e);
      }, true);
  });
})();
