/* ================= Settings ================= */

/* Intro animation on page load */
:root {
  --fade-duration: 1s; /* how long the title/icons intro takes */
  --fade-delay: 0s; /* wait before it starts */
  --fade-easing: ease-in-out; /* fade: slow start, faster middle, soft finish */
  --move-easing: cubic-bezier(0.45, 0, 0.55, 1); /* movement curve */
  --pad-x: 16px; /* left/right space around the page */
  --pad-y: 24px; /* space between the page content and the top/bottom edge */
  --drift-distance: 10px; /* how far the title and icons float after the intro */
  --drift-duration: 5s; /* how long that takes */
  --intro-distance: 40px; /* how far away the title and icons start (bigger = further) */
  --title-gap: clamp(
    16px,
    4vw,
    40px
  ); /* space on each side of the title/icons */
  --bar-fill-duration: 0.6s; /* how long the bar takes to fill on computers */
}

/* Hover bounce on icons */
:root {
  --hover-scale: 1.15; /* how big an icon gets on hover */
  --bounce-duration: 0.5s; /* how long the bounce takes */
  --bounce-easing: cubic-bezier(
    0.34,
    1.56,
    0.64,
    1
  ); /* overshoots, so it bounces both in and out */
}

/* Hover letters */
:root {
  --letter-lift: 14px; /* how high a letter jumps when hovered */
  --letter-rise: 0.15s; /* how fast it goes up */
  --letter-fall: 0.6s; /* how long it takes to drop back down */
}

/* The box: progress bar and opening */
:root {
  --pull: 0; /* 0 to 1, set by the script while you pull */
  --bar-height: 28px; /* height of the squished box (the progress bar) */
  --bar-gap: 14px; /* space above and below the bar/box */
  --box-max: 900px; /* tallest the box gets */
  --bar-fill-color: #588c32; /* progress bar fill */
  --box-expand-duration: 1.2s; /* how long the box takes to grow */
  --box-expand-easing: cubic-bezier(
    0.65,
    0,
    0.35,
    1
  ); /* smooth start and finish */
  --tabs-fade-delay: 0s; /* tabs/content start fading in this long after opening starts */
  --tabs-fade-duration: 0.9s; /* how long that fade takes */
}

/* Tab preview */
:root {
  --preview-opacity: 0.2; /* how faint a previewed section is while you hover its tab */
  --panel-fade: 0.2s; /* how fast sections fade */
}

