@font-face {
  font-family: "Unbounded";
  src: url("fonts/unbounded-latin-var.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Atkinson Hyperlegible";
  src: url("fonts/atkinson-hyperlegible-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Atkinson Hyperlegible";
  src: url("fonts/atkinson-hyperlegible-latin-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Depth bands, surface to deep */
  --surface: #DCE6E8;
  --shelf: #7FA3AE;
  --trench: #1F3D4F;
  --abyss: #06121C;
  /* Buoy orange: used only for the .si letters */
  --signal: #D9480F;

  --display: "Unbounded", "Segoe UI", system-ui, sans-serif;
  --text: "Atkinson Hyperlegible", "Segoe UI", system-ui, sans-serif;

  --gutter: clamp(1rem, 5vw, 4rem);
  --band-pad: clamp(4rem, 12vh, 9rem);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  /* Containing block for the page-wide .bubbles layer */
  position: relative;
  margin: 0;
  background: var(--abyss);
  color: var(--abyss);
  font-family: var(--text);
  font-size: 1.125rem;
  line-height: 1.6;
}

h1,
h2,
p,
ul {
  margin: 0;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Bands: one continuous descent. Each band blends into the next inside the
   padding between them, so text always sits on its own band's solid colour. */

.band {
  padding: var(--band-pad) var(--gutter);
}

.band-surface {
  background: linear-gradient(
    var(--surface) calc(100% - var(--band-pad)),
    color-mix(in srgb, var(--surface), var(--shelf))
  );
  color: var(--abyss);
  min-height: 88svh;
  display: flex;
  align-items: center;
  position: relative;
}

/* Scroll cue: centred on the hero's bottom edge. Once the visitor scrolls,
   script.js adds .is-gone and it glides down into the next band and fades out. */

.scroll-cue {
  position: absolute;
  z-index: 2;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  display: block;
  padding: 0.5rem;
  color: var(--abyss);
  border-radius: 0.25rem;
  transition:
    opacity 0.6s ease-out,
    transform 0.6s ease-in,
    visibility 0s linear 0s;
}

.scroll-cue.is-gone {
  opacity: 0;
  transform: translate(-50%, 3rem);
  visibility: hidden;
  transition:
    opacity 0.6s ease-out,
    transform 0.6s ease-in,
    visibility 0s linear 0.6s;
}

.scroll-cue svg {
  display: block;
  animation: bob 2.4s ease-in-out infinite;
}

.scroll-cue:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

@keyframes bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(0.5rem);
  }
}

.band-shelf {
  background: linear-gradient(
    color-mix(in srgb, var(--surface), var(--shelf)),
    var(--shelf) var(--band-pad),
    var(--shelf) calc(100% - var(--band-pad)),
    color-mix(in srgb, var(--shelf), var(--trench))
  );
  color: var(--abyss);
}

.band-trench {
  background: linear-gradient(
    color-mix(in srgb, var(--shelf), var(--trench)),
    var(--trench) var(--band-pad),
    var(--trench) calc(100% - var(--band-pad)),
    color-mix(in srgb, var(--trench), var(--abyss))
  );
  color: var(--surface);
}

.band-abyss {
  background: linear-gradient(
    color-mix(in srgb, var(--trench), var(--abyss)),
    var(--abyss) var(--band-pad)
  );
  color: var(--surface);
}

.inner {
  width: 100%;
  max-width: 76rem;
  margin: 0 auto;
  /* Above the page-wide .bubbles layer (z-index 1) */
  position: relative;
  z-index: 2;
}

/* Murk: drifting clouds straddling a band boundary â€” pale sea mist at the
   waterline (hero â†’ shelf), silt into the trench and into the abyss. Each layer
   covers only the padding either side of the boundary, so it never passes
   behind text. Drift uses transform; scroll parallax uses translate with
   --scroll (set by script.js). */

.band-shelf,
.band-trench,
.band-abyss {
  position: relative;
}

.murk-mist {
  --murk: color-mix(in srgb, white 60%, transparent);
}

.murk {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--band-pad));
  height: calc(2 * var(--band-pad));
  overflow: hidden;
  pointer-events: none;
}

