/* Ocean Jet Ski v4 - css/enter.css
   The entrance, and nothing else. Every rule here is scoped under .is-arming, which only ever
   exists while the sequence is running, so the resting page is untouched and a page without
   JavaScript never sees any of it. Opacity, transform and clip-path only. */

/* letters ---------------------------------------------------------------- */
.hero-paper__title .word, .hero-name .word{ display:inline-block; white-space:nowrap; }
.hero-paper__title .ch, .hero-name .ch{ display:inline-block; will-change:opacity, transform; }

/* A keyboard, not a fade (Tino, 2 Sep): each letter is simply THERE, fully black, at its turn.
   No blur, no scale, no easing in. The only thing that is timed is which letter is next, so what
   moves is the caret, exactly as it would on a screen you were typing on. */
.is-arming .hero-paper__title .ch,
.is-arming .hero-name .ch{ opacity:0; }

.is-arming.is-typed .hero-paper__title .ch,
.is-arming.is-typed .hero-name .ch{
  opacity:1;
  transition:opacity 0s linear calc(var(--i) * 140ms);
}

/* the caret: one hairline that keeps pace with the last letter, then leaves */
.is-arming .hero-paper__title::after,
.is-arming .hero-name > span:last-child::after{
  content:""; display:inline-block; width:2px; height:.78em; margin-left:.08em;
  vertical-align:-.06em; background:currentColor; opacity:.75;
  animation:ojs-caret .9s steps(1,end) infinite;
}
.is-arming.is-rest .hero-paper__title::after,
.is-arming.is-rest .hero-name > span:last-child::after{ opacity:0; animation:none; transition:opacity .3s linear; }
@keyframes ojs-caret{ 0%,49%{ opacity:.75; } 50%,100%{ opacity:0; } }

/* the water ------------------------------------------------------------- */
/* First move of the sequence (Tino, 2 Sep, from the rioproperty reference): the video panel
   sweeps in from the right edge to its place, THEN the name types on the white side. A transform,
   not a clip: hero.css pins .hero-media's clip-path with !important, and a panel that moves reads
   as arriving, which is what "pops from right to left" meant. */
.is-arming .hero-media{ animation:none !important; transform:translateX(100%); }
.is-arming.is-media .hero-media{ transform:none; transition:transform 1.15s cubic-bezier(.16,1,.3,1); }
html.is-arming, .is-arming body{ overflow-x:clip; }
/* the floating picture waits for the panel it straddles */
.is-arming .hero .hero-over{ opacity:0; }
.is-arming.is-rest .hero .hero-over{ opacity:1; transition:opacity .6s linear .25s; }
/* the picture inside settles as the panel opens, so the water is already moving when it lands */
.is-arming .hero-media .hero-still{ transform:scale(1.06); }
.is-arming.is-media .hero-media .hero-still{ transform:none; transition:transform 1.3s var(--ease); }

/* the mark, the line, the table, the chips ------------------------------- */
.is-arming .site-header__logo,
.is-arming .hero-sub,
.is-arming .hero-trust,
.is-arming .hero-cluster,
.is-arming .bookbar,
.is-arming .hero-facts,
.is-arming .hero-card{ opacity:0; transform:translateY(12px); }

.is-arming.is-rest .site-header__logo,
.is-arming.is-rest .hero-sub,
.is-arming.is-rest .hero-trust,
.is-arming.is-rest .hero-cluster,
.is-arming.is-rest .bookbar,
.is-arming.is-rest .hero-facts,
.is-arming.is-rest .hero-card{
  opacity:1; transform:none;
  transition:opacity .5s linear, transform .62s var(--ease);
}
.is-arming.is-rest .hero-sub{ transition-delay:.10s; }
.is-arming.is-rest .hero-trust{ transition-delay:.18s; }
.is-arming.is-rest .bookbar,
.is-arming.is-rest .hero-card{ transition-delay:.20s; }
.is-arming.is-rest .hero-facts{ transition-delay:.34s; }

/* nobody waits twice, and nobody waits who asked not to */
@media (prefers-reduced-motion:reduce){
  .is-arming, .is-arming *{ animation:none !important; transition:none !important;
    opacity:1 !important; transform:none !important; clip-path:none !important; }
}

/* the same typing, later down the page ------------------------------------ */
.type-armed .ch{ display:inline-block; opacity:0; }
.type-armed.type-go .ch{
  opacity:1;
  transition:opacity 0s linear calc(var(--i) * 90ms);
}
.type-armed .word{ display:inline-block; white-space:nowrap; }
@media (prefers-reduced-motion:reduce){
  .type-armed .ch{ opacity:1 !important; transform:none !important; transition:none !important; }
}