/* ================= Keyframes ================= */

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Start fully off screen: title from the top, icons from the bottom */
@keyframes slide-from-top {
  from {
    transform: translate3d(0, calc(var(--intro-distance) * -1), 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}

@keyframes slide-from-bottom {
  from {
    transform: translate3d(0, var(--intro-distance), 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}

/* The tiny scale(1.0001) stops browsers snapping the slow drift to whole pixels */
@keyframes drift-up {
  from {
    transform: translate3d(0, 0, 0) scale(1.0001);
  }
  to {
    transform: translate3d(0, calc(var(--drift-distance) * -1), 0) scale(1.0001);
  }
}

@keyframes drift-down {
  from {
    transform: translate3d(0, 0, 0) scale(1.0001);
  }
  to {
    transform: translate3d(0, var(--drift-distance), 0) scale(1.0001);
  }
}

@keyframes progress-bar-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Hint on the "g": two little tugs 0.5s apart, then a 2s pause, repeat */
@keyframes tug {
  0% {
    transform: translateY(0);
  }
  5% {
    transform: translateY(7px);
  }
  10% {
    transform: translateY(0);
  }
  15% {
    transform: translateY(7px);
  }
  20% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(0);
  }
}

@keyframes title-enter {
  from {
    opacity: 0;
    transform: translateY(-100vh);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes icons-enter {
  from {
    opacity: 0;
    transform: translateY(100vh);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ================= Intro: title and icons ================= */

/* Fully invisible (0% opacity) until the intro begins */
html.js h1,
html.js .icons {
  opacity: 0;
}

h1,
.icons {
  will-change: transform, opacity;
}

h1 {
  animation:
    fade-in var(--fade-duration) var(--fade-easing) var(--fade-delay) both,
    slide-from-top var(--fade-duration) var(--move-easing) var(--fade-delay)
      both;
  translate: 0 var(--drift-distance);
}

.icons {
  animation:
    fade-in var(--fade-duration) var(--fade-easing) var(--fade-delay) both,
    slide-from-bottom var(--fade-duration) var(--move-easing) var(--fade-delay)
      both;
  translate: 0 calc(var(--drift-distance) * -1);
}

/* Wait until the page and font have loaded (see script).
   These come AFTER the animation rules so they are not overridden. */
html.js h1,
html.js .icons {
  animation-play-state: paused;
}

html.js body.loaded h1,
html.js body.loaded .icons {
  animation-play-state: running;
}

/* ================= Page ================= */

* {
  box-sizing: border-box;
}

html {
  width: 100%;
  height: 100%;
  overflow: hidden;
  overflow: clip;
  overscroll-behavior: none;
  touch-action: none;
}

body {
  margin: 0;
  padding: max(var(--pad-y), env(safe-area-inset-top)) var(--pad-x)
    max(var(--pad-y), env(safe-area-inset-bottom));
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center; /* title + icons sit together in the middle until the box opens (computers switch to space-between below) */
  background: #121212;
  color: #fff;
  text-align: center;
  font-family: "Nunito", sans-serif;
  overflow: hidden;
  overflow: clip;
  overscroll-behavior: none;
  touch-action: none;
  contain: paint;
}

h1 {
  cursor: default; /* normal arrow pointer over the title */
  user-select: none; /* title text can't be selected */
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none; /* lets a finger slide across the letters */
  margin: 0 0 clamp(16px, 4vw, 32px);
  margin-bottom: var(--title-gap);
  font-size: clamp(2rem, 9vw, 4.5rem);
  line-height: 1.1;
  flex: 0 0 auto;
}

/* Visually hidden button that opens the box (keyboard / screen readers) */
.sr-open {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.sr-open:focus-visible {
  width: auto;
  height: auto;
  clip-path: none;
  top: 8px;
  left: 8px;
  padding: 8px 12px;
  background: #222;
  color: #fff;
  border: 1px solid #444;
  border-radius: 8px;
  font: inherit;
  z-index: 5;
}

/* ================= The box ================= */

/* Closed at the start. .peek = the progress bar is showing. .open = full box. */
.stage {
  flex: 0 1 0px;
  width: 100%;
  min-height: 0;
  max-height: calc(var(--box-max) + 2 * var(--bar-gap));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  opacity: 0;
  transition: flex-basis 0.25s ease;
}

.stage.peek {
  flex-basis: calc(var(--bar-height) + 2 * var(--bar-gap));
  animation: progress-bar-fade-in 0.25s ease both;
}

/* Opens up to fill the space, pushing the title up and the icons down */
.stage.open {
  flex-basis: 100%;
  transition: flex-basis var(--box-expand-duration) var(--box-expand-easing)
    0.3s;
}

.box {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  align-self: center;
  width: min(100%, 720px);
  margin: var(--bar-gap) 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #121212;
  border: 6px solid #fff;
  border-radius: 28px;
}

/* The progress fill: follows your pull, empties right to left if you let go early */
.box::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--bar-fill-color);
  transform: scaleX(var(--pull));
  transform-origin: left center;
  transition:
    transform 0.3s ease,
    opacity 0.25s ease;
  pointer-events: none;
}

/* While you are pulling, the fill follows right away */
html.pulling .box::before {
  transition: opacity 0.25s ease;
}

/* Once open, the fill fades away */
html.box-open .box::before {
  opacity: 0;
  transition:
    transform var(--bar-fill-duration) ease-in-out,
    opacity 0.6s ease 0s;
}

/* No JavaScript: just show the open box */
html:not(.js) .stage {
  flex-basis: 100%;
}

/* ================= Tabs and sections ================= */

/* Hidden until the box has opened, then fade in */
html.js .tabs,
html.js .panels {
  opacity: 0;
  pointer-events: none;
}

html.box-open .tabs,
html.box-open .panels {
  opacity: 1;
  pointer-events: auto;
  transition: opacity var(--tabs-fade-duration) var(--fade-easing)
    var(--tabs-fade-delay);
}

.tabs {
  --tab-gap: clamp(10px, 3vw, 28px); /* the visible space between tabs */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px var(--tab-gap);
  padding: 32px 16px 0;
  flex: 0 0 auto;
}

.tab {
  position: relative;
  font: inherit;
  font-weight: 700;
  font-size: clamp(1.05rem, 4.2vw, 1.5rem);
  color: #fff;
  opacity: 0.6;
  background: none;
  border: none;
  padding: 6px 4px 14px;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.2s;
}

.tab:hover,
.tab[aria-selected="true"] {
  opacity: 1;
}

/* Invisible hover area that reaches into the gap on both sides,
   so the mouse is always on one tab while moving left and right */
.tab::before {
  content: "";
  position: absolute;
  inset: -2px calc(var(--tab-gap) / -2 - 0.5px);
}

/* The green rounded pill under the text */
.tab::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 28%; /* the small size stays the same on hover, it only fades in */
  height: 5px;
  border-radius: 999px;
  background: #588c32;
  opacity: 0;
  transform: translateX(-50%);
  transition:
    opacity 0.25s ease,
    width 0.35s cubic-bezier(0.65, 0, 0.35, 1);
}

/* Hover: the small pill fades in (mouse only) */
@media (hover: hover) {
  .tab:hover::after {
    opacity: 1;
  }
}

.tab:focus-visible::after {
  opacity: 1;
}

/* Selected: the pill stretches across the whole word */
.tab[aria-selected="true"]::after {
  width: 100%;
  opacity: 1;
}

.scroll-dots {
  display: none;
}

html.js .scroll-dots {
  opacity: 0;
  pointer-events: none;
}

html.box-open .scroll-dots {
  opacity: 1;
  transition: opacity var(--tabs-fade-duration) var(--fade-easing)
    var(--tabs-fade-delay);
}

.panels {
  flex: 1;
  min-height: 0;
  display: grid; /* all sections share the same space */
  overflow: hidden;
}

.panel {
  grid-area: 1 / 1;
  min-height: 0;
  overflow: auto;
  display: flex;
  align-items: center; /* centers the text vertically */
  justify-content: center; /* and horizontally */
  text-align: center;
  padding: 20px;
  font-size: clamp(1.6rem, 6vw, 2.6rem);
  font-weight: 700;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity var(--panel-fade) ease,
    visibility var(--panel-fade);
}

.panel p {
  margin: 0;
}

/* The section you are on */
.panel.active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* A section you are hovering a tab for: faint */
.panel.preview {
  opacity: var(--preview-opacity);
  visibility: visible;
}

/* While previewing another section, the current one fades away */
.panels.previewing .panel.active:not(.preview) {
  opacity: 0;
}

/* ================= Icons ================= */

.icons {
  display: flex;
  justify-content: center;
  gap: clamp(10px, 3.5vw, 48px);
  margin-top: var(--title-gap);
  flex-wrap: wrap;
  flex: 0 0 auto;
}

.icon-element {
  position: relative;
  display: inline-block;
  width: min(64px, 10vw);
  height: min(64px, 10vw);
}

.icon-element::after {
  content: "";
  position: absolute;
  /* Drawn at its biggest (hover) size and shrunk at rest, so it is always
     rendered sharp and never re-drawn at in-between sizes while bouncing. */
  inset: calc((1 - var(--hover-scale)) * 50%);
  transform: scale(calc(1 / var(--hover-scale)));
  will-change: transform;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  transition: transform var(--bounce-duration) var(--bounce-easing);
}

/* Bounce in on hover, bounce back out when the mouse leaves */
@media (hover: hover) {
  html:not(.js) .icon-element:hover::after,
  html.intro-done .icon-element:hover::after {
    transform: scale(1);
  }
}

html:not(.js) .icon-element:focus-visible::after,
html.intro-done .icon-element:focus-visible::after {
  transform: scale(1);
}

.tiktok::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z'/%3E%3C/svg%3E");
}

.youtube::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E");
}

.twitch::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z'/%3E%3C/svg%3E");
}

.discord {
  font: inherit; /* so its pop-up uses Nunito too */
  padding: 0;
  border: none;
  background-color: transparent;
  cursor: pointer;
}

.discord::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189z'/%3E%3C/svg%3E");
}

.steam::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'%3E%3Cpath d='M11.979 0C5.678 0 .511 4.86.022 11.037l6.432 2.658c.545-.371 1.203-.59 1.912-.59.063 0 .125.004.188.006l2.861-4.142V8.91c0-2.495 2.028-4.524 4.524-4.524 2.494 0 4.524 2.031 4.524 4.527s-2.03 4.525-4.524 4.525h-.105l-4.076 2.911c0 .052.004.105.004.159 0 1.875-1.515 3.396-3.39 3.396-1.635 0-3.016-1.173-3.331-2.727L.436 15.27C1.862 20.307 6.486 24 11.979 24c6.627 0 11.999-5.373 11.999-12S18.605 0 11.979 0zM7.54 18.21l-1.473-.61c.262.543.714.999 1.314 1.25 1.297.539 2.793-.076 3.332-1.375.263-.63.264-1.319.005-1.949s-.75-1.121-1.377-1.383c-.624-.26-1.29-.249-1.878-.03l1.523.63c.956.4 1.409 1.5 1.009 2.455-.397.957-1.497 1.41-2.454 1.012H7.54zm11.415-9.303c0-1.662-1.353-3.015-3.015-3.015-1.665 0-3.015 1.353-3.015 3.015 0 1.665 1.35 3.015 3.015 3.015 1.663 0 3.015-1.35 3.015-3.015zm-5.273-.005c0-1.252 1.013-2.266 2.265-2.266 1.249 0 2.266 1.014 2.266 2.266 0 1.251-1.017 2.265-2.266 2.265-1.253 0-2.265-1.014-2.265-2.265z'/%3E%3C/svg%3E");
}