.murk-shallow {
  --murk: color-mix(in srgb, var(--abyss) 45%, transparent);
}

.murk-deep {
  /* Near-black water hides dark murk, so the deepest silt catches a little light */
  --murk: color-mix(in srgb, var(--shelf) 18%, transparent);
}

.murk span {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--murk), transparent);
  translate: calc(var(--scroll, 0) * var(--parallax) * 1px) 0;
  animation: murk-drift 38s ease-in-out infinite alternate;
}

.murk span:nth-child(1) {
  left: -10%;
  top: 10%;
  width: max(55%, 26rem);
  height: 80%;
  --parallax: -0.04;
}

.murk span:nth-child(2) {
  left: 30%;
  top: 0;
  width: max(50%, 24rem);
  height: 100%;
  --parallax: 0.03;
  animation-duration: 46s;
  animation-delay: -12s;
}

.murk span:nth-child(3) {
  left: 65%;
  top: 20%;
  width: max(45%, 22rem);
  height: 70%;
  --parallax: -0.06;
  animation-duration: 31s;
  animation-delay: -20s;
}

/* Bubbles: one layer over the whole page (body is its containing block),
   rising behind the text as they would past someone sinking. Layering: band
   backgrounds, then .bubbles (z-index 1), then each band's .inner content
   (z-index 2), then the hero fog (z-index 3). Each <i> is one bubble; its
   start (--from), travel (--travel), --dur and --delay are set by script.js
   from the data-from / data-to band positions in index.html. The bubble's
   look is its ::before, which wobbles. Rings have a pale line plus a faint
   dark edge so they show on both light and dark bands. */

.bubbles {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}

.bubbles i {
  position: absolute;
  top: var(--from, 0);
  /* Keep the whole bubble (plus its 5px wobble) inside the screen width */
  left: min(var(--x), calc(100% - var(--size) - 6px));
  width: var(--size);
  height: var(--size);
  opacity: 0;
  animation: bubble-fade var(--dur, 20s) linear var(--delay, 0s) infinite;
}

.bubbles i[data-end="pop"] {
  animation-name: bubble-pop;
}

.bubbles i::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--surface) 60%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--trench) 30%, transparent);
  background: radial-gradient(circle at 32% 30%, rgb(255 255 255 / 0.7) 0 10%, transparent 12%);
  animation: bubble-wobble 2.6s ease-in-out infinite alternate;
}

/* Glass orbs: larger, see-through, lit from the upper left like the porthole
   glass. Capped on narrow screens so three of them don't crowd a phone. */
.bubbles i.orb {
  --size: min(var(--orb-size), 22vw);
}

.bubbles i.orb::before {
  border: 1px solid color-mix(in srgb, var(--surface) 30%, transparent);
  box-shadow: none;
  background:
    radial-gradient(circle at 30% 28%, rgb(255 255 255 / 0.28), transparent 32%),
    radial-gradient(circle at 50% 50%, transparent 62%, color-mix(in srgb, var(--surface) 14%, transparent) 76%, transparent 78%),
    color-mix(in srgb, var(--surface) 5%, transparent);
  animation-duration: 6s;
}

/* Drifts out at the top of the page */
@keyframes bubble-fade {
  0% {
    transform: translateY(0);
    opacity: 0;
  }
  6%,
  85% {
    opacity: 1;
  }
  100% {
    transform: translateY(var(--travel));
    opacity: 0;
  }
}

/* Rises, then pops: a quick swell and fade at its end point */
@keyframes bubble-pop {
  0% {
    transform: translateY(0) scale(1);
    opacity: 0;
  }
  6% {
    opacity: 1;
  }
  92% {
    transform: translateY(calc(var(--travel) * 0.97)) scale(1);
    opacity: 1;
  }
  95%,
  100% {
    transform: translateY(var(--travel)) scale(1.35);
    opacity: 0;
  }
}