/* ==================================================================
   THE PHONE HERO: ARRIVAL AND THE NAME, 3 September 2026
   Tino, third pass: "the images are moved in in one second, from right to
   left and from left to right, because I realised that three seconds is
   just too much. What if somebody's in a rush and wants to check the
   location? It's not functional." And: "the title must be typed, and it
   can be untyped and typed, so it's always typing all the time, and the
   letters are falling down or falling up."

   So the phone no longer borrows the desktop's is-arming / is-typed /
   is-rest sequence at all - enter.js hands the phone straight over. The
   arrival is plain CSS, done in 1s, and the name loops for ever. The only
   thing that animates permanently is the name; the pictures move when the
   page moves and are otherwise still, which is what keeps a scroll smooth.
   ================================================================== */
@media (max-width:1023.98px){
  /* the whole hero has arrived by about 1.7s */
  .hero-media > picture{  animation:pheroInA 1s cubic-bezier(.22,.7,.3,1) .25s both; }
  .hero-media > .phero-frame{ animation:pheroInB 1s cubic-bezier(.22,.7,.3,1) .5s both; }
  .hero-sub{   animation:pheroRise .5s linear .95s both; }
  .hero .hero-trust{ animation:pheroRise .5s linear 1.1s both; }

  /* the name: types in, holds, falls away, and starts again. One animation per letter, staggered,
     so the browser owns the whole cycle and nothing is scheduled in script. */
  /* no will-change: steps(1,end) means there is nothing to interpolate, so a composited layer per
     letter would be 19 layers held for ever and bought nothing */
  .name-loop .lch{ display:inline-block; opacity:0; }
  .name-loop .lch{ animation:pheroLetter 9s steps(1,end) infinite; animation-delay:calc(var(--i) * 55ms); }
}
@keyframes pheroInA{ from{ opacity:0; transform:translate3d(46%,0,0); } to{ opacity:1; transform:none; } }
@keyframes pheroInB{ from{ opacity:0; transform:translate3d(-52%,0,0); } to{ opacity:1; transform:none; } }
@keyframes pheroRise{ from{ opacity:0; transform:translate3d(0,10px,0); } to{ opacity:1; transform:none; } }
/* falls in from above, sits, then falls on down and out. steps(1,end) on the timing function keeps
   each letter a hard on/off like a keyboard, which is how the desktop name reads too. */
/* The blank window has to be SHORT. At 58% the name was absent for well over three seconds of every
   nine, which on a phone reads as a missing headline, not as an effect. It now holds for about seven
   seconds and is away for well under one. */
@keyframes pheroLetter{
  0%    { opacity:0; transform:translate3d(0,-.34em,0); }
  2%    { opacity:1; transform:none; }
  86%   { opacity:1; transform:none; }
  89%   { opacity:0; transform:translate3d(0,.34em,0); }
  100%  { opacity:0; transform:translate3d(0,-.34em,0); }
}
@media (prefers-reduced-motion:reduce){
  .hero-media > picture, .hero-media > .phero-frame, .hero-sub, .hero .hero-trust{ animation:none !important; }
  .name-loop .lch{ animation:none !important; opacity:1 !important; transform:none !important; }
}

/* Alive. Whenever the entrance is not actually running, the two photographs breathe: they rise and
   fall a few pixels on different clocks, and the picture inside the top frame drifts very slowly
   across it, so the block is never quite still.
   The gate is `html:not(.is-arming)`, NOT `.is-entered`. .is-entered only lands about 9.5s after
   load, and it never lands at all for a visitor with reduced motion on, because the head snippet
   only arms the entrance when reduced motion is off. Gating on it meant scrolling in the first ten
   seconds showed nothing move, which is exactly what Tino reported on 3 Sep. */
/* The idle float came out on 3 Sep. Two frames breathing for ever, plus the name looping, was
   three permanent animations on a phone, and Tino reported the scroll going slow. The name loops;
   the pictures move only when the page moves. */
@media (prefers-reduced-motion:reduce){
  .hero-media > picture, .hero-media > .phero-frame,
  .hero-media picture > .hero-still, .phero-frame > .phero-slide{ animation:none !important; }
}


/* ==================================================================
   THE PHONE PICTURES ON SCROLL, 3 September 2026
   Tino: "as I scroll down they're also moving... maybe the photos are
   getting a little bit longer, we have that from one of the references."

   That reference feature is the desktop's `--closed` opening, written by
   js/lag.js. Here it is the same idea with no JavaScript at all: a
   scroll-driven animation on the root timeline, which runs off the main
   thread, so it costs nothing on a phone. Where scroll timelines are not
   supported the pictures simply sit still and the idle float still runs.
   ================================================================== */
