Sandbox: Canva Code: Difference between revisions

Replaced content with "<iframe loading="lazy" src="https://www.canva.com/design/XXXXXXXX/view?embed" allowfullscreen="allowfullscreen" allow="fullscreen" style="width:100%; height:600px; border:0;"> </iframe>"
(Created page with "<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vocabulary Matching Game</title> <script src="/_sdk/element_sdk.js"></script> <style> body { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Arial', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);...")
 
(Replaced content with "<iframe loading="lazy" src="https://www.canva.com/design/XXXXXXXX/view?embed" allowfullscreen="allowfullscreen" allow="fullscreen" style="width:100%; height:600px; border:0;"> </iframe>")
Tag: Replaced
Line 1: Line 1:
<!doctype html>
<iframe loading="lazy" src="https://www.canva.com/design/XXXXXXXX/view?embed"  
<html lang="en">
        allowfullscreen="allowfullscreen"  
<head>
        allow="fullscreen"  
  <meta charset="UTF-8">
        style="width:100%; height:600px; border:0;">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</iframe>
  <title>Vocabulary Matching Game</title>
  <script src="/_sdk/element_sdk.js"></script>
  <style>
    body {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      font-family: 'Arial', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
 
    * {
      box-sizing: border-box;
    }
 
    .container {
      width: 90%;
      max-width: 900px;
      padding: 32px;
      background: white;
      border-radius: 24px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    }
 
    .header {
      text-align: center;
      margin-bottom: 32px;
    }
 
    h1 {
      font-size: 40px;
      margin: 0 0 12px 0;
      background: linear-gradient(135deg, #667eea, #764ba2);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      background-clip: text;
    }
 
    .instructions {
      font-size: 16px;
      color: #64748b;
      margin: 0;
    }
 
    .game-area {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 24px;
      margin-bottom: 24px;
    }
 
    .column h2 {
      font-size: 20px;
      margin: 0 0 16px 0;
      text-align: center;
      color: #1e293b;
    }
 
    .term-card, .definition-card {
      padding: 16px 20px;
      border-radius: 12px;
      margin-bottom: 12px;
      cursor: pointer;
      transition: all 0.3s ease;
      border: 3px solid transparent;
      font-size: 15px;
      position: relative;
      overflow: hidden;
    }
 
    .term-card {
      background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
      color: #78350f;
      font-weight: bold;
    }
 
    .definition-card {
      background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
      color: #1e3a8a;
    }
 
    .term-card:hover:not(.matched):not(.showing-hint),
    .definition-card:hover:not(.matched):not(.showing-hint) {
      transform: translateY(-4px);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
    }
 
    .term-card.selected, .definition-card.selected {
      border-color: #8b5cf6;
      transform: scale(1.05);
      box-shadow: 0 8px 24px rgba(139, 92, 246, 0.4);
    }
 
    .term-card.matched, .definition-card.matched {
      background: linear-gradient(135deg, #34d399 0%, #10b981 100%);
      color: #064e3b;
      cursor: default;
      animation: matchPulse 0.6s ease;
    }
 
    .term-card.showing-hint {
      border-color: #8b5cf6;
      animation: hintPulse 1s ease-in-out;
    }
 
    @keyframes matchPulse {
      0%, 100% { transform: scale(1); }
      50% { transform: scale(1.1); }
    }
 
    @keyframes hintPulse {
      0%, 100% { transform: scale(1); }
      50% { transform: scale(1.05); }
    }
 
    .checkmark {
      position: absolute;
      top: 8px;
      right: 8px;
      font-size: 20px;
      animation: checkmarkPop 0.5s ease;
    }
 
    @keyframes checkmarkPop {
      0% { transform: scale(0) rotate(-45deg); }
      50% { transform: scale(1.2) rotate(10deg); }
      100% { transform: scale(1) rotate(0deg); }
    }
 
    .controls {
      display: flex;
      gap: 12px;
      justify-content: center;
      margin-bottom: 24px;
    }
 
    button {
      padding: 12px 24px;
      border: none;
      border-radius: 12px;
      font-size: 16px;
      font-weight: bold;
      cursor: pointer;
      transition: all 0.3s ease;
    }
 
    .hint-btn {
      background: linear-gradient(135deg, #a78bfa 0%, #8b5cf6 100%);
      color: white;
    }
 
    .hint-btn:hover:not(:disabled) {
      transform: translateY(-2px);
      box-shadow: 0 6px 16px rgba(139, 92, 246, 0.4);
    }
 
    .hint-btn:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
 
    .reset-btn {
      background: linear-gradient(135deg, #f87171 0%, #ef4444 100%);
      color: white;
    }
 
    .reset-btn:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 16px rgba(239, 68, 68, 0.4);
    }
 
    .progress {
      text-align: center;
      font-size: 18px;
      color: #475569;
      margin-bottom: 16px;
    }
 
    .progress-bar {
      width: 100%;
      height: 12px;
      background: #e2e8f0;
      border-radius: 6px;
      overflow: hidden;
      margin-bottom: 24px;
    }
 
    .progress-fill {
      height: 100%;
      background: linear-gradient(90deg, #34d399, #10b981);
      transition: width 0.5s ease;
      border-radius: 6px;
    }
 
    .success-message {
      text-align: center;
      padding: 24px;
      background: linear-gradient(135deg, #34d399 0%, #10b981 100%);
      border-radius: 16px;
      color: #064e3b;
      font-size: 24px;
      font-weight: bold;
      display: none;
      animation: successSlide 0.6s ease;
    }
 
    @keyframes successSlide {
      from {
        opacity: 0;
        transform: translateY(-20px);
      }
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }
 
    .confetti {
      position: fixed;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      animation: confettiFall 3s ease-out forwards;
      pointer-events: none;
    }
 
    @keyframes confettiFall {
      to {
        transform: translateY(100vh) rotate(720deg);
        opacity: 0;
      }
    }
 
    @media (max-width: 768px) {
      .game-area {
        grid-template-columns: 1fr;
      }
     
      h1 {
        font-size: 32px;
      }
     
      .container {
        padding: 24px;
      }
    }
  </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>
  <div class="container">
  <div class="header">
    <h1 id="game-title">Geometry Match Challenge</h1>
    <p class="instructions" id="instructions">Match each term with its correct definition</p>
  </div>
  <div class="progress" id="progress-text">
    Matched: 0 / 6
  </div>
  <div class="progress-bar">
    <div class="progress-fill" id="progress-fill" style="width: 0%"></div>
  </div>
  <div class="game-area">
    <div class="column">
    <h2>📐 Terms</h2>
    <div id="terms-container"></div>
    </div>
    <div class="column">
    <h2>📝 Definitions</h2>
    <div id="definitions-container"></div>
    </div>
  </div>
  <div class="controls"><button class="hint-btn" id="hint-btn">💡 <span id="hint-btn-text">Need a Hint?</span></button> <button class="reset-btn" id="reset-btn">🔄 Start Over</button>
  </div>
  <div class="success-message" id="success-message">
    🎉 <span id="success-text">Perfect! You matched all terms!</span> 🎉
  </div>
  </div>
  <script>
    const defaultConfig = {
      game_title: "Geometry Match Challenge",
      hint_text: "Need a Hint?",
      success_message: "Perfect! You matched all terms!",
      primary_color: "#667eea",
      secondary_color: "#fbbf24",
      text_color: "#1e293b",
      button_color: "#8b5cf6",
      success_color: "#10b981",
      font_family: "Arial",
      font_size: 16
    };
 
    const vocabularyPairs = [
      { id: 1, term: "Radius", definition: "The distance from the center of a circle to any point on its edge" },
      { id: 2, term: "Diameter", definition: "A straight line passing through the center connecting two points on a circle" },
      { id: 3, term: "Perimeter", definition: "The total distance around the outside of a shape" },
      { id: 4, term: "Angle", definition: "The space between two lines or surfaces that meet at a point" },
      { id: 5, term: "Polygon", definition: "A closed shape with straight sides" },
      { id: 6, term: "Parallel", definition: "Lines that never intersect and remain the same distance apart" }
    ];
 
    let selectedTerm = null;
    let selectedDefinition = null;
    let matchedPairs = [];
    let hintUsed = false;
 
    function shuffleArray(array) {
      const shuffled = [...array];
      for (let i = shuffled.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
      }
      return shuffled;
    }
 
    function initGame() {
      const termsContainer = document.getElementById('terms-container');
      const definitionsContainer = document.getElementById('definitions-container');
     
      termsContainer.innerHTML = '';
      definitionsContainer.innerHTML = '';
     
      const shuffledTerms = shuffleArray(vocabularyPairs);
      const shuffledDefinitions = shuffleArray(vocabularyPairs);
     
      shuffledTerms.forEach(pair => {
        const card = document.createElement('div');
        card.className = 'term-card';
        card.dataset.id = pair.id;
        card.textContent = pair.term;
        card.addEventListener('click', () => selectTerm(card, pair.id));
        termsContainer.appendChild(card);
      });
     
      shuffledDefinitions.forEach(pair => {
        const card = document.createElement('div');
        card.className = 'definition-card';
        card.dataset.id = pair.id;
        card.textContent = pair.definition;
        card.addEventListener('click', () => selectDefinition(card, pair.id));
        definitionsContainer.appendChild(card);
      });
     
      matchedPairs = [];
      selectedTerm = null;
      selectedDefinition = null;
      hintUsed = false;
      updateProgress();
      document.getElementById('hint-btn').disabled = false;
      document.getElementById('success-message').style.display = 'none';
    }
 
    function selectTerm(card, id) {
      if (matchedPairs.includes(id)) return;
     
      if (selectedTerm) {
        selectedTerm.classList.remove('selected');
      }
     
      selectedTerm = card;
      card.classList.add('selected');
     
      checkMatch(id, selectedDefinition ? parseInt(selectedDefinition.dataset.id) : null);
    }
 
    function selectDefinition(card, id) {
      if (matchedPairs.includes(id)) return;
     
      if (selectedDefinition) {
        selectedDefinition.classList.remove('selected');
      }
     
      selectedDefinition = card;
      card.classList.add('selected');
     
      checkMatch(selectedTerm ? parseInt(selectedTerm.dataset.id) : null, id);
    }
 
    function checkMatch(termId, definitionId) {
      if (termId && definitionId && termId === definitionId) {
        matchedPairs.push(termId);
       
        selectedTerm.classList.remove('selected');
        selectedDefinition.classList.remove('selected');
        selectedTerm.classList.add('matched');
        selectedDefinition.classList.add('matched');
       
        const checkmark1 = document.createElement('span');
        checkmark1.className = 'checkmark';
        checkmark1.textContent = '✓';
        selectedTerm.appendChild(checkmark1);
       
        const checkmark2 = document.createElement('span');
        checkmark2.className = 'checkmark';
        checkmark2.textContent = '✓';
        selectedDefinition.appendChild(checkmark2);
       
        selectedTerm = null;
        selectedDefinition = null;
       
        updateProgress();
       
        if (matchedPairs.length === vocabularyPairs.length) {
          setTimeout(() => {
            showSuccess();
          }, 500);
        }
      }
    }
 
    function updateProgress() {
      const progressText = document.getElementById('progress-text');
      const progressFill = document.getElementById('progress-fill');
      const percentage = (matchedPairs.length / vocabularyPairs.length) * 100;
     
      progressText.textContent = `Matched: ${matchedPairs.length} / ${vocabularyPairs.length}`;
      progressFill.style.width = percentage + '%';
    }
 
    function showHint() {
      if (hintUsed || matchedPairs.length === vocabularyPairs.length) return;
     
      const unmatchedPairs = vocabularyPairs.filter(pair => !matchedPairs.includes(pair.id));
      if (unmatchedPairs.length === 0) return;
     
      const hintPair = unmatchedPairs[0];
     
      const termCards = document.querySelectorAll('.term-card');
      const definitionCards = document.querySelectorAll('.definition-card');
     
      termCards.forEach(card => {
        if (parseInt(card.dataset.id) === hintPair.id) {
          card.classList.add('showing-hint');
          setTimeout(() => card.classList.remove('showing-hint'), 2000);
        }
      });
     
      definitionCards.forEach(card => {
        if (parseInt(card.dataset.id) === hintPair.id) {
          card.classList.add('showing-hint');
          setTimeout(() => card.classList.remove('showing-hint'), 2000);
        }
      });
     
      hintUsed = true;
      document.getElementById('hint-btn').disabled = true;
    }
 
    function showSuccess() {
      document.getElementById('success-message').style.display = 'block';
      createConfetti();
    }
 
    function createConfetti() {
      const colors = ['#fbbf24', '#60a5fa', '#34d399', '#a78bfa', '#f87171'];
      for (let i = 0; i < 50; i++) {
        setTimeout(() => {
          const confetti = document.createElement('div');
          confetti.className = 'confetti';
          confetti.style.left = Math.random() * 100 + '%';
          confetti.style.background = colors[Math.floor(Math.random() * colors.length)];
          confetti.style.animationDelay = Math.random() * 0.5 + 's';
          document.body.appendChild(confetti);
         
          setTimeout(() => confetti.remove(), 3000);
        }, i * 30);
      }
    }
 
    document.getElementById('hint-btn').addEventListener('click', showHint);
    document.getElementById('reset-btn').addEventListener('click', initGame);
 
    const element = {
      defaultConfig,
     
      onConfigChange: async (config) => {
        const gameTitle = document.getElementById('game-title');
        const hintBtnText = document.getElementById('hint-btn-text');
        const successText = document.getElementById('success-text');
        const body = document.body;
        const container = document.querySelector('.container');
        const buttons = document.querySelectorAll('button');
        const heading1 = document.querySelector('h1');
        const allText = document.querySelectorAll('p, .progress, h2, button, .term-card, .definition-card, .success-message');
       
        gameTitle.textContent = config.game_title || defaultConfig.game_title;
        hintBtnText.textContent = config.hint_text || defaultConfig.hint_text;
        successText.textContent = config.success_message || defaultConfig.success_message;
       
        const primaryColor = config.primary_color || defaultConfig.primary_color;
        const secondaryColor = config.secondary_color || defaultConfig.secondary_color;
        const textColor = config.text_color || defaultConfig.text_color;
        const buttonColor = config.button_color || defaultConfig.button_color;
        const successColor = config.success_color || defaultConfig.success_color;
       
        body.style.background = `linear-gradient(135deg, ${primaryColor} 0%, ${buttonColor} 100%)`;
        heading1.style.background = `linear-gradient(135deg, ${primaryColor}, ${buttonColor})`;
        heading1.style.webkitBackgroundClip = 'text';
        heading1.style.webkitTextFillColor = 'transparent';
        heading1.style.backgroundClip = 'text';
       
        document.querySelectorAll('.term-card:not(.matched)').forEach(card => {
          card.style.background = `linear-gradient(135deg, ${secondaryColor} 0%, ${secondaryColor}dd 100%)`;
        });
       
        document.querySelectorAll('.hint-btn').forEach(btn => {
          btn.style.background = `linear-gradient(135deg, ${buttonColor}cc 0%, ${buttonColor} 100%)`;
        });
       
        document.querySelector('.progress-fill').style.background = `linear-gradient(90deg, ${successColor}dd, ${successColor})`;
       
        const customFont = config.font_family || defaultConfig.font_family;
        const baseFontStack = '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
        body.style.fontFamily = `${customFont}, ${baseFontStack}`;
       
        const baseSize = config.font_size || defaultConfig.font_size;
        heading1.style.fontSize = `${baseSize * 2.5}px`;
        document.querySelector('.instructions').style.fontSize = `${baseSize}px`;
        document.querySelector('.progress').style.fontSize = `${baseSize * 1.125}px`;
        document.querySelectorAll('h2').forEach(h2 => h2.style.fontSize = `${baseSize * 1.25}px`);
        document.querySelectorAll('button').forEach(btn => btn.style.fontSize = `${baseSize}px`);
        document.querySelectorAll('.term-card, .definition-card').forEach(card => card.style.fontSize = `${baseSize * 0.9375}px`);
        document.querySelector('.success-message').style.fontSize = `${baseSize * 1.5}px`;
      },
     
      mapToCapabilities: (config) => ({
        recolorables: [
          {
            get: () => config.primary_color || defaultConfig.primary_color,
            set: (value) => {
              config.primary_color = value;
              window.elementSdk.setConfig({ primary_color: value });
            }
          },
          {
            get: () => config.secondary_color || defaultConfig.secondary_color,
            set: (value) => {
              config.secondary_color = value;
              window.elementSdk.setConfig({ secondary_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.success_color || defaultConfig.success_color,
            set: (value) => {
              config.success_color = value;
              window.elementSdk.setConfig({ success_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([
        ["game_title", config.game_title || defaultConfig.game_title],
        ["hint_text", config.hint_text || defaultConfig.hint_text],
        ["success_message", config.success_message || defaultConfig.success_message]
      ])
    };
 
    if (window.elementSdk) {
      window.elementSdk.init(element);
    }
 
    initGame();
  </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:'9a1a873237d4bc58',t:'MTc2MzY2ODc3MC4wMDAwMDA='};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>