<header>
  <section label="accounts">
    <button style="--img: url(https://assets.codepen.io/2585/gui-skull.png)">
      Kirby
    </button>
  </section>
  <section label="status bar">
    <datetime>11:11<small>AM</small></datetime>
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
      <label>Wifi Connected</label>
      <path fill="currentColor" d="M12 21q-1.05 0-1.775-.725T9.5 18.5t.725-1.775T12 16t1.775.725t.725 1.775t-.725 1.775T12 21m0-11q1.875 0 3.563.6t3.062 1.65q.5.375.513.988T18.7 14.3q-.425.425-1.05.438t-1.125-.338q-.95-.65-2.1-1.025T12 13t-2.425.375t-2.1 1.025q-.5.35-1.125.325t-1.05-.45q-.425-.45-.425-1.062t.5-.988q1.375-1.05 3.063-1.638T12 10m0-6q3.125 0 5.888 1.025t4.962 2.9q.5.425.525 1.05t-.425 1.075q-.425.425-1.05.438t-1.125-.388q-1.8-1.475-4.037-2.287T12 7t-4.737.813T3.225 10.1q-.5.4-1.125.388t-1.05-.438Q.6 9.6.625 8.975t.525-1.05q2.2-1.875 4.963-2.9T12 4"/>
    </svg>
    <span class="battery">
      <p>50<small>%</small></p>
      <svg aria-hidden xmlns="http://www.w3.org/2000/svg" width="38" height="38" viewBox="0 0 24 24"><path fill="currentColor" d="M5.289 16.116q-.344 0-.576-.233t-.232-.575v-1.616H3v-3.384h1.48v-1.62q0-.344.233-.574q.232-.23.576-.23h14.903q.344 0 .576.233t.232.575v6.613q0 .35-.232.58t-.576.23zm.173-1H13V8.885H5.462z"/></svg>
    </span>
  </section>
</header>

<main class="scroll--root">
  <div id="scroller" class="scroll--viewport">
    <ul class="scroll--content">
      <li style="--i: 1">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/Splatoon_2.jpg" alt="">
            </picture>
            <figcaption>Splatoon 2</figcaption>
          </figure>
        </div>
      </li>
      <li style="--i: 2">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/super-smash.jpg" alt="">
            </picture>
            <figcaption>Super Smash Bros.</figcaption>
          </figure>
        </div>
      </li>
      <li style="--i: 3">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/botw.webp" alt="">
            </picture>
            <figcaption>Zelda: BOTW</figcaption>
          </figure>
        </div>
      </li>
      <li style="--i: 4">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/Animal_Crossing_New_Horizons.jpg" alt="">
            </picture>
            <figcaption>Animal Crossing</figcaption>
          </figure>
        </div>
      </li>
      <li style="--i: 5">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/Kirby_Star_Allies.jpg" alt="">
            </picture>
            <figcaption>Kirby Star Allies</figcaption>
          </figure>
        </div>
      </li>
      <li style="--i: 6">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/totk.webp" alt="">
            </picture>
            <figcaption>Zelda: TOTK</figcaption>
          </figure>
        </div>
      </li>
      <li style="--i: 7">
        <div class="game">
          <figure>
            <picture>
              <img src="https://assets.codepen.io/2585/minecraft.jpg" alt="">
            </picture>
            <figcaption>Minecraft</figcaption>
          </figure>
        </div>
      </li>
    </ul>
  </div>
</main>

