// source --> https://www.daltec.at/wp-content/themes/daltec2025/js/wk-consent-mode-bootstrap.js 
/*!
 * Daltec — Consent Mode v2 Bootstrap  (v2, nach Review)
 * ---------------------------------------------------------------------------
 * ZWECK
 *   GTM lädt ab sofort IMMER. Consent steuert nur noch, WAS die Tags dürfen,
 *   nicht mehr OB überhaupt gemessen wird. Ohne Zustimmung sendet GA4
 *   cookielose Pings: Seitenaufrufe, Wege und Scrolltiefe bleiben sichtbar,
 *   ohne personenbezogene Wiedererkennung.
 *
 * consent.min.js WIRD NICHT VERÄNDERT.
 *   Es enthält auch die komplette Banner-UI. Diese Datei läuft davor, lädt GTM
 *   selbst und setzt einen synchronen Marker, den der vorhandene Double-Load-
 *   Guard in consent.min.js sieht. Banner, Cookies und UI bleiben unangetastet.
 *
 * EINBAU (Theme daltec2025, header.php)
 *   Als ERSTES Script im <head>, VOR consent.min.js. Kein async, kein defer:
 *
 *     <script src="<?php echo get_stylesheet_directory_uri(); ?>/js/wk-consent-mode-bootstrap.js"></script>
 *
 *   Die Reihenfolge ist der Kern: gtag('consent','default',...) MUSS vor dem
 *   GTM-Snippet laufen, sonst feuern Tags einen Moment ungeschützt.
 *
 * ---------------------------------------------------------------------------
 * VERIFIZIERTE GRUNDLAGEN (Audit 16./17.08.2026 — gemessen, nicht angenommen)
 *
 *   Guard in consent.min.js, wörtlich:
 *     const loadGTM = id => { if(!id) return;
 *                             if(window.google_tag_manager?.[id]) return; ... }
 *     ...aufgerufen erst in DOMContentLoaded.
 *
 *   Daraus das Race, das dieser Bootstrap schließt: gtm.js wird async geladen,
 *   window.google_tag_manager[id] existiert erst NACH dessen Ausführung. Ohne
 *   synchronen Marker sieht consent.min.js bei Wiederkehrern noch `undefined`
 *   und injiziert GTM ein zweites Mal -> Doppelzählung jedes Seitenaufrufs.
 *
 *   Marker-Verträglichkeit LIVE GETESTET auf daltec.at:
 *     google_tag_manager[id] vorbelegt -> GTM initialisiert trotzdem vollständig
 *     (tcf, pscdl, mb, sequence, autoEventsSettings vorhanden), GA4-Config-Tag
 *     aktiv, gtm.dom + gtm.load gefeuert, 1 collect-Hit gesendet, und der
 *     Marker bleibt erhalten. GTM legt seine Internals als Geschwister-Keys ab.
 *
 *   Cookies — drei separate Skalare, KEIN JSON:
 *     wk_cookie_consent  = "set"        (nur: eine Entscheidung wurde getroffen)
 *     wk_consent_gtm     = "1" | "0"
 *     wk_consent_matomo  = "1" | "0"    (Matomo derzeit enabled:false)
 *   host-only, path=/, samesite=Lax, +secure auf https, 180 Tage.
 *
 *   Container-ID kommt aus <meta name="wk-gtm-id">, aktuell GTM-TV8QXBC.
 *
 *   BASELINE VOR DEM UMBAU: GA4 21 aktive Nutzer / 28 Tage (Stand 16.08.2026).
 *   Bleibt diese Zahl nach dem Deploy in derselben Größenordnung, war die
 *   Umsetzung fehlerhaft — nicht die Diagnose.
 */