@keyframes bubble-wobble {
  from {
    transform: translateX(-5px);
  }
  to {
    transform: translateX(5px);
  }
}
/* Fog: one fixed layer over the whole page, at every scroll position. Clouds
   start just below the screen and rise past everything (text included) and
   out the top, so the visitor seems to be sinking. A mid-tone between surface
   and shelf reads as haze on the light hero and as faint light on the dark
   bands. Peak strength is kept at 14% so light text in the trench panels
   stays above 4.5:1. */

.fog {
  position: fixed;
  inset: 0;
  z-index: 10;
  overflow: hidden;
  pointer-events: none;
  --fog: color-mix(in srgb, color-mix(in srgb, var(--surface), var(--shelf)) 14%, transparent);
}

/* The page-wide fog colour is almost the hero's own colour, so it vanishes
   there. The hero gets its own rising fog in a darker tint, clipped to the
   hero, so clouds visibly lift out of the waterline over the name. */
.fog-hero {
  position: absolute;
  inset: 0;
  /* Above the text (.inner is z-index 2), so clouds pass over the name */
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
  --fog: color-mix(in srgb, var(--shelf) 30%, transparent);
  /* Fade the clouds in over the hero's bottom quarter, so the clip at the
     hero's bottom edge never shows as a straight line */
  -webkit-mask-image: linear-gradient(to top, transparent, #000 25%);
  mask-image: linear-gradient(to top, transparent, #000 25%);
}

.fog span,
.fog-hero span {
  position: absolute;
  top: 100%;
  width: max(60vw, 26rem);
  height: 45vh;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--fog), transparent);
  translate: calc(var(--scroll, 0) * var(--parallax) * 1px) 0;
  animation: fog-rise 46s linear infinite;
}

/* Negative delays spread the clouds through their climb, so the screen
   already has fog in it on load instead of waiting for the first cloud. */
.fog span:nth-child(1),
.fog-hero span:nth-child(1) {
  left: -15vw;
  --parallax: -0.02;
  animation-delay: -4s;
}

.fog span:nth-child(2),
.fog-hero span:nth-child(2) {
  left: 45vw;
  --parallax: 0.02;
  animation-duration: 54s;
  animation-delay: -13s;
}

.fog span:nth-child(3),
.fog-hero span:nth-child(3) {
  left: 10vw;
  --parallax: -0.03;
  animation-duration: 40s;
  animation-delay: -21s;
}

.fog span:nth-child(4),
.fog-hero span:nth-child(4) {
  left: 60vw;
  --parallax: 0.03;
  animation-duration: 58s;
  animation-delay: -33s;
}

.fog span:nth-child(5),
.fog-hero span:nth-child(5) {
  left: -5vw;
  --parallax: 0.02;
  animation-duration: 50s;
  animation-delay: -42s;
}

.fog span:nth-child(6),
.fog-hero span:nth-child(6) {
  left: 35vw;
  --parallax: -0.02;
  animation-duration: 44s;
  animation-delay: -30s;
}

@keyframes fog-rise {
  from {
    transform: translate(-3vw, 0) scale(1);
  }
  to {
    transform: translate(3vw, calc(-100vh - 100%)) scale(1.25);
  }
}

@keyframes murk-drift {
  from {
    transform: translateX(-8%) scale(1);
  }
  to {
    transform: translateX(8%) scale(1.15);
  }
}

/* Hero: the name, then .si unfolding into a rotating phrase */

.name {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2rem, 8.5vw, 7.5rem);
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: clamp(1rem, 2.5vw, 2.5rem);
}

.key {
  color: var(--signal);
}

.si {
  margin-top: 0.4em;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.375rem, 4.5vw, 3.5rem);
  line-height: 1.2;
  white-space: nowrap;
}

.fill {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
}

/* script.js drives max-width; without JS the full phrase simply shows. */
.js .fill {
  max-width: 0;
  transition: max-width 0.8s cubic-bezier(0.65, 0, 0.35, 1);
}

.tagline {
  margin-top: 0.75rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1rem, 2.2vw, 1.75rem);
  line-height: 1.3;
  white-space: nowrap;
}

.word {
  display: inline-block;
  font-weight: 600;
}

/* script.js toggles .is-shown; without JS the tagline simply shows. */
.js .tagline,
.js .word {
  opacity: 0;
  filter: blur(6px);
  transition:
    opacity 0.5s ease-out,
    filter 0.5s ease-out;
}