<footer>
  <button class="online">
    <svg aria-hidden xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="currentColor" d="M10.04 20.4H7.12c-.93 0-1.82-.4-2.48-1.04C4 18.7 3.6 17.81 3.6 16.88V7.12c0-.93.4-1.82 1.04-2.48C5.3 4 6.19 3.62 7.12 3.62h2.92zM7.12 2A5.12 5.12 0 0 0 2 7.12v9.76C2 19.71 4.29 22 7.12 22h4.53V2zM5.11 8c0 1.04.84 1.88 1.89 1.88c1.03 0 1.87-.84 1.87-1.88S8.03 6.12 7 6.12c-1.05 0-1.89.84-1.89 1.88m12.5 3c1.11 0 2.01.89 2.01 2c0 1.12-.9 2-2.01 2s-2.03-.88-2.03-2c0-1.11.92-2 2.03-2m-.73 11A5.12 5.12 0 0 0 22 16.88V7.12C22 4.29 19.71 2 16.88 2h-3.23v20z"/>
    </svg>
    Online
  </button>
  <button>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <label>Social</label>
      <g fill="none">
        <path fill="#d2705d" d="m13.087 21.388l.645.382zm.542-.916l-.646-.382zm-3.258 0l-.645.382zm.542.916l.646-.382zm-8.532-5.475l.693-.287zm5.409 3.078l-.013.75zm-2.703-.372l-.287.693zm16.532-2.706l.693.287zm-5.409 3.078l-.012-.75zm2.703-.372l.287.693zm.7-15.882l-.392.64zm1.65 1.65l.64-.391zM4.388 2.738l-.392-.64zm-1.651 1.65l-.64-.391zM9.403 19.21l.377-.649zm4.33 2.56l.541-.916l-1.29-.764l-.543.916zm-4.007-.916l.542.916l1.29-.764l-.541-.916zm2.715.152a.52.52 0 0 1-.882 0l-1.291.764c.773 1.307 2.69 1.307 3.464 0zM10.5 2.75h3v-1.5h-3zm10.75 7.75v1h1.5v-1zm-18.5 1v-1h-1.5v1zm-1.5 0c0 1.155 0 2.058.05 2.787c.05.735.153 1.347.388 1.913l1.386-.574c-.147-.352-.233-.782-.278-1.441c-.046-.666-.046-1.51-.046-2.685zm6.553 6.742c-1.256-.022-1.914-.102-2.43-.316L4.8 19.313c.805.334 1.721.408 2.977.43zM1.688 16.2A5.75 5.75 0 0 0 4.8 19.312l.574-1.386a4.25 4.25 0 0 1-2.3-2.3zm19.562-4.7c0 1.175 0 2.019-.046 2.685c-.045.659-.131 1.089-.277 1.441l1.385.574c.235-.566.338-1.178.389-1.913c.05-.729.049-1.632.049-2.787zm-5.027 8.241c1.256-.021 2.172-.095 2.977-.429l-.574-1.386c-.515.214-1.173.294-2.428.316zm4.704-4.115a4.25 4.25 0 0 1-2.3 2.3l.573 1.386a5.75 5.75 0 0 0 3.112-3.112zM13.5 2.75c1.651 0 2.837 0 3.762.089c.914.087 1.495.253 1.959.537l.783-1.279c-.739-.452-1.577-.654-2.6-.752c-1.012-.096-2.282-.095-3.904-.095zm9.25 7.75c0-1.622 0-2.891-.096-3.904c-.097-1.023-.299-1.862-.751-2.6l-1.28.783c.285.464.451 1.045.538 1.96c.088.924.089 2.11.089 3.761zm-3.53-7.124a4.25 4.25 0 0 1 1.404 1.403l1.279-.783a5.75 5.75 0 0 0-1.899-1.899zM10.5 1.25c-1.622 0-2.891 0-3.904.095c-1.023.098-1.862.3-2.6.752l.783 1.28c.464-.285 1.045-.451 1.96-.538c.924-.088 2.11-.089 3.761-.089zM2.75 10.5c0-1.651 0-2.837.089-3.762c.087-.914.253-1.495.537-1.959l-1.279-.783c-.452.738-.654 1.577-.752 2.6C1.25 7.61 1.25 8.878 1.25 10.5zm1.246-8.403a5.75 5.75 0 0 0-1.899 1.899l1.28.783a4.25 4.25 0 0 1 1.402-1.403zm7.02 17.993c-.202-.343-.38-.646-.554-.884a2.2 2.2 0 0 0-.682-.645l-.754 1.297c.047.028.112.078.224.232c.121.166.258.396.476.764zm-3.24-.349c.44.008.718.014.93.037c.198.022.275.054.32.08l.754-1.297a2.2 2.2 0 0 0-.909-.274c-.298-.033-.657-.038-1.069-.045zm6.498 1.113c.218-.367.355-.598.476-.764c.112-.154.177-.204.224-.232l-.754-1.297c-.29.17-.5.395-.682.645c-.173.238-.352.54-.555.884zm1.924-2.612c-.412.007-.771.012-1.069.045c-.311.035-.616.104-.909.274l.754 1.297c.045-.026.122-.058.32-.08c.212-.023.49-.03.93-.037z"/><path stroke="#d2705d" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 11h.009m3.982 0H12m3.991 0H16"/>
      </g>
    </svg>
  </button>
  <button>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="#ebb54a" d="M18 6h-2c0-2.21-1.79-4-4-4S8 3.79 8 6H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2m-6-2c1.1 0 2 .9 2 2h-4c0-1.1.9-2 2-2m6 16H6V8h2v2c0 .55.45 1 1 1s1-.45 1-1V8h4v2c0 .55.45 1 1 1s1-.45 1-1V8h2z"/>
    </svg>
  </button>
  <button>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="#4e9cf2" d="M3.08 5L3 5.08V19h17.92c.03-.02.06-.06.08-.08V5.08L20.92 5zM5 17l3.5-4.5l2.5 3.01L14.5 11l4.5 6z" opacity="0"/><path fill="#4e9cf2" d="M21 3H3C2 3 1 4 1 5v14c0 1.1.9 2 2 2h18c1 0 2-1 2-2V5c0-1-1-2-2-2m0 15.92c-.02.03-.06.06-.08.08H3V5.08L3.08 5h17.83c.03.02.06.06.08.08v13.84zm-10-3.41L8.5 12.5L5 17h14l-4.5-6z"/>
    </svg>
  </button>
  <button>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512">
      <path d="M194.822 240H160v-34.762c0-2.817-2.604-5.238-5.303-5.238h-22.145c-2.698 0-4.552 2.372-4.552 5.178V240H92.533c-2.615 0-4.533 2.143-4.533 4.771v21.427c0 2.698 2.031 5.803 4.861 5.803H128v35.467c0 2.615 2.143 4.533 4.771 4.533h21.427c2.698 0 5.803-2.031 5.803-4.861V272h34.762c2.817 0 5.238-2.604 5.238-5.303v-22.145c-.001-2.698-2.373-4.552-5.179-4.552z" fill="currentColor"/><path d="M362.314 279.063c-10.736 0-19.451 8.515-19.451 19.153 0 10.555 8.715 19.084 19.451 19.084 10.783 0 19.498-8.529 19.498-19.084 0-10.638-8.714-19.153-19.498-19.153z" fill="currentColor"/><path d="M319.766 237.165c-10.736 0-19.451 8.603-19.451 19.168 0 10.566 8.715 19.153 19.451 19.153 10.783 0 19.498-8.587 19.498-19.153 0-10.565-8.715-19.168-19.498-19.168z" fill="currentColor"/><path d="M404.862 237.165c-10.729 0-19.442 8.603-19.442 19.168 0 10.566 8.714 19.153 19.442 19.153 10.737 0 19.452-8.587 19.452-19.153 0-10.565-8.714-19.168-19.452-19.168z" fill="currentColor"/><path d="M362.314 195.301c-10.736 0-19.451 8.602-19.451 19.169 0 10.566 8.715 19.146 19.451 19.146 10.783 0 19.498-8.579 19.498-19.146 0-10.568-8.714-19.169-19.498-19.169z" fill="currentColor"/><path d="M369.269 162c25.838 0 49.704 9.314 67.204 26.229C454.225 205.386 464 229.247 464 255.418c0 26.303-9.806 50.405-27.611 67.869-17.563 17.226-41.4 26.713-67.12 26.713h-226.53c-25.712 0-49.548-9.487-67.117-26.715C57.81 305.818 48 281.717 48 255.418c0-26.167 9.78-50.028 27.539-67.188 17.504-16.915 41.37-26.23 67.2-26.23h226.53m0-16h-226.53C81.541 146 32 191.458 32 255.418 32 319.419 81.541 366 142.739 366h226.529C430.49 366 480 319.419 480 255.418 480 191.458 430.49 146 369.269 146z" fill="currentColor"/>
    </svg>
  </button>
  <button>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="currentColor" d="M19.5 12c0-.23-.01-.45-.03-.68l1.86-1.41c.4-.3.51-.86.26-1.3l-1.87-3.23a.987.987 0 0 0-1.25-.42l-2.15.91c-.37-.26-.76-.49-1.17-.68l-.29-2.31c-.06-.5-.49-.88-.99-.88h-3.73c-.51 0-.94.38-1 .88l-.29 2.31c-.41.19-.8.42-1.17.68l-2.15-.91c-.46-.2-1-.02-1.25.42L2.41 8.62c-.25.44-.14.99.26 1.3l1.86 1.41a7.3 7.3 0 0 0 0 1.35l-1.86 1.41c-.4.3-.51.86-.26 1.3l1.87 3.23c.25.44.79.62 1.25.42l2.15-.91c.37.26.76.49 1.17.68l.29 2.31c.06.5.49.88.99.88h3.73c.5 0 .93-.38.99-.88l.29-2.31c.41-.19.8-.42 1.17-.68l2.15.91c.46.2 1 .02 1.25-.42l1.87-3.23c.25-.44.14-.99-.26-1.3l-1.86-1.41c.03-.23.04-.45.04-.68m-7.46 3.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5s3.5 1.57 3.5 3.5s-1.57 3.5-3.5 3.5"/>
    </svg>
  </button>
  <button>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="currentColor" d="M11 13V3h2v10zm1 8q-1.85 0-3.488-.712T5.65 18.35t-1.937-2.863T3 12q0-2 .825-3.775T6.15 5.15l1.4 1.4q-1.2 1-1.875 2.425T5 12q0 2.9 2.05 4.95T12 19q2.925 0 4.963-2.05T19 12q0-1.6-.663-3.025T16.45 6.55l1.4-1.4q1.5 1.3 2.325 3.075T21 12q0 1.85-.713 3.488t-1.925 2.862t-2.85 1.938T12 21"/>
    </svg>
  </button>