/* Geometry Dash cube: frame, two eyes, mouth */
.gdbrowser::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff' fill-rule='evenodd'%3E%3Cpath d='M1 1h22v22H1zM2.8 2.8v18.4h18.4V2.8z'/%3E%3Cpath d='M6 5h4.8v4.8H6zM7.3 6.3v2.2h2.2V6.3zM13.2 5h4.8v4.8h-4.8zM14.5 6.3v2.2h2.2V6.3zM4.6 11.7h14.8v4.5H4.6zM6 13.1v1.7h12v-1.7z'/%3E%3C/svg%3E");
}

/* ================= Pop-ups ================= */

.tooltip {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  transform: translateX(-50%);
  padding: 8px 14px;
  border: 1px solid #444;
  border-radius: 8px;
  background: #222;
  color: #fff;
  font-family: inherit;
  font-size: clamp(0.85rem, 3.5vw, 1.1rem);
  line-height: 1.4;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity 0.3s,
    visibility 0.3s;
  z-index: 1;
}

.icon-element:focus-visible .tooltip,
.icon-element.show .tooltip {
  opacity: 1;
  visibility: visible;
}

@media (hover: hover) {
  .icon-element:hover .tooltip {
    opacity: 1;
    visibility: visible;
  }
}

/* ================= Title letters ================= */