(function (w, d) {
  'use strict';

  var FALLBACK_GTM_ID = 'GTM-TV8QXBC';
  var COOKIE_CHOICE   = 'wk_cookie_consent';
  var COOKIE_GTM      = 'wk_consent_gtm';
  var POLL_FAST_MS    = 400;   // bis zur ersten Entscheidung
  var POLL_SLOW_MS    = 1500;  // danach — läuft weiter, damit Opt-out greift

  // -------------------------------------------------------------------------
  // 1. dataLayer + gtag als Allererstes
  // -------------------------------------------------------------------------
  w.dataLayer = w.dataLayer || [];
  function gtag() { w.dataLayer.push(arguments); }
  if (typeof w.gtag !== 'function') { w.gtag = gtag; }

  // -------------------------------------------------------------------------
  // 2. Cookies lesen. Geschrieben wird weiterhin ausschliesslich von
  //    consent.min.js — diese Datei ist bei der Entscheidung nur Beobachter.
  // -------------------------------------------------------------------------
  function readCookie(name) {
    var parts = ('; ' + d.cookie).split('; ' + name + '=');
    if (parts.length !== 2) { return null; }
    return decodeURIComponent(parts.pop().split(';').shift());
  }

  // "granted" | "denied" | null (= noch keine Entscheidung getroffen)
  function currentDecision() {
    if (readCookie(COOKIE_CHOICE) !== 'set') { return null; }
    return readCookie(COOKIE_GTM) === '1' ? 'granted' : 'denied';
  }

  var initialDecision = currentDecision();

  // -------------------------------------------------------------------------
  // 3. Consent-Defaults: alles denied. MUSS vor dem GTM-Snippet laufen.
  //    security_storage wird bewusst nicht gesetzt (technisch notwendig).
  //
  //    wait_for_update: Wiederkehrer bekommen ihr Update unten synchron, die
  //    brauchen keine Wartezeit. Erstbesucher bekommen erst beim Banner-Klick
  //    eines — auf die zu warten würde nur den cookielosen Ping verzögern und
  //    Schnell-Absprünge unter 500 ms kosten. Deshalb 0.
  // -------------------------------------------------------------------------
  gtag('consent', 'default', {
    ad_storage:              'denied',
    ad_user_data:            'denied',
    ad_personalization:      'denied',
    analytics_storage:       'denied',
    functionality_storage:   'denied',
    personalization_storage: 'denied',
    wait_for_update:         initialDecision ? 500 : 0
  });

  gtag('set', 'ads_data_redaction', true);
  gtag('set', 'url_passthrough', true);

  // -------------------------------------------------------------------------
  // 4. Consent anwenden — bei jedem Zustandswechsel, in beide Richtungen.
  // -------------------------------------------------------------------------
  var lastApplied = null;

  function applyConsent(decision, source) {
    if (decision === lastApplied) { return; }
    lastApplied = decision;

    var state = decision === 'granted' ? 'granted' : 'denied';

    gtag('consent', 'update', {
      ad_storage:              state,
      ad_user_data:            state,
      ad_personalization:      state,
      analytics_storage:       state,
      functionality_storage:   state,
      personalization_storage: state
    });

    // Widerruf muss die Redaction wieder einschalten, nicht nur die Erteilung
    // sie ausschalten.
    gtag('set', 'ads_data_redaction', state !== 'granted');

    // Rückwärtskompatibilität: consent.min.js pusht dieses Event normalerweise
    // in loadGTM(). Da unser Marker den Guard dort auslöst, kommt es von hier.
    if (state === 'granted') {
      w.dataLayer.push({ event: 'wk_consent_granted_gtm' });
    }

    // Macht die Opt-in-Quote dauerhaft in GA4 messbar — die Zahl, an der sich
    // der Erfolg dieses Umbaus ablesen lässt.
    w.dataLayer.push({
      event: 'consent_state',
      consent_decision: decision,  // "granted" | "denied"
      consent_source: source       // "stored" | "banner"
    });
  }

  if (initialDecision) { applyConsent(initialDecision, 'stored'); }

  // -------------------------------------------------------------------------
  // 5. GTM laden — IMMER, und den Guard-Marker SYNCHRON setzen.
  //    Der Marker ist der eigentliche Fix gegen die Doppel-Injektion: er ist
  //    da, bevor consent.min.js in DOMContentLoaded überhaupt nachsieht.
  // -------------------------------------------------------------------------
  var meta  = d.querySelector('meta[name="wk-gtm-id"]');
  var gtmId = (meta && meta.content) ||
              (w.WK_CONSENT_CFG && w.WK_CONSENT_CFG.tools &&
               w.WK_CONSENT_CFG.tools.gtm && w.WK_CONSENT_CFG.tools.gtm.id) ||
              FALLBACK_GTM_ID;

  w.google_tag_manager = w.google_tag_manager || {};

  if (!w.google_tag_manager[gtmId]) {
    // Synchroner Claim. GTM überschreibt ihn beim Laden nicht und initialisiert
    // trotzdem vollständig — live verifiziert, siehe Kopfkommentar.
    w.google_tag_manager[gtmId] = {
      dataLayer: { name: 'dataLayer' },
      __wkBootstrapClaim: true
    };

    w.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });

    var s     = d.createElement('script');
    s.async   = true;
    s.src     = 'https://www.googletagmanager.com/gtm.js?id=' + encodeURIComponent(gtmId);
    var first = d.getElementsByTagName('script')[0];
    first.parentNode.insertBefore(s, first);
  }

  // -------------------------------------------------------------------------
  // 6. Auf Entscheidungswechsel reagieren — dauerhaft, nicht nur einmal.
  //
  //    Bewusst per Cookie-Polling statt Funktions-Hook: consent.min.js ist
  //    minifiziert und sein Signal wk_consent_granted_gtm wird INNERHALB von
  //    loadGTM() gepusht, hinter dem Guard — es kommt also nicht mehr an.
  //    Der Cookie-Zustand ist die einzige verlässliche Quelle.
  //
  //    Der Timer läuft weiter, nachdem eine Entscheidung getroffen wurde:
  //    Nutzer können das Banner über #wkPrivacyOpen erneut öffnen und
  //    widerrufen. Ein Widerruf, der nicht bemerkt wird, ist ein
  //    Datenschutzproblem, kein Messproblem.
  // -------------------------------------------------------------------------
  var timer = null;

  function checkNow() {
    var decision = currentDecision();
    if (decision && decision !== lastApplied) {
      applyConsent(decision, 'banner');
      schedule(POLL_SLOW_MS);   // ab jetzt genügt Widerrufs-Überwachung
    }
  }

  function schedule(ms) {
    if (timer) { w.clearInterval(timer); }
    timer = w.setInterval(checkNow, ms);
  }

  schedule(initialDecision ? POLL_SLOW_MS : POLL_FAST_MS);

  // Sofortprüfung bei Tab-Rückkehr, damit ein Widerruf in einem anderen Tab
  // nicht bis zum nächsten Intervall unbemerkt bleibt.
  d.addEventListener('visibilitychange', checkNow);
  w.addEventListener('focus', checkNow);
  w.addEventListener('pageshow', checkNow);

  // -------------------------------------------------------------------------
  // 7. Deploy-Prüfung. Keine Laufzeitlogik.
  //
  //    ERWARTUNG OHNE Banner-Klick:   gtmLoaded true,  decision null
  //    ERWARTUNG NACH "Zustimmen":    gtmLoaded true,  decision "granted"
  //    IN ALLEN FÄLLEN:               gtmScriptTags 1   <- kritisch
  //
  //    Steht dort 2, greift der Guard nicht und jeder Aufruf zählt doppelt.
  //    Besonders beim Reload MIT gesetztem Consent-Cookie prüfen — das ist
  //    der Fall, in dem der Fehler auftreten würde.
  // -------------------------------------------------------------------------
  w.wkConsentDebug = function () {
    var c = w.google_tag_manager[gtmId] || {};
    return {
      gtmId: gtmId,
      gtmLoaded: !!w.google_tag_manager[gtmId],
      gtmReallyInitialised: !!w.google_tag_manager['G-0KV5RS54V8'],
      bootstrapClaimIntact: c.__wkBootstrapClaim === true,
      gtmScriptTags: d.querySelectorAll('script[src*="googletagmanager.com/gtm.js"]').length,
      decision: currentDecision(),
      applied: lastApplied,
      dataLayerLength: w.dataLayer.length
    };
  };

})(window, document);