/* All motion on the site. Linked with media="(prefers-reduced-motion: no-preference)",
   so anyone who asks for less motion never downloads this file.
   Rules: animate transform and opacity where possible. Scroll-driven effects
   sit behind @supports, and their resting state is defined in site.css. */

/* Page changes: the new page rises like a tide */
@view-transition { navigation: auto; }
@keyframes tide-in { from { clip-path: polygon(0 110%, 25% 104%, 50% 110%, 75% 104%, 100% 110%, 100% 100%, 0 100%); } to { clip-path: polygon(0 -6%, 25% -2%, 50% -6%, 75% -2%, 100% -6%, 100% 100%, 0 100%); } }
@keyframes hold { to { opacity: .55; transform: translateY(-30px); } }
::view-transition-old(root) { animation: hold .75s ease-in both; }
::view-transition-new(root) { animation: tide-in .75s cubic-bezier(.7, 0, .2, 1) both; }

/* Small states */
.invite, .quiet, .plaque, .tabsw strong, .foot__row a { transition: color .25s, background-color .25s, border-color .25s; }
.plaque::before { content: ""; position: absolute; inset: 0 auto 0 -60%; width: 40%; background: linear-gradient(100deg, transparent, #fff9, transparent); transform: skewX(-20deg); }
.plaque:hover::before { animation: glint .85s var(--ease-swell); }
@keyframes glint { to { translate: 400% 0; } }
.plaque i { transition: transform .4s var(--ease-swell); }
.plaque:hover i { transform: translateX(7px); }
.plaque:active { transform: translateY(2px); }

/* Anchor in the header draws itself */
.mark svg * { stroke-dasharray: 1; animation: draw 1.8s .15s var(--ease-swell) both; }
@keyframes draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

/* Headlines come up from behind their own baseline */
.ln > span { animation: surface 1.25s var(--ease-swell) both; }
.ln:nth-of-type(2) > span { animation-delay: .13s; }
.ln:nth-of-type(3) > span { animation-delay: .26s; }
@keyframes surface { from { transform: translateY(112%) skewY(5deg); } to { transform: none; } }

.arrive { animation: arrive 1.1s var(--ease-swell) both; }
.arrive--1 { animation-delay: .35s; }
.arrive--2 { animation-delay: .5s; }
.arrive--3 { animation-delay: .65s; }
@keyframes arrive { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

/* Italic words carry a slow glint of brass */
@property --glint { syntax: "<percentage>"; inherits: false; initial-value: 130%; }
.display em { background: linear-gradient(100deg, var(--brass) calc(var(--glint) - 16%), var(--brass-pale) var(--glint), var(--brass) calc(var(--glint) + 16%)); -webkit-background-clip: text; background-clip: text; color: transparent; animation: brassglint 6.5s ease-in-out infinite; }
@keyframes brassglint { 0%, 30% { --glint: 130%; } 75%, 100% { --glint: -30%; } }
.disagree .display em { background: none; color: var(--rust); padding-right: 0; animation: none; }

/* The ship's wheel turns while you hover anything usable */
@keyframes helm-turn {
  0% { cursor: image-set(url("/assets/cursors/helm-0.png") 1x, url("/assets/cursors/helm-0@2x.png") 2x) 16 16, pointer; }
  25% { cursor: image-set(url("/assets/cursors/helm-1.png") 1x, url("/assets/cursors/helm-1@2x.png") 2x) 16 16, pointer; }
  50% { cursor: image-set(url("/assets/cursors/helm-2.png") 1x, url("/assets/cursors/helm-2@2x.png") 2x) 16 16, pointer; }
  75% { cursor: image-set(url("/assets/cursors/helm-3.png") 1x, url("/assets/cursors/helm-3@2x.png") 2x) 16 16, pointer; }
}
a:not(.arrive):hover, button:hover, .tabsw label:hover { animation: helm-turn .55s step-end infinite; }

/* Harbour: slow push-in, moving light on the water, instrument ring */
.hero__photo { animation: push-in 26s ease-in-out infinite alternate; transform-origin: 72% 70%; }
@keyframes push-in { from { transform: scale(1.02); } to { transform: scale(1.13); } }
.hero__glitter { animation: glitter 22s linear infinite; }
@keyframes glitter { from { background-position-x: 0; } to { background-position-x: 1040px; } }
.band__photo { animation: push-in 30s ease-in-out infinite alternate; }

@keyframes twinkle { from { opacity: .3; } to { opacity: 1; } }
.compass { animation: bearing 150s linear infinite; }
.compass--in { animation-duration: 94s; animation-direction: reverse; }
@keyframes bearing { to { rotate: 360deg; } }

/* Sea */
.wave { animation: drift 15s linear infinite, heave 6.4s ease-in-out infinite alternate; will-change: transform; }
.wave--2 { animation-duration: 10.5s, 5.2s; animation-delay: -4s, -2s; animation-direction: reverse, alternate; }
.wave--3 { animation-duration: 7.4s, 4.2s; animation-delay: -2s, -1s; }
@keyframes drift { to { translate: -50% 0; } }
@keyframes heave { from { transform: translateY(5%); } to { transform: translateY(-7%); } }

/* Rope of words */
.rope__track { animation: run 44s linear infinite; }
.rope__track + .rope__track { animation-direction: reverse; animation-duration: 58s; }
.rope:hover .rope__track { animation-play-state: paused; }
@keyframes run { to { transform: translateX(-50%); } }

/* Papers go in, records come out */
.paper { animation: feed 7.5s cubic-bezier(.55, 0, .75, .4) infinite both; }
.paper:nth-child(2) { animation-delay: -1.5s; }
.paper:nth-child(3) { animation-delay: -3s; }
.paper:nth-child(4) { animation-delay: -4.5s; }
.paper:nth-child(5) { animation-delay: -6s; }
@keyframes feed {
  0% { opacity: 0; transform: translateY(-120%) rotate(calc(var(--r) * -3)); }
  10% { opacity: 1; }
  60% { opacity: 1; transform: translateY(0) rotate(var(--r)); }
  90% { opacity: 1; transform: translateY(190%) rotate(0deg) scale(.82, .4); }
  96%, 100% { opacity: 0; transform: translateY(205%) rotate(0deg) scale(.5, .12); }
}
.slot { animation: scan 1.5s ease-in-out infinite alternate; }
@keyframes scan { from { opacity: .55; transform: scaleX(.97); } to { opacity: 1; transform: scaleX(1); } }
.rec { animation: emerge 7.5s var(--ease-swell) infinite both; }
.rec:nth-child(2) { animation-delay: -5.5s; }
.rec:nth-child(3) { animation-delay: -3.5s; }
.rec:nth-child(4) { animation-delay: -1.5s; }
@keyframes emerge {
  0% { opacity: 0; clip-path: inset(0 0 100% 0); transform: translateY(-16px); }
  12%, 82% { opacity: 1; clip-path: inset(0); transform: none; }
  96%, 100% { opacity: 0; clip-path: inset(0); transform: translateY(6px); }
}

/* Screens on the app page turn with depth */
.shot { transform: translateZ(0) scale(.965); transition: opacity .55s, transform .85s var(--ease-swell); }
#s1:checked ~ .gallery__phone .shot--1, #s2:checked ~ .gallery__phone .shot--2, #s3:checked ~ .gallery__phone .shot--3, #s4:checked ~ .gallery__phone .shot--4, #s5:checked ~ .gallery__phone .shot--5, #s6:checked ~ .gallery__phone .shot--6 { transform: none; }
.tabsw span { animation: arrive .7s var(--ease-swell) both; }


/* Waitlist */
.join:has(input:user-invalid) .join__row { animation: refuse .42s linear; }
@keyframes refuse { 20% { transform: translateX(-8px); } 40% { transform: translateX(7px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(3px); } }
.join:has(input:valid) .plaque i { animation: nudge 1.1s ease-in-out infinite; }
@keyframes nudge { 50% { transform: translateX(6px); } }

/* Short pages */
.sailor { animation: voyage 19s linear infinite, bob 3.4s ease-in-out infinite alternate; }
@keyframes voyage { from { left: -18vw; } to { left: 108vw; } }
@keyframes bob { from { rotate: -3deg; translate: 0 4px; } to { rotate: 4deg; translate: 0 -8px; } }
.flares i { animation: flare 3.2s ease-out infinite both; }
.flares i:nth-child(even) { animation-delay: .32s; }
@keyframes flare {
  0% { opacity: 0; transform: rotate(var(--a)) translateY(-20px) scaleY(.2); }
  20% { opacity: 1; }
  70%, 100% { opacity: 0; transform: rotate(var(--a)) translateY(-190px) scaleY(1); }
}
.foot__ship { left: 0; animation: passage 34s linear infinite; }
@keyframes passage { from { transform: translateX(-140px); } to { transform: translateX(calc(100vw + 40vw)); } }
.foot__ship svg { animation: bob 3.1s ease-in-out infinite alternate; }
.foot__cell a i { transition: transform .4s var(--ease-swell); }
.foot__cell a:hover i { transform: translateX(6px); }
.beam { animation: sweep 11s linear infinite; }
@keyframes sweep { to { rotate: 360deg; } }
.lamp { animation: twinkle 1.5s ease-in-out infinite alternate; }

/* Scroll-driven layer */
@supports (animation-timeline: view()) {
  /* A brass thread and a small hull track reading progress */
  .thread { position: fixed; z-index: 40; inset: 0 0 auto; height: 2px; background: var(--brass); transform-origin: left; animation: thread linear both; animation-timeline: scroll(root); }
  @keyframes thread { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  .rv { animation: rv linear both; animation-timeline: view(); animation-range: entry 0% entry 70%; }
  @keyframes rv { from { opacity: 0; transform: translateY(70px); } to { opacity: 1; transform: none; } }

  /* Hero sinks as you leave it */
  .hero__copy { animation: lift linear both; animation-timeline: scroll(root); animation-range: 0 100vh; }
  @keyframes lift { to { transform: translateY(-14vh); opacity: .1; } }

  /* Hour meters spin up and stop on their readings, one drum at a time */
  .reading { view-timeline: --reading block; }
  .reel b { animation: roll linear both; animation-timeline: --reading; animation-range: entry 40% cover 22%; }
  .reel:nth-child(2) b { animation-range: entry 40% cover 26%; }
  .reel:nth-child(3) b { animation-range: entry 40% cover 30%; }
  .reel:nth-child(4) b { animation-range: entry 40% cover 34%; }
  @keyframes roll { from { transform: translateY(calc(var(--cell) * -1.42 * 9)); filter: blur(2px); } 92% { filter: blur(0); } to { transform: translateY(calc(var(--cell) * -1.42 * var(--d))); filter: blur(0); } }
  .verdict__gap { transform-origin: left center; animation: stamp linear both; animation-timeline: view(); animation-range: entry 10% entry 100%; }
  @keyframes stamp { from { transform: scale(1.5) rotate(-4deg); opacity: 0; } to { transform: none; opacity: 1; } }

  /* Photos drift against the scroll */
  .band__photo { animation: band-drift linear both; animation-timeline: view(); }
  @keyframes band-drift { from { transform: translateY(-7%); } to { transform: translateY(7%); } }

  /* The footer's waterline draws itself in */
  .foot__water { animation: waterline linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; }
  @keyframes waterline { from { border-bottom-color: transparent; } }

  /* Phone held still while the walkthrough scrolls past it */
  @media (min-width: 861px) {
    .walk { grid-template-columns: minmax(0, 1fr) auto; column-gap: 7vw; timeline-scope: --one, --two, --three; }
    .walk__steps { grid-column: 1; grid-row: 1; }
    .step { min-height: 100vh; }
    .step .phone { display: none; }
    .step:nth-child(1) { view-timeline: --one block; }
    .step:nth-child(2) { view-timeline: --two block; }
    .step:nth-child(3) { view-timeline: --three block; }
    .walk__phone { display: block; grid-column: 2; grid-row: 1; position: sticky; top: calc(50vh - clamp(280px, 28vw, 410px)); align-self: start; perspective: 1400px; }
    .walk__phone .phone { --w: clamp(260px, 25.6vw, 378px); transform: rotateY(-8deg); }
    .walk__phone img { animation: screen-turn linear both; }
    .walk__phone img:nth-child(1) { animation-timeline: --one; animation-name: screen-first; }
    .walk__phone img:nth-child(2) { animation-timeline: --two; }
    .walk__phone img:nth-child(3) { animation-timeline: --three; animation-name: screen-last; }
    @keyframes screen-first { 0%, 62% { opacity: 1; transform: none; } 80%, 100% { opacity: 0; transform: translateY(-5%) scale(.96); } }
    @keyframes screen-turn { 0%, 20% { opacity: 0; transform: translateY(6%) scale(1.02); } 38%, 62% { opacity: 1; transform: none; } 80%, 100% { opacity: 0; transform: translateY(-5%) scale(.96); } }
    @keyframes screen-last { 0%, 20% { opacity: 0; transform: translateY(6%) scale(1.02); } 38%, 100% { opacity: 1; transform: none; } }
  }
}