/* Each letter of the title jumps up on hover, then drops back down */
h1 span {
  display: inline-block;
  /* dropping back down: speeds up like gravity, tiny bounce on landing */
  transition: transform var(--letter-fall) cubic-bezier(0.55, 0.05, 0.65, 1.45);
}

@media (hover: hover) {
  html:not(.js) h1 span:not(.handle):hover,
  html.intro-done h1 span:not(.handle):hover {
    transform: translateY(calc(var(--letter-lift) * -1));
    transition: transform var(--letter-rise) ease-out; /* quick lift */
  }
}

/* Touch: letters under a finger jump up (set by the script), same as hover */
html.intro-done h1 span.lift {
  transform: translateY(calc(var(--letter-lift) * -1));
  transition: transform var(--letter-rise) ease-out;
}

/* The "g" is the handle: pull it down (or click it) to open the box */
h1 .handle {
  cursor: grab;
}

h1 .handle.dragging {
  cursor: grabbing;
  transition: none;
}

/* The hint: two little tugs, a pause, repeat (stops when you hover the g) */
h1 .handle.hint {
  animation: tug 2.5s ease-in-out infinite;
}

/* ================= Swipe-down hint (phones only) ================= */

.swipe-hint {
  display: none;
}

@keyframes jelly {
  0% {
    transform: translateY(0) scaleY(1);
  }
  20% {
    transform: translateY(8px) scaleY(1.04);
  } /* gentle pull down */
  34% {
    transform: translateY(-2px) scaleY(0.98);
  } /* soft snap back */
  44% {
    transform: translateY(1px) scaleY(1.005);
  }
  54%,
  100% {
    transform: translateY(0) scaleY(1);
  }
}