.js .tagline.is-shown,
.js .word.is-shown {
  opacity: 1;
  filter: none;
}

.lede {
  margin-top: 2.5rem;
  max-width: 34ch;
  font-size: clamp(1.125rem, 2vw, 1.375rem);
}

/* Hero picture: a porthole into the deep. Beside the text on wide screens,
   below it on narrow ones. */

.hero {
  display: grid;
}

.deep-art {
  margin-top: 2.5rem;
  width: min(100%, 18rem);
}

.deep-art svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

@media (min-width: 60rem) {
  .hero {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    column-gap: 3rem;
  }

  .name {
    grid-column: 1 / -1;
  }

  .deep-art {
    grid-column: 2;
    grid-row: 2;
    width: 100%;
    margin-top: 2rem;
  }
}

.deep-art .water {
  fill: url(#deep-water);
}

.deep-art .rim {
  fill: none;
  stroke: var(--trench);
  stroke-width: 8;
}

.deep-art .rim-light {
  fill: none;
  stroke: var(--surface);
  stroke-opacity: 0.25;
  stroke-width: 1.5;
}

.deep-art .snow circle {
  fill: var(--surface);
  opacity: 0.35;
}

.deep-art .thread,
.deep-art .links line {
  fill: none;
  stroke: var(--shelf);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.deep-art .thread {
  stroke-opacity: 0.8;
}

.deep-art .links line {
  stroke-opacity: 0.35;
}

.deep-art .nodes circle {
  fill: var(--surface);
  animation: twinkle 4s ease-in-out infinite;
  animation-delay: var(--d);
}

.deep-art .signal {
  fill: none;
  stroke: var(--signal);
  stroke-width: 2.5;
  stroke-linecap: round;
  /* A short dash, then a long gap: each thread carries a pulse only about a quarter of the time */
  stroke-dasharray: 8 400;
  animation: signal var(--dur) linear var(--delay) infinite;
}

.deep-art .bell-body {
  fill: var(--surface);
  fill-opacity: 0.14;
  stroke: var(--surface);
  stroke-opacity: 0.75;
  stroke-width: 1.5;
}

.deep-art .bell-ribs {
  fill: none;
  stroke: var(--surface);
  stroke-opacity: 0.3;
  stroke-width: 1;
}

.deep-art .core {
  fill: var(--signal);
}

.deep-art .fizz circle {
  fill: var(--surface);
  opacity: 0;
  animation: fizz-rise var(--dur) linear var(--delay) infinite;
}

.deep-art .fizz .hot {
  fill: var(--signal);
}

@keyframes fizz-rise {
  0% {
    transform: translate(0, 0);
    opacity: 0;
  }
  15% {
    opacity: 0.8;
  }
  33% {
    transform: translate(-3px, -32px);
  }
  66% {
    transform: translate(3px, -63px);
  }
  100% {
    transform: translate(1px, -95px);
    opacity: 0;
  }
}

.deep-art .jelly {
  animation: bob-deep 7s ease-in-out infinite;
}

.deep-art .bell {
  transform-box: fill-box;
  transform-origin: center top;
  animation: pulse 3.5s ease-in-out infinite;
}

.deep-art .core-glow {
  animation: glow 3.5s ease-in-out infinite;
}

.deep-art .threads {
  transform-box: fill-box;
  transform-origin: center top;
  animation: sway 7s ease-in-out infinite alternate;
}

@keyframes bob-deep {
  0%,
  100% {
    transform: translateY(-8px);
  }
  50% {
    transform: translateY(8px);
  }
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(1, 1);
  }
  50% {
    transform: scale(1.05, 0.93);
  }
}

@keyframes glow {
  0%,
  100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}

@keyframes sway {
  from {
    transform: skewX(-3deg);
  }
  to {
    transform: skewX(3deg);
  }
}

@keyframes twinkle {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}

@keyframes signal {
  from {
    stroke-dashoffset: 0;
  }
  to {
    stroke-dashoffset: -408;
  }
}

/* Content bands */

h2 {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.2;
  margin-bottom: 1.75rem;
}

.futures {
  list-style: none;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem;
  font-size: clamp(1.25rem, 2.4vw, 1.625rem);
  line-height: 1.4;
}

/* Why the name works: panels step down, each one deeper than the last */
.steps {
  display: grid;
  gap: 1rem;
  font-size: clamp(1.125rem, 2vw, 1.375rem);
}

.steps .viewport:nth-child(2) {
  margin-left: 1rem;
}

.steps .viewport:nth-child(3) {
  margin-left: 2rem;
}

@media (min-width: 60rem) {
  .steps {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.25rem;
    align-items: start;
  }

  .steps .viewport:nth-child(2) {
    margin-left: 0;
    margin-top: 4rem;
  }

  .steps .viewport:nth-child(3) {
    margin-left: 0;
    margin-top: 8rem;
  }
}

/* Viewports: windows tinted a shade lighter than their band, with sunlight
   drifting across them as if seen from below the surface. --glint is kept
   faint in the trench so light text never loses contrast. */

.viewport {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(1.25rem, 2.5vw, 2rem);
  border-radius: 1.25rem;
}

.viewport::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse 40% 30% at 20% 30%, rgb(255 255 255 / var(--glint)), transparent),
    radial-gradient(ellipse 35% 25% at 70% 60%, rgb(255 255 255 / var(--glint)), transparent),
    radial-gradient(ellipse 30% 35% at 45% 85%, rgb(255 255 255 / var(--glint)), transparent);
  background-size: 200% 200%;
  animation: drift 16s ease-in-out infinite alternate;
  transition: opacity 0.4s ease-out;
  opacity: 0.8;
}

