/* ==========================================================================
   HERO · SENSORY TABLE
   The clip is a locked-off top-down shot of a craft table whose materials
   settle around a deliberately empty centre. Every word lives in that centre
   and is cut here in the page, so it stays sharp and works in both languages.
   ========================================================================== */

.hero-table{position:relative;z-index:2;padding:0;min-height:100svh;
  display:grid;align-items:center;overflow:hidden;isolation:isolate}

.cine{position:absolute;inset:0;z-index:-2;background:var(--cream-deep);overflow:hidden}
.cine-poster,.cine-vid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.cine-poster{background-size:cover;background-position:center}
.cine-vid{opacity:0;transition:opacity .7s var(--ease);transform:translateZ(0);will-change:transform}
.cine.vid-on .cine-vid{opacity:1}

/* the table is bright everywhere, so the centre gets only the faintest lift
   to guarantee the ink holds its contrast over the wood grain */
.hero-table::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(ellipse 62% 54% at 50% 46%,rgba(255,249,241,.86) 0%,rgba(255,249,241,.55) 52%,rgba(255,249,241,0) 80%)}

.hero-in{text-align:center;padding-block:calc(var(--nav-h) + 3rem) 3.4rem;
  max-width:min(46rem,92vw);margin-inline:auto}
.hero-in .lede{margin-inline:auto;max-width:44ch}
.hero-in .row{justify-content:center;margin-top:1.8rem}
.hero-in .cue{justify-content:center;margin-top:2rem}

/* the headline is laid out letter by letter, as if placed by hand */
.assemble{margin:1rem 0 .2rem}
.assemble .c{display:inline-block;white-space:pre;
  opacity:var(--kc,1);
  transform:translate(calc((1 - var(--kc,1))*var(--jx,0px)),calc((1 - var(--kc,1))*var(--jy,0px)))
            rotate(calc((1 - var(--kc,1))*var(--jr,0deg)))}

/* ---------- the felt words ----------
   Real felt is a texture, not a typeface, so the letterform stays as type and
   only its surface is dressed: a soft inner light, a fibrous grain and the
   short blunt shadow a 3mm sheet casts on wood. */
.felt-words{display:flex;flex-wrap:wrap;gap:.55rem 1.5rem;justify-content:center;
  margin:1.4rem 0 1.6rem}
.felt-word{display:flex;gap:.06em}
.felt{position:relative;display:inline-block;
  font-family:var(--display);font-weight:600;
  font-size:clamp(1.05rem,2.5vw,1.7rem);letter-spacing:.02em;line-height:1;
  color:var(--fc,var(--pink));
  padding:.18em .1em;
  opacity:var(--kf,1);
  transform:translateY(calc((1 - var(--kf,1))*-26px)) rotate(var(--fr,0deg)) scale(calc(.86 + .14*var(--kf,1)));
  text-shadow:
    0 1px 0 rgba(255,255,255,.55),
    0 2px 1px rgba(51,40,74,.18),
    0 5px 7px rgba(51,40,74,.16);
}
/* the fibre: a fine speckle laid over the glyph only */
.felt::after{content:attr(data-ch);position:absolute;inset:0;
  display:flex;align-items:center;justify-content:center;
  padding:.18em .1em;pointer-events:none;
  color:transparent;
  background-image:
    radial-gradient(circle at 22% 28%,rgba(255,255,255,.5) .5px,transparent .6px),
    radial-gradient(circle at 68% 62%,rgba(0,0,0,.16) .5px,transparent .6px),
    radial-gradient(circle at 45% 82%,rgba(255,255,255,.35) .4px,transparent .5px);
  background-size:3px 3px,4px 4px,5px 5px;
  -webkit-background-clip:text;background-clip:text;
  mix-blend-mode:overlay}

/* ---------- Kelly as a printed paper standee on the table ---------- */
.standee{position:absolute;right:clamp(1rem,5vw,4.5rem);bottom:0;z-index:3;
  width:clamp(150px,17vw,232px);
  opacity:var(--kelly,1);
  transform:translateY(calc((1 - var(--kelly,1))*26px));
  transition:opacity .7s var(--ease), transform .7s var(--ease)}
.standee-fig{position:relative;
  /* the standee leans back a touch, the way a folded tab holds a print */
  transform:perspective(900px) rotateX(4deg);
  transform-origin:bottom center}