</footer>
@layer support, lessons;

@import "https://unpkg.com/open-props" layer(support.design-system);
@import "https://unpkg.com/open-props/normalize.min.css" layer(support.demo);
@import "https://unpkg.com/open-props/buttons.min.css" layer(support.demo);

/* 
  HTML Structure, 3 elements

  .scroll--root 
    > .scroll--viewport 
      > .scroll--content
        > YOUR_CONTENT
*/

@layer lessons.essentials {
  /*
    - always specify both axis to prevent surprises
    - always specify overscroll behavior on the scrolling axis
    - always match your padding with your scroll-padding (for snap)
    - respect motion prefs when setting scroll-behavior
  */
  
  .scroll--viewport {
    display: flex;
    place-items: center start;
    
    overflow: auto hidden;
    overscroll-behavior-x: contain;
    
    padding-inline: var(--size-8);
    scroll-padding-inline: var(--size-8);
    
    @media (prefers-reduced-motion: no-preference) {
      scroll-behavior: smooth;
    }
  }
}

@layer lessons.colorize {
  /*
    - webkit scrollbars for more customization (Chromium, Safari)
    - scrollbar-color (Firefox, exclusively not Chromium even tho it has support)
    - most mobile browser scrollbars completely ignore all this
  */
  
  .scroll--viewport {
    
    /* we'll be showing our own scroller focus states */
    &:is(:focus-visible, :focus-within) {
      outline-offset: -2px;
      outline: none;
    }
    
    /* to be fair, Switch doesn't show it at all */
    &::-webkit-scrollbar {
      height: 10px;
    }

    /* transparent track is usually best */
    &::-webkit-scrollbar-track {
      background: #0000;
      
      /* so we can push away from the edge/border */
      background-clip: padding-box;
    }

    &::-webkit-scrollbar-thumb {
      /* create 50% opacity variant of a design system surface color */
      background: color-mix(in srgb, 
        light-dark(
          var(--surface-4), 
          var(--surface-2)
        ), 
        #0000 50%
      );
      
      /* maximum radius */
      border-radius: 1e3px;
      
      /* creates illusion of being inset, matches background */
      /* also free cool looking forced colors mode styles */
      border: 3px solid var(--surface-1);
    }
    
    /* highlight thumb to indicate focus is inside */
    &:is(:focus-visible, :focus-within)::-webkit-scrollbar-thumb {
      background: var(--link);
    }
    
    /* if user can hover, we can make it respond to hover */
    @media (hover) {

      /* make the thumb color solid on hover for full legibility */
      &::-webkit-scrollbar-thumb:hover {
        background: light-dark(var(--surface-4), var(--surface-2));
      }
      
      /* default now to 50% faded out */
      &::-webkit-scrollbar {
        opacity: .5;
      }

      /* hover full opacity */
      /* many native OS's wait for hover on the thumb, could try that */
      &::-webkit-scrollbar:hover {
        opacity: 1;
      }
    }
    
    /* styles for Firefox */
    /* this can't be @supports (scrollbar-color: white black) */
    /* or not (scrollbar-color: white black) */
    /* chromium is eager to switch to scrollbar-* and will drop all webkit-scrollbar
       styles if there's any scent of the standard ones
    */
    /* we can still provide a very nice experience for keyboard, mouse */
    @supports (-moz-appearance:none) {
      scrollbar-width: thin;
      scrollbar-color: var(--surface-4) #0000;
      transition: scrollbar-color .3s ease;

      &:is(:focus-visible, :focus-within) {
        scrollbar-color: var(--link) #0000;
      }

      @media (hover) {
        scrollbar-color: 
          color-mix(in srgb, var(--surface-4), #0000 50%) 
          #0000;

        &:hover {
          scrollbar-color: var(--surface-4) #0000;
        }
      }
    }
  }
}

@layer lessons.containerize {
  /*
    - scrollers are often fixed / extrinsically sized 
      - this one fills vertical space between 
        the intrinsically sized header and footer
    - children want to use @container
    - scroll-state snapped, stuck, or overflowing can be queried
  */
  
  .scroll--root {
    container: --main / size;
  }
  
  .scroll--viewport {
    container: --main-scroller / size scroll-state;
  }
  
  .scroll--content > li {
    /* children will use snapped scroll-state() */
    container-type: scroll-state;
  }
}

@layer lessons.scroll-snap {
  /*
    - perfect resting alignments
    - enables scroll-state(snapped) for showing 
      - highlight
      - game title
    - enables overscroll elastic effect
  */
  
  .scroll--viewport {
    scroll-snap-type: x mandatory;
  }
  
  .scroll--content > li {
    scroll-snap-align: start;
  }
}

@layer lessons.scroll-state {
  /*
    - upgrade if supported
    - highlight snapped game art
    - animate game title
  */
  
  /* pulsing blue outline color */
  @keyframes game-focus {
    from {
      outline-color: hsl(200 100% 50%);
    }
    to {
      outline-color: hsl(200 100% 80%);
    }
  }
  
  /* adjust space for features */
  .scroll--viewport {
    @supports (container-type: scroll-state) {
      padding-inline: var(--size-9);
      scroll-padding-inline: var(--size-9);
    }
  }
  
  .game {
    
    /* img child asks nearest scroll-state container
       ? are you snapped 
    */
    img {
      @container scroll-state(snapped: x) {
        /* create outline */
        outline: 5px solid blue;
        outline-offset: 5px;
        
        /* infinite outline animation */
        animation: game-focus .5s var(--ease-3) alternate infinite;
      }
    }
    
    /* if motion is ok, animate game titles */
    figcaption {
      @media (prefers-reduced-motion: no-preference) {
        z-index: -1;
        transition: 
          translate .5s var(--ease-spring-2) .2s,
          opacity .5s var(--ease-3) .2s;

        /* you = nearest scroll-state container */
        /* if you are not snapped… then hide yo'self! */
        /* if you are snapped, stay visible! */
        @container not scroll-state(snapped: x) {
          translate: 0 50px;
          opacity: 0;
        }
        /* saves from writing the out and in, 
           since in is the natural state we just tell things 
           what to do when they're out 
        */
      }
    }
  }
}

@layer lessons.overscroll-effect {
  /*
    - some OSs have overscroll effects built in
    - this add some some fun to overscrolling
    - also provides a hint that you're at the end
    - this works because of scroll-snap-stop: x mandatory
      - the scroller MUST snap on something
      - we'll be creating pseudo elements that ARE NOT snaps
      - so while we can scroll to see them, they'll never snap
  */
  
  .scroll--content {
    
    /* flex is often best for this
       we dont need columns, we need a row of intrinsic sized items
    */
    display: flex;
    
    /* our overscroll effect sentinels */
    &::before,
    &::after {
      /* empty nodes to consume space */
      content: "";
      display: block;
      
      /* how much space to consume */
      inline-size: 25cqi;
      
      /* uhuh, can't shrink me */
      flex-shrink: 0;
    }

    /* the after in this one is hella big so
       the last item can be snapped/highlighted/title shown
    */
    &::after {
      inline-size: 90cqi;
    }
  }
}

@layer lessons.scroll-animation {
  /*
    - subtle but effective exit scrollport animation
    - stylistically no entry animations
    - animation-range and view(x) make this easy
  */
  
  /* just the to keyframe effect */
  @keyframes leaving-scroller {
    to {
      opacity: .2;
    }
  }
  
  /* each game, if motion is coo and browser has support… */
  .scroll--content .game {
    @media (prefers-reduced-motion: no-preference) {
      @supports (animation-timeline: view(x)) {
        
        /* attach an animation to each game */
        animation: leaving-scroller linear both;
        
        /* power it with horizontal scroll viewport intersection */
        animation-timeline: view(x);
        
        /* clamp the timing to the last 50% of the element leaving */
        animation-range: exit 50% exit 100%;
      }
    }
  }
}

@layer lessons.loading-animation {
  /*
    - extra flair, introduce the elements
    - only if it's cool with the user's pref
    - would love to have used sibling-index()
    - magic is mostly from @starting-style
  */
  
  .scroll--content .game {
    @media (prefers-reduced-motion: no-preference) {
      transition: transform 1s var(--ease-spring-2);
      transition-delay: calc(var(--i) * .05s);

      @starting-style {
        transform: translateX(100vw) translateZ(calc(var(--i) * -1px));
      }
    }
  }
}












@layer support.demo {
  body {
    block-size: 100lvh;
    display: grid;
    grid-template-rows: auto 1fr min-content;
  }
  
  header {
    display: flex;
    place-content: space-between;
    padding-block: var(--size-fluid-3);
    padding-inline: var(--size-8);
    
    @media (height < 450px) {
      padding-block: var(--size-2);
    }
    
    > [label="accounts"] {
      button {
        padding: 2px;
        aspect-ratio: 1;
        border-radius: var(--radius-round);
        inline-size: var(--size-8);
        text-indent: 100cqi;
        overflow: hidden;
        background-image: 
          radial-gradient(#0000 65%, var(--surface-1) 0), 
          var(--img);
        background-size: cover;
        
        @media (height < 450px) {
          inline-size: var(--size-7);
        }
      }
    }
    
    > [label="status bar"] {
      display: flex;
      place-items: center;
      gap: var(--size-4);
      
      datetime {
        font-weight: bold;
        font-size: var(--font-size-2);
      }
    }
    
    .battery {
      display: flex;
      place-items: center;
      gap: var(--size-1);
    }
  }
  
  .scroll--root {
    display: grid;
  }
  
  .scroll--viewport {
    /* undo what normalize sets on the document */
    /* if not undone, webkit selectors wont match */
    scrollbar-color: auto;
    scrollbar-width: auto;
  }
  
  .scroll--content {
    display: flex;
    list-style-type: none;
    gap: var(--size-3);
    margin: 0;
    padding: 0;

    > li {
      padding: 0;
      flex-shrink: 0;
    }
  }
  
  .game {
    figure {
      display: flex;
      flex-direction: column-reverse; /* caption on top */
      gap: 1ch;
      
      @supports (container-type: scroll-state) {
        gap: var(--size-4);
      }
      
      img {
        background: var(--surface-2);
        block-size: 70cqb;
        inline-size: auto;
        aspect-ratio: 1;
        object-fit: cover;
      }
    }
    
    figcaption {
      text-box: cap alphabetic;
      text-align: center;
      white-space: nowrap;
      font-size: max(var(--font-size-4), 5cqb);
      font-weight: 500;
      letter-spacing: var(--font-letterspacing-2);
      color: light-dark(var(--blue-7), var(--blue-3));
      
      @media (height < 450px) {
        font-size: .9rem;
      }
    }
  }
  
  footer {
    display: flex;
    place-content: center;
    padding: var(--size-fluid-3);
    gap: var(--size-3);
    max-inline-size: 100vw;
    overflow-x: auto;
    
    @media (height < 450px) {
      padding: var(--size-fluid-2);
    }
    
    button {
      flex-shrink: 0;
      inline-size: var(--size-9);
      block-size: var(--size-9);
      border-radius: var(--radius-round);
      border-color: transparent;
      padding: 0;
        
      @media (height < 450px) {
        inline-size: var(--size-8);
        block-size: var(--size-8);
      }
      
      > svg {
        inline-size: 60%;
        height: auto;
      }
      
      &.online {
        background: red;
        color: white;
        font-size: var(--font-size-00);
        text-shadow: none;
        text-transform: uppercase;
        
        display: grid;
        place-items: center;
        place-content: center;
        gap: 0;
        
        > svg {
          width: 80%;
          height: auto;
        }
      }
    }
  }
}
const sounds = {
  snap: new Audio('https://assets.codepen.io/2585/snap.mp3'),
  pop: new Audio('https://assets.codepen.io/2585/pop.m4a'),
}

scroller.onclick = event => {
  let target = event.target.closest('.game')
  
  if (target) {
    scroller.scrollTo({
      left: target.offsetLeft,
      behavior: 'smooth'
    })
  }
}

scroller.onscrollsnapchanging = event => {
  navigator?.vibrate(50)
  sounds.pop.play()
}

scroller.onscrollsnapchange = event => {
  sounds.snap.play()
}
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.