/* ================= Reduced motion ================= */

@media (prefers-reduced-motion: reduce) {
  h1,
  .icons {
    opacity: 0;
    animation: none;
  }

  /* Title travels down from above the screen */
  html.box-open h1 {
    animation: title-enter var(--box-expand-duration) var(--box-expand-easing)
      0s both;
  }

  /* Icons travel up from below the screen */
  html.box-open .icons {
    animation: icons-enter var(--box-expand-duration) var(--box-expand-easing)
      0s both;
  }

  html.js h1,
  html.js .icons {
    opacity: 1;
  }

  h1 span,
  h1 .handle.hint,
  .icon-element::after,
  .stage,
  .stage.open,
  .box::before,
  .panel,
  .tab,
  .tab::after,
  html.box-open .tabs,
  html.box-open .panels {
    animation: none;
    transition: none;
  }
}

/* ================= Small screens ================= */

/* Phones: keep the title and all six icons comfortably inside the viewport. */
@media (max-width: 600px) {
  :root {
    --title-gap: clamp(15px, 4.5vw, 20px); /* was clamp(20px, 6.5vw, 32px) */
    --bar-gap: 22px; /* NEW: keeps the space around the progress bar and box */
  }

  body {
    --pad-x: 12px;
    --pad-y: 16px;
  }

  h1 {
    font-size: clamp(2.2rem, 10vw, 3.6rem);
    line-height: 1.08;
    margin-bottom: var(--title-gap);
  }

  .icons {
    width: 100%;
    justify-content: center;
    gap: clamp(16px, 5vw, 26px);
    margin-top: var(--title-gap);
  }

  .icon-element {
    flex: 0 0 auto;
    width: clamp(30px, 9.5vw, 50px);
    height: clamp(30px, 9.5vw, 50px);
  }
}

/* Landscape phones have plenty of width but limited height. */
@media (max-width: 900px) and (orientation: landscape) and (max-height: 500px) {
  body {
    --pad-x: 14px;
    --pad-y: 8px;
  }

  h1 {
    font-size: clamp(1.8rem, 6.5vw, 3rem);
    line-height: 1.05;
    margin-bottom: clamp(12px, 3vh, 22px);
  }

  .icons {
    gap: clamp(12px, 2.5vw, 24px);
  }

  .icon-element {
    width: clamp(26px, 7vw, 38px);
    height: clamp(26px, 7vw, 38px);
  }
}

/* Computers: the bar opens up and fills by itself, then becomes the box.
   When the bar is full, the box grows from the middle while the title and icons
   slide in from outside the screen, in step with it. */
