Test

<!doctype html>
<html lang="nl">
 <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Modern Timer</title>
  <script src="/_sdk/element_sdk.js"></script>
  <style>
    body {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      height: 100%;
      overflow: hidden;
    }
    
    html {
      height: 100%;
    }

    * {
      box-sizing: border-box;
    }

    .timer-container {
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      padding: 2rem;
      position: relative;
    }

    .timer-title {
      font-size: 2rem;
      font-weight: 700;
      color: white;
      margin-bottom: 3rem;
      text-align: center;
      letter-spacing: -0.02em;
    }

    .timer-display {
      position: relative;
      margin-bottom: 3rem;
    }

    .timer-circle {
      width: 280px;
      height: 280px;
      border-radius: 50%;
      background: rgba(255, 255, 255, 0.1);
      backdrop-filter: blur(10px);
      border: 3px solid rgba(255, 255, 255, 0.2);
      display: flex;
      align-items: center;
      justify-content: center;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
      transition: transform 0.3s ease;
    }

    .timer-circle.pulse {
      animation: pulse 1.5s ease-in-out infinite;
    }

    @keyframes pulse {
      0%, 100% {
        transform: scale(1);
        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
      }
      50% {
        transform: scale(1.05);
        box-shadow: 0 25px 70px rgba(0, 0, 0, 0.4);
      }
    }

    .timer-text {
      font-size: 4.5rem;
      font-weight: 700;
      color: white;
      letter-spacing: -0.03em;
      text-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    }

    .timer-controls {
      display: flex;
      gap: 1rem;
      flex-wrap: wrap;
      justify-content: center;
    }

    .control-button {
      padding: 1rem 2rem;
      font-size: 1.125rem;
      font-weight: 600;
      border: none;
      border-radius: 12px;
      cursor: pointer;
      transition: all 0.3s ease;
      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
      min-width: 120px;
    }

    .btn-start {
      background: white;
      color: #667eea;
    }

    .btn-start:hover {
      background: #f0f0f0;
      transform: translateY(-2px);
      box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
    }

    .btn-pause {
      background: rgba(255, 255, 255, 0.2);
      color: white;
      border: 2px solid white;
    }

    .btn-pause:hover {
      background: rgba(255, 255, 255, 0.3);
      transform: translateY(-2px);
    }

    .btn-reset {
      background: rgba(255, 87, 87, 0.9);
      color: white;
    }

    .btn-reset:hover {
      background: rgba(255, 87, 87, 1);
      transform: translateY(-2px);
    }

    .completion-overlay {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.8);
      display: none;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      animation: fadeIn 0.5s ease;
      z-index: 10;
    }

    .completion-overlay.show {
      display: flex;
    }

    @keyframes fadeIn {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }

    .completion-text {
      font-size: 3rem;
      font-weight: 700;
      color: white;
      margin-bottom: 2rem;
      text-align: center;
      animation: scaleIn 0.6s ease;
    }

    @keyframes scaleIn {
      0% {
        transform: scale(0.5);
        opacity: 0;
      }
      100% {
        transform: scale(1);
        opacity: 1;
      }
    }

    .celebration-emoji {
      font-size: 5rem;
      animation: bounce 0.8s ease infinite;
    }

    @keyframes bounce {
      0%, 100% {
        transform: translateY(0);
      }
      50% {
        transform: translateY(-20px);
      }
    }

    @media (max-width: 768px) {
      .timer-title {
        font-size: 1.5rem;
        margin-bottom: 2rem;
      }

      .timer-circle {
        width: 220px;
        height: 220px;
      }

      .timer-text {
        font-size: 3rem;
      }

      .control-button {
        padding: 0.875rem 1.5rem;
        font-size: 1rem;
        min-width: 100px;
      }

      .completion-text {
        font-size: 2rem;
        padding: 0 1rem;
      }

      .celebration-emoji {
        font-size: 4rem;
      }
    }
  </style>
  <style>@view-transition { navigation: auto; }</style>
  <script src="/_sdk/data_sdk.js" type="text/javascript"></script>
  <script src="https://cdn.tailwindcss.com" type="text/javascript"></script>
 </head>
 <body>
  <main class="timer-container">
   <h1 class="timer-title" id="timer-title">Focus Timer</h1>
   <div class="timer-display">
    <div class="timer-circle" id="timer-circle">
     <div class="timer-text" id="timer-text">
      15:00
     </div>
    </div>
   </div>
   <div class="timer-controls"><button class="control-button btn-start" id="start-btn">Start</button> <button class="control-button btn-pause" id="pause-btn">Pauze</button> <button class="control-button btn-reset" id="reset-btn">Reset</button>
   </div>
   <div class="completion-overlay" id="completion-overlay">
    <div class="celebration-emoji">
     🎉
    </div>
    <div class="completion-text" id="completion-text">
     Tijd is om!
    </div>
   </div>
  </main>
  <script>
    const defaultConfig = {
      timer_title: "Focus Timer",
      completion_message: "Tijd is om!",
      background_color: "#667eea",
      accent_color: "#764ba2",
      text_color: "#ffffff",
      button_color: "#ffffff",
      button_text_color: "#667eea",
      font_family: "Inter",
      font_size: 16
    };

    let totalSeconds = 15 * 60; // 15 minutes
    let remainingSeconds = totalSeconds;
    let timerInterval = null;
    let isRunning = false;

    const timerText = document.getElementById('timer-text');
    const timerCircle = document.getElementById('timer-circle');
    const startBtn = document.getElementById('start-btn');
    const pauseBtn = document.getElementById('pause-btn');
    const resetBtn = document.getElementById('reset-btn');
    const completionOverlay = document.getElementById('completion-overlay');
    const timerTitle = document.getElementById('timer-title');
    const completionText = document.getElementById('completion-text');

    function formatTime(seconds) {
      const mins = Math.floor(seconds / 60);
      const secs = seconds % 60;
      return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    }

    function updateDisplay() {
      timerText.textContent = formatTime(remainingSeconds);
    }

    function startTimer() {
      if (isRunning) return;
      
      isRunning = true;
      timerCircle.classList.add('pulse');
      
      timerInterval = setInterval(() => {
        remainingSeconds--;
        updateDisplay();
        
        if (remainingSeconds <= 0) {
          stopTimer();
          showCompletion();
        }
      }, 1000);
    }

    function pauseTimer() {
      isRunning = false;
      timerCircle.classList.remove('pulse');
      clearInterval(timerInterval);
    }

    function stopTimer() {
      pauseTimer();
    }

    function resetTimer() {
      stopTimer();
      remainingSeconds = totalSeconds;
      updateDisplay();
      completionOverlay.classList.remove('show');
    }

    function showCompletion() {
      completionOverlay.classList.add('show');
    }

    startBtn.addEventListener('click', startTimer);
    pauseBtn.addEventListener('click', pauseTimer);
    resetBtn.addEventListener('click', resetTimer);
    completionOverlay.addEventListener('click', resetTimer);

    async function onConfigChange(config) {
      const container = document.querySelector('.timer-container');
      const customFont = config.font_family || defaultConfig.font_family;
      const baseFontStack = '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
      const baseSize = config.font_size || defaultConfig.font_size;
      
      container.style.background = `linear-gradient(135deg, ${config.background_color || defaultConfig.background_color} 0%, ${config.accent_color || defaultConfig.accent_color} 100%)`;
      
      timerTitle.textContent = config.timer_title || defaultConfig.timer_title;
      timerTitle.style.fontFamily = `${customFont}, ${baseFontStack}`;
      timerTitle.style.fontSize = `${baseSize * 2}px`;
      timerTitle.style.color = config.text_color || defaultConfig.text_color;
      
      timerText.style.fontFamily = `${customFont}, ${baseFontStack}`;
      timerText.style.fontSize = `${baseSize * 4.5}px`;
      timerText.style.color = config.text_color || defaultConfig.text_color;
      
      completionText.textContent = config.completion_message || defaultConfig.completion_message;
      completionText.style.fontFamily = `${customFont}, ${baseFontStack}`;
      completionText.style.fontSize = `${baseSize * 3}px`;
      
      startBtn.style.background = config.button_color || defaultConfig.button_color;
      startBtn.style.color = config.button_text_color || defaultConfig.button_text_color;
      startBtn.style.fontFamily = `${customFont}, ${baseFontStack}`;
      startBtn.style.fontSize = `${baseSize * 1.125}px`;
      
      pauseBtn.style.fontFamily = `${customFont}, ${baseFontStack}`;
      pauseBtn.style.fontSize = `${baseSize * 1.125}px`;
      pauseBtn.style.color = config.text_color || defaultConfig.text_color;
      
      resetBtn.style.fontFamily = `${customFont}, ${baseFontStack}`;
      resetBtn.style.fontSize = `${baseSize * 1.125}px`;
    }

    if (window.elementSdk) {
      window.elementSdk.init({
        defaultConfig,
        onConfigChange,
        mapToCapabilities: (config) => ({
          recolorables: [
            {
              get: () => config.background_color || defaultConfig.background_color,
              set: (value) => {
                config.background_color = value;
                window.elementSdk.setConfig({ background_color: value });
              }
            },
            {
              get: () => config.accent_color || defaultConfig.accent_color,
              set: (value) => {
                config.accent_color = value;
                window.elementSdk.setConfig({ accent_color: value });
              }
            },
            {
              get: () => config.text_color || defaultConfig.text_color,
              set: (value) => {
                config.text_color = value;
                window.elementSdk.setConfig({ text_color: value });
              }
            },
            {
              get: () => config.button_color || defaultConfig.button_color,
              set: (value) => {
                config.button_color = value;
                window.elementSdk.setConfig({ button_color: value });
              }
            },
            {
              get: () => config.button_text_color || defaultConfig.button_text_color,
              set: (value) => {
                config.button_text_color = value;
                window.elementSdk.setConfig({ button_text_color: value });
              }
            }
          ],
          borderables: [],
          fontEditable: {
            get: () => config.font_family || defaultConfig.font_family,
            set: (value) => {
              config.font_family = value;
              window.elementSdk.setConfig({ font_family: value });
            }
          },
          fontSizeable: {
            get: () => config.font_size || defaultConfig.font_size,
            set: (value) => {
              config.font_size = value;
              window.elementSdk.setConfig({ font_size: value });
            }
          }
        }),
        mapToEditPanelValues: (config) => new Map([
          ["timer_title", config.timer_title || defaultConfig.timer_title],
          ["completion_message", config.completion_message || defaultConfig.completion_message]
        ])
      });
    }

    updateDisplay();
  </script>
 <script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9a06844cc3b213d7',t:'MTc2MzQ1ODkzNi4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
</html>