.standee .kelly-inner{position:relative;overflow:hidden;aspect-ratio:3/4;
  border-radius:14px 14px 4px 4px;
  background:var(--cream);
  border:7px solid #fff;
  box-shadow:0 2px 0 rgba(51,40,74,.06), 0 16px 26px rgba(51,40,74,.24), 0 40px 46px rgba(51,40,74,.14)}
.standee .kelly-inner img,.standee .kelly-inner video{
  width:100%;height:100%;object-fit:cover;object-position:center 16%;display:block}
.standee .kelly-inner video{position:absolute;inset:0;opacity:0;transition:opacity .8s var(--ease)}
.standee .kelly-inner.ready video{opacity:1}
.standee .kelly-inner.ready img{opacity:0}
.standee .kelly-inner img{transition:opacity .8s var(--ease)}
/* the folded tab and the shadow it drops on the wood */
.standee-tab{position:absolute;left:50%;bottom:-9px;width:44%;height:14px;
  transform:translateX(-50%) skewX(-14deg);
  background:linear-gradient(180deg,#fff,#EFE4D3);
  border-radius:0 0 6px 6px;
  box-shadow:0 8px 14px rgba(51,40,74,.24)}
.standee .speech{position:absolute;left:auto;right:74%;bottom:58%;max-width:12.5rem;
  font-size:.88rem;padding:.7rem .95rem}
.standee .speech::after{right:14%}

@media (max-width:1100px){
  .standee{width:clamp(130px,20vw,180px)}
  .standee .speech{right:auto;left:50%;transform:translateX(-50%);bottom:auto;top:-3.6rem;
    max-width:none;white-space:nowrap;font-size:.8rem}
  .standee .speech::after{left:50%;margin-left:-11px;right:auto}
}
@media (max-width:720px){
  .standee{position:relative;right:auto;margin:2rem auto 0;width:min(170px,44vw)}
  .hero-in{padding-bottom:1rem}
}

.skip-intro{position:absolute;right:1.4rem;top:calc(var(--nav-h) + .6rem);z-index:8;
  font-family:var(--display);font-weight:600;font-size:.82rem;color:var(--ink);
  background:rgba(255,255,255,.9);border:0;border-radius:999px;padding:.55rem 1.1rem;
  cursor:pointer;box-shadow:var(--shadow-soft);
  transition:transform .3s var(--ease-back)}
.skip-intro:hover{transform:translateY(-2px)}
.skip-intro[hidden]{display:none}

/* Phones open on the settled table with everything already placed: the clip is
   2.9 MB and the composition is built to work without it.

   Reduced motion used to be in this list too, and that was the bug behind "the
   hero video does not run". The clip was playing and its clock was advancing,
   but display:none meant nothing was ever painted, and the four rules below had
   already pushed the whole choreography to its finished state. The owner asked
   for the sequence to run for everyone, so only the phone rule remains. */
@media (max-width:720px){
  .cine-vid{display:none}
  .skip-intro{display:none}
  .hero-table{--kelly:1}
  .assemble .c{opacity:1;transform:none}
  .felt{opacity:1;transform:rotate(var(--fr,0deg))}
  .standee{opacity:1;transform:none}
}

/* --------------------------------------------------------------------------
   Fresh-eyes fixes after the first screenshot pass
   -------------------------------------------------------------------------- */

/* The felt was washing out: overlay blending on a pale wood ground drained the
   colour out of the glyph. The speckle is dialled back and now only shades. */
.felt::after{mix-blend-mode:multiply;opacity:.4}
.felt{text-shadow:
    0 1px 0 rgba(255,255,255,.7),
    0 2px 1px rgba(51,40,74,.22),
    0 6px 8px rgba(51,40,74,.18)}

/* the standee was running off the bottom edge, and its bubble was so narrow
   the line broke four times */
.standee{bottom:clamp(1.2rem,4vh,3rem)}
.standee .speech{right:78%;bottom:52%;max-width:none;width:12.5rem;line-height:1.35}

@media (max-width:1100px){
  .standee{bottom:0}
  .standee .speech{width:auto}
}

/* ==========================================================================
   REFINEMENT PASS
   ========================================================================== */

/* ---------- the hero's own decoration ----------
   The page universe is hidden behind the table for the whole first screen, so
   the opening had almost nothing moving in it. This layer sits in front of the
   footage and is what makes the hero feel alive. It answers the pointer too. */
.hero-decor{position:absolute;inset:0;z-index:1;pointer-events:none;overflow:hidden}
/* outer: the pointer offset. inner: the drifting loop. Never the same
   element, or the animation overwrites the parallax. */
.hd-item{position:absolute;
  transform:translate3d(var(--px,0px),var(--py,0px),0);
  transition:transform .5s cubic-bezier(.22,.61,.36,1);will-change:transform}
.hd-m{display:block;will-change:transform}
.hero-decor .u-cloud{color:#fff;opacity:.94;
  filter:drop-shadow(0 8px 14px rgba(51,40,74,.10))}
.hero-decor .u-rainbow{opacity:.72}
.hero-decor .u-star{filter:drop-shadow(0 3px 6px rgba(51,40,74,.14))}

/* the inner element carries the loop, the outer one the pointer offset, so the
   two never fight over the same transform */


.u-balloon{border-radius:50% 50% 48% 48% / 46% 46% 54% 54%;
  box-shadow:inset -6px -8px 14px rgba(0,0,0,.13), inset 6px 6px 12px rgba(255,255,255,.4),
             0 10px 20px rgba(51,40,74,.16);position:relative}
.u-balloon::after{content:"";position:absolute;left:50%;bottom:-38px;width:2px;height:38px;
  transform:translateX(-50%);
  background:linear-gradient(180deg,rgba(51,40,74,.34),rgba(51,40,74,0))}
.u-balloon::before{content:"";position:absolute;left:50%;bottom:-6px;width:11px;height:8px;
  transform:translateX(-50%);background:inherit;border-radius:3px 3px 60% 60%;filter:brightness(.86)}

.in-motion .hero-decor .u-cloud.hd-m,
.in-motion .hero-decor .u-rainbow.hd-m,
.in-motion .hero-decor .u-balloon.hd-m{
  animation:u-float var(--dur,14s) ease-in-out var(--delay,-4s) infinite}
.in-motion .hero-decor .u-star.hd-m,
.in-motion .hero-decor .u-spark.hd-m{
  animation:u-twinkle var(--dur,4s) ease-in-out var(--delay,-2s) infinite}

/* ---------- Kelly, free standing ----------
   No frame, no card. The clip's backdrop is a flat pale cream and the table
   under it is warm cream too, so a generous feathered mask dissolves the
   rectangle's edges and she reads as a cutout standing on the table. A ground
   shadow underneath does the rest of the work. */
.standee{right:auto;left:58%;bottom:0;width:clamp(190px,25vw,330px);z-index:4}
.standee-fig{transform:none}
.standee .kelly-inner{
  border:0;border-radius:0;background:transparent;box-shadow:none;
  aspect-ratio:3/4;overflow:visible;
  -webkit-mask-image:
    radial-gradient(ellipse 62% 76% at 50% 42%, #000 54%, rgba(0,0,0,.85) 68%, transparent 88%),
    linear-gradient(to top, transparent 0%, #000 12%);
  mask-image:
    radial-gradient(ellipse 62% 76% at 50% 42%, #000 54%, rgba(0,0,0,.85) 68%, transparent 88%),
    linear-gradient(to top, transparent 0%, #000 12%);
  -webkit-mask-composite:source-in;mask-composite:intersect;
  filter:drop-shadow(0 18px 22px rgba(51,40,74,.20))}
.standee .kelly-inner img,.standee .kelly-inner video{object-position:center 12%}
.standee-tab{display:none}

/* the shadow she casts on the table, so she is standing on it, not floating */
.standee::after{content:"";position:absolute;left:50%;bottom:2%;
  width:56%;height:22px;transform:translateX(-50%);
  background:radial-gradient(ellipse 50% 50% at 50% 50%,rgba(51,40,74,.30),rgba(51,40,74,0) 72%);
  z-index:-1;pointer-events:none}

/* ---------- the speech bubble as a sticker ---------- */
.standee .speech{
  right:82%;bottom:56%;width:13.5rem;
  background:linear-gradient(145deg,var(--yellow) 0%,#FFB01F 58%,var(--orange) 100%);
  color:var(--ink);
  border:4px solid #fff;
  border-radius:26px 26px 26px 8px;
  padding:.85rem 1.05rem;
  font-family:var(--display);font-weight:600;font-size:.94rem;line-height:1.32;
  box-shadow:0 10px 0 rgba(51,40,74,.12), 0 18px 30px rgba(51,40,74,.22);
  transform:rotate(-3deg)}
.standee .speech::after{
  left:auto;right:12%;bottom:-16px;
  border:0;width:22px;height:22px;
  background:var(--orange);
  border-right:4px solid #fff;border-bottom:4px solid #fff;
  border-radius:0 0 8px 0;
  transform:rotate(38deg) skewX(-6deg)}
/* two sticker dots, the kind a child sticks on a note */
.standee .speech::before{content:"";position:absolute;left:-14px;top:-14px;
  width:26px;height:26px;border-radius:50%;
  background:var(--pink);border:4px solid #fff;
  box-shadow:0 4px 10px rgba(51,40,74,.22)}

@media (max-width:1100px){
  .standee{left:auto;right:2%;width:clamp(160px,26vw,220px)}
  .standee .speech{right:auto;left:50%;transform:translateX(-50%) rotate(-3deg);
    bottom:auto;top:-4.4rem;width:auto;white-space:nowrap}
  .standee .speech::after{left:50%;right:auto;margin-left:-11px}
  .standee .speech::before{left:-12px;top:-12px}
}
@media (max-width:720px){
  .standee{position:relative;left:auto;right:auto;margin:1.6rem auto 0;width:min(220px,58vw)}
}

/* ==========================================================================
   FIX PASS · after looking at the first render
   ========================================================================== */

/* 1. Kelly was overlapping the reading column: she covered a button, part of
   the lede and the end of SPEAK. The copy column is narrowed a little and she
   is sized and placed so the two can never meet, at any width. */
.hero-in{max-width:min(40rem,74vw)}
.standee{left:auto;right:4%;width:clamp(170px,20vw,268px)}

/* 2. The cutout. mask-composite:source-in is the old prefixed syntax and it was
   not intersecting, which left the clip's rectangle showing as a pale box.
   One radial mask does the job instead, and multiply drops the flat cream
   backdrop into the pale wood so only she is left standing on the table. */
.standee .kelly-inner{
  -webkit-mask-image:radial-gradient(ellipse 58% 72% at 50% 40%,
    #000 46%, rgba(0,0,0,.92) 60%, rgba(0,0,0,.45) 76%, transparent 92%);
  mask-image:radial-gradient(ellipse 58% 72% at 50% 40%,
    #000 46%, rgba(0,0,0,.92) 60%, rgba(0,0,0,.45) 76%, transparent 92%);
  -webkit-mask-composite:source-over;mask-composite:add;
  mix-blend-mode:multiply}

/* 3. The nav needs its own air. Decoration is pushed out of the header band so
   nothing drifts behind the logo or the menu. */
.hero-decor{top:var(--nav-h);clip-path:inset(0 0 0 0)}

/* 4. the bubble follows her, and never lands on the copy */
.standee .speech{right:78%;bottom:60%;width:12.5rem;font-size:.9rem}

@media (max-width:1100px){
  .hero-in{max-width:min(38rem,88vw)}
  .standee{right:2%;width:clamp(150px,22vw,200px)}
}
@media (max-width:720px){
  .hero-decor{top:0}
  .standee{position:relative;right:auto;margin:1.4rem auto 0;width:min(210px,56vw)}
  .standee .kelly-inner{mix-blend-mode:normal}
}

/* words never break apart, only whole words wrap */
.assemble .w{display:inline-block;white-space:nowrap}

/* Kelly: as far in as the copy column allows without ever touching it, and the
   backdrop is feathered rather than blended. multiply darkened the flat cream
   against the pale wood, which is what drew the visible box around her. */
.standee{right:10%;width:clamp(175px,18vw,240px)}
.standee .kelly-inner{
  mix-blend-mode:normal;
  -webkit-mask-image:radial-gradient(ellipse 47% 68% at 50% 42%,
    #000 40%, rgba(0,0,0,.94) 56%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.14) 85%, transparent 96%);
  mask-image:radial-gradient(ellipse 47% 68% at 50% 42%,
    #000 40%, rgba(0,0,0,.94) 56%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.14) 85%, transparent 96%)}
.standee .speech{right:82%;bottom:62%}

@media (max-width:1100px){ .standee{right:3%;width:clamp(150px,21vw,196px)} }
@media (max-width:720px){ .standee{right:auto;width:min(210px,56vw)} }

/* the bubble was grazing the second button; lifted clear of the whole row */
.standee .speech{bottom:76%;right:74%}
@media (max-width:1100px){ .standee .speech{bottom:auto;right:auto} }