@media (max-width:1023.98px){
  @supports (animation-timeline: scroll()){
    /* WHAT IS GATED AND WHAT IS NOT.
       The arrival owns `transform` on the two frames and on the top photograph, so anything of ours
       that also writes transform has to wait for it (`html:not(.is-arming)`). Nothing else does.
       Height is not transform, and the lower photograph is not touched by the arrival at all, so
       those run from the very first pixel of scroll - including during the entrance, and including
       for a visitor with reduced motion, who never gets an entrance to wait for. Gating the whole
       lot on the entrance is what left Tino scrolling and seeing nothing move. */

    /* the frames lengthen as the page moves, alongside their own one-second arrival. Two animations,
       two timelines, and they touch different properties, so neither can fight the other. */
    .hero-media > picture{
      animation:pheroInA 1s cubic-bezier(.22,.7,.3,1) .25s both, pheroGrowA linear both;
      animation-timeline:auto, scroll(root);
      animation-range:normal, 0 460px;
    }
    .hero-media > .phero-frame{
      animation:pheroInB 1s cubic-bezier(.22,.7,.3,1) .5s both, pheroGrowB linear both;
      animation-timeline:auto, scroll(root);
      animation-range:normal, 0 560px;
    }
    /* the overlapping picture, the one Tino singled out, pushes in hardest inside its own box.
       Never gated either: the arrival moves its FRAME, not the picture inside it. */
    .phero-frame > .phero-slide{
      animation:pheroPanB linear both; animation-timeline:scroll(root); animation-range:0 760px;
    }

    /* the top photograph's travel. Nothing to wait for any more: the arrival writes transform on
       the FRAMES, never on the pictures inside them. */
    .hero-media picture > .hero-still{
      animation:pheroPan linear both; animation-timeline:scroll(root); animation-range:0 900px;
    }
  }
}
/* grows downward from its own resting height; B is anchored to its bottom edge, so it grows upward */
@keyframes pheroGrowA{ from{ height:var(--ph-a); } to{ height:calc(var(--ph-a) * 1.24); } }
@keyframes pheroGrowB{ from{ height:var(--ph-b); } to{ height:calc(var(--ph-b) * 1.30); } }
/* The Future Goals travel. The picture is 124% of its frame, so it can ride a full 12% either way
   against the page: the frame climbs the screen at scroll speed, the photograph inside it climbs
   slower, and what you read is the picture lengthening and revealing as you go. A little scale on
   top of it is the close-up Tino asked for. The two run in opposite directions so the overlapping
   pair never moves as one block. */
@keyframes pheroPan{ from{ transform:translate3d(0,-11%,0) scale(1.02); }
                     to{   transform:translate3d(0,11%,0) scale(1.12); } }
@keyframes pheroPanB{ from{ transform:translate3d(0,10%,0) scale(1.02); }
                      to{   transform:translate3d(0,-11%,0) scale(1.14); } }

/* Touch. The frames answer a finger: they lift and grow a little under it, then settle back.
   Class toggled by js/site.js on touchstart / touchend; no rAF loop, nothing measured. */
/* Point at a picture, with a mouse or a finger, and you get CLOSER INSIDE the box (Tino, 3 Sep) -
   the frame holds its edges and the photograph pushes in behind them. The zoom is written with the
   standalone `scale` property, NOT with `transform`, because the scroll travel already owns
   transform on these images and an animation always beats a transition. scale composes on top of
   it, so the two never fight. */
@media (max-width:1023.98px){
  .hero-media picture > .hero-still, .phero-frame > .phero-slide{
    transition:scale .4s cubic-bezier(.2,.7,.3,1);
  }
  .hero-media > picture.is-touched > .hero-still{ scale:1.09; }
  .hero-media > .phero-frame.is-touched > .phero-slide{ scale:1.11; }
  .hero-media > picture, .hero-media > .phero-frame{ transition:box-shadow .3s linear; }
  .hero-media > picture.is-touched{ box-shadow:0 26px 54px rgba(17,19,21,.30); }
  .hero-media > .phero-frame.is-touched{ box-shadow:0 26px 54px rgba(17,19,21,.34); }
}
@media (prefers-reduced-motion:reduce){
  html:not(.is-arming) .hero-media > picture,
  html:not(.is-arming) .hero-media > .phero-frame,
  html:not(.is-arming) .hero-media picture > .hero-still,
  html:not(.is-arming) .phero-frame > .phero-slide{ animation:none !important; }
  .hero-media > picture.is-touched, .hero-media > .phero-frame.is-touched{ transform:none !important; }
}
