/* ================= 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,
    32px
  ); /* 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: 720px; /* 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 */
  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);
  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 0.3s ease,
    opacity 0.8s ease 0.2s;
}

/* 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);
  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.
   The title and icons fade in when the bar finishes, and are only pushed by the box. */
@media (hover: hover) and (pointer: fine) {
  :root {
    --fade-delay: var(
      --bar-fill-duration
    ); /* title and icons wait for the bar */
    --title-gap: 40px; /* space between the title/icons and the box (raise for more) */
  }

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

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

  .stage.open {
    transition-delay: 0s; /* the box starts growing the moment the bar is full */
  }

  /* Title and icons only fade in: no sliding, no drifting closer */
  h1,
  .icons {
    animation: fade-in var(--fade-duration) var(--fade-easing) var(--fade-delay)
      both;
  }

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

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

  /* 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;
}

/* 
 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;
  }
}