Home / Widgets / Welcome Cards
Duplicate Snippet

Embed Snippet on Your Site

Welcome Cards

4 cards to display service offering

<10
Code Preview
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>MyOnlyTab Value Cards</title>
  <style>
    /* Move CSS variables to :root for global access */
    :root {
      --privacy-color: #e9f0fa;
      --privacy-accent: #007AFF; /* iOS System Blue */
      --instant-color: #f0e9fa;
      --instant-accent: #5856D6; /* iOS Purple */
      --premium-color: #fff8e6;
      --premium-accent: #FF9500; /* iOS Orange/Gold */
      --green-color: #e8f7ed;
      --green-accent: #34C759; /* iOS Green */
      --card-radius: 20px;
      --card-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
      --card-hover-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
      --transition-speed: 0.4s;
      --card-hover-bg: #ffffff;
      --card-hover-text: #333333;
      --mobile-breakpoint: 768px;
      --desktop-breakpoint: 1024px;
    }
    
    /* Add fallback styles for browsers without CSS variables */
    .myonlytab-cards-wrapper {
      box-sizing: border-box;
    }
    
    /* Fix white background issue: Add a class that will be added on actual hover/click instead of during swipe */
    .card-hover-active {
      background-color: var(--card-hover-bg, #ffffff) !important;
      color: var(--card-hover-text, #333333) !important;
    }
    
    .myonlytab-cards-container {
      display: flex;
      gap: 26px;
      margin: 0 auto;
      overflow-x: auto;
      overflow-y: hidden;
      padding: 8px 8px 24px;
      scroll-behavior: smooth;
      scroll-snap-type: x mandatory;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: none;
      -ms-overflow-style: none;
      overscroll-behavior-x: contain;
      overscroll-behavior-y: none;
      width: 100%;
      transform: translateZ(0);
      /* Only use will-change when actually scrolling (added/removed via JS) */
      contain: layout style;
      backface-visibility: hidden;
    }
    
    .myonlytab-cards-container::-webkit-scrollbar {
      display: none;
    }
    
    .myonlytab-card {
      background-position: center;
      border-radius: var(--card-radius, 20px);
      box-shadow: var(--card-shadow, 0 2px 6px rgba(0, 0, 0, 0.1));
      flex: 0 0 calc(80% - 32px);
      min-height: 240px;
      overflow: hidden;
      position: relative;
      scroll-snap-align: center;
      /* Refined animation curves for more natural movement */
      transition: transform var(--transition-speed, 0.4s) cubic-bezier(0.34, 1.56, 0.64, 1), 
                  box-shadow var(--transition-speed, 0.4s) cubic-bezier(0.25, 0.46, 0.45, 0.94),
                  background-color 0.3s ease, color 0.3s ease;
      contain: layout style;
      cursor: pointer;
      transform-origin: center center;
      display: block;
      text-decoration: none;
    }
    
    .myonlytab-card:hover {
      transform: scale(1.05);
      box-shadow: var(--card-hover-shadow, 0 6px 16px rgba(0, 0, 0, 0.15));
      z-index: 1;
    }
    
    /* Only apply white background on desktop hover */
    @media (hover: hover) and (pointer: fine) {
      .myonlytab-card:hover {
        background: var(--card-hover-bg, #ffffff) !important;
        color: var(--card-hover-text, #333333) !important;
      }
    }
    
    .myonlytab-card:active {
      transform: scale(0.95);
      transition: transform 0.1s ease-out;
    }
    
    .myonlytab-card-content {
      padding-left: 50px;
		padding-right: 40px;
		padding-top: 30px;
		padding-bottom: 20px;
      height: 100%;
      display: flex;
      flex-direction: column;
    }
    
    .myonlytab-card[data-card-id="privacy"] {
      background: linear-gradient(to bottom, var(--privacy-color), #d8e6f6);
      color: var(--privacy-accent);
    }
    
    .myonlytab-card[data-card-id="instant"] {
      background: linear-gradient(to bottom, var(--instant-color), #e0d5f0);
      color: var(--instant-accent);
    }
    
    .myonlytab-card[data-card-id="premium"] {
      background: linear-gradient(to bottom, var(--premium-color), #f5e9cc);
      color: var(--premium-accent);
    }
    
    .myonlytab-card[data-card-id="green"] {
      background: linear-gradient(to bottom, var(--green-color), #d5e8dd);
      color: var(--green-accent);
    }
    
    .myonlytab-card-title {
      color: #333;
      font-size: 1.5rem;
      font-weight: 600;
      margin: 16px 0 8px;
      transition: color 0.3s ease;
    }
    
    .myonlytab-card-description {
      color: #555;
      font-size: 1rem;
      line-height: 1.5;
      transition: color 0.3s ease;
    }
    
    .emoji-icon {
      font-size: 3.5rem;
      display: inline-block;
      margin-bottom: 8px;
      transform-origin: center;
      /* Improved for reduced motion preferences */
      animation-play-state: paused;
    }
    
    /* Animation for emojis - with reduced motion consideration */
    @media (prefers-reduced-motion: no-preference) {
      .emoji-icon.animated {
        animation-play-state: running;
      }
      
      /* Slightly reduced animation speeds */
      #privacy-icon.animated {
        animation: wobble 4s ease-in-out infinite;
      }
      
      #instant-icon.animated {
        animation: bounce 3s ease-in-out infinite;
      }
      
      #premium-icon.animated {
        animation: pulseAndFloat 4s ease-in-out infinite;
      }
      
      #green-icon.animated {
        animation: pulseAndFloat 5s ease-in-out infinite;
      }
    }
    
    @keyframes pulseAndFloat {
      0%, 100% { transform: scale(1) translateY(0); }
      50% { transform: scale(1.08) translateY(-5px); }
    }
    
    @keyframes bounce {
      0%, 100% { transform: translateY(0); }
      50% { transform: translateY(-8px); }
    }
    
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    
    @keyframes wobble {
      0%, 100% { transform: rotate(0deg); }
      25% { transform: rotate(-5deg); }
      75% { transform: rotate(5deg); }
    }
    /* Pagination styling */
    .myonlytab-pagination {
      display: flex;
      gap: 8px;
      justify-content: center;
      margin-top: 8px;
    }
    
    .myonlytab-pagination-dot {
      background-color: #ccc;
      border-radius: 50%;
      cursor: pointer;
      height: 8px;
      transition: all 0.3s ease;
      width: 8px;
      border: 0;
      padding: 0;
    }
    
    .myonlytab-pagination-dot.active {
      background-color: #666;
      transform: scale(1.2);
    }
    
    /* Close button styling */
    .myonlytab-cards-close {
		color:#666;
      background: rgba(255, 255, 255, 0.8);
      border: none;
      border-radius: 50%;
      cursor: pointer;
      height: 36px;
      padding: 6px;
      position: absolute;
      right: 24px;
      top: 12px;
      transition: all 0.2s ease;
      width: 36px;
      z-index: 5;
    }
    
    .myonlytab-cards-close:hover {
	color:#000;
      background: rgba(255, 255, 255, 0.9);
      transform: scale(1.2);
    }
    
    /* Hidden State with smoother transitions */
    .myonlytab-card.hidden {
      opacity: 0;
      transform: translateY(20px);
      transition: opacity 0.3s ease, transform 0.3s ease;
    }
    
    .myonlytab-cards-wrapper.all-hidden {
      display: none;
    }
    
    /* Graceful degradation for no-JS environments */
    .no-js .myonlytab-cards-container {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
      gap: 20px;
      padding: 16px;
    }
    
    .no-js .myonlytab-pagination, 
    .no-js .myonlytab-cards-close {
      display: none;
    }
    
    /* Improved CSS Grid implementation to avoid layout shifts */
    /* Tablet Styles */
    @media screen and (min-width: 768px) {
      .myonlytab-cards-container {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-template-rows: auto;
        grid-gap: 26px;
        overflow: visible;
        padding: 8px;
        height: auto;
      }
      
      .myonlytab-card {
        min-height: 220px;
        height: 100%;
        scroll-snap-align: unset;
        width: 100%;
      }
      
      .myonlytab-pagination {
        display: none;
      }
    }
    
    /* Responsive Styles: Desktop */
    @media screen and (min-width: 1024px) {
      .myonlytab-cards-container {
        grid-template-columns: repeat(4, minmax(0, 1fr));
      }
    }
  </style>
</head>
<body class="no-js">
  <div class="myonlytab-cards-wrapper" id="myonlytab-cards-wrapper">
    <div class="myonlytab-cards-container" aria-label="MyOnlyTab Value Proposition Cards">
      <a href="https://example.com/privacy" class="myonlytab-card" data-card-id="privacy" aria-labelledby="privacy-title">
        <div class="myonlytab-card-content">
          <div class="emoji-icon" id="privacy-icon" aria-hidden="true">🛡️</div>
          <h3 class="myonlytab-card-title" id="privacy-title">Zero Telemetry: No ads, No trackers</h3>
          <p class="myonlytab-card-description">F**k Tech Giants. Access Powerful Tools in One Place without being Watched or Sold to.</p>
        </div>
      </a>
      
      <a href="https://example.com/instant" class="myonlytab-card" data-card-id="instant" aria-labelledby="instant-title">
        <div class="myonlytab-card-content">
          <div class="emoji-icon" id="instant-icon" aria-hidden="true">🚀</div>
          <h3 class="myonlytab-card-title" id="instant-title">Explore Freely: No Forced SignUp</h3>
          <p class="myonlytab-card-description">Minimal by design with instant access and no distractions. Click Less to do more.</p>
        </div>
      </a>
      
      <a href="https://example.com/green" class="myonlytab-card" data-card-id="green" aria-labelledby="green-title">
        <div class="myonlytab-card-content">
          <div class="emoji-icon" id="green-icon" aria-hidden="true">🌱</div>
          <h3 class="myonlytab-card-title" id="green-title">Proudly Powered by 300% Renewable Energy</h3>
          <p class="myonlytab-card-description">EU-hosted on GreenGeek's Independant Servers, where Privacy meets Sustainability.</p>
        </div>
      </a>
      
      <a href="https://example.com/premium" class="myonlytab-card" data-card-id="premium" aria-labelledby="premium-title">
        <div class="myonlytab-card-content">
          <div class="emoji-icon" id="premium-icon" aria-hidden="true"></div>
          <h3 class="myonlytab-card-title" id="premium-title">Real Premium Perks: No Marketing Tricks</h3>
          <p class="myonlytab-card-description">Optional Upgrade for Sync, Advanced Customization, Exclusive Content and Rewards with No-Card 14-day Trial.
</p>
        </div>
      </a>
    </div>
    
    <div class="myonlytab-pagination" role="tablist" aria-label="Card navigation">
      <button class="myonlytab-pagination-dot active" aria-label="Card 1: Privacy" aria-selected="true"></button>
      <button class="myonlytab-pagination-dot" aria-label="Card 2: Instant" aria-selected="false"></button>
      <button class="myonlytab-pagination-dot" aria-label="Card 3: Premium" aria-selected="false"></button>
      <button class="myonlytab-pagination-dot" aria-label="Card 4: Eco-Friendly" aria-selected="false"></button>
    </div>
    
    <button id="myonlytab-cards-close" class="myonlytab-cards-close" aria-label="Close cards">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <line x1="18" y1="6" x2="6" y2="18"></line>
        <line x1="6" y1="6" x2="18" y2="18"></line>
      </svg>
    </button>
  </div>
  <script>
    // Remove no-js class when JavaScript is running
    document.body.classList.remove('no-js');
    
    (function() {
      'use strict';
      const MOT_CARDS = {
        config: {
          storageKey: 'myonlytabCardsDismissed',
          mobileBreakpoint: 768, // Match with CSS variable --mobile-breakpoint
          animationStartDelay: 300,
          scrollThrottleDelay: 100,
          cardHidingDelay: 50
        },
        
        elements: {}, // Will store DOM references
        state: {
          isMobile: false,
          supportsTouch: false,
          storageSupported: false,
          activeCardIndex: 0,
          scrollRAF: null,
          scrollEndTimeout: null,
          resizeRAF: null,
          resizeTimer: null,
          cardObserver: null,
          isScrolling: false,
          scrollStateTimeout: null
        },
        
        /**
         * Initialize the component when it becomes visible in the viewport
         */
        init: function() {
          // Check if browser idle callbacks are available
          if ('requestIdleCallback' in window) {
            requestIdleCallback(this.initializeWhenVisible.bind(this));
          } else {
            window.addEventListener('load', this.initializeWhenVisible.bind(this));
          }
        },
        
        /**
         * Set up intersection observer to initialize when visible
         */
        initializeWhenVisible: function() {
          const wrapper = document.getElementById('myonlytab-cards-wrapper');
          
          if (!wrapper) return;
          
          if ('IntersectionObserver' in window) {
            const observer = new IntersectionObserver((entries) => {
              if (entries[0].isIntersecting) {
                observer.disconnect();
                this.setup();
              }
            }, { rootMargin: '200px' });
            
            observer.observe(wrapper);
          } else {
            this.setup();
          }
        },
        
        /**
         * Set up the component, cache DOM elements, and check initial state
         */
        setup: function() {
          // Cache DOM elements
          this.cacheElements();
          
          // If no wrapper found, exit early
          if (!this.elements.wrapper) return;
          
          // Check browser capabilities
          this.checkEnvironment();
          
          // Check if cards should be hidden based on storage
          if (this.state.storageSupported && localStorage.getItem(this.config.storageKey) === 'true') {
            this.elements.wrapper.classList.add('all-hidden');
            return;
          }
          
          // Set up event listeners
          this.setupEventListeners();
          
          // Add touch handlers for mobile devices
          this.setupTouchHandlers();
          
          // Start animations with slight delay for better perceived performance
          setTimeout(this.startAnimations.bind(this), this.config.animationStartDelay);
          
          // Initialize mobile-specific functionality if needed
          if (this.state.isMobile) {
            this.initializeMobileView();
          }
        },
        
        /**
         * Cache DOM elements for better performance
         */
        cacheElements: function() {
          this.elements.wrapper = document.getElementById('myonlytab-cards-wrapper');
          
          if (!this.elements.wrapper) return;
          
          this.elements.container = this.elements.wrapper.querySelector('.myonlytab-cards-container');
          this.elements.cards = Array.from(this.elements.wrapper.querySelectorAll('.myonlytab-card'));
          this.elements.closeButton = document.getElementById('myonlytab-cards-close');
          this.elements.paginationDots = Array.from(this.elements.wrapper.querySelectorAll('.myonlytab-pagination-dot'));
          this.elements.emojiIcons = Array.from(this.elements.wrapper.querySelectorAll('.emoji-icon'));
        },
        
        /**
         * Check browser capabilities and device environment
         */
        checkEnvironment: function() {
          this.state.isMobile = window.innerWidth < this.config.mobileBreakpoint;
          this.state.supportsTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
          
          // Check if localStorage is available
          try {
            localStorage.setItem('test', 'test');
            localStorage.removeItem('test');
            this.state.storageSupported = true;
          } catch (e) {
            this.state.storageSupported = false;
          }
        },
        /**
         * Set up all event listeners
         */
        setupEventListeners: function() {
          // Close button
          if (this.elements.closeButton) {
            this.elements.closeButton.addEventListener('click', this.handleClose.bind(this));
          }
          
          // Mobile horizontal scroll handling
          if (this.state.isMobile && this.elements.container) {
            this.elements.container.addEventListener('scroll', this.handleScroll.bind(this), { passive: true });
            
            // Set up Intersection Observer if available
            if ('IntersectionObserver' in window) {
              this.setupIntersectionObserver();
            }
          }
          
          // Pagination dots click handling
          if (this.elements.paginationDots.length) {
            this.elements.paginationDots.forEach((dot, index) => {
              dot.addEventListener('click', () => this.handlePaginationClick(index));
            });
          }
          
          // Window resize handling with debouncing
          window.addEventListener('resize', this.handleResize.bind(this), { passive: true });
        },
        
        /**
         * Start emoji animations
         */
        startAnimations: function() {
          // Check for reduced motion preference
          const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
          
          if (!prefersReducedMotion && this.elements.emojiIcons) {
            this.elements.emojiIcons.forEach(icon => {
              icon.classList.add('animated');
            });
          }
        },
        
        /**
         * Initialize mobile-specific view
         */
        initializeMobileView: function() {
          if (this.elements.cards.length > 0) {
            // Scroll to first card
            requestAnimationFrame(() => {
              this.elements.cards[0].scrollIntoView({
                behavior: 'auto',
                block: 'nearest',
                inline: 'center'
              });
              
              // Set active card
              this.state.activeCardIndex = 0;
              this.elements.cards[0].classList.add('active-card');
              this.updatePaginationDots(0);
            });
          }
        },
        
        /**
         * Set up touch handlers for cards to handle tap/click events on mobile
         */
        setupTouchHandlers: function() {
          if (!this.state.supportsTouch) return;
          
          // Add handlers to each card
          this.elements.cards.forEach(card => {
            // Use touchstart/touchend or click events
            card.addEventListener('touchstart', () => {
              // Don't add hover state immediately to avoid flash during scroll
            }, { passive: true });
            
            card.addEventListener('touchend', (e) => {
              // Only add hover state if this was a tap, not a scroll
              if (!this.state.isScrolling) {
                // Add hover state class
                card.classList.add('card-hover-active');
                
                // Remove it after delay
                setTimeout(() => {
                  card.classList.remove('card-hover-active');
                }, 300);
              }
            }, { passive: true });
          });
          
          // Track scroll state
          this.elements.container.addEventListener('touchmove', () => {
            this.state.isScrolling = true;
            
            // Clear any existing timeout
            if (this.state.scrollStateTimeout) {
              clearTimeout(this.state.scrollStateTimeout);
            }
            
            // Reset scrolling state after a delay
            this.state.scrollStateTimeout = setTimeout(() => {
              this.state.isScrolling = false;
            }, 100);
          }, { passive: true });
        },
        
        /**
         * Handle scrolling in mobile view with requestAnimationFrame for better performance
         */
        handleScroll: function() {
          // Add will-change property during scrolling for better performance
          if (!this.elements.container.style.willChange) {
            this.elements.container.style.willChange = 'scroll-position';
          }
          
          // Clear existing RAF callback
          if (this.state.scrollRAF) {
            cancelAnimationFrame(this.state.scrollRAF);
          }
          
          // Schedule new RAF callback
          this.state.scrollRAF = requestAnimationFrame(() => {
            this.findActiveCard();
            
            // Remove will-change after scrolling stops
            if (this.state.scrollEndTimeout) {
              clearTimeout(this.state.scrollEndTimeout);
            }
            
            this.state.scrollEndTimeout = setTimeout(() => {
              this.elements.container.style.willChange = '';
            }, 150);
          });
        },
        /**
         * Setup Intersection Observer for card detection
         */
        setupIntersectionObserver: function() {
          if (!('IntersectionObserver' in window)) return;
          
          // Setup observer for cards in mobile view
          const options = {
            root: this.elements.container,
            rootMargin: '0px',
            threshold: 0.6 // Card is considered active when 60% visible
          };
          
          this.state.cardObserver = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
              if (entry.isIntersecting && entry.intersectionRatio >= 0.6) {
                const activeCard = entry.target;
                
                // Only update if this is a different card
                if (!activeCard.classList.contains('active-card')) {
                  // Remove active class from all cards
                  this.elements.cards.forEach(card => {
                    card.classList.remove('active-card');
                  });
                  
                  // Add active class to current card
                  activeCard.classList.add('active-card');
                  
                  // Update pagination
                  const newIndex = this.elements.cards.indexOf(activeCard);
                  this.state.activeCardIndex = newIndex;
                  this.updatePaginationDots(newIndex);
                }
              }
            });
          }, options);
          
          // Observe all cards
          this.elements.cards.forEach(card => {
            this.state.cardObserver.observe(card);
          });
        },
        
        /**
         * Find which card is currently most visible/centered (fallback for browsers without IntersectionObserver)
         */
        findActiveCard: function() {
          if (!this.elements.container || !this.elements.cards.length) return;
          
          const containerRect = this.elements.container.getBoundingClientRect();
          const containerCenter = containerRect.left + containerRect.width / 2;
          
          let bestVisibleCard = null;
          let bestDistance = Infinity;
          
          this.elements.cards.forEach(card => {
            // Remove any white background that might have been added during touch/swipe
            card.classList.remove('card-hover-active');
            
            const cardRect = card.getBoundingClientRect();
            const cardCenter = cardRect.left + cardRect.width / 2;
            const distance = Math.abs(cardCenter - containerCenter);
            
            if (distance < bestDistance) {
              bestDistance = distance;
              bestVisibleCard = card;
            }
          });
          
          if (bestVisibleCard && !bestVisibleCard.classList.contains('active-card')) {
            // Remove active class from all cards
            this.elements.cards.forEach(card => {
              card.classList.remove('active-card');
            });
            
            // Add active class to current card
            bestVisibleCard.classList.add('active-card');
            
            // Update pagination
            const newIndex = this.elements.cards.indexOf(bestVisibleCard);
            this.state.activeCardIndex = newIndex;
            this.updatePaginationDots(newIndex);
          }
        },
        
        /**
         * Update pagination dots to reflect current active card
         */
        updatePaginationDots: function(activeIndex) {
          if (!this.elements.paginationDots.length) return;
          
          requestAnimationFrame(() => {
            this.elements.paginationDots.forEach((dot, index) => {
              const isActive = index === activeIndex;
              dot.classList.toggle('active', isActive);
              dot.setAttribute('aria-selected', isActive ? 'true' : 'false');
            });
          });
        },
        /**
         * Handle pagination dot clicks
         */
        handlePaginationClick: function(index) {
          if (!this.elements.cards[index]) return;
          
          this.elements.cards[index].scrollIntoView({
            behavior: 'smooth',
            block: 'nearest',
            inline: 'center'
          });
          
          // Update state and UI directly for immediate feedback
          this.state.activeCardIndex = index;
          this.updatePaginationDots(index);
        },
        
        /**
         * Handle close button click
         */
        handleClose: function(e) {
          e.preventDefault();
          
          // Add hidden class to each card with staggered delay
          this.elements.cards.forEach((card, index) => {
            setTimeout(() => {
              card.classList.add('hidden');
            }, index * this.config.cardHidingDelay);
          });
          
          // Hide the entire component after animation completes
          setTimeout(() => {
            this.elements.wrapper.classList.add('all-hidden');
            
            // Save dismissal state if supported
            if (this.state.storageSupported) {
              try {
                localStorage.setItem(this.config.storageKey, 'true');
              } catch (e) {
                console.warn('Failed to save card state to localStorage');
              }
            }
          }, (this.elements.cards.length * this.config.cardHidingDelay) + 300);
        },
        
        /**
         * Handle window resize events with improved debouncing
         */
        handleResize: function() {
          // Add will-change during resize operations
          this.elements.wrapper.style.willChange = 'contents';
          
          // Clear previous timer
          clearTimeout(this.state.resizeTimer);
          
          // Use RAF for smoother visual updates during resize
          if (!this.state.resizeRAF) {
            this.state.resizeRAF = requestAnimationFrame(() => {
              const wasInMobileView = this.state.isMobile;
              this.state.isMobile = window.innerWidth < this.config.mobileBreakpoint;
              
              // Reset RAF flag
              this.state.resizeRAF = null;
              
              // Set a timer to perform the actual layout changes after resizing stops
              this.state.resizeTimer = setTimeout(() => {
                // Only make changes if the view type changed
                if (wasInMobileView !== this.state.isMobile) {
                  // If switched to mobile view, initialize it
                  if (this.state.isMobile) {
                    this.initializeMobileView();
                    
                    // Set up Intersection Observer for mobile view
                    if ('IntersectionObserver' in window && this.state.cardObserver == null) {
                      this.setupIntersectionObserver();
                    }
                  } else {
                    // Clean up observers when switching to desktop
                    if (this.state.cardObserver) {
                      this.state.cardObserver.disconnect();
                      this.state.cardObserver = null;
                    }
                  }
                }
                
                // Remove will-change after resize completes
                this.elements.wrapper.style.willChange = '';
              }, 150);
            });
          }
        }
      };
      
      // Start the component
      MOT_CARDS.init();
    })();
  </script>
</body>
</html>

Comments

Add a Comment