@media (hover: hover) and (pointer: fine) {
  :root {
    --fade-delay: var(--bar-fill-duration);
    --title-gap: 40px; /* space between the title/icons and the box */
  }

  @keyframes desktop-title-enter {
    from {
      opacity: 0;
      transform: translateY(
        calc(-100% - var(--pad-y) - 10px)
      ); /* minus: starts above */
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  @keyframes desktop-icons-enter {
    from {
      opacity: 0;
      transform: translateY(
        calc(100% + var(--pad-y) + 10px)
      ); /* plus: starts below */
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  /* Title at the top, icons at the bottom from the start; the stage fills the middle */
  body {
    justify-content: space-between;
  }

  h1 {
    margin-bottom: var(--title-gap);
  }

  .icons {
    margin-top: var(--title-gap);
  }

  .stage,
  .stage.peek,
  .stage.open {
    flex: 1 1 0px;
    max-height: none;
    justify-content: center; /* the bar sits in the middle */
    transition: none;
  }

  /* The bar is the box at its smallest; it grows from the middle */
  .box {
    flex: 0 1 var(--bar-height);
    max-height: var(--box-max);
  }

  html.box-open .box {
    flex-grow: 1;
    transition: flex-grow var(--box-expand-duration) var(--box-expand-easing) 0s;
  }

  /* Title and icons: hidden off-screen until the box opens, then slide in with it */
  h1,
  .icons {
    animation: none;
  }

  html.box-open h1 {
    opacity: 1;
    animation:
      desktop-title-enter var(--box-expand-duration) var(--box-expand-easing) 0s
        both,
      fade-in 0.8s ease-out 0s both;
  }

  html.box-open .icons {
    opacity: 1;
    animation: desktop-icons-enter var(--box-expand-duration)
      var(--box-expand-easing) 0s both;
  }

  /* The green fill: fills at the same speed, then disappears fast when the box opens */
  .box::before {
    transition:
      transform var(--bar-fill-duration) ease-in-out,
      opacity 0.25s ease;
  }

  html.box-open .box::before {
    transition:
      transform var(--bar-fill-duration) ease-in-out,
      opacity 0.15s ease 0s;
  }

  html.js .tab,
  html.js .panel {
    transition-delay: 0s;
  }

  /* Tabs and panel contents fade in together as the box expands */
  html.js .tabs,
  html.js .panels {
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--box-expand-duration) var(--box-expand-easing) 0s;
  }

  html.box-open .tabs,
  html.box-open .panels {
    opacity: 1;
    pointer-events: auto;
  }
}

/* Skip all transitions during the initial intro setup */
.skip-peek-transition,
.skip-peek-transition * {
  transition: none !important;
  animation: none !important;
}

/* Phones: no progress bar. Pulling down grows the box outline itself. */
@media (hover: none) {
  .box::before {
    display: none; /* no green fill */
  }

  .stage {
    opacity: 1; /* the outline is visible right away while pulling */
    transition: flex-basis 0.35s ease; /* smooth retract when you let go early */
  }

  .stage.peek {
    animation: none;
    /* the box height follows your finger (--reveal-px is set by the script) */
    flex-basis: var(--reveal-px, calc(2 * var(--bar-gap)));
  }

  /* Once triggered, grow to the full box (must come after .stage.peek) */
  .stage.peek.open {
    flex-basis: 100%;
  }

  /* While pulling: the tabs show at 50%, nothing else */
  .tabs {
    transition: opacity 0.2s ease;
  }

  .stage.peek .tabs {
    opacity: var(--pull); /* 0 at the start, 1 when all tabs are visible */
  }

  /* follow the finger exactly, no lag */
  html.pulling .tabs {
    transition: none;
  }

  /* Once it opens, the tabs go to full and the content fades in as before */
  html.box-open .stage.peek .tabs {
    opacity: 1;
  }

  /* While your finger is down, the box follows it exactly, with no lag */
  html.pulling .stage {
    transition: none;
  }

  /* Past the point, it finishes opening right away from wherever it is.
     Faster than before, and it starts moving immediately (no slow start). */
  .stage.open {
    transition: flex-basis 0.65s cubic-bezier(0.25, 0.8, 0.3, 1) 0s;
  }

  :root {
    --tabs-fade-duration: 0.5s; /* content fades in a bit quicker too */
  }

  /* Tabs: bigger text, closer to the outline, one scrollable row */
  .tabs {
    flex-wrap: nowrap;
    justify-content: flex-start;
    padding: 12px 16px 4px;
    overflow-x: auto;
    overflow-y: hidden;
    touch-action: pan-x; /* a finger can scroll the row sideways */
    overscroll-behavior-x: contain;
  }

  /* Centers the row when it fits, and still scrolls from the very first tab when it doesn't */
  .tabs > .tab:first-child {
    margin-left: auto;
  }

  .tabs > .tab:last-child {
    margin-right: auto;
  }

  .tab {
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: clamp(1.2rem, 5.4vw, 1.6rem); /* was 1.4rem, 6.4vw, 1.9rem */
    padding: 12px 16px 10px; /* bottom was 4px, this is the gap above the scroll bar */
  }

  /* hide the native scroll bar */
  .tabs {
    scrollbar-width: none;
    padding-bottom: 4px;
  }

  .tabs::-webkit-scrollbar {
    display: none;
  }

  /* Two dots, centered, lower than the tabs */
  .scroll-dots {
    display: block;
    position: relative;
    flex: 0 0 auto;
    width: 26px;
    height: 8px;
    margin: 14px auto 12px;
  }

  .scroll-dots.off {
    display: none; /* nothing to scroll, so no dots */
  }

  .scroll-dots::before,
  .scroll-dots::after {
    content: "";
    position: absolute;
    top: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.25);
  }

  .scroll-dots::before {
    left: 0;
  }
  .scroll-dots::after {
    right: 0;
  }

  .scroll-dots .pill {
    position: absolute;
    top: 0;
    left: 0;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: #fff;
  }

  /* Fades in with your pull, same as the tabs */
  .stage.peek .scroll-dots {
    opacity: var(--pull);
  }

  html.box-open .stage.peek .scroll-dots {
    opacity: 1;
  }

  html.pulling .scroll-dots {
    transition: none;
  }

  /* Outline grows from a hairline to full thickness as you pull */
  .box {
    border-width: calc(1px + 5px * var(--pull));
  }

  html:not(.pulling) .box {
    transition: border-width 0.3s ease; /* smooth when you let go early */
  }

  /* While pulling, the box's top/bottom gap follows the pull (starts at 0) */
  html.pulling .box {
    margin: var(--pull-gap, var(--bar-gap)) 0;
  }

  .swipe-hint {
    display: flex;
    justify-content: center;
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(env(safe-area-inset-bottom) + 60px);
    pointer-events: none;
    color: rgba(255, 255, 255, 0.45); /* the transparent white */
    font-size: 0.95rem;
    font-weight: 700;
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 0.4s ease,
      visibility 0.4s;
  }

  .swipe-hint-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    transform-origin: top center;
  }

  /* Shows after the intro */
  html.intro-done .swipe-hint {
    visibility: visible;
    /* fades out as you pull (gone at 25% of the pull), back in if you pull up again */
    opacity: max(0, calc(1 - var(--pull) * 1.25));
  }

  html.intro-done .swipe-hint-inner {
    animation: jelly 3.4s cubic-bezier(0.4, 0, 0.3, 1) infinite;
  }

  /* The finger is down: the fade follows it with no lag, the tug freezes */
  html.pulling .swipe-hint {
    transition: none;
  }

  html.pulling .swipe-hint-inner {
    animation-play-state: paused;
  }

  /* Once the box opens it's gone for good */
  html.box-open .swipe-hint {
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 0.3s ease,
      visibility 0.3s;
  }

  @media (prefers-reduced-motion: reduce) {
    html.intro-done .swipe-hint-inner {
      animation: none;
    }
  }
}