.band-shelf .viewport {
  --glint: 0.35;
  background: color-mix(in srgb, var(--surface) 35%, transparent);
  border: 1px solid color-mix(in srgb, var(--surface) 60%, transparent);
}

.band-trench .viewport {
  --glint: 0.06;
  background: color-mix(in srgb, var(--shelf) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--shelf) 40%, transparent);
}

.viewport:nth-child(2)::before {
  animation-delay: -5s;
}

.viewport:nth-child(3)::before {
  animation-delay: -10s;
}

@media (hover: hover) {
  .viewport:hover {
    translate: 0 -0.375rem;
  }

  .viewport:hover::before {
    opacity: 1;
  }
}

@keyframes drift {
  from {
    background-position: 0% 0%;
  }
  to {
    background-position: 100% 100%;
  }
}

.sale {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.25rem, 3.5vw, 2.5rem);
  line-height: 1.2;
}

/* Text surfaces: rises into focus from a slight blur, like seeing up through water */

.js [data-surface] {
  opacity: 0;
  filter: blur(10px);
  transform: translateY(1.5rem);
  transition:
    opacity 0.9s ease-out,
    filter 0.9s ease-out,
    transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 150ms);
}

.js [data-surface].is-visible {
  opacity: 1;
  filter: none;
  transform: none;
}

/* Viewports also lift on hover; that lift must not wait for the reveal stagger. */
.js .viewport[data-surface] {
  transition:
    opacity 0.9s ease-out,
    filter 0.9s ease-out,
    transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1),
    translate 0.4s ease-out;
  transition-delay:
    calc(var(--i, 0) * 150ms),
    calc(var(--i, 0) * 150ms),
    calc(var(--i, 0) * 150ms),
    0s;
}

@media (prefers-reduced-motion: reduce) {
  .scroll-cue svg {
    animation: none;
  }

  .scroll-cue,
  .scroll-cue.is-gone {
    transition: none;
  }

  .js .fill {
    max-width: none;
    transition: none;
  }

  .js .tagline,
  .js .word,
  .js [data-surface],
  .js .viewport[data-surface] {
    opacity: 1;
    filter: none;
    transform: none;
    transition: none;
  }

  .viewport::before,
  .deep-art *,
  .murk span,
  .fog span,
  .fog-hero span {
    animation: none;
  }

  .deep-art .signal,
  .bubbles {
    display: none;
  }

  .viewport:hover {
    translate: none;
  }
}
